rays 0.3.10 → 0.3.12

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/rays/image.cpp +10 -0
  3. data/.doc/ext/rays/painter.cpp +49 -1
  4. data/.doc/ext/rays/polygon.cpp +1 -1
  5. data/.doc/ext/rays/shader.cpp +8 -6
  6. data/.github/workflows/release-gem.yml +4 -1
  7. data/.github/workflows/test.yml +4 -4
  8. data/.github/workflows/utils.rb +88 -17
  9. data/ChangeLog.md +24 -0
  10. data/Gemfile.lock +6 -5
  11. data/Rakefile +3 -3
  12. data/VERSION +1 -1
  13. data/ext/rays/extconf.rb +3 -4
  14. data/ext/rays/image.cpp +11 -0
  15. data/ext/rays/painter.cpp +53 -1
  16. data/ext/rays/polygon.cpp +1 -1
  17. data/ext/rays/shader.cpp +8 -6
  18. data/include/rays/coord.h +6 -6
  19. data/include/rays/defs.h +2 -0
  20. data/include/rays/image.h +11 -1
  21. data/include/rays/painter.h +19 -0
  22. data/include/rays/ruby.h +2 -2
  23. data/include/rays/shader.h +5 -3
  24. data/include/rays.h +2 -2
  25. data/lib/rays/extension.rb +8 -2
  26. data/lib/rays/image.rb +2 -1
  27. data/lib/rays/shader.rb +13 -4
  28. data/rays.gemspec +3 -4
  29. data/src/bitmap.h +4 -0
  30. data/src/color_space.cpp +2 -42
  31. data/src/coord.h +10 -0
  32. data/src/font.cpp +1 -1
  33. data/src/image.cpp +85 -11
  34. data/src/ios/bitmap.mm +5 -32
  35. data/src/ios/rays.mm +3 -3
  36. data/src/opengl/bitmap.cpp +41 -0
  37. data/src/opengl/color_space.cpp +51 -0
  38. data/src/{color_space.h → opengl/color_space.h} +2 -2
  39. data/src/{frame_buffer.cpp → opengl/frame_buffer.cpp} +1 -1
  40. data/src/{frame_buffer.h → opengl/frame_buffer.h} +2 -2
  41. data/src/{ios → opengl/ios}/opengl.mm +3 -3
  42. data/src/{opengl.h → opengl/opengl.h} +2 -6
  43. data/src/{osx → opengl/osx}/opengl.mm +3 -3
  44. data/src/opengl/painter.cpp +1020 -0
  45. data/src/{render_buffer.cpp → opengl/render_buffer.cpp} +1 -1
  46. data/src/{render_buffer.h → opengl/render_buffer.h} +2 -2
  47. data/src/{sdl → opengl/sdl}/opengl.cpp +10 -3
  48. data/src/{shader.cpp → opengl/shader.cpp} +69 -53
  49. data/src/{shader.h → opengl/shader.h} +12 -8
  50. data/src/{shader_program.cpp → opengl/shader_program.cpp} +24 -10
  51. data/src/{shader_program.h → opengl/shader_program.h} +4 -3
  52. data/src/{shader_source.cpp → opengl/shader_source.cpp} +2 -4
  53. data/src/{shader_source.h → opengl/shader_source.h} +2 -2
  54. data/src/{texture.cpp → opengl/texture.cpp} +18 -7
  55. data/src/opengl/texture.h +21 -0
  56. data/src/{win32 → opengl/win32}/opengl.cpp +4 -3
  57. data/src/osx/bitmap.mm +6 -34
  58. data/src/osx/rays.mm +3 -3
  59. data/src/painter.cpp +96 -925
  60. data/src/painter.h +223 -11
  61. data/src/polygon.cpp +38 -13
  62. data/src/renderer.h +22 -0
  63. data/src/sdl/bitmap.cpp +5 -33
  64. data/src/sdl/font.cpp +358 -9
  65. data/src/sdl/rays.cpp +8 -3
  66. data/src/texture.h +6 -3
  67. data/src/win32/bitmap.cpp +6 -34
  68. data/src/win32/rays.cpp +3 -3
  69. data/test/test_painter.rb +36 -25
  70. data/test/test_painter_batch.rb +254 -0
  71. metadata +31 -24
  72. /data/src/{opengl.cpp → opengl/opengl.cpp} +0 -0
data/src/painter.cpp CHANGED
@@ -1,654 +1,29 @@
1
1
  #include "painter.h"
2
2
 
3
3
 
4
- #include <math.h>
5
4
  #include <string.h>
6
5
  #include <assert.h>
7
- #include <memory>
8
- #include <vector>
9
- #include <algorithm>
10
- #include <functional>
11
6
  #include "rays/exception.h"
12
7
  #include "rays/debug.h"
13
- #include "rays/point.h"
14
- #include "rays/bounds.h"
15
- #include "rays/color.h"
16
- #include "opengl.h"
17
- #include "glm.h"
18
- #include "matrix.h"
19
8
  #include "polygon.h"
20
- #include "bitmap.h"
21
- #include "texture.h"
22
9
  #include "image.h"
23
- #include "font.h"
24
- #include "frame_buffer.h"
25
- #include "shader.h"
26
- #include "shader_program.h"
27
- #include "shader_source.h"
28
10
 
29
11
 
30
12
  namespace Rays
