rays 0.1.14 → 0.1.15
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 +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
|
|