@@ -15,6 +15,7 @@ namespace SixLabors.Shapes
15
15
/// </summary>
16
16
public static class Outliner
17
17
{
18
+ private const double MiterOffsetDelta = 20 ;
18
19
private const float ScalingFactor = 1000.0f ;
19
20
20
21
/// <summary>
@@ -59,15 +60,34 @@ public static IPath GenerateOutline(this IPath path, float width, float[] patter
59
60
/// <param name="startOff">Weather the first item in the pattern is on or off.</param>
60
61
/// <returns>A new path representing the outline.</returns>
61
62
public static IPath GenerateOutline ( this IPath path , float width , ReadOnlySpan < float > pattern , bool startOff )
63
+ => GenerateOutline ( path , width , pattern , startOff , JointStyle . Square , EndCapStyle . Butt ) ;
64
+
65
+ /// <summary>
66
+ /// Generates a outline of the path with alternating on and off segments based on the pattern.
67
+ /// </summary>
68
+ /// <param name="path">the path to outline</param>
69
+ /// <param name="width">The final width outline</param>
70
+ /// <param name="pattern">The pattern made of multiples of the width.</param>
71
+ /// <param name="startOff">Weather the first item in the pattern is on or off.</param>
72
+ /// <param name="jointStyle">The style to render the joints.</param>
73
+ /// <param name="patternSectionCapStyle">The style to render between sections of the specified pattern.</param>
74
+ /// <returns>A new path representing the outline.</returns>
75
+ public static IPath GenerateOutline ( this IPath path , float width , ReadOnlySpan < float > pattern , bool startOff , JointStyle jointStyle = JointStyle . Square , EndCapStyle patternSectionCapStyle = EndCapStyle . Butt )
62
76
{
63
77
if ( pattern . Length < 2 )
64
78
{
65
79
return path . GenerateOutline ( width ) ;
66
80
}
67
81
82
+ var style = Convert ( jointStyle ) ;
83
+ var patternSectionCap = Convert ( patternSectionCapStyle ) ;
84
+
68
85
IEnumerable < ISimplePath > paths = path . Flatten ( ) ;
69
86
70
- var offset = new ClipperOffset ( ) ;
87
+ var offset = new ClipperOffset ( )
88
+ {
89
+ MiterLimit = MiterOffsetDelta
90
+ } ;
71
91
72
92
var buffer = new List < IntPoint > ( 3 ) ;
73
93
foreach ( ISimplePath p in paths )
@@ -103,7 +123,7 @@ public static IPath GenerateOutline(this IPath path, float width, ReadOnlySpan<f
103
123
// we now inset a line joining
104
124
if ( online )
105
125
{
106
- offset . AddPath ( buffer , JoinType . jtSquare , EndType . etOpenButt ) ;
126
+ offset . AddPath ( buffer , style , patternSectionCap ) ;
107
127
}
108
128
109
129
online = ! online ;
@@ -138,7 +158,7 @@ public static IPath GenerateOutline(this IPath path, float width, ReadOnlySpan<f
138
158
139
159
if ( online )
140
160
{
141
- offset . AddPath ( buffer , JoinType . jtSquare , EndType . etOpenButt ) ;
161
+ offset . AddPath ( buffer , style , patternSectionCap ) ;
142
162
}
143
163
144
164
online = ! online ;
@@ -158,9 +178,25 @@ public static IPath GenerateOutline(this IPath path, float width, ReadOnlySpan<f
158
178
/// <param name="path">the path to outline</param>
159
179
/// <param name="width">The final width outline</param>
160
180
/// <returns>A new path representing the outline.</returns>
161
- public static IPath GenerateOutline ( this IPath path , float width )
181
+ public static IPath GenerateOutline ( this IPath path , float width ) => GenerateOutline ( path , width , JointStyle . Square , EndCapStyle . Butt ) ;
182
+
183
+ /// <summary>
184
+ /// Generates a solid outline of the path.
185
+ /// </summary>
186
+ /// <param name="path">the path to outline</param>
187
+ /// <param name="width">The final width outline</param>
188
+ /// <param name="jointStyle">The style to render the joints.</param>
189
+ /// <param name="endCapStyle">The style to render the end caps of open paths (ignored on closed paths).</param>
190
+ /// <returns>A new path representing the outline.</returns>
191
+ public static IPath GenerateOutline ( this IPath path , float width , JointStyle jointStyle = JointStyle . Square , EndCapStyle endCapStyle = EndCapStyle . Butt )
162
192
{
163
- var offset = new ClipperOffset ( ) ;
193
+ var offset = new ClipperOffset ( )
194
+ {
195
+ MiterLimit = MiterOffsetDelta
196
+ } ;
197
+
198
+ var style = Convert ( jointStyle ) ;
199
+ var openEndCapStyle = Convert ( endCapStyle ) ;
164
200
165
201
// Pattern can be applied to the path by cutting it into segments
166
202
IEnumerable < ISimplePath > paths = path . Flatten ( ) ;
@@ -173,9 +209,9 @@ public static IPath GenerateOutline(this IPath path, float width)
173
209
points . Add ( new IntPoint ( v . X * ScalingFactor , v . Y * ScalingFactor ) ) ;
174
210
}
175
211
176
- EndType type = p . IsClosed ? EndType . etClosedLine : EndType . etOpenButt ;
212
+ EndType type = p . IsClosed ? EndType . etClosedLine : openEndCapStyle ;
177
213
178
- offset . AddPath ( points , JoinType . jtSquare , type ) ;
214
+ offset . AddPath ( points , style , type ) ;
179
215
}
180
216
181
217
return ExecuteOutliner ( width , offset ) ;
@@ -204,5 +240,33 @@ private static IntPoint ToPoint(this Vector2 vector)
204
240
{
205
241
return new IntPoint ( vector . X * ScalingFactor , vector . Y * ScalingFactor ) ;
206
242
}
243
+
244
+ private static JoinType Convert ( JointStyle style )
245
+ {
246
+ switch ( style )
247
+ {
248
+ case JointStyle . Round :
249
+ return JoinType . jtRound ;
250
+ case JointStyle . Miter :
251
+ return JoinType . jtMiter ;
252
+ case JointStyle . Square :
253
+ default :
254
+ return JoinType . jtSquare ;
255
+ }
256
+ }
257
+
258
+ private static EndType Convert ( EndCapStyle style )
259
+ {
260
+ switch ( style )
261
+ {
262
+ case EndCapStyle . Round :
263
+ return EndType . etOpenRound ;
264
+ case EndCapStyle . Square :
265
+ return EndType . etOpenSquare ;
266
+ case EndCapStyle . Butt :
267
+ default :
268
+ return EndType . etOpenButt ;
269
+ }
270
+ }
207
271
}
208
272
}
0 commit comments