1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
use lyon::tessellation::{LineCap, LineJoin, StrokeOptions};
/// Nodes that support stroke tessellation.
///
/// This trait allows the `Drawing` context to automatically provide an implementation of the
/// following builder methods for all primitives that provide some stroke tessellation options.
pub trait SetStroke: Sized {
/// Provide a mutable reference to the `StrokeOptions` field.
fn stroke_options_mut(&mut self) -> &mut StrokeOptions;
/// Specify the whole set of stroke tessellation options.
fn stroke_opts(mut self, opts: StrokeOptions) -> Self {
*self.stroke_options_mut() = opts;
self
}
/// The start line cap as specified by the SVG spec.
fn start_cap(mut self, cap: LineCap) -> Self {
self.stroke_options_mut().start_cap = cap;
self
}
/// The end line cap as specified by the SVG spec.
fn end_cap(mut self, cap: LineCap) -> Self {
self.stroke_options_mut().end_cap = cap;
self
}
/// The start and end line cap as specified by the SVG spec.
fn caps(self, cap: LineCap) -> Self {
self.start_cap(cap).end_cap(cap)
}
/// The stroke for each sub-path does not extend beyond its two endpoints. A zero length
/// sub-path will therefore not have any stroke.
fn start_cap_butt(self) -> Self {
self.start_cap(LineCap::Butt)
}
/// At the end of each sub-path, the shape representing the stroke will be extended by a
/// rectangle with the same width as the stroke width and whose length is half of the stroke
/// width. If a sub-path has zero length, then the resulting effect is that the stroke for that
/// sub-path consists solely of a square with side length equal to the stroke width, centered
/// at the sub-path's point.
fn start_cap_square(self) -> Self {
self.start_cap(LineCap::Square)
}
/// At each end of each sub-path, the shape representing the stroke will be extended by a half
/// circle with a radius equal to the stroke width. If a sub-path has zero length, then the
/// resulting effect is that the stroke for that sub-path consists solely of a full circle
/// centered at the sub-path's point.
fn start_cap_round(self) -> Self {
self.start_cap(LineCap::Round)
}
/// The stroke for each sub-path does not extend beyond its two endpoints. A zero length
/// sub-path will therefore not have any stroke.
fn end_cap_butt(self) -> Self {
self.end_cap(LineCap::Butt)
}
/// At the end of each sub-path, the shape representing the stroke will be extended by a
/// rectangle with the same width as the stroke width and whose length is half of the stroke
/// width. If a sub-path has zero length, then the resulting effect is that the stroke for that
/// sub-path consists solely of a square with side length equal to the stroke width, centered
/// at the sub-path's point.
fn end_cap_square(self) -> Self {
self.end_cap(LineCap::Square)
}
/// At each end of each sub-path, the shape representing the stroke will be extended by a half
/// circle with a radius equal to the stroke width. If a sub-path has zero length, then the
/// resulting effect is that the stroke for that sub-path consists solely of a full circle
/// centered at the sub-path's point.
fn end_cap_round(self) -> Self {
self.end_cap(LineCap::Round)
}
/// The stroke for each sub-path does not extend beyond its two endpoints. A zero length
/// sub-path will therefore not have any stroke.
fn caps_butt(self) -> Self {
self.caps(LineCap::Butt)
}
/// At the end of each sub-path, the shape representing the stroke will be extended by a
/// rectangle with the same width as the stroke width and whose length is half of the stroke
/// width. If a sub-path has zero length, then the resulting effect is that the stroke for that
/// sub-path consists solely of a square with side length equal to the stroke width, centered
/// at the sub-path's point.
fn caps_square(self) -> Self {
self.caps(LineCap::Square)
}
/// At each end of each sub-path, the shape representing the stroke will be extended by a half
/// circle with a radius equal to the stroke width. If a sub-path has zero length, then the
/// resulting effect is that the stroke for that sub-path consists solely of a full circle
/// centered at the sub-path's point.
fn caps_round(self) -> Self {
self.caps(LineCap::Round)
}
/// The way in which lines are joined at the vertices, matching the SVG spec.
///
/// Default value is `MiterClip`.
fn join(mut self, join: LineJoin) -> Self {
self.stroke_options_mut().line_join = join;
self
}
/// A sharp corner is to be used to join path segments.
fn join_miter(self) -> Self {
self.join(LineJoin::Miter)
}
/// Same as a `join_miter`, but if the miter limit is exceeded, the miter is clipped at a miter
/// length equal to the miter limit value multiplied by the stroke width.
fn join_miter_clip(self) -> Self {
self.join(LineJoin::MiterClip)
}
/// A round corner is to be used to join path segments.
fn join_round(self) -> Self {
self.join(LineJoin::Round)
}
/// A bevelled corner is to be used to join path segments. The bevel shape is a triangle that
/// fills the area between the two stroked segments.
fn join_bevel(self) -> Self {
self.join(LineJoin::Bevel)
}
/// The total stroke_weight (aka width) of the line.
fn stroke_weight(mut self, stroke_weight: f32) -> Self {
self.stroke_options_mut().line_width = stroke_weight;
self
}
/// Describes the limit before miter lines will clip, as described in the SVG spec.
///
/// Must be greater than or equal to `1.0`.
fn miter_limit(mut self, limit: f32) -> Self {
self.stroke_options_mut().miter_limit = limit;
self
}
/// Maximum allowed distance to the path when building an approximation.
fn stroke_tolerance(mut self, tolerance: f32) -> Self {
self.stroke_options_mut().tolerance = tolerance;
self
}
}
impl SetStroke for Option<StrokeOptions> {
fn stroke_options_mut(&mut self) -> &mut StrokeOptions {
self.get_or_insert_with(Default::default)
}
}