Merge pull request #379 from hecrj/canvas-fill-rule

Introduce fill rule setting in `canvas`
This commit is contained in:
Héctor Ramón 2020-06-02 22:43:21 +02:00 committed by GitHub
commit e7f0d3809b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 24 deletions

View File

@ -29,7 +29,7 @@ mod text;
pub use cache::Cache; pub use cache::Cache;
pub use cursor::Cursor; pub use cursor::Cursor;
pub use event::Event; pub use event::Event;
pub use fill::Fill; pub use fill::{Fill, FillRule};
pub use frame::Frame; pub use frame::Frame;
pub use geometry::Geometry; pub use geometry::Geometry;
pub use path::Path; pub use path::Path;
@ -84,7 +84,7 @@ pub use text::Text;
/// let circle = Path::circle(frame.center(), self.radius); /// let circle = Path::circle(frame.center(), self.radius);
/// ///
/// // And fill it with some color /// // And fill it with some color
/// frame.fill(&circle, Fill::Color(Color::BLACK)); /// frame.fill(&circle, Color::BLACK);
/// ///
/// // Finally, we produce the geometry /// // Finally, we produce the geometry
/// vec![frame.into_geometry()] /// vec![frame.into_geometry()]

View File

@ -2,19 +2,59 @@ use iced_native::Color;
/// The style used to fill geometry. /// The style used to fill geometry.
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub enum Fill { pub struct Fill {
/// Fill with a color. /// The color used to fill geometry.
Color(Color), ///
/// By default, it is set to `BLACK`.
pub color: Color,
/// The fill rule defines how to determine what is inside and what is
/// outside of a shape.
///
/// See the [SVG specification][1] for more details.
///
/// By default, it is set to `NonZero`.
///
/// [1]: https://www.w3.org/TR/SVG/painting.html#FillRuleProperty
pub rule: FillRule,
} }
impl Default for Fill { impl Default for Fill {
fn default() -> Fill { fn default() -> Fill {
Fill::Color(Color::BLACK) Fill {
color: Color::BLACK,
rule: FillRule::NonZero,
}
} }
} }
impl From<Color> for Fill { impl From<Color> for Fill {
fn from(color: Color) -> Fill { fn from(color: Color) -> Fill {
Fill::Color(color) Fill {
color,
..Fill::default()
}
}
}
/// The fill rule defines how to determine what is inside and what is outside of
/// a shape.
///
/// See the [SVG specification][1].
///
/// [1]: https://www.w3.org/TR/SVG/painting.html#FillRuleProperty
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[allow(missing_docs)]
pub enum FillRule {
NonZero,
EvenOdd,
}
impl From<FillRule> for lyon::tessellation::FillRule {
fn from(rule: FillRule) -> lyon::tessellation::FillRule {
match rule {
FillRule::NonZero => lyon::tessellation::FillRule::NonZero,
FillRule::EvenOdd => lyon::tessellation::FillRule::EvenOdd,
}
} }
} }

View File

@ -92,29 +92,22 @@ impl Frame {
BuffersBuilder, FillOptions, FillTessellator, BuffersBuilder, FillOptions, FillTessellator,
}; };
let Fill { color, rule } = fill.into();
let mut buffers = BuffersBuilder::new( let mut buffers = BuffersBuilder::new(
&mut self.buffers, &mut self.buffers,
FillVertex(match fill.into() { FillVertex(color.into_linear()),
Fill::Color(color) => color.into_linear(),
}),
); );
let mut tessellator = FillTessellator::new(); let mut tessellator = FillTessellator::new();
let options = FillOptions::default().with_fill_rule(rule.into());
let result = if self.transforms.current.is_identity { let result = if self.transforms.current.is_identity {
tessellator.tessellate_path( tessellator.tessellate_path(path.raw(), &options, &mut buffers)
path.raw(),
&FillOptions::default(),
&mut buffers,
)
} else { } else {
let path = path.transformed(&self.transforms.current.raw); let path = path.transformed(&self.transforms.current.raw);
tessellator.tessellate_path( tessellator.tessellate_path(path.raw(), &options, &mut buffers)
path.raw(),
&FillOptions::default(),
&mut buffers,
)
}; };
let _ = result.expect("Tessellate path"); let _ = result.expect("Tessellate path");
@ -132,11 +125,11 @@ impl Frame {
) { ) {
use lyon::tessellation::{BuffersBuilder, FillOptions}; use lyon::tessellation::{BuffersBuilder, FillOptions};
let Fill { color, rule } = fill.into();
let mut buffers = BuffersBuilder::new( let mut buffers = BuffersBuilder::new(
&mut self.buffers, &mut self.buffers,
FillVertex(match fill.into() { FillVertex(color.into_linear()),
Fill::Color(color) => color.into_linear(),
}),
); );
let top_left = let top_left =
@ -151,7 +144,7 @@ impl Frame {
let _ = lyon::tessellation::basic_shapes::fill_rectangle( let _ = lyon::tessellation::basic_shapes::fill_rectangle(
&lyon::math::Rect::new(top_left, size.into()), &lyon::math::Rect::new(top_left, size.into()),
&FillOptions::default(), &FillOptions::default().with_fill_rule(rule.into()),
&mut buffers, &mut buffers,
) )
.expect("Fill rectangle"); .expect("Fill rectangle");