summaryrefslogtreecommitdiffstats
path: root/vendor/plotters/src/style/size.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/plotters/src/style/size.rs')
-rw-r--r--vendor/plotters/src/style/size.rs186
1 files changed, 186 insertions, 0 deletions
diff --git a/vendor/plotters/src/style/size.rs b/vendor/plotters/src/style/size.rs
new file mode 100644
index 000000000..254df8d4f
--- /dev/null
+++ b/vendor/plotters/src/style/size.rs
@@ -0,0 +1,186 @@
+use crate::coord::CoordTranslate;
+use crate::drawing::DrawingArea;
+use plotters_backend::DrawingBackend;
+
+/// The trait indicates that the type has a dimensional data.
+/// This is the abstraction for the relative sizing model.
+/// A relative sizing value is able to be converted into a concrete size
+/// when coupling with a type with `HasDimension` type.
+pub trait HasDimension {
+ /// Get the dimensional data for this object
+ fn dim(&self) -> (u32, u32);
+}
+
+impl<D: DrawingBackend, C: CoordTranslate> HasDimension for DrawingArea<D, C> {
+ fn dim(&self) -> (u32, u32) {
+ self.dim_in_pixel()
+ }
+}
+
+impl HasDimension for (u32, u32) {
+ fn dim(&self) -> (u32, u32) {
+ *self
+ }
+}
+
+/// The trait that describes a size, it may be a relative size which the
+/// size is determined by the parent size, e.g., 10% of the parent width
+pub trait SizeDesc {
+ /// Convert the size into the number of pixels
+ ///
+ /// - `parent`: The reference to the parent container of this size
+ /// - **returns**: The number of pixels
+ fn in_pixels<T: HasDimension>(&self, parent: &T) -> i32;
+}
+
+impl SizeDesc for i32 {
+ fn in_pixels<D: HasDimension>(&self, _parent: &D) -> i32 {
+ *self
+ }
+}
+
+impl SizeDesc for u32 {
+ fn in_pixels<D: HasDimension>(&self, _parent: &D) -> i32 {
+ *self as i32
+ }
+}
+
+impl SizeDesc for f32 {
+ fn in_pixels<D: HasDimension>(&self, _parent: &D) -> i32 {
+ *self as i32
+ }
+}
+
+impl SizeDesc for f64 {
+ fn in_pixels<D: HasDimension>(&self, _parent: &D) -> i32 {
+ *self as i32
+ }
+}
+
+/// Describes a relative size, might be
+/// 1. portion of height
+/// 2. portion of width
+/// 3. portion of the minimal of height and weight
+pub enum RelativeSize {
+ /// Percentage height
+ Height(f64),
+ /// Percentage width
+ Width(f64),
+ /// Percentage of either height or width, which is smaller
+ Smaller(f64),
+}
+
+impl RelativeSize {
+ /// Set the lower bound of the relative size.
+ ///
+ /// - `min_sz`: The minimal size the relative size can be in pixels
+ /// - **returns**: The relative size with the bound
+ pub fn min(self, min_sz: i32) -> RelativeSizeWithBound {
+ RelativeSizeWithBound {
+ size: self,
+ min: Some(min_sz),
+ max: None,
+ }
+ }
+
+ /// Set the upper bound of the relative size
+ ///
+ /// - `max_size`: The maximum size in pixels for this relative size
+ /// - **returns** The relative size with the upper bound
+ pub fn max(self, max_sz: i32) -> RelativeSizeWithBound {
+ RelativeSizeWithBound {
+ size: self,
+ max: Some(max_sz),
+ min: None,
+ }
+ }
+}
+
+impl SizeDesc for RelativeSize {
+ fn in_pixels<D: HasDimension>(&self, parent: &D) -> i32 {
+ let (w, h) = parent.dim();
+ match self {
+ RelativeSize::Width(p) => *p * f64::from(w),
+ RelativeSize::Height(p) => *p * f64::from(h),
+ RelativeSize::Smaller(p) => *p * f64::from(w.min(h)),
+ }
+ .round() as i32
+ }
+}
+
+/// Allows a value turns into a relative size
+pub trait AsRelative: Into<f64> {
+ /// Make the value a relative size of percentage of width
+ fn percent_width(self) -> RelativeSize {
+ RelativeSize::Width(self.into() / 100.0)
+ }
+ /// Make the value a relative size of percentage of height
+ fn percent_height(self) -> RelativeSize {
+ RelativeSize::Height(self.into() / 100.0)
+ }
+ /// Make the value a relative size of percentage of minimal of height and width
+ fn percent(self) -> RelativeSize {
+ RelativeSize::Smaller(self.into() / 100.0)
+ }
+}
+
+impl<T: Into<f64>> AsRelative for T {}
+
+/// The struct describes a relative size with upper bound and lower bound
+pub struct RelativeSizeWithBound {
+ size: RelativeSize,
+ min: Option<i32>,
+ max: Option<i32>,
+}
+
+impl RelativeSizeWithBound {
+ /// Set the lower bound of the bounded relative size
+ ///
+ /// - `min_sz`: The lower bound of this size description
+ /// - **returns**: The newly created size description with the bound
+ pub fn min(mut self, min_sz: i32) -> RelativeSizeWithBound {
+ self.min = Some(min_sz);
+ self
+ }
+
+ /// Set the upper bound of the bounded relative size
+ ///
+ /// - `min_sz`: The upper bound of this size description
+ /// - **returns**: The newly created size description with the bound
+ pub fn max(mut self, max_sz: i32) -> RelativeSizeWithBound {
+ self.max = Some(max_sz);
+ self
+ }
+}
+
+impl SizeDesc for RelativeSizeWithBound {
+ fn in_pixels<D: HasDimension>(&self, parent: &D) -> i32 {
+ let size = self.size.in_pixels(parent);
+ let size_lower_capped = self.min.map_or(size, |x| x.max(size));
+ self.max.map_or(size_lower_capped, |x| x.min(size))
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ #[test]
+ fn test_relative_size() {
+ let size = (10).percent_height();
+ assert_eq!(size.in_pixels(&(100, 200)), 20);
+
+ let size = (10).percent_width();
+ assert_eq!(size.in_pixels(&(100, 200)), 10);
+
+ let size = (-10).percent_width();
+ assert_eq!(size.in_pixels(&(100, 200)), -10);
+
+ let size = (10).percent_width().min(30);
+ assert_eq!(size.in_pixels(&(100, 200)), 30);
+ assert_eq!(size.in_pixels(&(400, 200)), 40);
+
+ let size = (10).percent();
+ assert_eq!(size.in_pixels(&(100, 200)), 10);
+ assert_eq!(size.in_pixels(&(400, 200)), 20);
+ }
+}