rays 0.3.9 → 0.3.11

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/.doc/ext/rays/bounds.cpp +1 -1
  3. data/.doc/ext/rays/font.cpp +23 -5
  4. data/.doc/ext/rays/image.cpp +1 -1
  5. data/.doc/ext/rays/native.cpp +1 -5
  6. data/.doc/ext/rays/painter.cpp +1 -1
  7. data/.doc/ext/rays/polygon.cpp +1 -1
  8. data/.github/workflows/release-gem.yml +1 -1
  9. data/.github/workflows/test.yml +4 -4
  10. data/CLAUDE.md +25 -0
  11. data/ChangeLog.md +17 -0
  12. data/Gemfile.lock +6 -5
  13. data/Rakefile +4 -2
  14. data/VERSION +1 -1
  15. data/ext/rays/bounds.cpp +1 -1
  16. data/ext/rays/extconf.rb +4 -3
  17. data/ext/rays/font.cpp +27 -7
  18. data/ext/rays/image.cpp +1 -1
  19. data/ext/rays/native.cpp +1 -5
  20. data/ext/rays/painter.cpp +1 -1
  21. data/ext/rays/polygon.cpp +1 -1
  22. data/include/rays/font.h +5 -1
  23. data/include/rays/painter.h +1 -1
  24. data/lib/rays/ext.rb +1 -1
  25. data/lib/rays/image.rb +5 -0
  26. data/rays.gemspec +2 -2
  27. data/src/bitmap.h +6 -1
  28. data/src/color_space.cpp +1 -41
  29. data/src/font.cpp +17 -1
  30. data/src/image.cpp +0 -1
  31. data/src/ios/bitmap.mm +20 -35
  32. data/src/ios/rays.mm +3 -3
  33. data/src/opengl/bitmap.cpp +41 -0
  34. data/src/opengl/color_space.cpp +51 -0
  35. data/src/{color_space.h → opengl/color_space.h} +2 -2
  36. data/src/{frame_buffer.cpp → opengl/frame_buffer.cpp} +1 -1
  37. data/src/{frame_buffer.h → opengl/frame_buffer.h} +2 -2
  38. data/src/{ios → opengl/ios}/opengl.mm +3 -3
  39. data/src/{opengl.h → opengl/opengl.h} +3 -7
  40. data/src/{osx → opengl/osx}/opengl.mm +3 -3
  41. data/src/opengl/painter.cpp +756 -0
  42. data/src/{render_buffer.h → opengl/render_buffer.h} +2 -2
  43. data/src/opengl/sdl/opengl.cpp +103 -0
  44. data/src/{shader.cpp → opengl/shader.cpp} +1 -2
  45. data/src/{shader.h → opengl/shader.h} +2 -2
  46. data/src/{shader_program.cpp → opengl/shader_program.cpp} +3 -3
  47. data/src/{shader_program.h → opengl/shader_program.h} +2 -2
  48. data/src/{shader_source.h → opengl/shader_source.h} +2 -2
  49. data/src/{texture.cpp → opengl/texture.cpp} +2 -3
  50. data/src/opengl/texture.h +21 -0
  51. data/src/{win32 → opengl/win32}/opengl.cpp +4 -4
  52. data/src/osx/bitmap.mm +20 -36
  53. data/src/osx/rays.mm +3 -3
  54. data/src/painter.cpp +28 -910
  55. data/src/painter.h +210 -11
  56. data/src/polygon.cpp +38 -13
  57. data/src/renderer.h +22 -0
  58. data/src/sdl/bitmap.cpp +304 -0
  59. data/src/sdl/camera.cpp +119 -0
  60. data/src/sdl/font.cpp +93 -0
  61. data/src/sdl/rays.cpp +50 -0
  62. data/src/texture.h +0 -3
  63. data/src/win32/bitmap.cpp +8 -35
  64. data/src/win32/rays.cpp +3 -3
  65. data/test/test_image.rb +1 -0
  66. metadata +34 -35
  67. /data/src/{opengl.cpp → opengl/opengl.cpp} +0 -0
  68. /data/src/{render_buffer.cpp → opengl/render_buffer.cpp} +0 -0
  69. /data/src/{shader_source.cpp → opengl/shader_source.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
- #include "rays/point.h"
13
- #include "rays/bounds.h"
14
- #include "rays/color.h"
15
7
  #include "rays/debug.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
  }