31
13
  {
32
14
 
33
15
 
34
- enum ColorType
35
- {
36
-
37
- FILL = 0,
38
- STROKE,
39
-
40
- COLOR_TYPE_MAX
41
-
42
- };// ColorType
43
-
44
-
45
- struct State
46
- {
47
-
48
- Color background, colors[COLOR_TYPE_MAX];
49
-
50
- bool nocolors[COLOR_TYPE_MAX];
51
-
52
- coord stroke_width;
53
-
54
- float stroke_outset;
55
-
56
- CapType stroke_cap;
57
-
58
- JoinType stroke_join;
59
-
60
- coord miter_limit;
61
-
62
- uint nsegment;
63
-
64
- coord line_height;
65
-
66
- BlendMode blend_mode;
67
-
68
- Bounds clip;
69
-
70
- Font font;
71
-
72
- Image texture;
73
-
74
- TexCoordMode texcoord_mode;
75
-
76
- TexCoordWrap texcoord_wrap;
77
-
78
- Shader shader;
79
-
80
- void init ()
81
- {
82
- background .reset(0, 0);
83
- colors[FILL] .reset(1, 1);
84
- colors[STROKE] .reset(1, 0);
85
- nocolors[FILL] = false;
86
- nocolors[STROKE] = true;
87
- stroke_width = 0;
88
- stroke_outset = 0;
89
- stroke_cap = CAP_DEFAULT;
90
- stroke_join = JOIN_DEFAULT;
91
- miter_limit = JOIN_DEFAULT_MITER_LIMIT;
92
- nsegment = 0;
93
- line_height = -1;
94
- blend_mode = BLEND_NORMAL;
95
- clip .reset(-1);
96
- font = get_default_font();
97
- texture = Image();
98
- texcoord_mode = TEXCOORD_IMAGE;
99
- texcoord_wrap = TEXCOORD_CLAMP;
100
- shader = Shader();
101
- }
102
-
103
- bool get_color (Color* color, ColorType type) const
104
- {
105
- const Color& c = colors[type];
106
- if (blend_mode == BLEND_REPLACE ? nocolors[type] : !c)
107
- return false;
108
-
109
- *color = c;
110
- return true;
111
- }
112
-
113
- bool has_color () const
114
- {
115
- if (blend_mode == BLEND_REPLACE)
116
- return !nocolors[FILL] || !nocolors[STROKE];
117
- else
118
- return colors[FILL] || colors[STROKE];
119
- }
120
-
121
- };// State
122
-
123
-
124
- struct TextureInfo
125
- {
126
-
127
- const Texture& texture;
128
-
129
- Point min, max;
130
-
131
- TextureInfo (
132
- const Texture& texture,
133
- coord x_min, coord y_min,
134
- coord x_max, coord y_max)
135
- : texture(texture)
136
- {
137
- min.reset(x_min, y_min);
138
- max.reset(x_max, y_max);
139
- }
140
-
141
- operator bool () const
142
- {
143
- return
144
- texture &&
145
- min.x < max.x &&
146
- min.y < max.y;
147
- }
148
-
149
- bool operator ! () const
150
- {
151
- return !operator bool();
152
- }
153
-
154
- };// TextureInfo
155
-
156
-
157
- struct OpenGLState
158
- {
159
-
160
- GLint viewport[4];
161
-
162
- GLclampf color_clear[4];
163
-
164
- GLboolean depth_test;
165
- GLint depth_func;
166
-
167
- GLboolean scissor_test;
168
- GLint scissor_box[4];
169
-
170
- GLboolean blend;
171
- GLint blend_equation_rgb, blend_equation_alpha;
172
- GLint blend_src_rgb, blend_src_alpha, blend_dst_rgb, blend_dst_alpha;
173
-
174
- GLint framebuffer_binding;
175
-
176
- void push ()
177
- {
178
- glGetIntegerv(GL_VIEWPORT, viewport);
179
-
180
- glGetFloatv(GL_COLOR_CLEAR_VALUE, color_clear);
181
-
182
- glGetBooleanv(GL_DEPTH_TEST, &depth_test);
183
- glGetIntegerv(GL_DEPTH_FUNC, &depth_func);
184
-
185
- glGetBooleanv(GL_SCISSOR_TEST, &scissor_test);
186
- glGetIntegerv(GL_SCISSOR_BOX, scissor_box);
187
-
188
- glGetBooleanv(GL_BLEND, &blend);
189
- glGetIntegerv(GL_BLEND_EQUATION_RGB, &blend_equation_rgb);
190
- glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blend_equation_alpha);
191
- glGetIntegerv(GL_BLEND_SRC_RGB, &blend_src_rgb);
192
- glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_alpha);
193
- glGetIntegerv(GL_BLEND_DST_RGB, &blend_dst_rgb);
194
- glGetIntegerv(GL_BLEND_DST_ALPHA, &blend_dst_alpha);
195
-
196
- glGetIntegerv(GL_FRAMEBUFFER_BINDING, &framebuffer_binding);
197
- }
198
-
199
- void pop ()
200
- {
201
- glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
202
-
203
- glClearColor(
204
- color_clear[0], color_clear[1], color_clear[2], color_clear[3]);
205
-
206
- enable(GL_DEPTH_TEST, depth_test);
207
- glDepthFunc(depth_func);
208
-
209
- enable(GL_SCISSOR_TEST, scissor_test);
210
- glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]);
211
-
212
- enable(GL_BLEND, blend);
213
- glBlendEquationSeparate(blend_equation_rgb, blend_equation_alpha);
214
- glBlendFuncSeparate(
215
- blend_src_rgb, blend_dst_rgb, blend_src_alpha, blend_dst_alpha);
216
-
217
- glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_binding);
218
- }
219
-
220
- private:
221
-
222
- void enable(GLenum type, GLboolean value)
223
- {
224
- if (value)
225
- glEnable(type);
226
- else
227
- glDisable(type);
228
- }
229
-
230
- };// OpenGLState
231
-
232
-
233
- class DefaultIndices
234
- {
235
-
236
- public:
237
-
238
- void resize (size_t size)
239
- {
240
- indices.reserve(size);
241
- while (indices.size() < size)
242
- indices.emplace_back(indices.size());
243
- }
244
-
245
- void clear ()
246
- {
247
- decltype(indices)().swap(indices);
248
- }
249
-
250
- const uint* get () const
251
- {
252
- return &indices[0];
253
- }
254
-
255
- private:
256
-
257
- std::vector<uint> indices;
258
-
259
- };// DefaultIndices
260
-
261
-
262
- template <typename COORD>
263
- static GLenum get_gl_type ();
264
-
265
- template <>
266
- GLenum
267
- get_gl_type<float> ()
268
- {
269
- return GL_FLOAT;
270
- }
271
-
272
-
273
- struct Painter::Data
274
- {
275
-
276
- bool painting = false;
277
-
278
- float pixel_density = 1;
279
-
280
- Bounds viewport;
281
-
282
- State state;
283
-
284
- std::vector<State> state_stack;
285
-
286
- Matrix position_matrix;
287
-
288
- std::vector<Matrix> position_matrix_stack;
289
-
290
- FrameBuffer frame_buffer;
291
-
292
- Image text_image;
293
-
294
- OpenGLState opengl_state;
295
-
296
- DefaultIndices default_indices;
297
-
298
- Data ()
299
- {
300
- state.init();
301
- }
302
-
303
- void set_pixel_density (float density)
304
- {
305
- if (density <= 0)
306
- argument_error(__FILE__, __LINE__, "invalid pixel_density.");
307
-
308
- this->pixel_density = density;
309
- text_image = Image();
310
- }
311
-
312
- void update_clip ()
313
- {
314
- const Bounds& clip = state.clip;
315
- if (clip)
316
- {
317
- coord y = frame_buffer ? clip.y : viewport.h - (clip.y + clip.h);
318
- glEnable(GL_SCISSOR_TEST);
319
- glScissor(
320
- pixel_density * clip.x,
321
- pixel_density * y,
322
- pixel_density * clip.width,
323
- pixel_density * clip.height);
324
- }
325
- else
326
- {
327
- glDisable(GL_SCISSOR_TEST);
328
- }
329
-
330
- OpenGL_check_error(__FILE__, __LINE__);
331
- }
332
-
333
- void draw (
334
- GLenum mode, const Color* color,
335
- const Coord3* points, size_t npoints,
336
- const uint* indices = NULL, size_t nindices = 0,
337
- const Color* colors = NULL,
338
- const Coord3* texcoords = NULL,
339
- const TextureInfo* texinfo = NULL,
340
- const Shader* shader = NULL)
341
- {
342
- if (!points)
343
- argument_error(__FILE__, __LINE__);
344
- if (npoints <= 0)
345
- argument_error(__FILE__, __LINE__);
346
-
347
- if (!painting)
348
- invalid_state_error(__FILE__, __LINE__, "'painting' should be true.");
349
-
350
- std::unique_ptr<TextureInfo> ptexinfo;
351
- texinfo = setup_texinfo(texinfo, ptexinfo);
352
- shader = setup_shader(shader, texinfo);
353
-
354
- const ShaderProgram* program = Shader_get_program(*shader);
355
- if (!program || !*program) return;
356
-
357
- ShaderProgram_activate(*program);
358
-
359
- const auto& names = Shader_get_builtin_variable_names(*shader);
360
- apply_builtin_uniforms(*program, names, texinfo);
361
- apply_attributes(*program, names, points, npoints, texcoords, color, colors);
362
- draw_indices(mode, indices, nindices, npoints);
363
- cleanup();
364
-
365
- ShaderProgram_deactivate();
366
- }
367
-
368
- private:
369
-
370
- std::vector<GLint> locations;
371
-
372
- std::vector<GLuint> buffers;
373
-
374
- const TextureInfo* setup_texinfo (const TextureInfo* texinfo, auto& ptr)
375
- {
376
- if (texinfo) return texinfo;
377
-
378
- const Texture* tex =
379
- state.texture ? &Image_get_texture(state.texture) : NULL;
380
- if (!tex) return NULL;
381
-
382
- ptr.reset(new TextureInfo(*tex, 0, 0, tex->width(), tex->height()));
383
- return ptr.get();
384
- }
385
-
386
- const Shader* setup_shader (const Shader* shader, bool for_texture)
387
- {
388
- if (state.shader) return &state.shader;
389
- if (shader) return shader;
390
- return for_texture
391
- ? &Shader_get_default_shader_for_texture(state.texcoord_wrap)
392
- : &Shader_get_default_shader_for_shape();
393
- }
394
-
395
- void apply_builtin_uniforms (
396
- const ShaderProgram& program, const ShaderBuiltinVariableNames& names,
397
- const TextureInfo* texinfo)
398
- {
399
- const Texture* texture = texinfo ? &texinfo->texture : NULL;
400
-
401
- Matrix texcoord_matrix(1);
402
- if (texture && *texture)
403
- {
404
- bool normal = state.texcoord_mode == TEXCOORD_NORMAL;
405
- texcoord_matrix.scale(
406
- (normal ? texture->width() : 1.0) / texture->reserved_width(),
407
- (normal ? texture->height() : 1.0) / texture->reserved_height());
408
- }
409
-
410
- for (const auto& name : names.uniform_position_matrix_names)
411
- {
412
- apply_uniform(program, name, [&](GLint loc) {
413
- glUniformMatrix4fv(loc, 1, GL_FALSE, position_matrix.array);
414
- });
415
- }
416
- for (const auto& name : names.uniform_texcoord_matrix_names)
417
- {
418
- apply_uniform(program, name, [&](GLint loc) {
419
- glUniformMatrix4fv(loc, 1, GL_FALSE, texcoord_matrix.array);
420
- });
421
- }
422
-
423
- if (!texinfo || !texture || !*texture) return;
424
-
425
- coord tw = texture->reserved_width();
426
- coord th = texture->reserved_height();
427
- Point min(texinfo->min.x / tw, texinfo->min.y / th);
428
- Point max(texinfo->max.x / tw, texinfo->max.y / th);
429
- Point offset( 1 / tw, 1 / th);
430
-
431
- for (const auto& name : names.uniform_texcoord_min_names)
432
- {
433
- apply_uniform(program, name, [&](GLint loc) {
434
- glUniform3fv(loc, 1, min.array);
435
- });
436
- }
437
- for (const auto& name : names.uniform_texcoord_max_names)
438
- {
439
- apply_uniform(program, name, [&](GLint loc) {
440
- glUniform3fv(loc, 1, max.array);
441
- });
442
- }
443
- for (const auto& name : names.uniform_texcoord_offset_names)
444
- {
445
- apply_uniform(program, name, [&](GLint loc) {
446
- glUniform3fv(loc, 1, offset.array);
447
- });
448
- }
449
- for (const auto& name : names.uniform_texture_names)
450
- {
451
- apply_uniform(program, name, [&](GLint loc) {
452
- glActiveTexture(GL_TEXTURE0);
453
- OpenGL_check_error(__FILE__, __LINE__);
454
-
455
- glBindTexture(GL_TEXTURE_2D, texture->id());
456
- OpenGL_check_error(__FILE__, __LINE__);
457
-
458
- glUniform1i(loc, 0);
459
- });
460
- }
461
- }
462
-
463
- void apply_attributes (
464
- const ShaderProgram& program, const ShaderBuiltinVariableNames& names,
465
- const Coord3* points, size_t npoints, const Coord3* texcoords,
466
- const Color* color, const Color* colors)
467
- {
468
- assert(npoints > 0);
469
- assert(!!color != !!colors);
470
-
471
- apply_attribute(
472
- program, names.attribute_position_names,
473
- points, npoints);
474
-
475
- apply_attribute(
476
- program, names.attribute_texcoord_names,
477
- texcoords ? texcoords : points, npoints);
478
-
479
- if (colors)
480
- {
481
- apply_attribute(
482
- program, names.attribute_color_names,
483
- colors, npoints);
484
- }
485
- else if (color)
486
- {
487
- #if defined(GL_VERSION_2_1) && !defined(GL_VERSION_3_0)
488
- // to fix that GL 2.1 with glVertexAttrib4fv() draws nothing
489
- // with specific glsl 'attribute' name.
490
- std::vector<Color> colors_(npoints, *color);
491
- apply_attribute(
492
- program, names.attribute_color_names,
493
- (const Coord4*) &colors_[0], npoints);
494
- #else
495
- for (const auto& name : names.attribute_color_names)
496
- {
497
- apply_attribute(program, name, [&](GLint loc) {
498
- glVertexAttrib4fv(loc, color->array);
499
- });
500
- }
501
- #endif
502
- }
503
- }
504
-
505
- template <typename CoordN>
506
- void apply_attribute(
507
- const ShaderProgram& program, const auto& names,
508
- const CoordN* values, size_t nvalues)
509
- {
510
- GLuint buffer = 0;
511
- for (const auto& name : names)
512
- {
513
- #ifndef IOS
514
- if (buffer == 0)
515
- {
516
- buffer = create_and_bind_buffer(
517
- GL_ARRAY_BUFFER, values, sizeof(CoordN) * nvalues);
518
- values = 0;
519
- }
520
- #endif
521
-
522
- apply_attribute(program, name, [&](GLint loc) {
523
- glEnableVertexAttribArray(loc);
524
- OpenGL_check_error(
525
- __FILE__, __LINE__, "loc: %d %s\n", loc, name.c_str());
526
-
527
- glVertexAttribPointer(
528
- loc, CoordN::SIZE, get_gl_type<coord>(), GL_FALSE, 0, values);
529
-
530
- locations.push_back(loc);
531
- });
532
- }
533
-
534
- glBindBuffer(GL_ARRAY_BUFFER, 0);
535
- OpenGL_check_error(__FILE__, __LINE__);
536
- }
537
-
538
- void apply_attribute (
539
- const ShaderProgram& program, const char* name,
540
- std::function<void(GLint)> apply_fun)
541
- {
542
- GLint loc = glGetAttribLocation(program.id(), name);
543
- if (loc < 0) return;
544
-
545
- apply_fun(loc);
546
- OpenGL_check_error(__FILE__, __LINE__);
547
- }
548
-
549
- void apply_uniform (
550
- const ShaderProgram& program, const char* name,
551
- std::function<void(GLint)> apply_fun)
552
- {
553
- GLint loc = glGetUniformLocation(program.id(), name);
554
- if (loc < 0) return;
555
-
556
- apply_fun(loc);
557
- OpenGL_check_error(__FILE__, __LINE__);
558
- }
559
-
560
- void draw_indices (
561
- GLenum mode, const uint* indices, size_t nindices, size_t npoints)
562
- {
563
- if (!indices || nindices <= 0)
564
- {
565
- default_indices.resize(npoints);
566
- indices = default_indices.get();
567
- nindices = npoints;
568
- }
569
-
570
- #ifdef IOS
571
- glDrawElements(mode, (GLsizei) nindices, GL_UNSIGNED_INT, indices);
572
- OpenGL_check_error(__FILE__, __LINE__);
573
- #else
574
- create_and_bind_buffer(
575
- GL_ELEMENT_ARRAY_BUFFER, indices, sizeof(uint) * nindices);
576
-
577
- glDrawElements(mode, (GLsizei) nindices, GL_UNSIGNED_INT, 0);
578
- OpenGL_check_error(__FILE__, __LINE__);
579
-
580
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
581
- OpenGL_check_error(__FILE__, __LINE__);
582
- #endif
583
- }
584
-
585
- GLuint create_and_bind_buffer (
586
- GLenum target, const void* data, GLsizeiptr size)
587
- {
588
- GLuint id = 0;
589
- glGenBuffers(1, &id);
590
- OpenGL_check_error(__FILE__, __LINE__);
591
-
592
- buffers.push_back(id);
593
-
594
- glBindBuffer(target, id);
595
- OpenGL_check_error(__FILE__, __LINE__);
596
-
597
- glBufferData(target, size, data, GL_STREAM_DRAW);
598
- OpenGL_check_error(__FILE__, __LINE__);
599
-
600
- return id;
601
- }
602
-
603
- void cleanup ()
604
- {
605
- for (auto loc : locations)
606
- {
607
- glDisableVertexAttribArray(loc);
608
- OpenGL_check_error(__FILE__, __LINE__);
609
- }
610
-
611
- if (!buffers.empty())
612
- {
613
- glDeleteBuffers((GLsizei) buffers.size(), &buffers[0]);
614
- OpenGL_check_error(__FILE__, __LINE__);
615
- }
616
-
617
- locations.clear();
618
- buffers.clear();
619
- }
620
-
621
- };// Painter::Data
622
-
623
-
624
16
  void
