rays 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/.doc/ext/rays/bitmap.cpp +70 -233
  3. data/.doc/ext/rays/bounds.cpp +339 -57
  4. data/.doc/ext/rays/color.cpp +58 -48
  5. data/.doc/ext/rays/color_space.cpp +174 -0
  6. data/.doc/ext/rays/font.cpp +31 -53
  7. data/.doc/ext/rays/image.cpp +64 -67
  8. data/.doc/ext/rays/matrix.cpp +22 -50
  9. data/.doc/ext/rays/native.cpp +9 -2
  10. data/.doc/ext/rays/painter.cpp +276 -259
  11. data/.doc/ext/rays/point.cpp +186 -52
  12. data/.doc/ext/rays/rays.cpp +25 -20
  13. data/.doc/ext/rays/shader.cpp +61 -0
  14. data/.doc/ext/rays/texture.cpp +47 -59
  15. data/{README → README.md} +0 -0
  16. data/Rakefile +6 -5
  17. data/VERSION +1 -1
  18. data/ext/rays/bitmap.cpp +88 -248
  19. data/ext/rays/bounds.cpp +437 -141
  20. data/ext/rays/color.cpp +79 -69
  21. data/ext/rays/color_space.cpp +185 -0
  22. data/ext/rays/extconf.rb +14 -63
  23. data/ext/rays/font.cpp +44 -65
  24. data/ext/rays/image.cpp +82 -81
  25. data/ext/rays/matrix.cpp +32 -60
  26. data/ext/rays/native.cpp +9 -2
  27. data/ext/rays/painter.cpp +345 -321
  28. data/ext/rays/point.cpp +212 -69
  29. data/ext/rays/rays.cpp +29 -23
  30. data/ext/rays/shader.cpp +63 -0
  31. data/ext/rays/texture.cpp +64 -74
  32. data/include/rays/bitmap.h +21 -12
  33. data/include/rays/bounds.h +67 -9
  34. data/include/rays/color.h +23 -7
  35. data/include/rays/{colorspace.h → color_space.h} +6 -3
  36. data/include/rays/exception.h +17 -11
  37. data/include/rays/font.h +4 -3
  38. data/include/rays/image.h +11 -6
  39. data/include/rays/matrix.h +15 -12
  40. data/include/rays/opengl.h +54 -1
  41. data/include/rays/painter.h +98 -108
  42. data/include/rays/point.h +45 -5
  43. data/include/rays/rays.h +2 -2
  44. data/include/rays/ruby/bitmap.h +2 -16
  45. data/include/rays/ruby/bounds.h +4 -16
  46. data/include/rays/ruby/color.h +3 -16
  47. data/include/rays/ruby/color_space.h +27 -0
  48. data/include/rays/ruby/font.h +2 -16
  49. data/include/rays/ruby/image.h +2 -16
  50. data/include/rays/ruby/matrix.h +2 -16
  51. data/include/rays/ruby/painter.h +2 -16
  52. data/include/rays/ruby/point.h +3 -16
  53. data/include/rays/ruby/shader.h +27 -0
  54. data/include/rays/ruby/texture.h +2 -16
  55. data/include/rays/ruby.h +1 -0
  56. data/include/rays/shader.h +48 -0
  57. data/include/rays/texture.h +13 -2
  58. data/include/rays.h +2 -1
  59. data/lib/rays/bitmap.rb +20 -11
  60. data/lib/rays/bounds.rb +29 -68
  61. data/lib/rays/color.rb +39 -0
  62. data/lib/rays/color_space.rb +33 -0
  63. data/lib/rays/font.rb +29 -0
  64. data/lib/rays/image.rb +22 -0
  65. data/lib/rays/module.rb +11 -7
  66. data/lib/rays/painter.rb +103 -40
  67. data/lib/rays/point.rb +19 -36
  68. data/lib/rays/shader.rb +13 -0
  69. data/lib/rays/texture.rb +9 -0
  70. data/lib/rays.rb +4 -0
  71. data/rays.gemspec +3 -4
  72. data/src/bounds.cpp +272 -63
  73. data/src/color.cpp +168 -21
  74. data/src/{colorspace.cpp → color_space.cpp} +38 -1
  75. data/src/exception.cpp +24 -15
  76. data/src/frame_buffer.cpp +275 -0
  77. data/src/frame_buffer.h +79 -0
  78. data/src/image.cpp +80 -36
  79. data/src/ios/bitmap.mm +340 -0
  80. data/src/ios/font.mm +206 -0
  81. data/src/{cocoa → ios}/helper.h +2 -2
  82. data/src/{cocoa → ios}/helper.mm +0 -0
  83. data/src/ios/opengl.mm +21 -0
  84. data/src/ios/program.cpp +122 -0
  85. data/src/{cocoa → ios}/rays.mm +8 -7
  86. data/src/matrix.cpp +10 -22
  87. data/src/opengl.cpp +64 -0
  88. data/src/{cocoa → osx}/bitmap.mm +121 -70
  89. data/src/{cocoa → osx}/font.mm +32 -24
  90. data/src/osx/helper.h +26 -0
  91. data/src/osx/helper.mm +25 -0
  92. data/src/osx/opengl.mm +103 -0
  93. data/src/osx/rays.mm +43 -0
  94. data/src/painter.cpp +596 -422
  95. data/src/point.cpp +154 -11
  96. data/src/program.cpp +513 -0
  97. data/src/program.h +73 -0
  98. data/src/render_buffer.cpp +120 -0
  99. data/src/render_buffer.h +47 -0
  100. data/src/shader.cpp +117 -0
  101. data/src/texture.cpp +104 -134
  102. data/test/helper.rb +10 -3
  103. data/test/test_bitmap.rb +18 -0
  104. data/test/test_bounds.rb +81 -35
  105. data/test/test_color.rb +29 -2
  106. data/test/test_image.rb +63 -0
  107. data/test/test_painter.rb +120 -0
  108. data/test/test_point.rb +30 -9
  109. data/test/test_shader.rb +37 -0
  110. data/test/test_texture.rb +18 -0
  111. metadata +75 -58
  112. data/.gitignore +0 -14
  113. data/ChangeLog +0 -8
