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.h
CHANGED
|
@@ -4,26 +4,225 @@
|
|
|
4
4
|
#define __RAYS_SRC_PAINTER_H__
|
|
5
5
|
|
|
6
6
|
|
|
7
|
+
#include <vector>
|
|
7
8
|
#include "rays/painter.h"
|
|
8
|
-
#include "
|
|
9
|
+
#include "rays/bounds.h"
|
|
10
|
+
#include "rays/color.h"
|
|
11
|
+
#include "rays/font.h"
|
|
12
|
+
#include "rays/image.h"
|
|
13
|
+
#include "rays/shader.h"
|
|
14
|
+
#include "matrix.h"
|
|
15
|
+
#include "texture.h"
|
|
9
16
|
|
|
10
17
|
|
|
11
18
|
namespace Rays
|
|
12
19
|
{
|
|
13
20
|
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
enum ColorType
|
|
23
|
+
{
|
|
24
|
+
|
|
25
|
+
FILL = 0,
|
|
26
|
+
|
|
27
|
+
STROKE,
|
|
28
|
+
|
|
29
|
+
COLOR_TYPE_MAX
|
|
30
|
+
|
|
31
|
+
};// ColorType
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
enum PrimitiveMode
|
|
35
|
+
{
|
|
36
|
+
|
|
37
|
+
MODE_NONE = -1,
|
|
38
|
+
|
|
39
|
+
MODE_POINTS = 0x0,
|
|
40
|
+
|
|
41
|
+
MODE_LINES = 0x1,
|
|
42
|
+
|
|
43
|
+
MODE_LINE_LOOP = 0x2,
|
|
44
|
+
|
|
45
|
+
MODE_LINE_STRIP = 0x3,
|
|
46
|
+
|
|
47
|
+
MODE_TRIANGLES = 0x4,
|
|
48
|
+
|
|
49
|
+
MODE_TRIANGLE_STRIP = 0x5,
|
|
50
|
+
|
|
51
|
+
MODE_TRIANGLE_FAN = 0x6,
|
|
52
|
+
|
|
53
|
+
MODE_QUADS = 0x7,
|
|
54
|
+
|
|
55
|
+
MODE_QUAD_STRIP = 0x8,
|
|
56
|
+
|
|
57
|
+
MODE_POLYGON = 0x9,
|
|
58
|
+
|
|
59
|
+
};// PrimitiveMode
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
struct State
|
|
63
|
+
{
|
|
64
|
+
|
|
65
|
+
Color background, colors[COLOR_TYPE_MAX];
|
|
66
|
+
|
|
67
|
+
bool nocolors[COLOR_TYPE_MAX];
|
|
68
|
+
|
|
69
|
+
coord stroke_width;
|
|
70
|
+
|
|
71
|
+
float stroke_outset;
|
|
72
|
+
|
|
73
|
+
CapType stroke_cap;
|
|
74
|
+
|
|
75
|
+
JoinType stroke_join;
|
|
76
|
+
|
|
77
|
+
coord miter_limit;
|
|
78
|
+
|
|
79
|
+
uint nsegment;
|
|
80
|
+
|
|
81
|
+
coord line_height;
|
|
82
|
+
|
|
83
|
+
BlendMode blend_mode;
|
|
84
|
+
|
|
85
|
+
Bounds clip;
|
|
86
|
+
|
|
87
|
+
Font font;
|
|
88
|
+
|
|
89
|
+
Image texture;
|
|
90
|
+
|
|
91
|
+
TexCoordMode texcoord_mode;
|
|
92
|
+
|
|
93
|
+
TexCoordWrap texcoord_wrap;
|
|
94
|
+
|
|
95
|
+
Shader shader;
|
|
96
|
+
|
|
97
|
+
void init ()
|
|
98
|
+
{
|
|
99
|
+
background .reset(0, 0);
|
|
100
|
+
colors[FILL] .reset(1, 1);
|
|
101
|
+
colors[STROKE] .reset(1, 0);
|
|
102
|
+
nocolors[FILL] = false;
|
|
103
|
+
nocolors[STROKE] = true;
|
|
104
|
+
stroke_width = 0;
|
|
105
|
+
stroke_outset = 0;
|
|
106
|
+
stroke_cap = CAP_DEFAULT;
|
|
107
|
+
stroke_join = JOIN_DEFAULT;
|
|
108
|
+
miter_limit = JOIN_DEFAULT_MITER_LIMIT;
|
|
109
|
+
nsegment = 0;
|
|
110
|
+
line_height = -1;
|
|
111
|
+
blend_mode = BLEND_NORMAL;
|
|
112
|
+
clip .reset(-1);
|
|
113
|
+
font = get_default_font();
|
|
114
|
+
texture = Image();
|
|
115
|
+
texcoord_mode = TEXCOORD_IMAGE;
|
|
116
|
+
texcoord_wrap = TEXCOORD_CLAMP;
|
|
117
|
+
shader = Shader();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
bool get_color (Color* color, ColorType type) const
|
|
121
|
+
{
|
|
122
|
+
const Color& c = colors[type];
|
|
123
|
+
if (blend_mode == BLEND_REPLACE ? nocolors[type] : !c)
|
|
124
|
+
return false;
|
|
125
|
+
|
|
126
|
+
*color = c;
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
bool has_color () const
|
|
131
|
+
{
|
|
132
|
+
if (blend_mode == BLEND_REPLACE)
|
|
133
|
+
return !nocolors[FILL] || !nocolors[STROKE];
|
|
134
|
+
else
|
|
135
|
+
return colors[FILL] || colors[STROKE];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
};// State
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
struct TextureInfo
|
|
142
|
+
{
|
|
143
|
+
|
|
144
|
+
const Texture& texture;
|
|
145
|
+
|
|
146
|
+
Point min, max;
|
|
147
|
+
|
|
148
|
+
TextureInfo (
|
|
149
|
+
const Texture& texture,
|
|
150
|
+
coord x_min, coord y_min,
|
|
151
|
+
coord x_max, coord y_max)
|
|
152
|
+
: texture(texture)
|
|
153
|
+
{
|
|
154
|
+
min.reset(x_min, y_min);
|
|
155
|
+
max.reset(x_max, y_max);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
operator bool () const
|
|
159
|
+
{
|
|
160
|
+
return
|
|
161
|
+
texture &&
|
|
162
|
+
min.x < max.x &&
|
|
163
|
+
min.y < max.y;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
bool operator ! () const
|
|
167
|
+
{
|
|
168
|
+
return !operator bool();
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
};// TextureInfo
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
struct Painter::Data
|
|
175
|
+
{
|
|
176
|
+
|
|
177
|
+
bool painting = false;
|
|
178
|
+
|
|
179
|
+
float pixel_density = 1;
|
|
180
|
+
|
|
181
|
+
Bounds viewport;
|
|
182
|
+
|
|
183
|
+
State state;
|
|
184
|
+
|
|
185
|
+
std::vector<State> state_stack;
|
|
186
|
+
|
|
187
|
+
Matrix position_matrix;
|
|
188
|
+
|
|
189
|
+
std::vector<Matrix> position_matrix_stack;
|
|
190
|
+
|
|
191
|
+
Image text_image;
|
|
192
|
+
|
|
193
|
+
Data ()
|
|
194
|
+
{
|
|
195
|
+
state.init();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
virtual ~Data () = default;
|
|
199
|
+
|
|
200
|
+
void set_pixel_density (float density);
|
|
201
|
+
|
|
202
|
+
};// Painter::Data
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
void Painter_update_clip (Painter* painter);
|
|
20
206
|
|
|
21
207
|
void Painter_draw (
|
|
22
|
-
Painter* painter,
|
|
23
|
-
const Coord3* points,
|
|
24
|
-
const uint* indices
|
|
25
|
-
const Color* colors
|
|
26
|
-
const Coord3* texcoords
|
|
208
|
+
Painter* painter, PrimitiveMode mode, const Color* color,
|
|
209
|
+
const Coord3* points, size_t npoints,
|
|
210
|
+
const uint* indices = NULL, size_t nindices = 0,
|
|
211
|
+
const Color* colors = NULL,
|
|
212
|
+
const Coord3* texcoords = NULL,
|
|
213
|
+
const TextureInfo* texinfo = NULL,
|
|
214
|
+
const Shader* shader = NULL);
|
|
215
|
+
|
|
216
|
+
void Painter_draw_image (
|
|
217
|
+
Painter* painter, const Image& image,
|
|
218
|
+
coord src_x, coord src_y, coord src_w, coord src_h,
|
|
219
|
+
coord dst_x, coord dst_y, coord dst_w, coord dst_h,
|
|
220
|
+
bool nofill = false, bool nostroke = false,
|
|
221
|
+
const Shader* shader = NULL);
|
|
222
|
+
|
|
223
|
+
void Painter_draw_text_line (
|
|
224
|
+
Painter* painter, const Font& font, const char* line, coord x, coord y,
|
|
225
|
+
coord width = 0, coord height = 0);
|
|
27
226
|
|
|
28
227
|
|
|
29
228
|
}// Rays
|
data/src/polygon.cpp
CHANGED
|
@@ -50,6 +50,32 @@ namespace Rays
|
|
|
50
50
|
{
|
|
51
51
|
|
|
52
52
|
|
|
53
|
+
static void
|
|
54
|
+
draw_polygon (
|
|
55
|
+
Painter* painter, PrimitiveMode mode, const Color& color,
|
|
56
|
+
const Coord3* points, size_t npoints,
|
|
57
|
+
const uint* indices = NULL, size_t nindices = 0,
|
|
58
|
+
const Coord3* texcoords = NULL)
|
|
59
|
+
{
|
|
60
|
+
Painter_draw(
|
|
61
|
+
painter, mode, &color, points, npoints, indices, nindices,
|
|
62
|
+
NULL, texcoords);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static void
|
|
66
|
+
draw_polygon (
|
|
67
|
+
Painter* painter, PrimitiveMode mode,
|
|
68
|
+
const Coord3* points, size_t npoints,
|
|
69
|
+
const uint* indices = NULL, size_t nindices = 0,
|
|
70
|
+
const Color* colors = NULL,
|
|
71
|
+
const Coord3* texcoords = NULL)
|
|
72
|
+
{
|
|
73
|
+
Painter_draw(
|
|
74
|
+
painter, mode, NULL, points, npoints, indices, nindices,
|
|
75
|
+
colors, texcoords);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
53
79
|
class Triangles
|
|
54
80
|
{
|
|
55
81
|
|
|
@@ -119,8 +145,8 @@ namespace Rays
|
|
|
119
145
|
|
|
120
146
|
if (pcolors)
|
|
121
147
|
{
|
|
122
|
-
|
|
123
|
-
painter,
|
|
148
|
+
draw_polygon(
|
|
149
|
+
painter, MODE_TRIANGLES,
|
|
124
150
|
&points[0], points.size(),
|
|
125
151
|
&indices[0], indices.size(),
|
|
126
152
|
&(*pcolors)[0],
|
|
@@ -128,8 +154,8 @@ namespace Rays
|
|
|
128
154
|
}
|
|
129
155
|
else
|
|
130
156
|
{
|
|
131
|
-
|
|
132
|
-
painter,
|
|
157
|
+
draw_polygon(
|
|
158
|
+
painter, MODE_TRIANGLES, color,
|
|
133
159
|
&points[0], points.size(),
|
|
134
160
|
&indices[0], indices.size(),
|
|
135
161
|
ptexcoords ? &(*ptexcoords)[0] : NULL);
|
|
@@ -383,8 +409,8 @@ namespace Rays
|
|
|
383
409
|
|
|
384
410
|
for (const auto& polyline : polylines)
|
|
385
411
|
{
|
|
386
|
-
|
|
387
|
-
painter, polyline.loop() ?
|
|
412
|
+
draw_polygon(
|
|
413
|
+
painter, polyline.loop() ? MODE_LINE_LOOP : MODE_LINE_STRIP, color,
|
|
388
414
|
&polyline[0], polyline.size());
|
|
389
415
|
}
|
|
390
416
|
}
|
|
@@ -666,8 +692,7 @@ namespace Rays
|
|
|
666
692
|
invalid_state_error(__FILE__, __LINE__);
|
|
667
693
|
|
|
668
694
|
const auto& outline = polylines[0];
|
|
669
|
-
|
|
670
|
-
painter, GL_TRIANGLE_FAN, color, &outline[0], outline.size());
|
|
695
|
+
draw_polygon(painter, MODE_TRIANGLE_FAN, color, &outline[0], outline.size());
|
|
671
696
|
}
|
|
672
697
|
|
|
673
698
|
private:
|
|
@@ -802,7 +827,7 @@ namespace Rays
|
|
|
802
827
|
|
|
803
828
|
typedef Polygon::Data Super;
|
|
804
829
|
|
|
805
|
-
|
|
830
|
+
PrimitiveMode mode = MODE_NONE;
|
|
806
831
|
|
|
807
832
|
EllipseData (
|
|
808
833
|
coord x, coord y, coord width, coord height,
|
|
@@ -826,7 +851,7 @@ namespace Rays
|
|
|
826
851
|
if (polylines.size() <= 0)
|
|
827
852
|
invalid_state_error(__FILE__, __LINE__);
|
|
828
853
|
|
|
829
|
-
if (mode ==
|
|
854
|
+
if (mode == MODE_NONE)
|
|
830
855
|
{
|
|
831
856
|
Super::fill(painter, color);
|
|
832
857
|
return;
|
|
@@ -836,7 +861,7 @@ namespace Rays
|
|
|
836
861
|
invalid_state_error(__FILE__, __LINE__);
|
|
837
862
|
|
|
838
863
|
const auto& outline = polylines[0];
|
|
839
|
-
|
|
864
|
+
draw_polygon(painter, mode, color, &outline[0], outline.size());
|
|
840
865
|
}
|
|
841
866
|
|
|
842
867
|
private:
|
|
@@ -867,7 +892,7 @@ namespace Rays
|
|
|
867
892
|
float radian_from = Xot::deg2rad(0);
|
|
868
893
|
float radian_to = Xot::deg2rad(360);
|
|
869
894
|
|
|
870
|
-
if (!has_hole) mode =
|
|
895
|
+
if (!has_hole) mode = MODE_TRIANGLE_FAN;
|
|
871
896
|
|
|
872
897
|
std::vector<Point> points;
|
|
873
898
|
points.reserve(nsegment);
|
|
@@ -915,7 +940,7 @@ namespace Rays
|
|
|
915
940
|
if (!has_hole)
|
|
916
941
|
{
|
|
917
942
|
points.emplace_back(x + width / 2, y + height / 2);
|
|
918
|
-
mode =
|
|
943
|
+
mode = MODE_TRIANGLE_FAN;
|
|
919
944
|
}
|
|
920
945
|
|
|
921
946
|
for (uint seg = 0; seg <= nsegment; ++seg)
|
data/src/renderer.h
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// -*- c++ -*-
|
|
2
|
+
#pragma once
|
|
3
|
+
#ifndef __RAYS_SRC_RENDERER_H__
|
|
4
|
+
#define __RAYS_SRC_RENDERER_H__
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
#include "rays/defs.h"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
namespace Rays
|
|
11
|
+
{
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
void Renderer_init ();
|
|
15
|
+
|
|
16
|
+
void Renderer_fin ();
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
}// Rays
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
#endif//EOH
|
data/src/sdl/bitmap.cpp
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#include "../bitmap.h"
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
#define STB_IMAGE_IMPLEMENTATION
|
|
5
|
+
#include <stb_image.h>
|
|
6
|
+
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
7
|
+
#include <stb_image_write.h>
|
|
8
|
+
|
|
9
|
+
#include <SDL.h>
|
|
10
|
+
#include <xot/util.h>
|
|
11
|
+
#include "rays/exception.h"
|
|
12
|
+
#include "../font.h"
|
|
13
|
+
#include "../texture.h"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
namespace Rays
|
|
17
|
+
{
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
struct Bitmap::Data
|
|
21
|
+
{
|
|
22
|
+
|
|
23
|
+
SDL_Surface* surface = NULL;
|
|
24
|
+
|
|
25
|
+
ColorSpace color_space;
|
|
26
|
+
|
|
27
|
+
bool modified;
|
|
28
|
+
|
|
29
|
+
Data ()
|
|
30
|
+
{
|
|
31
|
+
clear();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
~Data ()
|
|
35
|
+
{
|
|
36
|
+
clear();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
void clear ()
|
|
40
|
+
{
|
|
41
|
+
if (surface) SDL_FreeSurface(surface);
|
|
42
|
+
|
|
43
|
+
surface = NULL;
|
|
44
|
+
color_space = COLORSPACE_UNKNOWN;
|
|
45
|
+
modified = false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
};// Bitmap::Data
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
void
|
|
52
|
+
Bitmap_setup (
|
|
53
|
+
Bitmap* bitmap, int w, int h, const ColorSpace& cs,
|
|
54
|
+
const void* pixels, bool clear_pixels)
|
|
55
|
+
{
|
|
56
|
+
if (w <= 0)
|
|
57
|
+
argument_error(__FILE__, __LINE__);
|
|
58
|
+
if (h <= 0)
|
|
59
|
+
argument_error(__FILE__, __LINE__);
|
|
60
|
+
if (!cs)
|
|
61
|
+
argument_error(__FILE__, __LINE__);
|
|
62
|
+
|
|
63
|
+
Bitmap::Data* self = bitmap->self.get();
|
|
64
|
+
self->clear();
|
|
65
|
+
|
|
66
|
+
Uint32 r = 0, g = 0, b = 0, a = 0;
|
|
67
|
+
int depth = 0;
|
|
68
|
+
switch (cs.type())
|
|
69
|
+
{
|
|
70
|
+
case RGB_888:
|
|
71
|
+
case RGBA_8888:
|
|
72
|
+
depth = cs.bpp();
|
|
73
|
+
r = 0x000000FF;
|
|
74
|
+
g = 0x0000FF00;
|
|
75
|
+
b = 0x00FF0000;
|
|
76
|
+
if (depth == 32) a = 0xFF000000;
|
|
77
|
+
break;
|
|
78
|
+
|
|
79
|
+
case GRAY_8:
|
|
80
|
+
depth = 8;
|
|
81
|
+
break;
|
|
82
|
+
|
|
83
|
+
default:
|
|
84
|
+
not_implemented_error(__FILE__, __LINE__, "unsupported color space");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
self->surface = SDL_CreateRGBSurface(0, w, h, depth, r, g, b, a);
|
|
88
|
+
if (!self->surface)
|
|
89
|
+
rays_error(__FILE__, __LINE__, SDL_GetError());
|
|
90
|
+
|
|
91
|
+
self->color_space = cs;
|
|
92
|
+
self->modified = true;
|
|
93
|
+
|
|
94
|
+
if (pixels)
|
|
95
|
+
{
|
|
96
|
+
SDL_LockSurface(self->surface);
|
|
97
|
+
memcpy(self->surface->pixels, pixels, self->surface->pitch * h);
|
|
98
|
+
SDL_UnlockSurface(self->surface);
|
|
99
|
+
}
|
|
100
|
+
else if (clear_pixels)
|
|
101
|
+
SDL_FillRect(self->surface, NULL, 0);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
void
|
|
105
|
+
Bitmap_draw_string (
|
|
106
|
+
Bitmap* bitmap, const RawFont& font,
|
|
107
|
+
const char* str, coord x, coord y, bool smooth)
|
|
108
|
+
{
|
|
109
|
+
if (!bitmap)
|
|
110
|
+
argument_error(__FILE__, __LINE__);
|
|
111
|
+
if (!*bitmap)
|
|
112
|
+
argument_error(__FILE__, __LINE__);
|
|
113
|
+
if (!font)
|
|
114
|
+
argument_error(__FILE__, __LINE__);
|
|
115
|
+
if (!str)
|
|
116
|
+
argument_error(__FILE__, __LINE__);
|
|
117
|
+
|
|
118
|
+
if (*str == '\0') return;
|
|
119
|
+
|
|
120
|
+
font.draw_string(bitmap->self->surface, bitmap->height(), str, x, y);
|
|
121
|
+
Bitmap_set_modified(bitmap);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
void
|
|
125
|
+
Bitmap_set_modified (Bitmap* bitmap, bool modified)
|
|
126
|
+
{
|
|
127
|
+
bitmap->self->modified = modified;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
bool
|
|
131
|
+
Bitmap_get_modified (const Bitmap& bitmap)
|
|
132
|
+
{
|
|
133
|
+
return bitmap.self->modified;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static const char*
|
|
137
|
+
get_ext (const char* path)
|
|
138
|
+
{
|
|
139
|
+
if (!path)
|
|
140
|
+
return NULL;
|
|
141
|
+
|
|
142
|
+
return strrchr(path, '.');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
void
|
|
146
|
+
Bitmap_save (const Bitmap& bmp, const char* path)
|
|
147
|
+
{
|
|
148
|
+
const char* extension = get_ext(path);
|
|
149
|
+
if (!extension)
|
|
150
|
+
{
|
|
151
|
+
argument_error(
|
|
152
|
+
__FILE__, __LINE__, "invalid image file extension: '%s'", path);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const auto& cs = bmp.color_space();
|
|
156
|
+
int w = bmp.width();
|
|
157
|
+
int h = bmp.height();
|
|
158
|
+
int pitch = w * cs.Bpp();
|
|
159
|
+
|
|
160
|
+
std::unique_ptr<uchar[]> pixels(new uchar[h * pitch]);
|
|
161
|
+
for (int y = 0; y < h; ++y)
|
|
162
|
+
memcpy(pixels.get() + pitch * y, bmp.at<uchar>(0, y), pitch);
|
|
163
|
+
|
|
164
|
+
String ext = extension;
|
|
165
|
+
ext.downcase();
|
|
166
|
+
|
|
167
|
+
int ret = 0;
|
|
168
|
+
if (ext == ".bmp")
|
|
169
|
+
ret = stbi_write_bmp(path, w, h, cs.Bpp(), pixels.get());
|
|
170
|
+
else if (ext == ".png")
|
|
171
|
+
ret = stbi_write_png(path, w, h, cs.Bpp(), pixels.get(), 0);
|
|
172
|
+
else if (ext == ".jpg" || ext == ".jpeg")
|
|
173
|
+
ret = stbi_write_jpg(path, w, h, cs.Bpp(), pixels.get(), 90);
|
|
174
|
+
else if (ext == ".tga")
|
|
175
|
+
ret = stbi_write_tga(path, w, h, cs.Bpp(), pixels.get());
|
|
176
|
+
else
|
|
177
|
+
argument_error(__FILE__, __LINE__, "unknown image file type");
|
|
178
|
+
|
|
179
|
+
if (!ret)
|
|
180
|
+
rays_error(__FILE__, __LINE__, "failed to save: '%s'", path);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
Bitmap
|
|
184
|
+
Bitmap_load (const char* path)
|
|
185
|
+
{
|
|
186
|
+
if (!path)
|
|
187
|
+
argument_error(__FILE__, __LINE__);
|
|
188
|
+
|
|
189
|
+
int w = 0, h = 0, Bpp = 0;
|
|
190
|
+
uchar* pixels = stbi_load(path, &w, &h, &Bpp, 0);
|
|
191
|
+
if (!pixels)
|
|
192
|
+
rays_error(__FILE__, __LINE__, "failed to load: '%s'", path);
|
|
193
|
+
|
|
194
|
+
ColorSpace cs;
|
|
195
|
+
switch (Bpp)
|
|
196
|
+
{
|
|
197
|
+
case 1: cs = GRAY_8; break;
|
|
198
|
+
case 3: cs = RGB_888; break;
|
|
199
|
+
case 4: cs = RGBA_8888; break;
|
|
200
|
+
default:
|
|
201
|
+
rays_error(__FILE__, __LINE__, "unsupported image file: '%s'", path);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
Bitmap bmp(w, h, cs);
|
|
205
|
+
if (!bmp)
|
|
206
|
+
rays_error(__FILE__, __LINE__, "failed to create Bitmap object");
|
|
207
|
+
|
|
208
|
+
int pitch = Bpp * w;
|
|
209
|
+
for (int y = 0; y < h; ++y)
|
|
210
|
+
memcpy(bmp.at<uchar>(0, y), pixels + pitch * y, pitch);
|
|
211
|
+
|
|
212
|
+
return bmp;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
Bitmap::Bitmap ()
|
|
217
|
+
{
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
Bitmap::Bitmap (
|
|
221
|
+
int width, int height, const ColorSpace& color_space, const void* pixels)
|
|
222
|
+
{
|
|
223
|
+
Bitmap_setup(this, width, height, color_space, pixels);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
Bitmap::~Bitmap ()
|
|
227
|
+
{
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
Bitmap
|
|
231
|
+
Bitmap::dup () const
|
|
232
|
+
{
|
|
233
|
+
return Bitmap(width(), height(), color_space(), pixels());
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
int
|
|
237
|
+
Bitmap::width () const
|
|
238
|
+
{
|
|
239
|
+
if (!*this) return 0;
|
|
240
|
+
return self->surface->w;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
int
|
|
244
|
+
Bitmap::height () const
|
|
245
|
+
{
|
|
246
|
+
if (!*this) return 0;
|
|
247
|
+
return self->surface->h;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const ColorSpace&
|
|
251
|
+
Bitmap::color_space () const
|
|
252
|
+
{
|
|
253
|
+
if (!*this)
|
|
254
|
+
{
|
|
255
|
+
static const ColorSpace UNKNOWN = COLORSPACE_UNKNOWN;
|
|
256
|
+
return UNKNOWN;
|
|
257
|
+
}
|
|
258
|
+
return self->color_space;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
int
|
|
262
|
+
Bitmap::pitch () const
|
|
263
|
+
{
|
|
264
|
+
if (!*this) return 0;
|
|
265
|
+
return self->surface->pitch;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
size_t
|
|
269
|
+
Bitmap::size () const
|
|
270
|
+
{
|
|
271
|
+
return pitch() * height();
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
void*
|
|
275
|
+
Bitmap::pixels ()
|
|
276
|
+
{
|
|
277
|
+
if (!*this) return NULL;
|
|
278
|
+
return self->surface->pixels;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const void*
|
|
282
|
+
Bitmap::pixels () const
|
|
283
|
+
{
|
|
284
|
+
return const_cast<This*>(this)->pixels();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
Bitmap::operator bool () const
|
|
288
|
+
{
|
|
289
|
+
return
|
|
290
|
+
self->surface &&
|
|
291
|
+
self->surface->w > 0 &&
|
|
292
|
+
self->surface->h > 0 &&
|
|
293
|
+
self->surface->pixels &&
|
|
294
|
+
self->color_space;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
bool
|
|
298
|
+
Bitmap::operator ! () const
|
|
299
|
+
{
|
|
300
|
+
return !operator bool();
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
}// Rays
|