625
- Painter_draw (
626
- Painter* painter, GLenum mode, const Color& color,
627
- const Coord3* points, size_t npoints,
628
- const uint* indices, size_t nindices,
629
- const Coord3* texcoords)
17
+ Painter::Data::set_pixel_density (float density)
630
18
  {
631
- painter->self->draw(
632
- mode, &color, points, npoints, indices, nindices, NULL, texcoords);
633
- }
19
+ if (density <= 0)
20
+ argument_error(__FILE__, __LINE__, "invalid pixel_density.");
634
21
 
635
- void
636
- Painter_draw (
637
- Painter* painter, GLenum mode,
638
- const Coord3* points, size_t npoints,
639
- const uint* indices, size_t nindices,
640
- const Color* colors,
641
- const Coord3* texcoords)
642
- {
643
- painter->self->draw(
644
- mode, NULL, points, npoints, indices, nindices, colors, texcoords);
22
+ this->pixel_density = density;
23
+ text_image = Image();
645
24
  }
646
25
 
647
26
 
648
- Painter::Painter ()
649
- {
650
- }
651
-
652
27
  Painter::~Painter ()
653
28
  {
654
29
  }
@@ -674,41 +49,13 @@ namespace Rays
674
49
  if (!viewport)
675
50
  argument_error(__FILE__, __LINE__);
