diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-18 02:49:50 +0000 |
commit | 9835e2ae736235810b4ea1c162ca5e65c547e770 (patch) | |
tree | 3fcebf40ed70e581d776a8a4c65923e8ec20e026 /vendor/plotters-backend/src/text.rs | |
parent | Releasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff) | |
download | rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip |
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/plotters-backend/src/text.rs')
-rw-r--r-- | vendor/plotters-backend/src/text.rs | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/vendor/plotters-backend/src/text.rs b/vendor/plotters-backend/src/text.rs new file mode 100644 index 000000000..16e2c6652 --- /dev/null +++ b/vendor/plotters-backend/src/text.rs @@ -0,0 +1,245 @@ +use super::{BackendColor, BackendCoord}; +use std::error::Error; + +/// Describes font family. +/// This can be either a specific font family name, such as "arial", +/// or a general font family class, such as "serif" and "sans-serif" +#[derive(Clone, Copy)] +pub enum FontFamily<'a> { + /// The system default serif font family + Serif, + /// The system default sans-serif font family + SansSerif, + /// The system default monospace font + Monospace, + /// A specific font family name + Name(&'a str), +} + +impl<'a> FontFamily<'a> { + /// Make a CSS compatible string for the font family name. + /// This can be used as the value of `font-family` attribute in SVG. + pub fn as_str(&self) -> &str { + match self { + FontFamily::Serif => "serif", + FontFamily::SansSerif => "sans-serif", + FontFamily::Monospace => "monospace", + FontFamily::Name(face) => face, + } + } +} + +impl<'a> From<&'a str> for FontFamily<'a> { + fn from(from: &'a str) -> FontFamily<'a> { + match from.to_lowercase().as_str() { + "serif" => FontFamily::Serif, + "sans-serif" => FontFamily::SansSerif, + "monospace" => FontFamily::Monospace, + _ => FontFamily::Name(from), + } + } +} + +/// Text anchor attributes are used to properly position the text. +/// +/// # Examples +/// +/// In the example below, the text anchor (X) position is `Pos::new(HPos::Right, VPos::Center)`. +/// ```text +/// ***** X +/// ``` +/// The position is always relative to the text regardless of its rotation. +/// In the example below, the text has style +/// `style.transform(FontTransform::Rotate90).pos(Pos::new(HPos::Center, VPos::Top))`. +/// ```text +/// * +/// * +/// * X +/// * +/// * +/// ``` +pub mod text_anchor { + /// The horizontal position of the anchor point relative to the text. + #[derive(Clone, Copy)] + pub enum HPos { + /// Anchor point is on the left side of the text + Left, + /// Anchor point is on the right side of the text + Right, + /// Anchor point is in the horizontal center of the text + Center, + } + + /// The vertical position of the anchor point relative to the text. + #[derive(Clone, Copy)] + pub enum VPos { + /// Anchor point is on the top of the text + Top, + /// Anchor point is in the vertical center of the text + Center, + /// Anchor point is on the bottom of the text + Bottom, + } + + /// The text anchor position. + #[derive(Clone, Copy)] + pub struct Pos { + /// The horizontal position of the anchor point + pub h_pos: HPos, + /// The vertical position of the anchor point + pub v_pos: VPos, + } + + impl Pos { + /// Create a new text anchor position. + /// + /// - `h_pos`: The horizontal position of the anchor point + /// - `v_pos`: The vertical position of the anchor point + /// - **returns** The newly created text anchor position + /// + /// ```rust + /// use plotters_backend::text_anchor::{Pos, HPos, VPos}; + /// + /// let pos = Pos::new(HPos::Left, VPos::Top); + /// ``` + pub fn new(h_pos: HPos, v_pos: VPos) -> Self { + Pos { h_pos, v_pos } + } + + /// Create a default text anchor position (top left). + /// + /// - **returns** The default text anchor position + /// + /// ```rust + /// use plotters_backend::text_anchor::{Pos, HPos, VPos}; + /// + /// let pos = Pos::default(); + /// ``` + pub fn default() -> Self { + Pos { + h_pos: HPos::Left, + v_pos: VPos::Top, + } + } + } +} + +/// Specifying text transformations +#[derive(Clone)] +pub enum FontTransform { + /// Nothing to transform + None, + /// Rotating the text 90 degree clockwise + Rotate90, + /// Rotating the text 180 degree clockwise + Rotate180, + /// Rotating the text 270 degree clockwise + Rotate270, +} + +impl FontTransform { + /// Transform the coordinate to perform the rotation + /// + /// - `x`: The x coordinate in pixels before transform + /// - `y`: The y coordinate in pixels before transform + /// - **returns**: The coordinate after transform + pub fn transform(&self, x: i32, y: i32) -> (i32, i32) { + match self { + FontTransform::None => (x, y), + FontTransform::Rotate90 => (-y, x), + FontTransform::Rotate180 => (-x, -y), + FontTransform::Rotate270 => (y, -x), + } + } +} + +/// Describes the font style. Such as Italic, Oblique, etc. +#[derive(Clone, Copy)] +pub enum FontStyle { + /// The normal style + Normal, + /// The oblique style + Oblique, + /// The italic style + Italic, + /// The bold style + Bold, +} + +impl FontStyle { + /// Convert the font style into a CSS compatible string which can be used in `font-style` attribute. + pub fn as_str(&self) -> &str { + match self { + FontStyle::Normal => "normal", + FontStyle::Italic => "italic", + FontStyle::Oblique => "oblique", + FontStyle::Bold => "bold", + } + } +} + +impl<'a> From<&'a str> for FontStyle { + fn from(from: &'a str) -> FontStyle { + match from.to_lowercase().as_str() { + "normal" => FontStyle::Normal, + "italic" => FontStyle::Italic, + "oblique" => FontStyle::Oblique, + "bold" => FontStyle::Bold, + _ => FontStyle::Normal, + } + } +} + +/// The trait that abstracts a style of a text. +/// +/// This is used because the the backend crate have no knowledge about how +/// the text handling is implemented in plotters. +/// +/// But the backend still wants to know some information about the font, for +/// the backend doesn't handles text drawing, may want to call the `draw` method which +/// is implemented by the plotters main crate. While for the backend that handles the +/// text drawing, those font information provides instructions about how the text should be +/// rendered: color, size, slant, anchor, font, etc. +/// +/// This trait decouples the detailed implementaiton about the font and the backend code which +/// wants to perfome some operation on the font. +/// +pub trait BackendTextStyle { + /// The error type of this text style implementation + type FontError: Error + Sync + Send + 'static; + + fn color(&self) -> BackendColor { + BackendColor { + alpha: 1.0, + rgb: (0, 0, 0), + } + } + + fn size(&self) -> f64 { + 1.0 + } + + fn transform(&self) -> FontTransform { + FontTransform::None + } + + fn style(&self) -> FontStyle { + FontStyle::Normal + } + + fn anchor(&self) -> text_anchor::Pos { + text_anchor::Pos::default() + } + + fn family(&self) -> FontFamily; + + #[allow(clippy::type_complexity)] + fn layout_box(&self, text: &str) -> Result<((i32, i32), (i32, i32)), Self::FontError>; + + fn draw<E, DrawFunc: FnMut(i32, i32, BackendColor) -> Result<(), E>>( + &self, + text: &str, + pos: BackendCoord, + draw: DrawFunc, + ) -> Result<Result<(), E>, Self::FontError>; +} |