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.
@@ -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 (Polygon* result, coord width) const;
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
 
@@ -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 (Polygon* result, coord width) const;
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
 
@@ -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
@@ -24,7 +24,7 @@ module Rays
24
24
  end
25
25
 
26
26
  def bounds ()
27
- Bounds.new 0, 0, *size
27
+ Bounds.new 0, 0, width, height
28
28
  end
29
29
 
30
30
  end# Image
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, :nsegment, :shader, :clip, :font
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 || COLORSPACE_LAST <= type_) return BPPS[COLORSPACE_UNKNOWN];
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 || COLORSPACE_LAST <= type_) return BPPS[COLORSPACE_UNKNOWN];
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
- ? kCGImageAlphaPremultipliedFirst
31
- : kCGImageAlphaFirst;
30
+ ? kCGImageAlphaPremultipliedFirst
31
+ : kCGImageAlphaFirst;
32
32
  }
33
33
  else if (cs.is_alpha_last())
34
34
  {
35
35
  info |= cs.is_premult()
36
- ? kCGImageAlphaPremultipliedLast
37
- : kCGImageAlphaLast;
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
- ? CTFontCreateWithName(cfstring(name).get(), size, NULL)
76
- : CTFontCreateUIFontForLanguage(kCTFontSystemFontType, size, NULL);
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
- ? kCGImageAlphaPremultipliedFirst
30
- : kCGImageAlphaFirst;
29
+ ? kCGImageAlphaPremultipliedFirst
30
+ : kCGImageAlphaFirst;
31
31
  }
32
32
  else if (cs.is_alpha_last())
33
33
  {
34
34
  info |= cs.is_premult()
35
- ? kCGImageAlphaPremultipliedLast
36
- : kCGImageAlphaLast;
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
- ? CTFontCreateWithName(cfstring(name).get(), size, NULL)
75
- : CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, size, NULL);
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
- //glEnable(GL_CULL_FACE);
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.push_back(self->state);
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.push_back(self->position_matrix);
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
- using namespace ClipperLib;
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 EndType
271
- get_end_type (const Polyline& polyline, bool fill)
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
- return etOpenButt;
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, bool hole, bool fill)
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(path, jtMiter, get_end_type(polyline, fill));
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 (ClipperOffset* offsetter, const Polygon& polygon)
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
- added |= add_polyline_to_offsetter(offsetter, line, line.hole(), true);
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 (const Polygon& subject, const Polygon& clip, ClipType type)
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 (Polygon* result, const Polygon& polygon, coord width)
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
- if (!add_polygon_to_offsetter(&co, polygon))
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 (Polygon* result, const Polyline& polyline, coord width)
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
- if (!add_polyline_to_offsetter(&co, polyline, false, false))
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 (Polygon* result, coord width) const
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