@@ -681,34 +56,6 @@ namespace Rays
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,101 +68,12 @@ 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
74
  return self->painting;
805
75
  }
806
76
 
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__);
817
- }
818
-
819
77
  static inline void
820
78
  debug_draw_triangulation (
821
79
  Painter* painter, const Polygon& polygon, const Color& color)
@@ -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
  }
@@ -1065,15 +323,15 @@ 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
+ bool nofill, bool nostroke,
332
+ const Shader* shader)
1075
333
  {
1076
- static const GLenum MODES[] = {GL_TRIANGLE_FAN, GL_LINE_LOOP};
334
+ static const PrimitiveMode MODES[] = {MODE_TRIANGLE_FAN, MODE_LINE_LOOP};
1077
335
 
1078
336
  assert(painter && image);
1079
337
 
@@ -1116,8 +374,8 @@ namespace Rays
1116
374
  if (!painter->self->state.get_color(&color, (ColorType) type))
1117
375
  continue;
1118
376
 
1119
- painter->self->draw(
1120
- MODES[type], &color, points, 4, NULL, 0, NULL, texcoords,
377
+ Painter_draw(
378
+ painter, MODES[type], &color, points, 4, NULL, 0, NULL, texcoords,
1121
379
  &texinfo, shader);
1122
380
  }
1123
381
  }
@@ -1128,7 +386,7 @@ namespace Rays
1128
386
  if (!image_)
1129
387
  argument_error(__FILE__, __LINE__);
1130
388
 
1131
- draw_image(
389
+ Painter_draw_image(
1132
390
  this, image_,
1133
391
  0, 0, image_.width(), image_.height(),
1134
392
  x, y, image_.width(), image_.height());
@@ -1147,7 +405,7 @@ namespace Rays
1147
405
  if (!image_)
1148
406
  argument_error(__FILE__, __LINE__);
1149
407
 
1150
- draw_image(
408
+ Painter_draw_image(
1151
409
  this, image_,
1152
410
  0, 0, image_.width(), image_.height(),
1153
411
  x, y, width, height);
@@ -1169,7 +427,7 @@ namespace Rays
1169
427
  if (!image_)
1170
428
  argument_error(__FILE__, __LINE__);
1171
429
 
1172
- draw_image(
430
+ Painter_draw_image(
1173
431
  this, image_,
1174
432
  src_x, src_y, src_width, src_height,
1175
433
  dst_x, dst_y, image_.width(), image_.height());
@@ -1194,7 +452,7 @@ namespace Rays
1194
452
  if (!image_)
1195
453
  argument_error(__FILE__, __LINE__);
1196
454
 
1197
- draw_image(
455
+ Painter_draw_image(
1198
456
  this, image_,
1199
457
  src_x, src_y, src_width, src_height,
1200
458
  dst_x, dst_y, dst_width, dst_height);
@@ -1210,87 +468,6 @@ namespace Rays
1210
468
  dst_bounds.x, dst_bounds.y, dst_bounds.width, dst_bounds.height);
1211
469
  }
1212
470
 
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(&self->text_image.bitmap(), rawfont, line, 0, 0);
1279
-
1280
- str_w /= density;
1281
- str_h /= density;
1282
- if (width == 0) width = str_w;
1283
- if (height == 0) height = str_h;
1284
-
1285
- draw_image(
1286
- painter, self->text_image,
1287
- 0, 0, str_w, str_h,
1288
- x, y, str_w, str_h,
1289
- false, true, &Shader_get_shader_for_text());
1290
-
1291
- debug_draw_line(painter, font, x, y, str_w / density, str_h / density);
1292
- }
1293
-
1294
471
  static void
1295
472
  draw_text (
1296
473
  Painter* painter, const Font& font,
@@ -1307,7 +484,7 @@ namespace Rays
1307
484
  return;
1308
485
 
1309
486
  if (!strchr(str, '\n'))
1310
- draw_line(painter, font, str, x, y, width, height);
487
+ Painter_draw_text_line(painter, font, str, x, y, width, height);
1311
488
  else
1312
489
  {
1313
490
  coord line_height = painter->line_height();
@@ -1316,7 +493,7 @@ namespace Rays
1316
493
  split(&lines, str, '\n');
1317
494
  for (const auto& line : lines)
1318
495
  {
1319
- draw_line(painter, font, line.c_str(), x, y, width, height);
496
+ Painter_draw_text_line(painter, font, line.c_str(), x, y, width, height);
1320
497
  y += line_height;
1321
498
  }
1322
499
  }
@@ -1533,66 +710,6 @@ namespace Rays
1533
710
  return height;
1534
711
  }
1535
712
 
1536
- void
1537
- Painter::set_blend_mode (BlendMode mode)
1538
- {
1539
- self->state.blend_mode = mode;
1540
- switch (mode)
1541
- {
1542
- case BLEND_NORMAL:
1543
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1544
- glBlendFuncSeparate(
1545
- GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
1546
- break;
1547
-
1548
- case BLEND_ADD:
1549
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1550
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
1551
- break;
1552
-
1553
- case BLEND_SUBTRACT:
1554
- glBlendEquationSeparate(GL_FUNC_REVERSE_SUBTRACT, GL_FUNC_ADD);
1555
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE, GL_ONE);
1556
- break;
1557
-
1558
- case BLEND_LIGHTEST:
1559
- glBlendEquationSeparate(GL_MAX, GL_FUNC_ADD);
1560
- glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
1561
- break;
1562
-
1563
- case BLEND_DARKEST:
1564
- glBlendEquationSeparate(GL_MIN, GL_FUNC_ADD);
1565
- glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ONE);
1566
- break;
1567
-
1568
- case BLEND_EXCLUSION:
1569
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1570
- glBlendFuncSeparate(
1571
- GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE);
1572
- break;
1573
-
1574
- case BLEND_MULTIPLY:
1575
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1576
- glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ONE, GL_ONE);
1577
- break;
1578
-
1579
- case BLEND_SCREEN:
1580
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1581
- glBlendFuncSeparate(GL_ONE_MINUS_DST_COLOR, GL_ONE, GL_ONE, GL_ONE);
1582
- break;
1583
-
1584
- case BLEND_REPLACE:
1585
- glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
1586
- glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE, GL_ZERO);
1587
- break;
1588
-
1589
- default:
1590
- argument_error(__FILE__, __LINE__, "unknown blend mode");
1591
- break;
1592
- }
1593
- OpenGL_check_error(__FILE__, __LINE__);
1594
- }
1595
-
1596
713
  BlendMode