676
51
 
677
- if (self->painting)
52
+ if (self->is_painting())
678
53
  invalid_state_error(__FILE__, __LINE__, "painting flag should be false.");
679
54
 
680
55
  self->viewport = viewport;
681
56
  self->set_pixel_density(pixel_density);
682
57
  }
683
58
 
684
- void
685
- Painter::bind (const Image& image)
686
- {
687
- if (!image)
688
- argument_error(__FILE__, __LINE__, "invalid image.");
689
-
690
- if (self->painting)
691
- invalid_state_error(__FILE__, __LINE__, "painting flag should be false.");
692
-
693
- FrameBuffer fb(Image_get_texture(image));
694
- if (!fb)
695
- rays_error(__FILE__, __LINE__, "invalid frame buffer.");
696
-
697
- unbind();
698
-
699
- self->frame_buffer = fb;
700
- canvas(0, 0, image.width(), image.height(), image.pixel_density());
701
- }
702
-
703
- void
704
- Painter::unbind ()
705
- {
706
- if (self->painting)
707
- invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
708
-
709
- self->frame_buffer = FrameBuffer();
710
- }
711
-
712
59
  const Bounds&
713
60
  Painter::bounds () const
714
61
  {
@@ -721,99 +68,10 @@ namespace Rays
721
68
  return self->pixel_density;
722
69
  }
