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.
- checksums.yaml +4 -4
- data/.doc/ext/rays/image.cpp +10 -0
- data/.doc/ext/rays/painter.cpp +49 -1
- data/.doc/ext/rays/polygon.cpp +1 -1
- data/.doc/ext/rays/shader.cpp +8 -6
- data/.github/workflows/release-gem.yml +4 -1
- data/.github/workflows/test.yml +4 -4
- data/.github/workflows/utils.rb +88 -17
- data/ChangeLog.md +24 -0
- data/Gemfile.lock +6 -5
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/ext/rays/extconf.rb +3 -4
- data/ext/rays/image.cpp +11 -0
- data/ext/rays/painter.cpp +53 -1
- data/ext/rays/polygon.cpp +1 -1
- data/ext/rays/shader.cpp +8 -6
- data/include/rays/coord.h +6 -6
- data/include/rays/defs.h +2 -0
- data/include/rays/image.h +11 -1
- data/include/rays/painter.h +19 -0
- data/include/rays/ruby.h +2 -2
- data/include/rays/shader.h +5 -3
- data/include/rays.h +2 -2
- data/lib/rays/extension.rb +8 -2
- data/lib/rays/image.rb +2 -1
- data/lib/rays/shader.rb +13 -4
- data/rays.gemspec +3 -4
- data/src/bitmap.h +4 -0
- data/src/color_space.cpp +2 -42
- data/src/coord.h +10 -0
- data/src/font.cpp +1 -1
- data/src/image.cpp +85 -11
- data/src/ios/bitmap.mm +5 -32
- data/src/ios/rays.mm +3 -3
- data/src/opengl/bitmap.cpp +41 -0
- data/src/opengl/color_space.cpp +51 -0
- data/src/{color_space.h → opengl/color_space.h} +2 -2
- data/src/{frame_buffer.cpp → opengl/frame_buffer.cpp} +1 -1
- data/src/{frame_buffer.h → opengl/frame_buffer.h} +2 -2
- data/src/{ios → opengl/ios}/opengl.mm +3 -3
- data/src/{opengl.h → opengl/opengl.h} +2 -6
- data/src/{osx → opengl/osx}/opengl.mm +3 -3
- data/src/opengl/painter.cpp +1020 -0
- data/src/{render_buffer.cpp → opengl/render_buffer.cpp} +1 -1
- data/src/{render_buffer.h → opengl/render_buffer.h} +2 -2
- data/src/{sdl → opengl/sdl}/opengl.cpp +10 -3
- data/src/{shader.cpp → opengl/shader.cpp} +69 -53
- data/src/{shader.h → opengl/shader.h} +12 -8
- data/src/{shader_program.cpp → opengl/shader_program.cpp} +24 -10
- data/src/{shader_program.h → opengl/shader_program.h} +4 -3
- data/src/{shader_source.cpp → opengl/shader_source.cpp} +2 -4
- data/src/{shader_source.h → opengl/shader_source.h} +2 -2
- data/src/{texture.cpp → opengl/texture.cpp} +18 -7
- data/src/opengl/texture.h +21 -0
- data/src/{win32 → opengl/win32}/opengl.cpp +4 -3
- data/src/osx/bitmap.mm +6 -34
- data/src/osx/rays.mm +3 -3
- data/src/painter.cpp +96 -925
- data/src/painter.h +223 -11
- data/src/polygon.cpp +38 -13
- data/src/renderer.h +22 -0
- data/src/sdl/bitmap.cpp +5 -33
- data/src/sdl/font.cpp +358 -9
- data/src/sdl/rays.cpp +8 -3
- data/src/texture.h +6 -3
- data/src/win32/bitmap.cpp +6 -34
- data/src/win32/rays.cpp +3 -3
- data/test/test_painter.rb +36 -25
- data/test/test_painter_batch.rb +254 -0
- metadata +31 -24
- /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
|
-
|
|
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
|
-
|
|
632
|
-
|
|
633
|
-
}
|
|
19
|
+
if (density <= 0)
|
|
20
|
+
argument_error(__FILE__, __LINE__, "invalid pixel_density.");
|
|
634
21
|
|
|
635
|
-
|
|
636
|
-
|
|
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->
|
|
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->
|
|
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
|
|
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->
|
|
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
|
-
|
|
1069
|
-
|
|
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
|
-
|
|
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->
|
|
337
|
+
if (!self->is_painting())
|
|
1083
338
|
invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
|
|
1084
339
|
|
|
1085
|
-
|
|
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
|
-
|
|
1111
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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->
|
|
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
|
-
|
|
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
|
-
|
|
480
|
+
StringList lines;
|
|
1317
481
|
split(&lines, str, '\n');
|
|
1318
482
|
for (const auto& line : lines)
|
|
1319
483
|
{
|
|
1320
|
-
|
|
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->
|
|
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
|
-
|
|
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
|
-
|
|
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
|