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.
- checksums.yaml +4 -4
- data/.doc/ext/rays/bounds.cpp +1 -1
- data/.doc/ext/rays/font.cpp +23 -5
- data/.doc/ext/rays/image.cpp +1 -1
- data/.doc/ext/rays/native.cpp +1 -5
- data/.doc/ext/rays/painter.cpp +1 -1
- data/.doc/ext/rays/polygon.cpp +1 -1
- data/.github/workflows/release-gem.yml +1 -1
- data/.github/workflows/test.yml +4 -4
- data/CLAUDE.md +25 -0
- data/ChangeLog.md +17 -0
- data/Gemfile.lock +6 -5
- data/Rakefile +4 -2
- data/VERSION +1 -1
- data/ext/rays/bounds.cpp +1 -1
- data/ext/rays/extconf.rb +4 -3
- data/ext/rays/font.cpp +27 -7
- data/ext/rays/image.cpp +1 -1
- data/ext/rays/native.cpp +1 -5
- data/ext/rays/painter.cpp +1 -1
- data/ext/rays/polygon.cpp +1 -1
- data/include/rays/font.h +5 -1
- data/include/rays/painter.h +1 -1
- data/lib/rays/ext.rb +1 -1
- data/lib/rays/image.rb +5 -0
- data/rays.gemspec +2 -2
- data/src/bitmap.h +6 -1
- data/src/color_space.cpp +1 -41
- data/src/font.cpp +17 -1
- data/src/image.cpp +0 -1
- data/src/ios/bitmap.mm +20 -35
- 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} +3 -7
- data/src/{osx → opengl/osx}/opengl.mm +3 -3
- data/src/opengl/painter.cpp +756 -0
- data/src/{render_buffer.h → opengl/render_buffer.h} +2 -2
- data/src/opengl/sdl/opengl.cpp +103 -0
- data/src/{shader.cpp → opengl/shader.cpp} +1 -2
- data/src/{shader.h → opengl/shader.h} +2 -2
- data/src/{shader_program.cpp → opengl/shader_program.cpp} +3 -3
- data/src/{shader_program.h → opengl/shader_program.h} +2 -2
- data/src/{shader_source.h → opengl/shader_source.h} +2 -2
- data/src/{texture.cpp → opengl/texture.cpp} +2 -3
- data/src/opengl/texture.h +21 -0
- data/src/{win32 → opengl/win32}/opengl.cpp +4 -4
- data/src/osx/bitmap.mm +20 -36
- data/src/osx/rays.mm +3 -3
- data/src/painter.cpp +28 -910
- data/src/painter.h +210 -11
- data/src/polygon.cpp +38 -13
- data/src/renderer.h +22 -0
- data/src/sdl/bitmap.cpp +304 -0
- data/src/sdl/camera.cpp +119 -0
- data/src/sdl/font.cpp +93 -0
- data/src/sdl/rays.cpp +50 -0
- data/src/texture.h +0 -3
- data/src/win32/bitmap.cpp +8 -35
- data/src/win32/rays.cpp +3 -3
- data/test/test_image.rb +1 -0
- metadata +34 -35
- /data/src/{opengl.cpp → opengl/opengl.cpp} +0 -0
- /data/src/{render_buffer.cpp → opengl/render_buffer.cpp} +0 -0
- /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
|
-
|
|
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
|
}
|
|
@@ -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
|
|
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
|
-
|
|
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
|
-
bool nofill
|
|
1074
|
-
const Shader* shader
|
|
331
|
+
bool nofill, bool nostroke,
|
|
332
|
+
const Shader* shader)
|
|
1075
333
|
{
|
|
1076
|
-
static const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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()
|
|
1632
|
-
font.
|
|
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
|
-
|
|
847
|
+
Painter_update_clip(this);
|
|
1730
848
|
}
|
|
1731
849
|
|
|
1732
850
|
void
|