723
70
 
724
- void
725
- Painter::begin ()
726
- {
727
- if (self->painting)
728
- invalid_state_error(__FILE__, __LINE__, "painting flag should be false.");
729
-
730
- self->opengl_state.push();
731
-
732
- //glEnable(GL_CULL_FACE);
733
-
734
- glEnable(GL_DEPTH_TEST);
735
- glDepthFunc(GL_LEQUAL);
736
- OpenGL_check_error(__FILE__, __LINE__);
737
-
738
- glEnable(GL_BLEND);
739
- set_blend_mode(self->state.blend_mode);
740
-
741
- FrameBuffer& fb = self->frame_buffer;
742
- if (fb)
743
- {
744
- FrameBuffer_bind(fb.id());
745
-
746
- Texture& tex = fb.texture();
747
- if (tex) tex.set_modified();
748
- }
749
-
750
- const Bounds& vp = self->viewport;
751
- float density = self->pixel_density;
752
- glViewport(
753
- (int) (vp.x * density), (int) (vp.y * density),
754
- (int) (vp.width * density), (int) (vp.height * density));
755
- OpenGL_check_error(__FILE__, __LINE__);
756
-
757
- coord x1 = vp.x, x2 = vp.x + vp.width;
758
- coord y1 = vp.y, y2 = vp.y + vp.height;
759
- coord z1 = vp.z, z2 = vp.z + vp.depth;
760
- if (z1 == 0 && z2 == 0) {z1 = -1000; z2 = 1000;}
761
- if (!fb) std::swap(y1, y2);
762
-
763
- self->position_matrix.reset(1);
764
- self->position_matrix *= to_rays(glm::ortho(x1, x2, y1, y2));
765
-
766
- // map z to 0.0-1.0
767
- self->position_matrix.scale(1, 1, 1.0 / (z2 - z1));
768
- self->position_matrix.translate(0, 0, -z2);
769
-
770
- //self->position_matrix.translate(0.375f, 0.375f);
771
-
772
- self->update_clip();
773
-
774
- self->painting = true;
775
-
776
- glClear(GL_DEPTH_BUFFER_BIT);
777
- }
778
-
779
- void
780
- Painter::end ()
781
- {
782
- if (!self->painting)
783
- invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
784
-
785
- if (!self->state_stack.empty())
786
- invalid_state_error(__FILE__, __LINE__, "state stack is not empty.");
787
-
788
- if (!self->position_matrix_stack.empty())
789
- invalid_state_error(__FILE__, __LINE__, "position matrix stack is not empty.");
790
-
791
- self->painting = false;
792
- self->opengl_state.pop();
793
- self->default_indices.clear();
794
-
795
- glFinish();
796
-
797
- if (self->frame_buffer)
798
- FrameBuffer_unbind();
799
- }
800
-
801
71
  bool
