rays 0.1.12 → 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
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
  {