1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use crate::{Color, ShallowImage};
use lyon_tessellation::StrokeOptions;
use ribir_text::{Em, FontFace, FontSize, Pixel};
use serde::{Deserialize, Serialize};

/// Encapsulates the text style for painting.
#[derive(Clone, Debug, PartialEq)]
pub struct TextStyle {
  /// The size of glyphs (in logical pixels) to use when painting the text.
  pub font_size: FontSize,
  // todo: needn't a color in style?
  /// The style drawn as a foreground for the text.
  pub foreground: Brush,
  /// The font face to use when painting the text.
  // todo: use ids instead of
  pub font_face: FontFace,
  /// Not support now.
  pub letter_space: Option<Pixel>,
  /// The path style(fill or stroke) to use when painting.
  pub path_style: PathStyle,
  /// The factor use to multiplied by the font size to specify the text line
  /// height.
  pub line_height: Option<Em>,
}

bitflags::bitflags! {
  /// - Repeat mode repeat the image to full tile the path, if the image greater
  /// than the path, image will be clipped.
  /// - Cover mode resize the image to cover the entire path, even if it has to
  /// stretch the image or cut a little bit off one of the edges
  #[derive(Serialize, Deserialize)]
  pub struct TileMode: u8 {
    const REPEAT_X = 0b00000001;
    const REPEAT_Y = 0b00000010;
    const REPEAT_BOTH = Self::REPEAT_X.bits | Self::REPEAT_Y.bits;
    const COVER_X = 0b00000100;
    const COVER_Y = 0b00001000;
    const COVER_BOTH = Self::COVER_X.bits | Self::COVER_Y.bits;
    const REPEAT_X_COVER_Y = Self::REPEAT_X.bits | Self::COVER_Y.bits;
    const COVER_X_REPEAT_Y = Self::COVER_X.bits | Self::REPEAT_Y.bits;
  }
}

impl TileMode {
  #[inline]
  pub fn is_cover_mode(&self) -> bool { self.bits & (TileMode::COVER_BOTH.bits) > 0 }
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Brush {
  Color(Color),
  Image {
    img: ShallowImage,
    tile_mode: TileMode,
  },
  Gradient, // todo,
}

/// The style to paint path, maybe fill or stroke.
#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
pub enum PathStyle {
  /// Fill the path.
  Fill,
  /// Stroke path with line width.
  Stroke(StrokeOptions),
}

impl Default for TextStyle {
  fn default() -> Self {
    Self {
      font_size: FontSize::Pixel(14.0.into()),
      foreground: Color::BLACK.into(),
      font_face: Default::default(),
      letter_space: None,
      path_style: PathStyle::Fill,
      line_height: None,
    }
  }
}

impl From<Color> for Brush {
  #[inline]
  fn from(c: Color) -> Self { Brush::Color(c) }
}

impl Default for Brush {
  #[inline]
  fn default() -> Self { Color::BLACK.into() }
}