@@ -1,7 +1,9 @@
1
- #include "rays/colorspace.h"
1
+ #include "rays/color_space.h"
2
2
 
3
3
 
4
+ #include <assert.h>
4
5
  #include <xot/util.h>
6
+ #include "rays/exception.h"
5
7
 
6
8
 
7
9
  namespace Rays
@@ -168,6 +170,41 @@ namespace Rays
168
170
  return premult;
169
171
  }
170
172
 
173
+ void
174
+ ColorSpace::get_gl_enums (GLenum* format, GLenum* type, bool alpha_only) const
175
+ {
176
+ if (!format && !type)
177
+ argument_error(__FILE__, __LINE__);
178
+
179
+ if (!*this)
180
+ invalid_state_error(__FILE__, __LINE__);
181
+
182
+ if (format)
183
+ {
184
+ if (is_rgb()) *format = has_alpha() ? GL_RGBA : GL_RGB;
185
+ #ifndef IOS
186
+ else if (is_bgr()) *format = has_alpha() ? GL_BGRA : GL_BGR;
187
+ #endif
188
+ else if (is_gray()) *format = alpha_only ? GL_ALPHA : GL_LUMINANCE;
189
+ else rays_error(__FILE__, __LINE__, "invalid color space.");
190
+ }
191
+
192
+ if (type)
193
+ {
194
+ if (is_float())
195
+ *type = GL_FLOAT;
196
+ else switch (bpc())
197
+ {
198
+ case 8: *type = GL_UNSIGNED_BYTE; break;
199
+ case 16: *type = GL_UNSIGNED_SHORT; break;
200
+ #ifndef IOS
201
+ case 32: *type = GL_UNSIGNED_INT; break;
202
+ #endif
203
+ default: rays_error(__FILE__, __LINE__, "invalid bpc.");
204
+ }
205
+ }
206
+ }
207
+
171
208
  ColorSpace::operator bool () const