802
72
  Painter::painting () const
803
73
  {
804
- return self->painting;
805
- }
806
-
807
- void
808
- Painter::clear ()
809
- {
810
- if (!self->painting)
811
- invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
812
-
813
- const Color& c = self->state.background;
814
- glClearColor(c.red, c.green, c.blue, c.alpha);
815
- glClear(GL_COLOR_BUFFER_BIT);
816
- OpenGL_check_error(__FILE__, __LINE__);
74
+ return self->is_painting();
817
75
  }
818
76
 
819
77
  static inline void
@@ -832,7 +90,7 @@ namespace Rays
832
90
  if (Polygon_triangulate(&triangles, polygon))
833
91
  {
834
92
  for (size_t i = 0; i < triangles.size(); i += 3)
835
- painter->self->draw(GL_LINE_LOOP, &invert_color, &triangles[i], 3);
93
+ Painter_draw(painter, MODE_LINE_LOOP, &invert_color, &triangles[i], 3);
836
94
  }
837
95
  #endif
838
96
  }
@@ -844,7 +102,7 @@ namespace Rays
844
102
  {
845
103
  Painter::Data* self = painter->self.get();
846
104
 
847
- if (!self->painting)
105
+ if (!self->is_painting())
848
106
  invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
849
107
 
850
108
  if (!self->state.has_color())
@@ -1065,24 +323,22 @@ namespace Rays
1065
323
  polygon(create_bezier(points, size, loop, nsegment()));
1066
324
  }
1067
325
 
1068
- static void
1069
- draw_image (
326
+ void
327
+ Painter_draw_image (
1070
328
  Painter* painter, const Image& image,
1071
329
  coord src_x, coord src_y, coord src_w, coord src_h,
1072
330
  coord dst_x, coord dst_y, coord dst_w, coord dst_h,
1073
- bool nofill = false, bool nostroke = false,
1074
- const Shader* shader = NULL)
331
+ const Shader* shader)
1075
332
  {
1076
- static const GLenum MODES[] = {GL_TRIANGLE_FAN, GL_LINE_LOOP};
1077
-
1078
333
  assert(painter && image);
1079
334
 
1080
335
  Painter::Data* self = painter->self.get();
1081
336
 
1082
- if (!self->painting)
337
+ if (!self->is_painting())
1083
338
  invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
1084
339
 
1085
- if (!self->state.has_color())
340
+ Color color;
341
+ if (!self->state.get_color(&color, FILL))
1086
342
  return;
1087
343
 
1088
344
  const Texture& texture = Image_get_texture(image);
@@ -1107,19 +363,9 @@ namespace Rays
1107
363
 
1108
364
  TextureInfo texinfo(texture, src_x, src_y, src_x + src_w, src_y + src_h);
1109
365
 
1110
- Color color;
1111
- for (int type = 0; type < COLOR_TYPE_MAX; ++type)
1112
- {
1113
- if ((nofill && type == FILL) || (nostroke && type == STROKE))
1114
- continue;
1115
-
1116
- if (!painter->self->state.get_color(&color, (ColorType) type))
1117
- continue;
1118
-
1119
- painter->self->draw(
1120
- MODES[type], &color, points, 4, NULL, 0, NULL, texcoords,
1121
- &texinfo, shader);
1122
- }
366
+ Painter_draw(
367
+ painter, MODE_TRIANGLE_FAN, &color, points, 4, NULL, 0, NULL, texcoords,
368
+ &texinfo, shader);
1123
369
  }
1124
370
 
1125
371
  void
@@ -1128,7 +374,7 @@ namespace Rays
1128
374
  if (!image_)
1129
375
  argument_error(__FILE__, __LINE__);
1130
376
 
