2020-05-19 20:28:57 +00:00
|
|
|
use {
|
2020-10-01 20:25:44 +00:00
|
|
|
super::{font::Galley, fonts::TextStyle, Fonts, Srgba, Triangles},
|
|
|
|
crate::{
|
|
|
|
align::{anchor_rect, Align},
|
|
|
|
math::{Pos2, Rect},
|
|
|
|
},
|
2020-05-19 20:28:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// TODO: rename, e.g. `paint::Cmd`?
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum PaintCmd {
|
2020-07-30 12:11:09 +00:00
|
|
|
/// Paint nothing. This can be useful as a placeholder.
|
|
|
|
Noop,
|
2020-05-19 20:28:57 +00:00
|
|
|
Circle {
|
|
|
|
center: Pos2,
|
2020-08-05 17:45:39 +00:00
|
|
|
radius: f32,
|
2020-08-31 20:56:24 +00:00
|
|
|
fill: Srgba,
|
2020-09-01 21:54:21 +00:00
|
|
|
stroke: Stroke,
|
2020-05-19 20:28:57 +00:00
|
|
|
},
|
|
|
|
LineSegment {
|
|
|
|
points: [Pos2; 2],
|
2020-09-01 21:54:21 +00:00
|
|
|
stroke: Stroke,
|
2020-05-19 20:28:57 +00:00
|
|
|
},
|
|
|
|
Path {
|
2020-09-01 18:03:50 +00:00
|
|
|
points: Vec<Pos2>,
|
|
|
|
/// If true, connect the first and last of the points together.
|
|
|
|
/// This is required if `fill != TRANSPARENT`.
|
2020-05-19 20:28:57 +00:00
|
|
|
closed: bool,
|
2020-08-31 20:56:24 +00:00
|
|
|
fill: Srgba,
|
2020-09-01 21:54:21 +00:00
|
|
|
stroke: Stroke,
|
2020-05-19 20:28:57 +00:00
|
|
|
},
|
|
|
|
Rect {
|
|
|
|
rect: Rect,
|
|
|
|
corner_radius: f32,
|
2020-08-31 20:56:24 +00:00
|
|
|
fill: Srgba,
|
2020-09-01 21:54:21 +00:00
|
|
|
stroke: Stroke,
|
2020-05-19 20:28:57 +00:00
|
|
|
},
|
|
|
|
Text {
|
|
|
|
/// Top left corner of the first character.
|
|
|
|
pos: Pos2,
|
|
|
|
/// The layed out text
|
|
|
|
galley: Galley,
|
|
|
|
text_style: TextStyle, // TODO: Font?
|
2020-08-29 14:58:01 +00:00
|
|
|
color: Srgba,
|
2020-05-19 20:28:57 +00:00
|
|
|
},
|
|
|
|
Triangles(Triangles),
|
|
|
|
}
|
|
|
|
|
2020-09-13 07:28:54 +00:00
|
|
|
impl PaintCmd {
|
|
|
|
pub fn line_segment(points: [Pos2; 2], stroke: impl Into<Stroke>) -> Self {
|
|
|
|
Self::LineSegment {
|
|
|
|
points,
|
|
|
|
stroke: stroke.into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn circle_filled(center: Pos2, radius: f32, fill_color: impl Into<Srgba>) -> Self {
|
|
|
|
Self::Circle {
|
|
|
|
center,
|
|
|
|
radius,
|
|
|
|
fill: fill_color.into(),
|
|
|
|
stroke: Default::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn circle_stroke(center: Pos2, radius: f32, stroke: impl Into<Stroke>) -> Self {
|
|
|
|
Self::Circle {
|
|
|
|
center,
|
|
|
|
radius,
|
|
|
|
fill: Default::default(),
|
|
|
|
stroke: stroke.into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn rect_filled(rect: Rect, corner_radius: f32, fill_color: impl Into<Srgba>) -> Self {
|
|
|
|
Self::Rect {
|
|
|
|
rect,
|
|
|
|
corner_radius,
|
|
|
|
fill: fill_color.into(),
|
|
|
|
stroke: Default::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn rect_stroke(rect: Rect, corner_radius: f32, stroke: impl Into<Stroke>) -> Self {
|
|
|
|
Self::Rect {
|
|
|
|
rect,
|
|
|
|
corner_radius,
|
|
|
|
fill: Default::default(),
|
|
|
|
stroke: stroke.into(),
|
|
|
|
}
|
|
|
|
}
|
2020-10-01 20:25:44 +00:00
|
|
|
|
|
|
|
pub fn text(
|
|
|
|
fonts: &Fonts,
|
|
|
|
pos: Pos2,
|
|
|
|
anchor: (Align, Align),
|
|
|
|
text: impl Into<String>,
|
|
|
|
text_style: TextStyle,
|
|
|
|
color: Srgba,
|
|
|
|
) -> Self {
|
|
|
|
let font = &fonts[text_style];
|
|
|
|
let galley = font.layout_multiline(text.into(), f32::INFINITY);
|
|
|
|
let rect = anchor_rect(Rect::from_min_size(pos, galley.size), anchor);
|
|
|
|
Self::Text {
|
|
|
|
pos: rect.min,
|
|
|
|
galley,
|
|
|
|
text_style,
|
|
|
|
color,
|
|
|
|
}
|
|
|
|
}
|
2020-10-21 09:04:22 +00:00
|
|
|
|
|
|
|
pub fn triangles(triangles: Triangles) -> Self {
|
|
|
|
debug_assert!(triangles.is_valid());
|
|
|
|
Self::Triangles(triangles)
|
|
|
|
}
|
2020-10-21 09:09:42 +00:00
|
|
|
|
|
|
|
pub fn texture_id(&self) -> super::TextureId {
|
|
|
|
if let PaintCmd::Triangles(triangles) = self {
|
|
|
|
triangles.texture_id
|
|
|
|
} else {
|
|
|
|
super::TextureId::Egui
|
|
|
|
}
|
|
|
|
}
|
2020-09-13 07:28:54 +00:00
|
|
|
}
|
|
|
|
|
2020-10-10 11:04:40 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq)]
|
2020-08-09 15:34:26 +00:00
|
|
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
2020-09-01 21:54:21 +00:00
|
|
|
pub struct Stroke {
|
2020-05-19 20:28:57 +00:00
|
|
|
pub width: f32,
|
2020-08-29 14:58:01 +00:00
|
|
|
pub color: Srgba,
|
2020-05-19 20:28:57 +00:00
|
|
|
}
|
|
|
|
|
2020-09-01 21:54:21 +00:00
|
|
|
impl Stroke {
|
2020-08-31 20:56:24 +00:00
|
|
|
pub fn none() -> Self {
|
|
|
|
Self::new(0.0, crate::color::TRANSPARENT)
|
|
|
|
}
|
|
|
|
|
2020-08-29 14:58:01 +00:00
|
|
|
pub fn new(width: impl Into<f32>, color: impl Into<Srgba>) -> Self {
|
2020-05-19 20:28:57 +00:00
|
|
|
Self {
|
|
|
|
width: width.into(),
|
|
|
|
color: color.into(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-08-29 15:30:06 +00:00
|
|
|
|
2020-09-01 21:54:21 +00:00
|
|
|
impl<Color> From<(f32, Color)> for Stroke
|
2020-08-29 15:30:06 +00:00
|
|
|
where
|
|
|
|
Color: Into<Srgba>,
|
|
|
|
{
|
2020-09-01 21:54:21 +00:00
|
|
|
fn from((width, color): (f32, Color)) -> Stroke {
|
|
|
|
Stroke::new(width, color)
|
2020-08-29 15:30:06 +00:00
|
|
|
}
|
|
|
|
}
|