wasm_game_lib/graphics/
text.rs

1use super::font::Font;
2use crate::graphics::drawable::Drawable;
3use crate::graphics::canvas::Canvas;
4use crate::graphics::color::Color;
5use wasm_bindgen::JsValue;
6
7const PX_STR: &str = "px";
8
9/// A struct representing the style of a [Text](struct.Text.html).
10pub struct TextStyle {
11    /// Italic
12    pub italic: bool,
13    /// Bold
14    pub bold: bool,
15    /// Underlined is not supported for now!
16    pub underlined: bool,
17    /// The color of the text
18    pub color: Color
19}
20
21impl Default for TextStyle {
22    fn default() -> TextStyle {
23        TextStyle {
24            italic: false,
25            bold: false,
26            underlined: false,
27            color: Color::black()
28        }
29    }
30}
31
32/// A text drawable on a [Canvas](../canvas/struct.Canvas.html).
33/// Multiline (\n) works only when using a character size in px.
34pub struct Text<'a> {
35    /// The coords of the text in px.
36    pub coords: (usize, usize),
37    /// The [font](../font/struct.Font.html) of the text.
38    pub font: &'a Font,
39    /// The text.
40    pub text: String,
41    /// The [style](struct.TextStyle.html) of the text (bold/italic...)
42    pub style: TextStyle,
43    /// The character_size. example: (14, "px")
44    pub character_size: (usize, &'a str)
45}
46
47impl<'a> Text<'a> {
48    /// Create a new text with default values.
49    pub fn new(font: &'a Font) -> Text<'a> {
50        Text {
51            coords: (0,0),
52            font,
53            text: String::new(),
54            style: TextStyle::default(),
55            character_size: (26, PX_STR)
56        }
57    }
58
59    /// Create a new text with some default values.
60    pub fn new_with_text_and_coords(font: &'a Font, text: String, coords: (usize, usize)) -> Text<'a> {
61        Text {
62            coords,
63            font,
64            text,
65            style: TextStyle::default(),
66            character_size: (26, PX_STR)
67        }
68    }
69
70    /// Create a new text with no default value.
71    pub fn new_with_options(font: &'a Font, text: String, coords: (usize, usize), style: TextStyle, character_size: (usize, &'a str)) -> Text<'a> {
72        Text {
73            coords,
74            font,
75            text,
76            style,
77            character_size
78        }
79    }
80
81    /// Set the displayed text.
82    pub fn set_text(&mut self, text: String) {
83        self.text = text;
84    }
85
86    /// Set the [style](struct.TextStyle.html) of the text.
87    pub fn set_style(&mut self, style: TextStyle) {
88        self.style = style;
89    }
90
91    /// Get the width of the text
92    /// Needs a mutable reference to a canvas
93    pub fn get_width(&self, mut canvas: &mut Canvas) -> f64 {
94        self.apply_style_on_canvas(&mut canvas);
95        let mut max_width = 0.0;
96        for text in self.text.split('\n') {
97            let width = canvas.context.measure_text(&text).unwrap().width();
98            if width > max_width {
99                max_width = width;
100            }
101        }
102        max_width
103    }
104
105    /// Get the width of the text.
106    /// Works only for font size specified using a value in px.
107    pub fn get_height(&self) -> usize {
108        self.text.split('\n').count() * self.character_size.0
109    }
110
111    fn apply_style_on_canvas(&self, canvas: &mut Canvas) {
112        let mut font = String::new();
113        if self.style.italic {
114            font.push_str("italic ");
115        }
116        if self.style.bold {
117            font.push_str("bold ");
118        }
119        if self.style.underlined {
120            unimplemented!("avoid underlined text for now");
121        }
122        font.push_str(&self.character_size.0.to_string());
123        font.push_str(self.character_size.1);
124        font.push_str(" '");
125        font.push_str(&self.font.name);
126        font.push_str("'");
127
128        canvas.context.set_font(&font);
129        canvas.context.set_fill_style(&JsValue::from_str(&self.style.color.to_string()));
130    }
131}
132
133impl<'a> Drawable for Text<'a> {
134    fn draw_on_canvas(&self, mut canvas: &mut Canvas) {
135        self.apply_style_on_canvas(&mut canvas);
136        for (idx, text) in self.text.split('\n').enumerate() {
137            let mut coords = self.coords;
138            coords.1 += self.character_size.0 * idx;
139            canvas.fill_text(coords, text, None);
140        }
141    }
142}