rays 0.1.12 → 0.1.13

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