1597
714
  Painter::blend_mode () const
1598
715
  {
@@ -1609,7 +726,7 @@ namespace Rays
1609
726
  Painter::set_clip (const Bounds& bounds)
1610
727
  {
1611
728
  self->state.clip = bounds;
1612
- self->update_clip();
729
+ Painter_update_clip(this);
1613
730
  }
1614
731
 
1615
732
  void
@@ -1625,19 +742,20 @@ namespace Rays
1625
742
  }
1626
743
 
1627
744
  static bool
1628
- has_same_font (const Font& font, const char* name, coord size)
745
+ has_same_font (const Font& font, const char* name, coord size, bool smooth)
1629
746
  {
1630
747
  return
1631
- font.size() == size &&
1632
- font.name() == (name ? name : get_default_font().name().c_str());
748
+ font.size() == size &&
749
+ font.smooth() == smooth &&
750
+ font.name() == (name ? name : get_default_font().name().c_str());
1633
751
  }
1634
752
 
1635
753
  void
1636
- Painter::set_font (const char* name, coord size)
754
+ Painter::set_font (const char* name, coord size, bool smooth)
1637
755
  {
1638
- if (has_same_font(self->state.font, name, size)) return;
756
+ if (has_same_font(self->state.font, name, size, smooth)) return;
1639
757
 
1640
- set_font(Font(name, size));
758
+ set_font(Font(name, size, smooth));
1641
759
  }
1642
760
 
1643
761
  void
@@ -1726,7 +844,7 @@ namespace Rays
1726
844
 
1727
845
  self->state = self->state_stack.back();
1728
846
  self->state_stack.pop_back();
1729
- self->update_clip();
847
+ Painter_update_clip(this);
1730
848
  }
1731
849
 
1732
850
  void