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.
- checksums.yaml +5 -5
- data/.doc/ext/rays/bitmap.cpp +22 -76
- data/.doc/ext/rays/bounds.cpp +95 -125
- data/.doc/ext/rays/color.cpp +224 -45
- data/.doc/ext/rays/color_space.cpp +137 -45
- data/.doc/ext/rays/defs.cpp +183 -0
- data/.doc/ext/rays/font.cpp +39 -21
- data/.doc/ext/rays/image.cpp +26 -37
- data/.doc/ext/rays/matrix.cpp +186 -29
- data/.doc/ext/rays/native.cpp +12 -6
- data/.doc/ext/rays/noise.cpp +53 -0
- data/.doc/ext/rays/painter.cpp +120 -308
- data/.doc/ext/rays/point.cpp +82 -77
- data/.doc/ext/rays/polygon.cpp +287 -0
- data/.doc/ext/rays/polygon_line.cpp +96 -0
- data/.doc/ext/rays/polyline.cpp +161 -0
- data/.doc/ext/rays/rays.cpp +0 -13
- data/.doc/ext/rays/shader.cpp +83 -9
- data/README.md +1 -1
- data/Rakefile +21 -9
- data/VERSION +1 -1
- data/ext/rays/bitmap.cpp +22 -80
- data/ext/rays/bounds.cpp +100 -128
- data/ext/rays/color.cpp +232 -51
- data/ext/rays/color_space.cpp +140 -46
- data/ext/rays/defs.cpp +183 -0
- data/ext/rays/defs.h +26 -2
- data/ext/rays/extconf.rb +1 -2
- data/ext/rays/font.cpp +39 -22
- data/ext/rays/image.cpp +27 -39
- data/ext/rays/matrix.cpp +198 -30
- data/ext/rays/native.cpp +12 -6
- data/ext/rays/noise.cpp +55 -0
- data/ext/rays/painter.cpp +129 -315
- data/ext/rays/point.cpp +89 -81
- data/ext/rays/polygon.cpp +301 -0
- data/ext/rays/polygon_line.cpp +99 -0
- data/ext/rays/polyline.cpp +170 -0
- data/ext/rays/rays.cpp +0 -14
- data/ext/rays/shader.cpp +84 -9
- data/include/rays.h +10 -2
- data/include/rays/bitmap.h +14 -26
- data/include/rays/bounds.h +21 -4
- data/include/rays/color.h +25 -14
- data/include/rays/color_space.h +11 -8
- data/include/rays/coord.h +114 -0
- data/include/rays/debug.h +22 -0
- data/include/rays/defs.h +3 -0
- data/include/rays/font.h +4 -4
- data/include/rays/image.h +11 -17
- data/include/rays/matrix.h +50 -24
- data/include/rays/noise.h +42 -0
- data/include/rays/opengl.h +2 -50
- data/include/rays/painter.h +57 -99
- data/include/rays/point.h +44 -51
- data/include/rays/polygon.h +164 -0
- data/include/rays/polyline.h +65 -0
- data/include/rays/rays.h +3 -0
- data/include/rays/ruby.h +7 -1
- data/include/rays/ruby/bounds.h +1 -1
- data/include/rays/ruby/color.h +1 -1
- data/include/rays/ruby/color_space.h +1 -1
- data/include/rays/ruby/font.h +1 -1
- data/include/rays/ruby/matrix.h +1 -1
- data/include/rays/ruby/point.h +1 -1
- data/include/rays/ruby/polygon.h +52 -0
- data/include/rays/ruby/polyline.h +41 -0
- data/include/rays/ruby/shader.h +1 -1
- data/include/rays/shader.h +36 -8
- data/lib/rays.rb +6 -1
- data/lib/rays/bitmap.rb +0 -15
- data/lib/rays/bounds.rb +17 -23
- data/lib/rays/color.rb +20 -47
- data/lib/rays/color_space.rb +13 -13
- data/lib/rays/image.rb +2 -6
- data/lib/rays/matrix.rb +28 -0
- data/lib/rays/module.rb +4 -19
- data/lib/rays/painter.rb +60 -97
- data/lib/rays/point.rb +13 -21
- data/lib/rays/polygon.rb +50 -0
- data/lib/rays/polygon_line.rb +36 -0
- data/lib/rays/polyline.rb +32 -0
- data/lib/rays/shader.rb +20 -1
- data/rays.gemspec +5 -7
- data/src/bitmap.h +36 -0
- data/src/bounds.cpp +74 -11
- data/src/color.cpp +58 -23
- data/src/color_space.cpp +50 -32
- data/src/color_space.h +22 -0
- data/src/coord.cpp +170 -0
- data/src/coord.h +35 -0
- data/src/font.cpp +118 -0
- data/src/font.h +64 -0
- data/src/frame_buffer.cpp +37 -71
- data/src/frame_buffer.h +4 -4
- data/src/image.cpp +171 -97
- data/src/image.h +25 -0
- data/src/ios/bitmap.mm +107 -105
- data/src/ios/font.mm +48 -60
- data/src/ios/helper.h +2 -2
- data/src/ios/opengl.mm +19 -4
- data/src/ios/rays.mm +3 -0
- data/src/matrix.cpp +111 -26
- data/src/matrix.h +30 -0
- data/src/noise.cpp +74 -0
- data/src/opengl.cpp +9 -27
- data/src/opengl.h +37 -0
- data/src/osx/bitmap.mm +111 -106
- data/src/osx/font.mm +48 -61
- data/src/osx/helper.h +2 -2
- data/src/osx/opengl.mm +19 -83
- data/src/osx/rays.mm +3 -0
- data/src/painter.cpp +780 -696
- data/src/painter.h +24 -0
- data/src/point.cpp +140 -119
- data/src/polygon.cpp +1100 -0
- data/src/polygon.h +32 -0
- data/src/polyline.cpp +158 -0
- data/src/polyline.h +67 -0
- data/src/render_buffer.cpp +11 -4
- data/src/render_buffer.h +2 -2
- data/src/shader.cpp +163 -106
- data/src/shader.h +38 -0
- data/src/shader_program.cpp +533 -0
- data/src/{program.h → shader_program.h} +28 -16
- data/src/shader_source.cpp +140 -0
- data/src/shader_source.h +52 -0
- data/src/texture.cpp +136 -160
- data/src/texture.h +65 -0
- data/src/win32/bitmap.cpp +62 -52
- data/src/win32/font.cpp +11 -13
- data/src/win32/font.h +24 -0
- data/src/win32/gdi.h +6 -6
- data/test/helper.rb +0 -3
- data/test/test_bitmap.rb +31 -7
- data/test/test_bounds.rb +36 -0
- data/test/test_color.rb +59 -19
- data/test/test_color_space.rb +95 -0
- data/test/test_image.rb +24 -20
- data/test/test_matrix.rb +106 -0
- data/test/test_painter.rb +92 -46
- data/test/test_painter_shape.rb +57 -0
- data/test/test_point.rb +21 -0
- data/test/test_polygon.rb +234 -0
- data/test/test_polygon_line.rb +167 -0
- data/test/test_polyline.rb +145 -0
- data/test/test_shader.rb +9 -9
- metadata +88 -67
- data/.doc/ext/rays/texture.cpp +0 -138
- data/ext/rays/texture.cpp +0 -149
- data/include/rays/ruby/texture.h +0 -41
- data/include/rays/texture.h +0 -71
- data/lib/rays/texture.rb +0 -24
- data/src/program.cpp +0 -648
- data/test/test_texture.rb +0 -27
data/src/osx/font.mm
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
// -*- objc -*-
|
2
|
-
#include "
|
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
|
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
|
-
};//
|
33
|
+
};// RawFont::Data
|
34
34
|
|
35
35
|
|
36
36
|
static CTLineRef
|
@@ -64,29 +64,61 @@ namespace Rays
|
|
64
64
|
}
|
65
65
|
|
66
66
|
|
67
|
-
|
67
|
+
RawFont::RawFont ()
|
68
68
|
{
|
69
69
|
}
|
70
70
|
|
71
|
-
|
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(
|
75
|
+
: CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, size, NULL);
|
76
76
|
}
|
77
77
|
|
78
|
-
|
78
|
+
RawFont::~RawFont ()
|
79
79
|
{
|
80
80
|
}
|
81
81
|
|
82
|
-
|
83
|
-
|
82
|
+
void
|
83
|
+
RawFont::draw_string (
|
84
|
+
void* context_, coord context_height,
|
85
|
+
const char* str, coord x, coord y) const
|
84
86
|
{
|
85
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
181
|
+
RawFont::operator bool () const
|
150
182
|
{
|
151
183
|
return !!self->font;
|
152
184
|
}
|
153
185
|
|
154
186
|
bool
|
155
|
-
|
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
|
data/src/osx/helper.h
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
#define __RAYS_SRC_OSX_HELPER_H__
|
5
5
|
|
6
6
|
|
7
|
-
#include <
|
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
|
18
|
+
typedef std::shared_ptr<const __CFString> CFString;
|
19
19
|
|
20
20
|
CFString cfstring (const char* str);
|
21
21
|
|
data/src/osx/opengl.mm
CHANGED
@@ -1,102 +1,38 @@
|
|
1
1
|
// -*- objc -*-
|
2
|
-
#include "
|
2
|
+
#include "../opengl.h"
|
3
3
|
|
4
4
|
|
5
|
-
#
|
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
|
-
|
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
|
-
|
60
|
-
|
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
|
-
|
19
|
+
Context
|
20
|
+
OpenGL_get_context ()
|
83
21
|
{
|
84
|
-
|
85
|
-
[super dealloc];
|
22
|
+
return [NSOpenGLContext currentContext];
|
86
23
|
}
|
87
24
|
|
88
|
-
@end// OffscreenWindow
|
89
|
-
|
90
25
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
void
|
96
|
-
init_offscreen_context ()
|
26
|
+
Context
|
27
|
+
get_offscreen_context ()
|
97
28
|
{
|
98
|
-
|
99
|
-
|
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
|
|
data/src/osx/rays.mm
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
|
5
5
|
#import <Foundation/Foundation.h>
|
6
6
|
#include "rays/exception.h"
|
7
|
+
#include "../opengl.h"
|
7
8
|
|
8
9
|
|
9
10
|
namespace Rays
|
@@ -27,6 +28,8 @@ namespace Rays
|
|
27
28
|
rays_error(__FILE__, __LINE__, "Rays::init(): already initialized.");
|
28
29
|
|
29
30
|
global::pool = [[NSAutoreleasePool alloc] init];
|
31
|
+
|
32
|
+
OpenGL_set_context(get_offscreen_context());
|
30
33
|
}
|
31
34
|
|
32
35
|
void
|
data/src/painter.cpp
CHANGED
@@ -1,22 +1,28 @@
|
|
1
|
-
#include "
|
1
|
+
#include "painter.h"
|
2
2
|
|
3
3
|
|
4
4
|
#include <math.h>
|
5
|
-
#include <
|
5
|
+
#include <assert.h>
|
6
|
+
#include <memory>
|
7
|
+
#include <vector>
|
6
8
|
#include <algorithm>
|
7
|
-
#include <
|
9
|
+
#include <glm/gtc/matrix_transform.hpp>
|
8
10
|
#include "rays/exception.h"
|
9
11
|
#include "rays/point.h"
|
10
12
|
#include "rays/bounds.h"
|
11
13
|
#include "rays/color.h"
|
12
|
-
#include "rays/
|
13
|
-
#include "
|
14
|
-
#include "
|
15
|
-
#include "
|
16
|
-
#include "
|
17
|
-
#include "
|
14
|
+
#include "rays/debug.h"
|
15
|
+
#include "opengl.h"
|
16
|
+
#include "matrix.h"
|
17
|
+
#include "polygon.h"
|
18
|
+
#include "bitmap.h"
|
19
|
+
#include "texture.h"
|
20
|
+
#include "image.h"
|
21
|
+
#include "font.h"
|
18
22
|
#include "frame_buffer.h"
|
19
|
-
#include "
|
23
|
+
#include "shader.h"
|
24
|
+
#include "shader_program.h"
|
25
|
+
#include "shader_source.h"
|
20
26
|
|
21
27
|
|
22
28
|
namespace Rays
|
@@ -35,152 +41,519 @@ namespace Rays
|
|
35
41
|
};// ColorType
|
36
42
|
|
37
43
|
|
38
|
-
|
44
|
+
struct State
|
45
|
+
{
|
39
46
|
|
40
|
-
|
47
|
+
Color background, colors[2];
|
41
48
|
|
49
|
+
coord stroke_width;
|
42
50
|
|
43
|
-
|
44
|
-
{
|
51
|
+
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
|
-
|
71
|
+
bool has_color ()
|
72
|
+
{
|
73
|
+
return colors[FILL] || colors[STROKE];
|
74
|
+
}
|
62
75
|
|
76
|
+
};// State
|
63
77
|
|
64
|
-
|
78
|
+
|
79
|
+
struct TextureInfo
|
65
80
|
{
|
66
81
|
|
67
|
-
|
82
|
+
const Texture& texture;
|
68
83
|
|
69
|
-
|
84
|
+
Coord2 texcoord_min, texcoord_max;
|
70
85
|
|
71
|
-
|
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
|
-
|
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
|
104
|
+
bool operator ! () const
|
105
|
+
{
|
106
|
+
return !operator bool();
|
107
|
+
}
|
76
108
|
|
77
|
-
|
109
|
+
};// TextureInfo
|
78
110
|
|
79
|
-
GLuint current_texture;
|
80
111
|
|
81
|
-
|
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
|
-
|
273
|
+
Image text_image;
|
274
|
+
|
275
|
+
OpenGLState opengl_state;
|
86
276
|
|
87
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
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
|
-
|
311
|
+
OpenGL_check_error(__FILE__, __LINE__);
|
113
312
|
}
|
114
313
|
|
115
|
-
bool
|
314
|
+
bool get_color (Color* color, ColorType type)
|
116
315
|
{
|
117
|
-
const Color& c =
|
118
|
-
if (c
|
316
|
+
const Color& c = state.colors[type];
|
317
|
+
if (!c) return false;
|
119
318
|
|
120
|
-
|
319
|
+
*color = c;
|
121
320
|
return true;
|
122
321
|
}
|
123
322
|
|
124
|
-
void
|
125
|
-
GLenum mode,
|
126
|
-
|
127
|
-
|
128
|
-
const
|
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 (
|
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
|
-
|
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
|
-
|
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 !=
|
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
|
-
|
153
|
-
|
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
|
-
|
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
|
-
|
162
|
-
glVertexPointer(vertex_size, GL_FLOAT, 0, vertices);
|
508
|
+
};// Painter::Data
|
163
509
|
|
164
|
-
glDrawElements(mode, nindices, GL_UNSIGNED_INT, indices);
|
165
510
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 (
|
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 (
|
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&
|
584
|
+
Painter::canvas (const Bounds& viewport, float pixel_density)
|
209
585
|
{
|
210
|
-
if (!
|
586
|
+
if (!viewport)
|
211
587
|
argument_error(__FILE__, __LINE__);
|
212
588
|
|
213
589
|
if (self->painting)
|
214
|
-
invalid_state_error(__FILE__, __LINE__, "
|
590
|
+
invalid_state_error(__FILE__, __LINE__, "painting flag should be false.");
|
215
591
|
|
216
|
-
self->viewport =
|
592
|
+
self->viewport = viewport;
|
593
|
+
self->set_pixel_density(pixel_density);
|
217
594
|
}
|
218
595
|
|
219
596
|
void
|
220
|
-
Painter::bind (const
|
597
|
+
Painter::bind (const Image& image)
|
221
598
|
{
|
222
|
-
if (!
|
223
|
-
argument_error(__FILE__, __LINE__, "invalid
|
599
|
+
if (!image)
|
600
|
+
argument_error(__FILE__, __LINE__, "invalid image.");
|
224
601
|
|
225
602
|
if (self->painting)
|
226
|
-
invalid_state_error(__FILE__, __LINE__, "
|
603
|
+
invalid_state_error(__FILE__, __LINE__, "painting flag should be false.");
|
227
604
|
|
228
|
-
FrameBuffer fb(
|
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,
|
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__, "
|
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__, "
|
640
|
+
invalid_state_error(__FILE__, __LINE__, "painting flag should be false.");
|
259
641
|
|
260
|
-
|
261
|
-
if (fb) bind_frame_buffer(fb.id());
|
642
|
+
self->opengl_state.push();
|
262
643
|
|
263
|
-
|
264
|
-
|
644
|
+
FrameBuffer& fb = self->frame_buffer;
|
645
|
+
if (fb) FrameBuffer_bind(fb.id());
|
265
646
|
|
266
647
|
const Bounds& vp = self->viewport;
|
267
|
-
float
|
648
|
+
float density = self->pixel_density;
|
268
649
|
glViewport(
|
269
|
-
(int) vp.x,
|
270
|
-
(int) vp.width
|
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)
|
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
|
-
|
295
|
-
glMatrixMode(GL_COLOR);
|
296
|
-
glPushMatrix();
|
297
|
-
glLoadIdentity();
|
298
|
-
#endif
|
659
|
+
self->state.init();
|
299
660
|
|
300
|
-
|
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__, "
|
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
|
-
|
331
|
-
|
681
|
+
if (!self->state_stack.empty())
|
682
|
+
invalid_state_error(__FILE__, __LINE__, "state stack is not empty.");
|
332
683
|
|
333
|
-
|
334
|
-
|
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
|
-
|
339
|
-
|
340
|
-
|
341
|
-
pop_attr();
|
687
|
+
self->painting = false;
|
688
|
+
self->opengl_state.pop();
|
689
|
+
self->default_indices.clear();
|
342
690
|
|
343
|
-
|
691
|
+
glFinish();
|
344
692
|
|
345
693
|
if (self->frame_buffer)
|
346
694
|
{
|
347
|
-
|
695
|
+
FrameBuffer_unbind();
|
348
696
|
|
349
697
|
Texture& tex = self->frame_buffer.texture();
|
350
|
-
if (tex) tex.
|
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__, "
|
706
|
+
invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
|
359
707
|
|
360
|
-
const Color& c = self->
|
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
|
-
|
714
|
+
static inline void
|
715
|
+
debug_draw_triangulation (
|
716
|
+
Painter* painter, const Polygon& polygon, const Color& color)
|
369
717
|
{
|
370
|
-
|
371
|
-
|
372
|
-
0, 1
|
373
|
-
};
|
374
|
-
|
375
|
-
Data* pself = self.get();
|
718
|
+
#ifdef _DEBUG
|
719
|
+
assert(painter);
|
376
720
|
|
377
|
-
|
378
|
-
|
721
|
+
Color invert_color(
|
722
|
+
1.f - color.red,
|
723
|
+
1.f - color.green,
|
724
|
+
1.f - color.blue);
|
379
725
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
coord vertices[] =
|
726
|
+
Polygon::TrianglePointList triangles;
|
727
|
+
if (Polygon_triangulate(&triangles, polygon))
|
384
728
|
{
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
void
|
393
|
-
Painter::line (const Point& p1, const Point& p2)
|
394
|
-
{
|
395
|
-
line(p1.x, p1.y, p2.x, p2.y);
|
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::
|
739
|
+
Painter::polygon (const Polygon& polygon)
|
400
740
|
{
|
401
|
-
|
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 (!
|
744
|
+
if (!self->state.has_color())
|
407
745
|
return;
|
408
746
|
|
409
|
-
|
410
|
-
for (size_t i = 0; i < size; ++i)
|
411
|
-
indices[i] = (uint) i;
|
412
|
-
|
413
|
-
pself->draw_shape(GL_LINES, (int) size, indices.get(), 2, (coord*) points);
|
414
|
-
}
|
415
|
-
|
416
|
-
void
|
417
|
-
Painter::lines (const Coord3* points, size_t size)
|
418
|
-
{
|
419
|
-
Data* pself = self.get();
|
420
|
-
|
421
|
-
if (!pself->painting)
|
422
|
-
invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
|
747
|
+
Color color;
|
423
748
|
|
424
|
-
if (
|
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
|
-
|
432
|
-
|
751
|
+
Polygon_fill(polygon, this, color);
|
752
|
+
debug_draw_triangulation(this, polygon, color);
|
433
753
|
}
|
434
754
|
|
435
|
-
|
436
|
-
|
755
|
+
if (self->get_color(&color, STROKE))
|
756
|
+
Polygon_stroke(polygon, this, color);
|
437
757
|
}
|
438
758
|
|
439
759
|
void
|
440
|
-
Painter::
|
760
|
+
Painter::line (coord x1, coord y1, coord x2, coord y2)
|
441
761
|
{
|
442
|
-
|
443
|
-
|
444
|
-
if (!pself->painting)
|
445
|
-
invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
|
446
|
-
|
447
|
-
GLenum modes[] = {GL_TRIANGLE_FAN, GL_LINE_LOOP};
|
448
|
-
boost::scoped_array<uint> indices;
|
449
|
-
|
450
|
-
for (int type = COLOR_TYPE_BEGIN; type < COLOR_TYPE_END; ++type)
|
451
|
-
{
|
452
|
-
if (!pself->use_color((ColorType) type)) continue;
|
453
|
-
|
454
|
-
if (!indices.get())
|
455
|
-
{
|
456
|
-
indices.reset(new uint[size]);
|
457
|
-
for (size_t i = 0; i < size; ++i)
|
458
|
-
indices[i] = (uint) i;
|
459
|
-
}
|
460
|
-
|
461
|
-
pself->draw_shape(
|
462
|
-
modes[type], (int) size, indices.get(), 2, (coord*) points);
|
463
|
-
}
|
762
|
+
polygon(create_line(x1, y1, x2, y2));
|
464
763
|
}
|
465
764
|
|
466
765
|
void
|
467
|
-
Painter::
|
766
|
+
Painter::line (const Point& p1, const Point& p2)
|
468
767
|
{
|
469
|
-
|
470
|
-
|
471
|
-
if (!pself->painting)
|
472
|
-
invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
|
473
|
-
|
474
|
-
GLenum modes[] = {GL_TRIANGLE_FAN, GL_LINE_LOOP};
|
475
|
-
boost::scoped_array<uint> indices;
|
476
|
-
boost::scoped_array<Coord2> vertices;
|
477
|
-
|
478
|
-
for (int type = COLOR_TYPE_BEGIN; type < COLOR_TYPE_END; ++type)
|
479
|
-
{
|
480
|
-
if (!pself->use_color((ColorType) type)) continue;
|
481
|
-
|
482
|
-
if (!indices.get())
|
483
|
-
{
|
484
|
-
indices.reset(new uint[size]);
|
485
|
-
for (size_t i = 0; i < size; ++i)
|
486
|
-
indices[i] = (uint) i;
|
487
|
-
}
|
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::
|
772
|
+
Painter::line (const Point* points, size_t size, bool loop)
|
503
773
|
{
|
504
|
-
|
774
|
+
polygon(create_line(points, size, loop));
|
505
775
|
}
|
506
776
|
|
507
777
|
void
|
508
|
-
Painter::
|
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
|
-
|
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 (
|
784
|
+
Painter::rect (coord x, coord y, coord width, coord height, coord round)
|
548
785
|
{
|
549
|
-
|
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 (
|
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
|
-
|
567
|
-
|
792
|
+
coord round_left_top, coord round_right_top,
|
793
|
+
coord round_left_bottom, coord round_right_bottom)
|
568
794
|
{
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
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::
|
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
|
-
|
805
|
+
polygon(create_rect(bounds, round, nsegment()));
|
638
806
|
}
|
639
807
|
|
640
808
|
void
|
641
|
-
Painter::
|
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
|
-
|
644
|
-
bounds
|
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
|
-
|
824
|
+
const Point& hole_size,
|
825
|
+
float angle_from, float angle_to)
|
660
826
|
{
|
661
|
-
|
662
|
-
|
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::
|
832
|
+
Painter::ellipse (
|
667
833
|
const Bounds& bounds,
|
668
|
-
|
834
|
+
const Point& hole_size,
|
835
|
+
float angle_from, float angle_to)
|
669
836
|
{
|
670
|
-
|
671
|
-
bounds
|
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::
|
677
|
-
const Point& center,
|
678
|
-
float angle_from, float angle_to
|
842
|
+
Painter::ellipse (
|
843
|
+
const Point& center, const Point& radius, const Point& hole_radius,
|
844
|
+
float angle_from, float angle_to)
|
679
845
|
{
|
680
|
-
|
681
|
-
center
|
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
|
688
|
-
|
689
|
-
coord
|
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(
|
859
|
+
assert(painter && image);
|
699
860
|
|
700
|
-
|
701
|
-
argument_error(__FILE__, __LINE__);
|
861
|
+
Painter::Data* self = painter->self.get();
|
702
862
|
|
703
|
-
|
863
|
+
if (!self->painting)
|
864
|
+
invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
|
704
865
|
|
705
|
-
if (!
|
706
|
-
|
866
|
+
if (!self->state.has_color())
|
867
|
+
return;
|
707
868
|
|
708
|
-
|
709
|
-
|
710
|
-
|
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
|
-
|
719
|
-
|
720
|
-
|
721
|
-
|
722
|
-
|
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
|
-
|
728
|
-
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
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,
|
754
|
-
0, 0,
|
755
|
-
x, y,
|
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,
|
777
|
-
0, 0,
|
778
|
-
x, y, width,
|
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
|
792
|
-
coord
|
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,
|
805
|
-
|
806
|
-
|
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&
|
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
|
-
|
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
|
823
|
-
coord
|
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,
|
836
|
-
|
837
|
-
|
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&
|
979
|
+
const Image& image_, const Bounds& src_bounds, const Bounds& dst_bounds)
|
843
980
|
{
|
844
981
|
image(
|
845
982
|
image_,
|
846
|
-
|
847
|
-
|
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
|
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'
|
1026
|
+
assert(painter && font && str && *str != '\0');
|
857
1027
|
|
858
|
-
|
859
|
-
argument_error(__FILE__, __LINE__);
|
1028
|
+
Painter::Data* self = painter->self.get();
|
860
1029
|
|
861
|
-
if (!
|
862
|
-
invalid_state_error(__FILE__, __LINE__, "
|
1030
|
+
if (!self->painting)
|
1031
|
+
invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
|
863
1032
|
|
864
|
-
|
865
|
-
|
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
|
-
|
870
|
-
|
1043
|
+
texture.width() < tex_w ||
|
1044
|
+
texture.height() < tex_h ||
|
1045
|
+
self->text_image.pixel_density() != density)
|
871
1046
|
{
|
872
|
-
|
873
|
-
|
874
|
-
|
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
|
-
|
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
|
-
|
902
|
-
|
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
|
-
|
906
|
-
|
907
|
-
|
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,
|
918
|
-
0, 0,
|
919
|
-
x, y,
|
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
|
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
|
-
|
932
|
-
if (
|
933
|
-
|
1082
|
+
const Font& font = self->state.font;
|
1083
|
+
if (!font)
|
1084
|
+
invalid_state_error(__FILE__, __LINE__);
|
934
1085
|
|
935
|
-
|
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
|
1090
|
+
Painter::text (const char* str, const Point& position)
|
943
1091
|
{
|
944
|
-
text(str, position.x, position.y
|
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
|
-
|
958
|
-
if (
|
959
|
-
|
1103
|
+
const Font& font = self->state.font;
|
1104
|
+
if (!font)
|
1105
|
+
invalid_state_error(__FILE__, __LINE__);
|
960
1106
|
|
961
|
-
|
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
|
1111
|
+
Painter::text (const char* str, const Bounds& bounds)
|
969
1112
|
{
|
970
|
-
text(str, bounds.x, bounds.y, bounds.width, bounds.height
|
1113
|
+
text(str, bounds.x, bounds.y, bounds.width, bounds.height);
|
971
1114
|
}
|
972
1115
|
|
973
|
-
|
974
1116
|
void
|
975
|
-
Painter::set_background (
|
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->
|
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->
|
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->
|
1154
|
+
self->state.colors[FILL] = color;
|
1012
1155
|
}
|
1013
1156
|
|
1014
1157
|
void
|
1015
1158
|
Painter::no_fill ()
|
1016
1159
|
{
|
1017
|
-
self->
|
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->
|
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->
|
1178
|
+
self->state.colors[STROKE] = color;
|
1036
1179
|
}
|
1037
1180
|
|
1038
1181
|
void
|
1039
1182
|
Painter::no_stroke ()
|
1040
1183
|
{
|
1041
|
-
self->
|
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->
|
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::
|
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
|
-
|
1196
|
+
self->state.stroke_width = width;
|
1073
1197
|
}
|
1074
1198
|
|
1075
|
-
|
1076
|
-
Painter::
|
1199
|
+
coord
|
1200
|
+
Painter::stroke_width () const
|
1077
1201
|
{
|
1078
|
-
|
1202
|
+
return self->state.stroke_width;
|
1079
1203
|
}
|
1080
1204
|
|
1081
1205
|
void
|
1082
|
-
Painter::
|
1206
|
+
Painter::set_nsegment (int nsegment)
|
1083
1207
|
{
|
1084
|
-
|
1208
|
+
if (nsegment < 0) nsegment = 0;
|
1209
|
+
self->state.nsegment = nsegment;
|
1085
1210
|
}
|
1086
1211
|
|
1087
|
-
|
1088
|
-
Painter::
|
1212
|
+
uint
|
1213
|
+
Painter::nsegment () const
|
1089
1214
|
{
|
1090
|
-
return self->
|
1215
|
+
return self->state.nsegment;
|
1091
1216
|
}
|
1092
1217
|
|
1093
1218
|
void
|
1094
|
-
Painter::
|
1219
|
+
Painter::set_clip (coord x, coord y, coord width, coord height)
|
1095
1220
|
{
|
1096
|
-
|
1221
|
+
set_clip(Bounds(x, y, width, height));
|
1097
1222
|
}
|
1098
1223
|
|
1099
1224
|
void
|
1100
|
-
Painter::
|
1225
|
+
Painter::set_clip (const Bounds& bounds)
|
1101
1226
|
{
|
1102
|
-
|
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::
|
1232
|
+
Painter::no_clip ()
|
1131
1233
|
{
|
1132
|
-
|
1234
|
+
set_clip(0, 0, -1, -1);
|
1133
1235
|
}
|
1134
1236
|
|
1135
|
-
|
1136
|
-
Painter::
|
1237
|
+
const Bounds&
|
1238
|
+
Painter::clip () const
|
1137
1239
|
{
|
1138
|
-
self->
|
1240
|
+
return self->state.clip;
|
1139
1241
|
}
|
1140
1242
|
|
1141
1243
|
void
|
1142
|
-
Painter::
|
1244
|
+
Painter::set_font (const char* name, coord size)
|
1143
1245
|
{
|
1144
|
-
|
1246
|
+
set_font(Font(name, size));
|
1145
1247
|
}
|
1146
1248
|
|
1147
1249
|
void
|
1148
|
-
Painter::
|
1250
|
+
Painter::set_font (const Font& font)
|
1149
1251
|
{
|
1150
|
-
self->
|
1252
|
+
self->state.font = font;
|
1151
1253
|
}
|
1152
1254
|
|
1153
|
-
|
1154
|
-
Painter::
|
1255
|
+
const Font&
|
1256
|
+
Painter::font () const
|
1155
1257
|
{
|
1156
|
-
self->
|
1258
|
+
return self->state.font;
|
1157
1259
|
}
|
1158
1260
|
|
1159
1261
|
void
|
1160
|
-
Painter::
|
1262
|
+
Painter::set_shader (const Shader& shader)
|
1161
1263
|
{
|
1162
|
-
self->
|
1264
|
+
self->state.shader = shader;
|
1163
1265
|
}
|
1164
1266
|
|
1165
1267
|
void
|
1166
|
-
Painter::
|
1268
|
+
Painter::no_shader ()
|
1167
1269
|
{
|
1168
|
-
self->
|
1270
|
+
self->state.shader = Shader();
|
1169
1271
|
}
|
1170
1272
|
|
1171
|
-
|
1172
|
-
Painter::
|
1273
|
+
const Shader&
|
1274
|
+
Painter::shader () const
|
1173
1275
|
{
|
1174
|
-
self->
|
1276
|
+
return self->state.shader;
|
1175
1277
|
}
|
1176
1278
|
|
1177
1279
|
void
|
1178
|
-
Painter::
|
1280
|
+
Painter::push_state ()
|
1179
1281
|
{
|
1180
|
-
self->
|
1282
|
+
self->state_stack.push_back(self->state);
|
1181
1283
|
}
|
1182
1284
|
|
1183
1285
|
void
|
1184
|
-
Painter::
|
1286
|
+
Painter::pop_state ()
|
1185
1287
|
{
|
1186
|
-
self->
|
1187
|
-
|
1288
|
+
if (self->state_stack.empty())
|
1289
|
+
invalid_state_error(__FILE__, __LINE__, "state stack underflow.");
|
1188
1290
|
|
1189
|
-
|
1190
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
1317
|
+
self->position_matrix.scale(value);
|
1218
1318
|
}
|
1219
1319
|
|
1220
1320
|
void
|
1221
|
-
Painter::rotate (float
|
1321
|
+
Painter::rotate (float degree, coord x, coord y, coord z)
|
1222
1322
|
{
|
1223
|
-
|
1323
|
+
self->position_matrix.rotate(degree, x, y, z);
|
1224
1324
|
}
|
1225
1325
|
|
1226
1326
|
void
|
1227
|
-
Painter::rotate (float angle, const Point&
|
1327
|
+
Painter::rotate (float angle, const Point& normalized_axis)
|
1228
1328
|
{
|
1229
|
-
rotate(angle,
|
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
|
-
|
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
|
-
|
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
|
1353
|
+
Painter::set_matrix (const coord* elements, size_t size)
|
1266
1354
|
{
|
1267
|
-
|
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
|
-
|
1361
|
+
self->position_matrix = matrix;
|
1277
1362
|
}
|
1278
1363
|
|
1279
1364
|
const Matrix&
|
1280
1365
|
Painter::matrix () const
|
1281
1366
|
{
|
1282
|
-
|
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
|
-
|
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
|
-
|
1298
|
-
|
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
|
{
|