use types::{Color, Radius, Resolution};
use {types, triangulation, Graphics, DrawState};
use math::{Matrix2d, Scalar};
pub use math::margin_rectangle as margin;
pub fn rectangle_by_corners(x0: Scalar, y0: Scalar, x1: Scalar, y1: Scalar) -> types::Rectangle {
let (xmin, w) = if x0 <= x1 {
(x0, x1 - x0)
} else {
(x1, x0 - x1)
};
let (ymin, h) = if y0 <= y1 {
(y0, y1 - y0)
} else {
(y1, y0 - y1)
};
[xmin, ymin, w, h]
}
pub fn centered(rect: types::Rectangle) -> types::Rectangle {
[rect[0] - rect[2], rect[1] - rect[3], 2.0 * rect[2], 2.0 * rect[3]]
}
pub fn centered_square(x: Scalar, y: Scalar, radius: Scalar) -> types::Rectangle {
[x - radius, y - radius, 2.0 * radius, 2.0 * radius]
}
pub fn square(x: Scalar, y: Scalar, size: Scalar) -> types::Rectangle {
[x, y, size, size]
}
#[derive(Copy, Clone)]
pub enum Shape {
Square,
Round(Radius, Resolution),
Bevel(Radius),
}
#[derive(Copy, Clone)]
pub struct Border {
pub color: Color,
pub radius: Radius,
}
#[derive(Copy, Clone)]
pub struct Rectangle {
pub color: Color,
pub shape: Shape,
pub border: Option<Border>,
}
impl Rectangle {
pub fn new(color: Color) -> Rectangle {
Rectangle {
color: color,
shape: Shape::Square,
border: None,
}
}
pub fn new_round(color: Color, round_radius: Radius) -> Rectangle {
Rectangle {
color: color,
shape: Shape::Round(round_radius, 32),
border: None,
}
}
pub fn new_border(color: Color, radius: Radius) -> Rectangle {
Rectangle {
color: [0.0; 4],
shape: Shape::Square,
border: Some(Border {
color: color,
radius: radius,
}),
}
}
pub fn new_round_border(color: Color,
round_radius: Radius,
border_radius: Radius)
-> Rectangle {
Rectangle {
color: [0.0; 4],
shape: Shape::Round(round_radius, 32),
border: Some(Border {
color: color,
radius: border_radius,
}),
}
}
pub fn color(mut self, value: Color) -> Self {
self.color = value;
self
}
pub fn shape(mut self, value: Shape) -> Self {
self.shape = value;
self
}
pub fn border(mut self, value: Border) -> Self {
self.border = Some(value);
self
}
pub fn maybe_border(mut self, value: Option<Border>) -> Self {
self.border = value;
self
}
#[inline(always)]
pub fn draw_from_to<P: Into<types::Vec2d>, G>(&self,
from: P,
to: P,
draw_state: &DrawState,
transform: Matrix2d,
g: &mut G)
where G: Graphics
{
let from = from.into();
let to = to.into();
g.rectangle(self, rectangle_by_corners(from[0], from[1], to[0], to[1]), draw_state, transform);
}
#[inline(always)]
pub fn draw<R: Into<types::Rectangle>, G>(&self,
rectangle: R,
draw_state: &DrawState,
transform: Matrix2d,
g: &mut G)
where G: Graphics
{
g.rectangle(self, rectangle, draw_state, transform);
}
pub fn draw_tri<R: Into<types::Rectangle>, G>(&self,
rectangle: R,
draw_state: &DrawState,
transform: Matrix2d,
g: &mut G)
where G: Graphics
{
let rectangle = rectangle.into();
if self.color[3] != 0.0 {
match self.shape {
Shape::Square => {
g.tri_list(draw_state,
&self.color,
|f| f(&triangulation::rect_tri_list_xy(transform, rectangle)));
}
Shape::Round(round_radius, resolution) => {
g.tri_list(draw_state, &self.color, |f| {
triangulation::with_round_rectangle_tri_list(resolution,
transform,
rectangle,
round_radius,
|vertices| f(vertices))
});
}
Shape::Bevel(bevel_radius) => {
g.tri_list(draw_state, &self.color, |f| {
triangulation::with_round_rectangle_tri_list(2,
transform,
rectangle,
bevel_radius,
|vertices| f(vertices))
});
}
}
}
if let Some(Border { color, radius: border_radius }) = self.border {
if color[3] == 0.0 {
return;
}
match self.shape {
Shape::Square => {
g.tri_list(draw_state, &color, |f| {
f(&triangulation::rect_border_tri_list_xy(transform,
rectangle,
border_radius))
});
}
Shape::Round(round_radius, resolution) => {
g.tri_list(draw_state, &color, |f| {
triangulation::with_round_rectangle_border_tri_list(resolution,
transform,
rectangle,
round_radius,
border_radius,
|vertices| f(vertices))
});
}
Shape::Bevel(bevel_radius) => {
g.tri_list(draw_state, &color, |f| {
triangulation::with_round_rectangle_border_tri_list(2,
transform,
rectangle,
bevel_radius,
border_radius,
|vertices| f(vertices))
});
}
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_rectangle() {
let _rectangle = Rectangle::new([1.0; 4])
.color([0.0; 4])
.shape(Shape::Round(10.0, 32))
.border(Border {
color: [0.0; 4],
radius: 4.0,
});
}
#[test]
fn test_rectangle_by_corners() {
assert_eq!(rectangle_by_corners(1.0, -1.0, 2.0, 3.0),
[1.0, -1.0, 1.0, 4.0]);
assert_eq!(rectangle_by_corners(2.0, 3.0, 1.0, -1.0),
[1.0, -1.0, 1.0, 4.0]);
}
}