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