172
209
  {
173
210
  return FIRST <= (int) type_ && (int) type_ <= LAST;
data/src/exception.cpp CHANGED
@@ -1,34 +1,43 @@
1
1
  #include "rays/exception.h"
2
2
 
3
3
 
4
+ #include "xot/string.h"
5
+
6
+
4
7
  namespace Rays
5
8
  {
6
9
 
7
10
 
8
- RaysException::RaysException (const char* format, ...)
9
- : Super("")
11
+ RaysError::RaysError (const char* str)
12
+ : Super(str)
10
13
  {
11
- XOT_STRINGF(format, s);
12
- text = s;
13
14
  }
14
15
 
15
- RaysException::~RaysException () throw()
16
- {
17
- }
18
16
 
19
- const char*
20
- RaysException::what () const throw()
17
+ OpenGLError::OpenGLError (const char* str)
18
+ : Super(str)
21
19
  {
22
- return text.c_str();
23
20
  }
24
21
 
25
22
 
26
- void
27
- rays_error (const char* format, ...)
23
+ namespace ErrorFunctions
28
24
  {
29
- XOT_STRINGF(format, s);
30
- throw RaysException(s.c_str());
31
- }
25
+
26
+ void
27
+ rays_error (const char* file, int line, const char* format, ...)
28
+ {
29
+ XOT_STRINGF(format, s);
30
+ throw RaysError(Xot::error_text(file, line, s));
31
+ }
32
+
33
+ void
34
+ opengl_error (const char* file, int line, const char* format, ...)
35
+ {
36
+ XOT_STRINGF(format, s);
37
+ throw OpenGLError(Xot::error_text(file, line, s));
38
+ }
39
+
40
+ }// ErrorFunctions
32
41
 
33
42
 
34
43
  }// Rays