1131
- draw_image(
377
+ Painter_draw_image(
1132
378
  this, image_,
1133
379
  0, 0, image_.width(), image_.height(),
1134
380
  x, y, image_.width(), image_.height());
@@ -1147,7 +393,7 @@ namespace Rays
1147
393
  if (!image_)
1148
394
  argument_error(__FILE__, __LINE__);
1149
395
 
1150
- draw_image(
396
+ Painter_draw_image(
1151
397
  this, image_,
1152
398
  0, 0, image_.width(), image_.height(),
1153
399
  x, y, width, height);
@@ -1169,7 +415,7 @@ namespace Rays
1169
415
  if (!image_)
1170
416
  argument_error(__FILE__, __LINE__);
1171
417
 
1172
- draw_image(
418
+ Painter_draw_image(
1173
419
  this, image_,
1174
420
  src_x, src_y, src_width, src_height,
1175
421
  dst_x, dst_y, image_.width(), image_.height());
@@ -1194,7 +440,7 @@ namespace Rays
1194
440
  if (!image_)
1195
441
  argument_error(__FILE__, __LINE__);
1196
442
 
1197
- draw_image(
443
+ Painter_draw_image(
1198
444
  this, image_,
1199
445
  src_x, src_y, src_width, src_height,
1200
446
  dst_x, dst_y, dst_width, dst_height);
@@ -1210,88 +456,6 @@ namespace Rays
1210
456
  dst_bounds.x, dst_bounds.y, dst_bounds.width, dst_bounds.height);
1211
457
  }
1212
458
 
1213
- static inline void
1214
- debug_draw_line (
1215
- Painter* painter, const Font& font,
1216
- coord x, coord y, coord str_width, coord str_height)
1217
- {
1218
- #if 0
1219
- painter->self->text_image.save("/tmp/font.png");
1220
-
1221
- painter->push_state();
1222
- {
1223
- coord asc, desc, lead;
1224
- font.get_height(&asc, &desc, &lead);
1225
- //printf("%f %f %f %f \n", str_height, asc, desc, lead);
1226
-
1227
- painter->set_stroke(0.5, 0.5, 1);
1228
- painter->no_fill();
1229
- painter->rect(x - 1, y - 1, str_width + 2, str_height + 2);
1230
-
1231
- coord yy = y;
1232
- painter->set_stroke(1, 0.5, 0.5, 0.4);
1233
- painter->rect(x, yy, str_width, asc);//str_height);
1234
-
1235
- yy += asc;
1236
- painter->set_stroke(1, 1, 0.5, 0.4);
1237
- painter->rect(x, yy, str_width, desc);
1238
-
1239
- yy += desc;
1240
- painter->set_stroke(1, 0.5, 1, 0.4);
1241
- painter->rect(x, yy, str_width, lead);
1242
- }
1243
- painter->pop_state();
1244
- #endif
1245
- }
1246
-
1247
- static void
1248
- draw_line (
1249
- Painter* painter, const Font& font,
1250
- const char* line, coord x, coord y, coord width = 0, coord height = 0)
1251
- {
1252
- assert(painter && font && line && *line != '\0');
1253
-
1254
- Painter::Data* self = painter->self.get();
1255
-
1256
- float density = self->pixel_density;
1257
- const RawFont& rawfont = Font_get_raw(font, density);
1258
- coord str_w = rawfont.get_width(line);
1259
- coord str_h = rawfont.get_height();
1260
- int tex_w = ceil(str_w);
1261
- int tex_h = ceil(str_h);
1262
- const Texture& texture = Image_get_texture(self->text_image);
1263
- if (
1264
- texture.width() < tex_w ||
1265
- texture.height() < tex_h ||
1266
- self->text_image.pixel_density() != density)
1267
- {
1268
- int bmp_w = std::max(texture.width(), tex_w);
1269
- int bmp_h = std::max(texture.height(), tex_h);
1270
- self->text_image = Image(Bitmap(bmp_w, bmp_h), density);
1271
- }
1272
-
1273
- if (!self->text_image)
1274
- invalid_state_error(__FILE__, __LINE__);
1275
-
1276
- assert(self->text_image.pixel_density() == density);
1277
-
1278
- Bitmap_draw_string(
1279
- &self->text_image.bitmap(), rawfont, line, 0, 0, font.smooth());
1280
-
1281
- str_w /= density;
1282
- str_h /= density;
1283
- if (width == 0) width = str_w;
1284
- if (height == 0) height = str_h;
1285
-
1286
- draw_image(
1287
- painter, self->text_image,
1288
- 0, 0, str_w, str_h,
1289
- x, y, str_w, str_h,
1290
- false, true, &Shader_get_shader_for_text());
1291
-
1292
- debug_draw_line(painter, font, x, y, str_w / density, str_h / density);
1293
- }
1294
-
1295
459
  static void
1296
460
  draw_text (
1297
461
  Painter* painter, const Font& font,
@@ -1301,23 +465,23 @@ namespace Rays
1301
465
 
1302
466
  Painter::Data* self = painter->self.get();
1303
467
 
1304
- if (!self->painting)
468
+ if (!self->is_painting())
1305
469
  invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
1306
470
 
1307
471
  if (!self->state.has_color())
1308
472
  return;
1309
473
 
1310
474
  if (!strchr(str, '\n'))
1311
- draw_line(painter, font, str, x, y, width, height);
475
+ Painter_draw_text_line(painter, font, str, x, y, width, height);
1312
476
  else
1313
477
  {
1314
478
  coord line_height = painter->line_height();
1315
479
 
1316
- Xot::StringList lines;
480
+ StringList lines;
1317
481
  split(&lines, str, '\n');
1318
482
  for (const auto& line : lines)
1319
483
  {
1320
- draw_line(painter, font, line.c_str(), x, y, width, height);
484
+ Painter_draw_text_line(painter, font, line.c_str(), x, y, width, height);
1321
485
  y += line_height;
1322
486
  }
1323
487
  }
@@ -1377,7 +541,7 @@ namespace Rays
1377
541
  {
1378
542
  self->state.background = color;
1379
543
 
1380
- if (self->painting && clear) this->clear();
544
+ if (self->is_painting() && clear) this->clear();
1381
545
  }
1382
546
 
1383
547
  void
@@ -1534,66 +698,6 @@ namespace Rays
1534
698
  return height;
1535
699
  }
1536
700
 
1537
- void
1538
- Painter::set_blend_mode (BlendMode mode)
1539
- {
1540
- self->state.blend_mode = mode;
1541
- switch (mode)
1542
- {
1543
- case BLEND_NORMAL:
1544
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1545
- glBlendFuncSeparate(
1546
- GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
1547
- break;
1548
-
1549
- case BLEND_ADD:
1550
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1551
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
1552
- break;
1553
-
1554
- case BLEND_SUBTRACT:
1555
- glBlendEquationSeparate(GL_FUNC_REVERSE_SUBTRACT, GL_FUNC_ADD);
1556
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
1557
- break;
1558
-
1559
- case BLEND_LIGHTEST:
1560
- glBlendEquationSeparate(GL_MAX, GL_FUNC_ADD);
1561
- glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
1562
- break;
1563
-
1564
- case BLEND_DARKEST:
1565
- glBlendEquationSeparate(GL_MIN, GL_FUNC_ADD);
1566
- glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
1567
- break;
1568
-
1569
- case BLEND_EXCLUSION:
1570
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1571
- glBlendFuncSeparate(
1572
- GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
1573
- break;
1574
-
1575
- case BLEND_MULTIPLY:
1576
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1577
- glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ONE, GL_ONE);
1578
- break;
1579
-
1580
- case BLEND_SCREEN:
1581
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1582
- glBlendFuncSeparate(GL_ONE_MINUS_DST_COLOR, GL_ONE, GL_ONE, GL_ONE);
1583
- break;
1584
-
1585
- case BLEND_REPLACE:
1586
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1587
- glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);
1588
- break;
1589
-
1590
- default:
1591
- argument_error(__FILE__, __LINE__, "unknown blend mode");
1592
- break;
1593
- }
1594
- OpenGL_check_error(__FILE__, __LINE__);
1595
- }
1596
-
1597
701
  BlendMode
1598
702
  Painter::blend_mode () const
1599
703
  {
@@ -1609,8 +713,13 @@ namespace Rays
1609
713
  void
1610
714
  Painter::set_clip (const Bounds& bounds)
1611
715
  {
716
+ if (bounds == self->state.clip)
717
+ return;
718
+
719
+ Painter_flush(this);
720
+
1612
721
  self->state.clip = bounds;
1613
- self->update_clip();
722
+ Painter_update_clip(this);
1614
723
  }
1615
724
 
1616
725
  void
@@ -1657,12 +766,21 @@ namespace Rays
1657
766
  void
1658
767
  Painter::set_texture (const Image& image)
1659
768
  {
769
+ if (image == self->state.texture)
770
+ return;
771
+
772
+ Painter_flush(this);
773
+
1660
774
  self->state.texture = image;
1661
775
  }
1662
776
 
1663
777
  void
1664
778
  Painter::no_texture ()
1665
779
  {
780
+ if (!self->state.texture) return;
781
+
782
+ Painter_flush(this);
783
+
1666
784
  self->state.texture = Image();
1667
785
  }
1668
786
 
@@ -1675,6 +793,11 @@ namespace Rays
1675
793
  void
1676
794
  Painter::set_texcoord_mode (TexCoordMode mode)
1677
795
  {
796
+ if (mode == self->state.texcoord_mode)
797
+ return;
798
+
799
+ Painter_flush(this);
800
+
1678
801
  self->state.texcoord_mode = mode;
1679
802
  }
1680
803
 
@@ -1687,6 +810,11 @@ namespace Rays
1687
810
  void
1688
811
  Painter::set_texcoord_wrap (TexCoordWrap wrap)
1689
812
  {
813
+ if (wrap == self->state.texcoord_wrap)
814
+ return;
815
+
816
+ Painter_flush(this);
817
+
1690
818
  self->state.texcoord_wrap = wrap;
1691
819
  }
1692
820
 
@@ -1699,12 +827,21 @@ namespace Rays
1699
827
  void
1700
828
  Painter::set_shader (const Shader& shader)
1701
829
  {
830
+ if (shader == self->state.shader)
831
+ return;
832
+
833
+ Painter_flush(this);
834
+
1702
835
  self->state.shader = shader;
1703
836
  }
1704
837
 
1705
838
  void
1706
839
  Painter::no_shader ()
1707
840
  {
841
+ if (!self->state.shader) return;
842
+
843
+ Painter_flush(this);
844
+
1708
845
  self->state.shader = Shader();
1709
846
  }
1710
847
 
@@ -1726,9 +863,11 @@ namespace Rays
1726
863
  if (self->state_stack.empty())
1727
864
  invalid_state_error(__FILE__, __LINE__, "state stack underflow.");
1728
865
 
866
+ Painter_flush(this);
867
+
1729
868
  self->state = self->state_stack.back();
1730
869
  self->state_stack.pop_back();
1731
- self->update_clip();
870
+ Painter_update_clip(this);
1732
871
  }
1733
872
 
1734
873
  void
@@ -1821,6 +960,24 @@ namespace Rays
1821
960
  self->position_matrix_stack.pop_back();
1822
961
  }
1823
962
 
963
+ void
964
+ Painter::add_flag (uint flags)
965
+ {
966
+ Xot::add_flag(&self->flags, flags);
967
+ }
968
+
969
+ void
970
+ Painter::remove_flag (uint flags)
971
+ {
972
+ Xot::remove_flag(&self->flags, flags);
973
+ }
974
+
975
+ bool
976
+ Painter::has_flag (uint flags) const
977
+ {
978
+ return Xot::has_flag(self->flags, flags);
979
+ }
980
+
1824
981
  Painter::operator bool () const
1825
982
  {
1826
983
  return self->viewport;
@@ -1832,5 +989,19 @@ namespace Rays
1832
989
  return !operator bool();
1833
990
  }
1834
991
 
992
+ static bool g_debug = false;
993
+
994
+ void
995
+ Painter::set_debug (bool debug)
996
+ {
997
+ g_debug = debug;
998
+ }
999
+
1000
+ bool
1001
+ Painter::debug ()
1002
+ {
1003
+ return g_debug;
1004
+ }
1005
+
1835
1006
 
1836
1007
  }// Rays