rays 0.1.14 → 0.1.15
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.doc/ext/rays/color_space.cpp +22 -14
- data/.doc/ext/rays/painter.cpp +93 -0
- data/.doc/ext/rays/polygon.cpp +30 -4
- data/.doc/ext/rays/polyline.cpp +9 -3
- data/.doc/ext/rays/rays.cpp +105 -1
- data/Rakefile +3 -0
- data/VERSION +1 -1
- data/ext/rays/color_space.cpp +22 -14
- data/ext/rays/painter.cpp +104 -3
- data/ext/rays/polygon.cpp +31 -3
- data/ext/rays/polyline.cpp +8 -2
- data/ext/rays/rays.cpp +105 -1
- data/include/rays/color_space.h +4 -2
- data/include/rays/defs.h +33 -0
- data/include/rays/image.h +1 -1
- data/include/rays/painter.h +38 -0
- data/include/rays/polygon.h +35 -1
- data/include/rays/polyline.h +7 -1
- data/include/rays/ruby/rays.h +8 -0
- data/lib/rays/image.rb +1 -1
- data/lib/rays/painter.rb +23 -1
- data/lib/rays/polygon.rb +8 -0
- data/src/color_space.cpp +2 -2
- data/src/ios/bitmap.mm +4 -4
- data/src/ios/font.mm +2 -2
- data/src/osx/bitmap.mm +4 -4
- data/src/osx/font.mm +2 -2
- data/src/painter.cpp +100 -10
- data/src/polygon.cpp +199 -37
- data/src/polyline.cpp +4 -2
- data/src/polyline.h +3 -1
- data/test/test_painter_shape.rb +48 -3
- metadata +2 -2
data/include/rays/polygon.h
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
|
7
7
|
#include <vector>
|
8
8
|
#include <xot/pimpl.h>
|
9
|
+
#include <rays/defs.h>
|
9
10
|
#include <rays/bounds.h>
|
10
11
|
#include <rays/polyline.h>
|
11
12
|
|
@@ -61,7 +62,12 @@ namespace Rays
|
|
61
62
|
|
62
63
|
~Polygon ();
|
63
64
|
|
64
|
-
bool expand (
|
65
|
+
bool expand (
|
66
|
+
Polygon* result,
|
67
|
+
coord width,
|
68
|
+
CapType cap = CAP_DEFAULT,
|
69
|
+
JoinType join = JOIN_DEFAULT,
|
70
|
+
coord miter_limit = JOIN_DEFAULT_MITER_LIMIT) const;
|
65
71
|
|
66
72
|
Bounds bounds () const;
|
67
73
|
|
@@ -158,6 +164,34 @@ namespace Rays
|
|
158
164
|
uint nsegment = 0);
|
159
165
|
|
160
166
|
|
167
|
+
Polygon create_curve (
|
168
|
+
coord x1, coord y1, coord x2, coord y2,
|
169
|
+
coord x3, coord y3, coord x4, coord y4,
|
170
|
+
bool loop = false);
|
171
|
+
|
172
|
+
Polygon create_curve (
|
173
|
+
const Point& p1, const Point& p2, const Point& p3, const Point& p4,
|
174
|
+
bool loop = false);
|
175
|
+
|
176
|
+
Polygon create_curve (
|
177
|
+
const Point* points, size_t size,
|
178
|
+
bool loop = false);
|
179
|
+
|
180
|
+
|
181
|
+
Polygon create_bezier (
|
182
|
+
coord x1, coord y1, coord x2, coord y2,
|
183
|
+
coord x3, coord y3, coord x4, coord y4,
|
184
|
+
bool loop = false);
|
185
|
+
|
186
|
+
Polygon create_bezier (
|
187
|
+
const Point& p1, const Point& p2, const Point& p3, const Point& p4,
|
188
|
+
bool loop = false);
|
189
|
+
|
190
|
+
Polygon create_bezier (
|
191
|
+
const Point* points, size_t size,
|
192
|
+
bool loop = false);
|
193
|
+
|
194
|
+
|
161
195
|
}// Rays
|
162
196
|
|
163
197
|
|
data/include/rays/polyline.h
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
|
7
7
|
#include <vector>
|
8
8
|
#include <xot/pimpl.h>
|
9
|
+
#include <rays/defs.h>
|
9
10
|
#include <rays/point.h>
|
10
11
|
#include <rays/bounds.h>
|
11
12
|
|
@@ -32,7 +33,12 @@ namespace Rays
|
|
32
33
|
|
33
34
|
~Polyline ();
|
34
35
|
|
35
|
-
bool expand (
|
36
|
+
bool expand (
|
37
|
+
Polygon* result,
|
38
|
+
coord width,
|
39
|
+
CapType cap = CAP_DEFAULT,
|
40
|
+
JoinType join = JOIN_DEFAULT,
|
41
|
+
coord miter_limit = JOIN_DEFAULT_MITER_LIMIT) const;
|
36
42
|
|
37
43
|
Bounds bounds () const;
|
38
44
|
|
data/include/rays/ruby/rays.h
CHANGED
@@ -4,7 +4,10 @@
|
|
4
4
|
#define __RAYS_RUBY_RAYS_H__
|
5
5
|
|
6
6
|
|
7
|
+
#include <rucy/rucy.h>
|
7
8
|
#include <rucy/module.h>
|
9
|
+
#include <rucy/extension.h>
|
10
|
+
#include <rays/rays.h>
|
8
11
|
|
9
12
|
|
10
13
|
namespace Rays
|
@@ -18,4 +21,9 @@ namespace Rays
|
|
18
21
|
}// Rays
|
19
22
|
|
20
23
|
|
24
|
+
RUCY_DECLARE_VALUE_OR_ARRAY_TO(Rays::CapType)
|
25
|
+
|
26
|
+
RUCY_DECLARE_VALUE_OR_ARRAY_TO(Rays::JoinType)
|
27
|
+
|
28
|
+
|
21
29
|
#endif//EOH
|
data/lib/rays/image.rb
CHANGED
data/lib/rays/painter.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
3
|
|
4
|
+
require 'xot/const_symbol_accessor'
|
4
5
|
require 'xot/universal_accessor'
|
5
6
|
require 'xot/block_util'
|
6
7
|
require 'rays/ext'
|
@@ -73,6 +74,14 @@ module Rays
|
|
73
74
|
draw_ellipse args, center, radius, hole, from, to
|
74
75
|
end
|
75
76
|
|
77
|
+
def curve (*args, loop: false)
|
78
|
+
draw_curve args, loop
|
79
|
+
end
|
80
|
+
|
81
|
+
def bezier (*args, loop: false)
|
82
|
+
draw_bezier args, loop
|
83
|
+
end
|
84
|
+
|
76
85
|
def color= (fill, stroke = nil)
|
77
86
|
self.fill fill
|
78
87
|
self.stroke stroke
|
@@ -87,8 +96,21 @@ module Rays
|
|
87
96
|
set_shader shader
|
88
97
|
end
|
89
98
|
|
99
|
+
const_symbol_accessor :stroke_cap, {
|
100
|
+
butt: CAP_BUTT,
|
101
|
+
round: CAP_ROUND,
|
102
|
+
square: CAP_SQUARE
|
103
|
+
}
|
104
|
+
|
105
|
+
const_symbol_accessor :stroke_join, {
|
106
|
+
miter: JOIN_MITER,
|
107
|
+
round: JOIN_ROUND,
|
108
|
+
square: JOIN_SQUARE
|
109
|
+
}
|
110
|
+
|
90
111
|
universal_accessor :background, :fill, :stroke, :color,
|
91
|
-
:stroke_width, :
|
112
|
+
:stroke_width, :stroke_cap, :stroke_join, :miter_limit,
|
113
|
+
:nsegment, :shader, :clip, :font
|
92
114
|
|
93
115
|
private
|
94
116
|
|
data/lib/rays/polygon.rb
CHANGED
@@ -44,6 +44,14 @@ module Rays
|
|
44
44
|
create_ellipse args, center, radius, hole, from, to, nsegment
|
45
45
|
end
|
46
46
|
|
47
|
+
def self.curve (*args, loop: false)
|
48
|
+
create_curve args, loop
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.bezier (*args, loop: false)
|
52
|
+
create_bezier args, loop
|
53
|
+
end
|
54
|
+
|
47
55
|
end# Polygon
|
48
56
|
|
49
57
|
|
data/src/color_space.cpp
CHANGED
@@ -55,7 +55,7 @@ namespace Rays
|
|
55
55
|
32, 32, 32, // RGB(A) float
|
56
56
|
32, 32, 32, // BGR(A) float
|
57
57
|
};
|
58
|
-
if (type_ < 0 ||
|
58
|
+
if (type_ < 0 || COLORSPACE_MAX <= type_) return BPPS[COLORSPACE_UNKNOWN];
|
59
59
|
return BPPS[type_];
|
60
60
|
}
|
61
61
|
|
@@ -78,7 +78,7 @@ namespace Rays
|
|
78
78
|
96, 128, 128, // RGB(A) float
|
79
79
|
96, 128, 128, // BGR(A) float
|
80
80
|
};
|
81
|
-
if (type_ < 0 ||
|
81
|
+
if (type_ < 0 || COLORSPACE_MAX <= type_) return BPPS[COLORSPACE_UNKNOWN];
|
82
82
|
return BPPS[type_];
|
83
83
|
}
|
84
84
|
|
data/src/ios/bitmap.mm
CHANGED
@@ -27,14 +27,14 @@ namespace Rays
|
|
27
27
|
if (cs.is_alpha_first())
|
28
28
|
{
|
29
29
|
info |= cs.is_premult()
|
30
|
-
?
|
31
|
-
:
|
30
|
+
? kCGImageAlphaPremultipliedFirst
|
31
|
+
: kCGImageAlphaFirst;
|
32
32
|
}
|
33
33
|
else if (cs.is_alpha_last())
|
34
34
|
{
|
35
35
|
info |= cs.is_premult()
|
36
|
-
?
|
37
|
-
:
|
36
|
+
? kCGImageAlphaPremultipliedLast
|
37
|
+
: kCGImageAlphaLast;
|
38
38
|
}
|
39
39
|
else if (cs.is_skip_first())
|
40
40
|
info |= kCGImageAlphaNoneSkipFirst;
|
data/src/ios/font.mm
CHANGED
@@ -72,8 +72,8 @@ namespace Rays
|
|
72
72
|
RawFont::RawFont (const char* name, coord size)
|
73
73
|
{
|
74
74
|
self->font = name
|
75
|
-
?
|
76
|
-
:
|
75
|
+
? CTFontCreateWithName(cfstring(name).get(), size, NULL)
|
76
|
+
: CTFontCreateUIFontForLanguage(kCTFontSystemFontType, size, NULL);
|
77
77
|
}
|
78
78
|
|
79
79
|
RawFont::~RawFont ()
|
data/src/osx/bitmap.mm
CHANGED
@@ -26,14 +26,14 @@ namespace Rays
|
|
26
26
|
if (cs.is_alpha_first())
|
27
27
|
{
|
28
28
|
info |= cs.is_premult()
|
29
|
-
?
|
30
|
-
:
|
29
|
+
? kCGImageAlphaPremultipliedFirst
|
30
|
+
: kCGImageAlphaFirst;
|
31
31
|
}
|
32
32
|
else if (cs.is_alpha_last())
|
33
33
|
{
|
34
34
|
info |= cs.is_premult()
|
35
|
-
?
|
36
|
-
:
|
35
|
+
? kCGImageAlphaPremultipliedLast
|
36
|
+
: kCGImageAlphaLast;
|
37
37
|
}
|
38
38
|
else if (cs.is_skip_first())
|
39
39
|
info |= kCGImageAlphaNoneSkipFirst;
|
data/src/osx/font.mm
CHANGED
@@ -71,8 +71,8 @@ namespace Rays
|
|
71
71
|
RawFont::RawFont (const char* name, coord size)
|
72
72
|
{
|
73
73
|
self->font = name
|
74
|
-
?
|
75
|
-
:
|
74
|
+
? CTFontCreateWithName(cfstring(name).get(), size, NULL)
|
75
|
+
: CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, size, NULL);
|
76
76
|
}
|
77
77
|
|
78
78
|
RawFont::~RawFont ()
|
data/src/painter.cpp
CHANGED
@@ -48,6 +48,12 @@ namespace Rays
|
|
48
48
|
|
49
49
|
coord stroke_width;
|
50
50
|
|
51
|
+
CapType stroke_cap;
|
52
|
+
|
53
|
+
JoinType stroke_join;
|
54
|
+
|
55
|
+
coord miter_limit;
|
56
|
+
|
51
57
|
uint nsegment;
|
52
58
|
|
53
59
|
Bounds clip;
|
@@ -62,6 +68,9 @@ namespace Rays
|
|
62
68
|
colors[FILL] .reset(1, 1);
|
63
69
|
colors[STROKE] .reset(1, 0);
|
64
70
|
stroke_width = 0;
|
71
|
+
stroke_cap = CAP_DEFAULT;
|
72
|
+
stroke_join = JOIN_DEFAULT;
|
73
|
+
miter_limit = JOIN_DEFAULT_MITER_LIMIT;
|
65
74
|
nsegment = 0;
|
66
75
|
clip .reset(-1);
|
67
76
|
font = default_font();
|
@@ -641,6 +650,11 @@ namespace Rays
|
|
641
650
|
|
642
651
|
self->opengl_state.push();
|
643
652
|
|
653
|
+
//glEnable(GL_CULL_FACE);
|
654
|
+
glEnable(GL_BLEND);
|
655
|
+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
656
|
+
OpenGL_check_error(__FILE__, __LINE__);
|
657
|
+
|
644
658
|
FrameBuffer& fb = self->frame_buffer;
|
645
659
|
if (fb) FrameBuffer_bind(fb.id());
|
646
660
|
|
@@ -649,6 +663,7 @@ namespace Rays
|
|
649
663
|
glViewport(
|
650
664
|
(int) (vp.x * density), (int) (vp.y * density),
|
651
665
|
(int) (vp.width * density), (int) (vp.height * density));
|
666
|
+
OpenGL_check_error(__FILE__, __LINE__);
|
652
667
|
|
653
668
|
coord x1 = vp.x, x2 = vp.x + vp.width;
|
654
669
|
coord y1 = vp.y, y2 = vp.y + vp.height;
|
@@ -656,20 +671,13 @@ namespace Rays
|
|
656
671
|
if (z1 == 0 && z2 == 0) {z1 = -100; z2 = 200;}
|
657
672
|
if (!fb) std::swap(y1, y2);
|
658
673
|
|
659
|
-
self->state.init();
|
660
|
-
|
661
674
|
self->position_matrix.reset(1);
|
662
675
|
self->position_matrix *= to_rays(glm::ortho(x1, x2, y1, y2));
|
663
676
|
//self->position_matrix.translate(0.375f, 0.375f);
|
664
677
|
|
665
|
-
|
666
|
-
glEnable(GL_BLEND);
|
667
|
-
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
668
|
-
OpenGL_check_error(__FILE__, __LINE__);
|
678
|
+
self->update_clip();
|
669
679
|
|
670
680
|
self->painting = true;
|
671
|
-
|
672
|
-
no_clip();
|
673
681
|
}
|
674
682
|
|
675
683
|
void
|
@@ -847,6 +855,52 @@ namespace Rays
|
|
847
855
|
center, radius, hole_radius, angle_from, angle_to, nsegment()));
|
848
856
|
}
|
849
857
|
|
858
|
+
void
|
859
|
+
Painter::curve (
|
860
|
+
coord x1, coord y1, coord x2, coord y2,
|
861
|
+
coord x3, coord y3, coord x4, coord y4,
|
862
|
+
bool loop)
|
863
|
+
{
|
864
|
+
polygon(create_curve(x1, y1, x2, y2, x3, y3, x4, y4, loop));
|
865
|
+
}
|
866
|
+
|
867
|
+
void
|
868
|
+
Painter::curve (
|
869
|
+
const Point& p1, const Point& p2, const Point& p3, const Point& p4,
|
870
|
+
bool loop)
|
871
|
+
{
|
872
|
+
polygon(create_curve(p1, p2, p3, p4, loop));
|
873
|
+
}
|
874
|
+
|
875
|
+
void
|
876
|
+
Painter::curve (const Point* points, size_t size, bool loop)
|
877
|
+
{
|
878
|
+
polygon(create_curve(points, size, loop));
|
879
|
+
}
|
880
|
+
|
881
|
+
void
|
882
|
+
Painter::bezier (
|
883
|
+
coord x1, coord y1, coord x2, coord y2,
|
884
|
+
coord x3, coord y3, coord x4, coord y4,
|
885
|
+
bool loop)
|
886
|
+
{
|
887
|
+
polygon(create_bezier(x1, y1, x2, y2, x3, y3, x4, y4, loop));
|
888
|
+
}
|
889
|
+
|
890
|
+
void
|
891
|
+
Painter::bezier (
|
892
|
+
const Point& p1, const Point& p2, const Point& p3, const Point& p4,
|
893
|
+
bool loop)
|
894
|
+
{
|
895
|
+
polygon(create_bezier(p1, p2, p3, p4, loop));
|
896
|
+
}
|
897
|
+
|
898
|
+
void
|
899
|
+
Painter::bezier (const Point* points, size_t size, bool loop)
|
900
|
+
{
|
901
|
+
polygon(create_bezier(points, size, loop));
|
902
|
+
}
|
903
|
+
|
850
904
|
static void
|
851
905
|
draw_image (
|
852
906
|
Painter* painter, const Image& image,
|
@@ -1202,6 +1256,42 @@ namespace Rays
|
|
1202
1256
|
return self->state.stroke_width;
|
1203
1257
|
}
|
1204
1258
|
|
1259
|
+
void
|
1260
|
+
Painter::set_stroke_cap (CapType cap)
|
1261
|
+
{
|
1262
|
+
self->state.stroke_cap = cap;
|
1263
|
+
}
|
1264
|
+
|
1265
|
+
CapType
|
1266
|
+
Painter::stroke_cap () const
|
1267
|
+
{
|
1268
|
+
return self->state.stroke_cap;
|
1269
|
+
}
|
1270
|
+
|
1271
|
+
void
|
1272
|
+
Painter::set_stroke_join (JoinType join)
|
1273
|
+
{
|
1274
|
+
self->state.stroke_join = join;
|
1275
|
+
}
|
1276
|
+
|
1277
|
+
JoinType
|
1278
|
+
Painter::stroke_join () const
|
1279
|
+
{
|
1280
|
+
return self->state.stroke_join;
|
1281
|
+
}
|
1282
|
+
|
1283
|
+
void
|
1284
|
+
Painter::set_miter_limit (coord limit)
|
1285
|
+
{
|
1286
|
+
self->state.miter_limit = limit;
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
coord
|
1290
|
+
Painter::miter_limit () const
|
1291
|
+
{
|
1292
|
+
return self->state.miter_limit;
|
1293
|
+
}
|
1294
|
+
|
1205
1295
|
void
|
1206
1296
|
Painter::set_nsegment (int nsegment)
|
1207
1297
|
{
|
@@ -1279,7 +1369,7 @@ namespace Rays
|
|
1279
1369
|
void
|
1280
1370
|
Painter::push_state ()
|
1281
1371
|
{
|
1282
|
-
self->state_stack.
|
1372
|
+
self->state_stack.emplace_back(self->state);
|
1283
1373
|
}
|
1284
1374
|
|
1285
1375
|
void
|
@@ -1370,7 +1460,7 @@ namespace Rays
|
|
1370
1460
|
void
|
1371
1461
|
Painter::push_matrix ()
|
1372
1462
|
{
|
1373
|
-
self->position_matrix_stack.
|
1463
|
+
self->position_matrix_stack.emplace_back(self->position_matrix);
|
1374
1464
|
}
|
1375
1465
|
|
1376
1466
|
void
|
data/src/polygon.cpp
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
#include <assert.h>
|
6
6
|
#include <utility>
|
7
7
|
#include <poly2tri.h>
|
8
|
+
#include <Splines.h>
|
8
9
|
#include "xot/util.h"
|
9
10
|
#include "rays/color.h"
|
10
11
|
#include "rays/exception.h"
|
@@ -13,7 +14,7 @@
|
|
13
14
|
#include "painter.h"
|
14
15
|
|
15
16
|
|
16
|
-
|
17
|
+
namespace clip = ClipperLib;
|
17
18
|
|
18
19
|
|
19
20
|
namespace Rays
|
@@ -155,6 +156,10 @@ namespace Rays
|
|
155
156
|
|
156
157
|
if (!polygon || polygon.empty()) return;
|
157
158
|
|
159
|
+
CapType cap = painter->stroke_cap();
|
160
|
+
JoinType join = painter->stroke_join();
|
161
|
+
coord ml = painter->miter_limit();
|
162
|
+
|
158
163
|
bool has_loop = false;
|
159
164
|
for (const auto& polyline : polygon)
|
160
165
|
{
|
@@ -168,7 +173,7 @@ namespace Rays
|
|
168
173
|
}
|
169
174
|
|
170
175
|
Polygon stroke;
|
171
|
-
if (!polyline.expand(&stroke, stroke_width / 2))
|
176
|
+
if (!polyline.expand(&stroke, stroke_width / 2, cap, join, ml))
|
172
177
|
continue;
|
173
178
|
|
174
179
|
Polygon_fill(stroke, painter, color);
|
@@ -177,7 +182,7 @@ namespace Rays
|
|
177
182
|
if (has_loop)
|
178
183
|
{
|
179
184
|
Polygon hole;
|
180
|
-
if (polygon.expand(&hole, -stroke_width))
|
185
|
+
if (polygon.expand(&hole, -stroke_width, cap, join, ml))
|
181
186
|
Polygon_fill(polygon - hole, painter, color);
|
182
187
|
}
|
183
188
|
}
|
@@ -251,11 +256,11 @@ namespace Rays
|
|
251
256
|
|
252
257
|
static void
|
253
258
|
add_polygon_to_clipper (
|
254
|
-
Clipper* clipper, const Polygon& polygon, PolyType type)
|
259
|
+
clip::Clipper* clipper, const Polygon& polygon, clip::PolyType type)
|
255
260
|
{
|
256
261
|
assert(clipper);
|
257
262
|
|
258
|
-
Path path;
|
263
|
+
clip::Path path;
|
259
264
|
for (const auto& line : polygon)
|
260
265
|
{
|
261
266
|
if (!line) continue;
|
@@ -267,42 +272,68 @@ namespace Rays
|
|
267
272
|
}
|
268
273
|
}
|
269
274
|
|
270
|
-
static
|
271
|
-
|
275
|
+
static clip::JoinType
|
276
|
+
get_join_type (JoinType join)
|
277
|
+
{
|
278
|
+
switch (join)
|
279
|
+
{
|
280
|
+
case JOIN_MITER: return clip::jtMiter;
|
281
|
+
case JOIN_ROUND: return clip::jtRound;
|
282
|
+
case JOIN_SQUARE: return clip::jtSquare;
|
283
|
+
}
|
284
|
+
|
285
|
+
argument_error(__FILE__, __LINE__);
|
286
|
+
}
|
287
|
+
|
288
|
+
static clip::EndType
|
289
|
+
get_end_type (const Polyline& polyline, CapType cap, bool fill)
|
272
290
|
{
|
273
291
|
if (polyline.loop())
|
274
|
-
return fill ? etClosedPolygon : etClosedLine;
|
275
|
-
else
|
276
|
-
|
292
|
+
return fill ? clip::etClosedPolygon : clip::etClosedLine;
|
293
|
+
else switch (cap)
|
294
|
+
{
|
295
|
+
case CAP_BUTT: return clip::etOpenButt;
|
296
|
+
case CAP_ROUND: return clip::etOpenRound;
|
297
|
+
case CAP_SQUARE: return clip::etOpenSquare;
|
298
|
+
}
|
299
|
+
|
300
|
+
argument_error(__FILE__, __LINE__);
|
277
301
|
}
|
278
302
|
|
279
303
|
static bool
|
280
304
|
add_polyline_to_offsetter (
|
281
|
-
ClipperOffset* offsetter, const Polyline& polyline,
|
305
|
+
clip::ClipperOffset* offsetter, const Polyline& polyline,
|
306
|
+
CapType cap, JoinType join, bool hole, bool fill)
|
282
307
|
{
|
283
308
|
assert(offsetter);
|
284
309
|
|
285
310
|
if (!polyline) return false;
|
286
311
|
|
287
|
-
Path path;
|
312
|
+
clip::Path path;
|
288
313
|
Polyline_get_path(&path, polyline, hole);
|
289
|
-
offsetter->AddPath(
|
314
|
+
offsetter->AddPath(
|
315
|
+
path, get_join_type(join), get_end_type(polyline, cap, fill));
|
290
316
|
return true;
|
291
317
|
}
|
292
318
|
|
293
319
|
static bool
|
294
|
-
add_polygon_to_offsetter (
|
320
|
+
add_polygon_to_offsetter (
|
321
|
+
clip::ClipperOffset* offsetter, const Polygon& polygon,
|
322
|
+
CapType cap, JoinType join)
|
295
323
|
{
|
296
324
|
assert(offsetter);
|
297
325
|
|
298
326
|
bool added = false;
|
299
327
|
for (const auto& line : polygon.self->lines)
|
300
|
-
|
328
|
+
{
|
329
|
+
added |= add_polyline_to_offsetter(
|
330
|
+
offsetter, line, cap, join, line.hole(), true);
|
331
|
+
}
|
301
332
|
return added;
|
302
333
|
}
|
303
334
|
|
304
335
|
static bool
|
305
|
-
append_outline (Polygon* polygon, const PolyNode& node)
|
336
|
+
append_outline (Polygon* polygon, const clip::PolyNode& node)
|
306
337
|
{
|
307
338
|
assert(polygon);
|
308
339
|
|
@@ -319,7 +350,7 @@ namespace Rays
|
|
319
350
|
}
|
320
351
|
|
321
352
|
static void
|
322
|
-
append_hole (Polygon* polygon, const PolyNode& node)
|
353
|
+
append_hole (Polygon* polygon, const clip::PolyNode& node)
|
323
354
|
{
|
324
355
|
assert(polygon);
|
325
356
|
|
@@ -338,7 +369,7 @@ namespace Rays
|
|
338
369
|
}
|
339
370
|
|
340
371
|
static void
|
341
|
-
get_polygon (Polygon* polygon, const PolyNode& node)
|
372
|
+
get_polygon (Polygon* polygon, const clip::PolyNode& node)
|
342
373
|
{
|
343
374
|
assert(polygon);
|
344
375
|
|
@@ -350,15 +381,16 @@ namespace Rays
|
|
350
381
|
}
|
351
382
|
|
352
383
|
static Polygon
|
353
|
-
clip_polygons (
|
384
|
+
clip_polygons (
|
385
|
+
const Polygon& subject, const Polygon& clip, clip::ClipType type)
|
354
386
|
{
|
355
|
-
Clipper c;
|
387
|
+
clip::Clipper c;
|
356
388
|
c.StrictlySimple(true);
|
357
389
|
|
358
|
-
add_polygon_to_clipper(&c, subject, ptSubject);
|
359
|
-
add_polygon_to_clipper(&c, clip, ptClip);
|
390
|
+
add_polygon_to_clipper(&c, subject, clip::ptSubject);
|
391
|
+
add_polygon_to_clipper(&c, clip, clip::ptClip);
|
360
392
|
|
361
|
-
PolyTree tree;
|
393
|
+
clip::PolyTree tree;
|
362
394
|
c.Execute(type, tree);
|
363
395
|
assert(tree.Contour.empty());
|
364
396
|
|
@@ -369,16 +401,19 @@ namespace Rays
|
|
369
401
|
}
|
370
402
|
|
371
403
|
static bool
|
372
|
-
expand_polygon (
|
404
|
+
expand_polygon (
|
405
|
+
Polygon* result, const Polygon& polygon,
|
406
|
+
coord width, CapType cap, JoinType join, coord miter_limit)
|
373
407
|
{
|
374
408
|
if (width == 0)
|
375
409
|
return false;
|
376
410
|
|
377
|
-
ClipperOffset co;
|
378
|
-
|
411
|
+
clip::ClipperOffset co;
|
412
|
+
co.MiterLimit = miter_limit;
|
413
|
+
if (!add_polygon_to_offsetter(&co, polygon, cap, join))
|
379
414
|
return false;
|
380
415
|
|
381
|
-
PolyTree tree;
|
416
|
+
clip::PolyTree tree;
|
382
417
|
co.Execute(tree, to_clipper(width));
|
383
418
|
assert(tree.Contour.empty());
|
384
419
|
|
@@ -387,16 +422,19 @@ namespace Rays
|
|
387
422
|
}
|
388
423
|
|
389
424
|
bool
|
390
|
-
Polyline_expand (
|
425
|
+
Polyline_expand (
|
426
|
+
Polygon* result, const Polyline& polyline,
|
427
|
+
coord width, CapType cap, JoinType join, coord miter_limit)
|
391
428
|
{
|
392
429
|
if (width == 0)
|
393
430
|
return false;
|
394
431
|
|
395
|
-
ClipperOffset co;
|
396
|
-
|
432
|
+
clip::ClipperOffset co;
|
433
|
+
co.MiterLimit = miter_limit;
|
434
|
+
if (!add_polyline_to_offsetter(&co, polyline, cap, join, false, false))
|
397
435
|
return false;
|
398
436
|
|
399
|
-
PolyTree tree;
|
437
|
+
clip::PolyTree tree;
|
400
438
|
co.Execute(tree, to_clipper(width));
|
401
439
|
assert(tree.Contour.empty());
|
402
440
|
|
@@ -865,6 +903,128 @@ namespace Rays
|
|
865
903
|
hole_radius * 2, angle_from, angle_to, nsegment);
|
866
904
|
}
|
867
905
|
|
906
|
+
static inline const SplineLib::Vec3f&
|
907
|
+
to_splinelib (const Point& val)
|
908
|
+
{
|
909
|
+
return *(const SplineLib::Vec3f*) &val;
|
910
|
+
}
|
911
|
+
|
912
|
+
static inline const Point&
|
913
|
+
to_rays (const SplineLib::Vec3f& val)
|
914
|
+
{
|
915
|
+
return *(const Point*) &val;
|
916
|
+
}
|
917
|
+
|
918
|
+
enum SplineType {BEZIER, HERMITE, CATMULLROM};
|
919
|
+
|
920
|
+
typedef SplineLib::cSpline3 (*SplineFun) (
|
921
|
+
const SplineLib::Vec3f&, const SplineLib::Vec3f&,
|
922
|
+
const SplineLib::Vec3f&, const SplineLib::Vec3f&);
|
923
|
+
|
924
|
+
static SplineFun
|
925
|
+
get_spline_fun (SplineType type)
|
926
|
+
{
|
927
|
+
switch (type)
|
928
|
+
{
|
929
|
+
case BEZIER: return SplineLib::BezierSpline;
|
930
|
+
case HERMITE: return SplineLib::HermiteSpline;
|
931
|
+
case CATMULLROM: return SplineLib::CatmullRomSpline;
|
932
|
+
default:
|
933
|
+
argument_error(__FILE__, __LINE__, "unknown spline type %d.", type);
|
934
|
+
}
|
935
|
+
}
|
936
|
+
|
937
|
+
static Polygon
|
938
|
+
create_spline (
|
939
|
+
SplineType type,
|
940
|
+
const Point* points, size_t size, bool loop,
|
941
|
+
uint nsegment = 16)
|
942
|
+
{
|
943
|
+
if (size % 4 != 0)
|
944
|
+
argument_error(__FILE__, __LINE__);
|
945
|
+
|
946
|
+
size_t count = size / 4;
|
947
|
+
auto spline_fun = get_spline_fun(type);
|
948
|
+
|
949
|
+
std::vector<Point> result;
|
950
|
+
result.reserve(nsegment * count);
|
951
|
+
for (size_t i = 0; i < count; ++i)
|
952
|
+
{
|
953
|
+
SplineLib::cSpline3 spline = spline_fun(
|
954
|
+
to_splinelib(points[i * 4 + 0]),
|
955
|
+
to_splinelib(points[i * 4 + 1]),
|
956
|
+
to_splinelib(points[i * 4 + 2]),
|
957
|
+
to_splinelib(points[i * 4 + 3]));
|
958
|
+
for (uint j = 0; j <= nsegment; ++j)
|
959
|
+
{
|
960
|
+
float t = (float) j / nsegment;
|
961
|
+
result.emplace_back(to_rays(SplineLib::Position(spline, t)));
|
962
|
+
}
|
963
|
+
}
|
964
|
+
|
965
|
+
return create_line(&result[0], result.size(), loop);
|
966
|
+
}
|
967
|
+
|
968
|
+
Polygon
|
969
|
+
create_curve (
|
970
|
+
coord x1, coord y1, coord x2, coord y2,
|
971
|
+
coord x3, coord y3, coord x4, coord y4,
|
972
|
+
bool loop)
|
973
|
+
{
|
974
|
+
const Point points[] = {
|
975
|
+
Point(x1, y1),
|
976
|
+
Point(x2, y2),
|
977
|
+
Point(x3, y3),
|
978
|
+
Point(x4, y4)
|
979
|
+
};
|
980
|
+
return create_spline(CATMULLROM, points, 4, loop);
|
981
|
+
}
|
982
|
+
|
983
|
+
Polygon
|
984
|
+
create_curve (
|
985
|
+
const Point& p1, const Point& p2, const Point& p3, const Point& p4,
|
986
|
+
bool loop)
|
987
|
+
{
|
988
|
+
const Point points[] = {p1, p2, p3, p4};
|
989
|
+
return create_spline(CATMULLROM, points, 4, loop);
|
990
|
+
}
|
991
|
+
|
992
|
+
Polygon
|
993
|
+
create_curve (const Point* points, size_t size, bool loop)
|
994
|
+
{
|
995
|
+
return create_spline(CATMULLROM, points, size, loop);
|
996
|
+
}
|
997
|
+
|
998
|
+
Polygon
|
999
|
+
create_bezier (
|
1000
|
+
coord x1, coord y1, coord x2, coord y2,
|
1001
|
+
coord x3, coord y3, coord x4, coord y4,
|
1002
|
+
bool loop)
|
1003
|
+
{
|
1004
|
+
const Point points[] = {
|
1005
|
+
Point(x1, y1),
|
1006
|
+
Point(x2, y2),
|
1007
|
+
Point(x3, y3),
|
1008
|
+
Point(x4, y4)
|
1009
|
+
};
|
1010
|
+
return create_spline(BEZIER, points, 4, loop);
|
1011
|
+
}
|
1012
|
+
|
1013
|
+
Polygon
|
1014
|
+
create_bezier (
|
1015
|
+
const Point& p1, const Point& p2, const Point& p3, const Point& p4,
|
1016
|
+
bool loop)
|
1017
|
+
{
|
1018
|
+
const Point points[] = {p1, p2, p3, p4};
|
1019
|
+
return create_spline(BEZIER, points, 4, loop);
|
1020
|
+
}
|
1021
|
+
|
1022
|
+
Polygon
|
1023
|
+
create_bezier (const Point* points, size_t size, bool loop)
|
1024
|
+
{
|
1025
|
+
return create_spline(BEZIER, points, size, loop);
|
1026
|
+
}
|
1027
|
+
|
868
1028
|
void
|
869
1029
|
Polygon_fill (const Polygon& polygon, Painter* painter, const Color& color)
|
870
1030
|
{
|
@@ -935,9 +1095,11 @@ namespace Rays
|
|
935
1095
|
}
|
936
1096
|
|
937
1097
|
bool
|
938
|
-
Polygon::expand (
|
1098
|
+
Polygon::expand (
|
1099
|
+
Polygon* result,
|
1100
|
+
coord width, CapType cap, JoinType join, coord miter_limit) const
|
939
1101
|
{
|
940
|
-
return expand_polygon(result, *this, width);
|
1102
|
+
return expand_polygon(result, *this, width, cap, join, miter_limit);
|
941
1103
|
}
|
942
1104
|
|
943
1105
|
Bounds
|
@@ -1029,7 +1191,7 @@ namespace Rays
|
|
1029
1191
|
{
|
1030
1192
|
if (lhs.self == rhs.self) return Polygon();
|
1031
1193
|
|
1032
|
-
return clip_polygons(lhs, rhs, ctDifference);
|
1194
|
+
return clip_polygons(lhs, rhs, clip::ctDifference);
|
1033
1195
|
}
|
1034
1196
|
|
1035
1197
|
Polygon
|
@@ -1037,7 +1199,7 @@ namespace Rays
|
|
1037
1199
|
{
|
1038
1200
|
if (lhs.self == rhs.self) return lhs;
|
1039
1201
|
|
1040
|
-
return clip_polygons(lhs, rhs, ctIntersection);
|
1202
|
+
return clip_polygons(lhs, rhs, clip::ctIntersection);
|
1041
1203
|
}
|
1042
1204
|
|
1043
1205
|
Polygon
|
@@ -1045,7 +1207,7 @@ namespace Rays
|
|
1045
1207
|
{
|
1046
1208
|
if (lhs.self == rhs.self) return lhs;
|
1047
1209
|
|
1048
|
-
return clip_polygons(lhs, rhs, ctUnion);
|
1210
|
+
return clip_polygons(lhs, rhs, clip::ctUnion);
|
1049
1211
|
}
|
1050
1212
|
|
1051
1213
|
Polygon
|
@@ -1053,7 +1215,7 @@ namespace Rays
|
|
1053
1215
|
{
|
1054
1216
|
if (lhs.self == rhs.self) return Polygon();
|
1055
1217
|
|
1056
|
-
return clip_polygons(lhs, rhs, ctXor);
|
1218
|
+
return clip_polygons(lhs, rhs, clip::ctXor);
|
1057
1219
|
}
|
1058
1220
|
|
1059
1221
|
|