@@ -0,0 +1,275 @@
1
+ #include "frame_buffer.h"
2
+
3
+
4
+ #include <vector>
5
+ #include "rays/exception.h"
6
+ #include "rays/texture.h"
7
+ #include "rays/opengl.h"
8
+ #include "render_buffer.h"
9
+
10
+
11
+ namespace Rays
12
+ {
13
+
14
+
15
+ struct FrameBuffer::Data
16
+ {
17
+
18
+ int id;
19
+
20
+ Texture texture;
21
+
22
+ RenderBuffer render_buffer;
23
+
24
+ Data ()
25
+ : id(-1)
26
+ {
27
+ }
28
+
29
+ ~Data ()
30
+ {
31
+ clear();
32
+ }
33
+
34
+ void create ()
35
+ {
36
+ if (is_valid()) return;
37
+
38
+ GLuint id_ = 0;
39
+ glGenFramebuffers(1, &id_);
40
+ check_error(__FILE__, __LINE__);
41
+
42
+ id = id_;
43
+ }
44
+
45
+ void clear ()
46
+ {
47
+ texture = Texture();
48
+ render_buffer = RenderBuffer();
49
+
50
+ if (id >= 0)
51
+ {
52
+ GLenum id_ = id;
53
+ glDeleteFramebuffers(1, &id_);
54
+ check_error(__FILE__, __LINE__);
55
+ }
56
+
57
+ id = -1;
58
+ }
59
+
60
+ bool is_valid () const
61
+ {
62
+ return id >= 0;
63
+ }
64
+
65
+ };// FrameBuffer::Data
66
+
67
+
68
+ FrameBuffer::FrameBuffer ()
69
+ {
70
+ }
71
+
72
+ FrameBuffer::FrameBuffer (const Texture& texture)
73
+ {
74
+ attach(texture);
75
+ }
76
+
77
+ FrameBuffer::~FrameBuffer ()
78
+ {
79
+ }
80
+
81
+ static String
82
+ get_error_status_name (GLenum status)
83
+ {
84
+ switch (status)
85
+ {
86
+ #ifdef IOS
87
+ case GL_FRAMEBUFFER_UNSUPPORTED_OES: return "GL_FRAMEBUFFER_UNSUPPORTED_OES";
88
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES";
89
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES";
90
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES: return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES";
91
+ case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES: return "GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES";
92
+ #else
93
+ case GL_FRAMEBUFFER_UNDEFINED: return "GL_FRAMEBUFFER_UNDEFINED";
94
+ case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED";
95
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
96
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
97
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
98
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
99
+ case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
100
+ //case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: return "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS";
101
+ #endif
102
+ }
103
+ return "UNKNOWN STATUS";
104
+ }
105
+
106
+ void
107
+ FrameBuffer::attach (const Texture& texture)
108
+ {
109
+ if (!texture)
110
+ argument_error(__FILE__, __LINE__, "FrameBuffer::attach(): invalid texture.");
111
+
112
+ self->create();
113
+
114
+ FrameBufferBinder binder(id());
115
+
116
+ glFramebufferTexture2D(
117
+ GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
118
+ GL_TEXTURE_2D, texture.id(), 0);
119
+ check_error(__FILE__, __LINE__);
120
+
121
+ self->texture = texture;
122
+
123
+ #if 0
124
+ int w = texture.width(), h = texture.height();
125
+ if (
126
+ w != self->render_buffer.width() ||
127
+ h != self->render_buffer.height())
128
+ {
129
+ RenderBuffer rb = RenderBuffer(w, h);
130
+
131
+ glFramebufferRenderbuffer(
132
+ GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
133
+ GL_RENDERBUFFER, rb.id());
134
+ check_error(__FILE__, __LINE__);
135
+
136
+ self->render_buffer = rb;
137
+ }
138
+ #endif
139
+
140
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
141
+ if (status != GL_FRAMEBUFFER_COMPLETE)
142
+ {
143
+ opengl_error(__FILE__, __LINE__,
144
+ "frame buffer status is %s", get_error_status_name(status).c_str());
145
+ }
146
+ }
147
+
148
+ GLuint
149
+ FrameBuffer::id () const
150
+ {
151
+ return self->id;
152
+ }
153
+
154
+ int
155
+ FrameBuffer::width () const
156
+ {
157
+ return self->texture.width();
158
+ }
159
+
160
+ int
161
+ FrameBuffer::height () const
162
+ {
163
+ return self->texture.height();
164
+ }
165
+
166
+ Texture&
167
+ FrameBuffer::texture ()
168
+ {
169
+ return self->texture;
170
+ }
171
+
172
+ const Texture&
173
+ FrameBuffer::texture () const
174
+ {
175
+ return const_cast<FrameBuffer*>(this)->texture();
176
+ }
177
+
178
+ FrameBuffer::operator bool () const
179
+ {
180
+ if (!self || !self->is_valid())
181
+ return false;
182
+
183
+ const Texture& t = self->texture;
184
+ if (!t)
185
+ return false;
186
+
187
+ const RenderBuffer& r = self->render_buffer;
188
+ if (r && (t.width() != r.width() || t.height() != r.height()))
189
+ return false;
190
+
191
+ return true;
192
+ }
193
+
194
+ bool
195
+ FrameBuffer::operator ! () const
196
+ {
197
+ return !operator bool();
198
+ }
199
+
200
+
201
+ FrameBufferBinder::FrameBufferBinder (GLuint id)
202
+ : id(id)
203
+ {
204
+ bind_frame_buffer(id);
205
+ }
206
+
207
+ FrameBufferBinder::~FrameBufferBinder ()
208
+ {
209
+ unbind_frame_buffer();
210
+ }
211
+
212
+ GLuint
213
+ FrameBufferBinder::current () const
214
+ {
215
+ return id;
216
+ }
217
+
218
+
219
+ struct FrameBufferID
220
+ {
221
+
222
+ GLuint draw, read;
223
+
224
+ FrameBufferID ()
225
+ : draw(0), read(0)
226
+ {
227
+ }
228
+
229
+ FrameBufferID (GLuint draw, GLuint read)
230
+ : draw(draw), read(read)
231
+ {
232
+ }
233
+
234
+ };// FrameBufferID
235
+
236
+ static std::vector<FrameBufferID> frame_buffer_bind_stack;
237
+
238
+
239
+ static void
240
+ bind_frame_buffer (GLuint draw, GLuint read)
241
+ {
242
+ FrameBufferID id;
243
+ glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, (GLint*) &id.draw);
244
+ glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, (GLint*) &id.read);
245
+ check_error(__FILE__, __LINE__);
246
+
247
+ frame_buffer_bind_stack.push_back(id);
248
+
249
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw);
250
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, read);
251
+ check_error(__FILE__, __LINE__);
252
+ }
253
+
254
+ void
255
+ bind_frame_buffer (GLuint id)
256
+ {
257
+ bind_frame_buffer(id, id);
258
+ }
259
+
260
+ void
261
+ unbind_frame_buffer ()
262
+ {
263
+ if (frame_buffer_bind_stack.empty())
264
+ rays_error(__FILE__, __LINE__, "frame_buffer_bind_stack is empty.");
265
+
266
+ FrameBufferID id = frame_buffer_bind_stack.back();
267
+ frame_buffer_bind_stack.pop_back();
268
+
269
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, id.draw);
270
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, id.read);
271
+ check_error(__FILE__, __LINE__);
272
+ }
273
+
274
+
275
+ }// Rays
@@ -0,0 +1,79 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __RAYS_FRAME_BUFFER_H__
4
+ #define __RAYS_FRAME_BUFFER_H__
5
+
6
+
7
+ #include <xot/pimpl.h>
8
+ #include <rays/defs.h>
9
+ #include <rays/opengl.h>
10
+
11
+
12
+ namespace Rays
13
+ {
14
+
15
+
16
+ class Texture;
17
+
18
+
19
+ class FrameBuffer
20
+ {
21
+
22
+ public:
23
+
24
+ FrameBuffer ();
25
+
26
+ FrameBuffer (const Texture& texture);
27
+
28
+ ~FrameBuffer ();
29
+
30
+ void attach (const Texture& texture);
31
+
32
+ GLuint id () const;
33
+
34
+ int width () const;
35
+
36
+ int height () const;
37
+
38
+ Texture& texture ();
39
+
40
+ const Texture& texture () const;
41
+
42
+ operator bool () const;
43
+
44
+ bool operator ! () const;
45
+
46
+ struct Data;
47
+
48
+ Xot::PImpl<Data, true> self;
49
+
50
+ };// FrameBuffer
51
+
52
+
53
+ class FrameBufferBinder
54
+ {
55
+
56
+ public:
57
+
58
+ FrameBufferBinder (GLuint id);
59
+
60
+ ~FrameBufferBinder ();
61
+
62
+ GLuint current () const;
63
+
64
+ private:
65
+
66
+ GLuint id;
67
+
68
+ };// FrameBufferBinder
69
+
70
+
71
+ void bind_frame_buffer (GLuint id);
72
+
73
+ void unbind_frame_buffer ();
74
+
75
+
76
+ }// Rays
77
+
78
+
79
+ #endif//EOH
data/src/image.cpp CHANGED
@@ -1,8 +1,9 @@
1
1
  #include "rays/image.h"
2
2
 
3
3
 
4
- #include <rays/bitmap.h>
5
- #include <rays/texture.h>
4
+ #include "rays/exception.h"
5
+ #include "rays/bitmap.h"
6
+ #include "rays/texture.h"
6
7
 
7
8
 
8
9
  namespace Rays
@@ -12,14 +13,18 @@ namespace Rays
12
13
  struct Image::Data
13
14
  {
14
15
 
15
- Bitmap bitmap;
16
+ int width, height;
16
17
 
17
- bool alphatex;
18
+ ColorSpace color_space;
19
+
20
+ bool alpha_only;
21
+
22
+ mutable Bitmap bitmap;
18
23
 
19
24
  mutable Texture texture;
20
25
 
21
26
  Data ()
22
- : alphatex(false)
27
+ : width(0), height(0), alpha_only(false)
23
28
  {
24
29
  }
25
30
 
@@ -30,51 +35,81 @@ namespace Rays
30
35
  {
31
36
  }
32
37
 
33
- Image::Image (
34
- int width, int height, const ColorSpace& cs,
35
- bool alphatex)
38
+ Image::Image (int width, int height, const ColorSpace& cs, bool alpha_only)
36
39
  {
37
- self->bitmap = Bitmap(width, height, cs);
38
- self->alphatex = alphatex;
40
+ self->width = width;
41
+ self->height = height;
42
+ self->color_space = cs;
43
+ self->alpha_only = alpha_only;
39
44
  }
40
45
 
41
- Image::Image (const Bitmap& bitmap, bool alphatex)
46
+ Image::Image (const Bitmap& bitmap, bool alpha_only)
42
47
  {
43
- self->bitmap = bitmap;
44
- self->alphatex = alphatex;
48
+ self->width = bitmap.width();
49
+ self->height = bitmap.height();
50
+ self->color_space = bitmap.color_space();
51
+ self->alpha_only = alpha_only;
52
+ self->bitmap = bitmap;
45
53
  }
46
54
 
47
55
  Image::~Image ()
48
56
  {
49
57
  }
50
58
 
59
+ Image
60
+ Image::copy () const
61
+ {
62
+ return Image(width(), height(), color_space(), alpha_only());
63
+ }
64
+
65
+ Painter
66
+ Image::painter ()
67
+ {
68
+ Painter p;
69
+ p.bind(texture());
70
+ return p;
71
+ }
72
+
51
73
  int
52
74
  Image::width () const
53
75
  {
54
- return self->bitmap.width();
76
+ return self->width;
55
77
  }
56
78
 
57
79
  int
58
80
  Image::height () const
59
81
  {
60
- return self->bitmap.height();
82
+ return self->height;
61
83
  }
62
84
 
63
85
  const ColorSpace&
64
86
  Image::color_space () const
65
87
  {
66
- return self->bitmap.color_space();
88
+ return self->color_space;
67
89
  }
68
90
 
69
91
  bool
70
- Image::alpha_texture () const
92
+ Image::alpha_only () const
71
93
  {
72
- return self->alphatex;
94
+ return self->alpha_only;
73
95
  }
74
96
 
75
97
  Bitmap&
76
98
  Image::bitmap ()
77
99
  {
100
+ if (!self->bitmap)
101
+ {
102
+ if (self->texture)
103
+ self->bitmap = Bitmap(self->texture);
104
+ else
105
+ self->bitmap = Bitmap(self->width, self->height, self->color_space);
106
+ }
107
+ else if (self->texture && !self->bitmap.dirty() && self->texture.dirty())
108
+ self->bitmap = Bitmap(self->texture);
109
+
110
+ if (self->bitmap) self->bitmap.set_dirty(false);
111
+ if (self->texture) self->texture.set_dirty(false);
112
+
78
113
  return self->bitmap;
79
114
  }
80
115
 
@@ -87,13 +122,27 @@ namespace Rays
87
122
  Texture&
88
123
  Image::texture ()
89
124
  {
90
- if (
91
- self->bitmap &&
92
- (!self->texture || self->bitmap.dirty()))
125
+ if (!self->texture)
93
126
  {
94
- self->texture = Texture(self->bitmap, self->alphatex);
95
- self->bitmap.set_dirty(false);
127
+ if (self->bitmap)
128
+ self->texture = Texture(self->bitmap, self->alpha_only);
129
+ else
130
+ {
131
+ self->texture = Texture(
132
+ self->width, self->height, self->color_space, self->alpha_only);
133
+
134
+ Painter p;
135
+ p.bind(self->texture);
136
+ p.begin();
137
+ p.clear();
138
+ p.end();
139
+ }
96
140
  }
141
+ else if (self->bitmap && !self->texture.dirty() && self->bitmap.dirty())
142
+ self->texture = Texture(self->bitmap, self->alpha_only);
143
+
144
+ if (self->bitmap) self->bitmap.set_dirty(false);
145
+ if (self->texture) self->texture.set_dirty(false);
97
146
 
98
147
  return self->texture;
99
148
  }
@@ -106,7 +155,7 @@ namespace Rays
106
155
 
107
156
  Image::operator bool () const
108
157
  {
109
- return !!self->bitmap;
158
+ return self->width > 0 && self->height > 0 && self->color_space;
110
159
  }
111
160
 
112
161
  bool
@@ -116,23 +165,18 @@ namespace Rays
116
165
  }
117
166
 
118
167
 
119
- bool
120
- load_image (Image* image, const char* path, bool alphatex)
168
+ Image
169
+ load_image (const char* path, bool alphatex)
121
170
  {
122
- if (!image || !path) return false;
123
-
124
- Bitmap bitmap;
125
- if (!load_bitmap(&bitmap, path))
126
- return false;
127
-
128
- *image = Image(bitmap, alphatex);
129
- return *image;
171
+ return Image(load_bitmap(path), alphatex);
130
172
  }
131
173
 
132
- bool
174
+ void
133
175
  save_image (const Image& image, const char* path)
134
176
  {
135
- if (!image || !path) return false;
177
+ if (!image)
178
+ argument_error(__FILE__, __LINE__);
179
+
136
180
  return save_bitmap(image.bitmap(), path);
137
181
  }
138
182