Skip to main content

fyrox_ui/formatted_text/
run.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use crate::core::type_traits::prelude::*;
22use crate::font::FontHeight;
23use std::ops::{Deref, DerefMut};
24
25use super::*;
26
27#[deprecated]
28pub type RunBuilder = Run;
29
30#[derive(Clone, PartialEq, Debug, Default, Reflect)]
31pub struct RunSet(Vec<Run>);
32
33impl IntoIterator for RunSet {
34    type Item = Run;
35    type IntoIter = std::vec::IntoIter<Run>;
36    fn into_iter(self) -> Self::IntoIter {
37        self.0.into_iter()
38    }
39}
40
41impl From<&[Run]> for RunSet {
42    fn from(value: &[Run]) -> Self {
43        Self(value.to_vec())
44    }
45}
46
47impl From<Vec<Run>> for RunSet {
48    fn from(value: Vec<Run>) -> Self {
49        Self(value)
50    }
51}
52
53impl Visit for RunSet {
54    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
55        self.0.visit(name, visitor)
56    }
57}
58
59impl Deref for RunSet {
60    type Target = Vec<Run>;
61
62    fn deref(&self) -> &Self::Target {
63        &self.0
64    }
65}
66
67impl DerefMut for RunSet {
68    fn deref_mut(&mut self) -> &mut Self::Target {
69        &mut self.0
70    }
71}
72
73impl RunSet {
74    /// Updates the run set with the given run, overriding any previous runs
75    /// that may have set some of the same formatting attributes in the same range.
76    /// Runs within this set may be merged if appropriate.
77    pub fn push(&mut self, run: Run) {
78        if let Some(last) = self.0.last_mut() {
79            if last.range == run.range {
80                *last = last.clone().with_values_from(run);
81            } else {
82                self.0.push(run);
83            }
84        } else {
85            self.0.push(run);
86        }
87    }
88    /// Find the font at the given position.
89    pub fn font_at(&self, index: usize) -> Option<FontResource> {
90        for run in self.0.iter().rev() {
91            if run.range.contains(&(index as u32)) && run.font().is_some() {
92                return Some(run.font().unwrap().clone());
93            }
94        }
95        None
96    }
97    /// Find the size at the given position.
98    pub fn font_size_at(&self, index: usize) -> Option<f32> {
99        for run in self.0.iter().rev() {
100            if run.range.contains(&(index as u32)) && run.font_size().is_some() {
101                return Some(run.font_size().unwrap());
102            }
103        }
104        None
105    }
106    /// Find the brush at the given position.
107    pub fn brush_at(&self, index: usize) -> Option<Brush> {
108        for run in self.0.iter().rev() {
109            if run.range.contains(&(index as u32)) && run.brush().is_some() {
110                return Some(run.brush().unwrap().clone());
111            }
112        }
113        None
114    }
115    /// Find whether the text shadow is enabled at the given position.
116    pub fn shadow_at(&self, index: usize) -> Option<bool> {
117        for run in self.0.iter().rev() {
118            if run.range.contains(&(index as u32)) && run.shadow().is_some() {
119                return Some(run.shadow().unwrap());
120            }
121        }
122        None
123    }
124    /// Find the shadow brush at the given position.
125    pub fn shadow_brush_at(&self, index: usize) -> Option<Brush> {
126        for run in self.0.iter().rev() {
127            if run.range.contains(&(index as u32)) && run.shadow_brush().is_some() {
128                return Some(run.shadow_brush().unwrap().clone());
129            }
130        }
131        None
132    }
133    /// Find the shadow dilation at the given position.
134    pub fn shadow_dilation_at(&self, index: usize) -> Option<f32> {
135        for run in self.0.iter().rev() {
136            if run.range.contains(&(index as u32)) && run.shadow_dilation().is_some() {
137                return Some(run.shadow_dilation().unwrap());
138            }
139        }
140        None
141    }
142    /// Find the shadow offset at the given position.
143    pub fn shadow_offset_at(&self, index: usize) -> Option<Vector2<f32>> {
144        for run in self.0.iter().rev() {
145            if run.range.contains(&(index as u32)) && run.shadow_offset().is_some() {
146                return Some(run.shadow_offset().unwrap());
147            }
148        }
149        None
150    }
151}
152
153/// The style of a portion of text within a range.
154#[derive(Clone, PartialEq, Debug, Default, Visit, Reflect, TypeUuidProvider)]
155#[type_uuid(id = "f0e5cc5d-0b82-4d6f-a505-12f890ffe7ea")]
156pub struct Run {
157    /// The range of characters that this run applies to within the text.
158    pub range: Range<u32>,
159    font: Option<FontResource>,
160    brush: Option<Brush>,
161    font_size: Option<f32>,
162    shadow: Option<bool>,
163    shadow_brush: Option<Brush>,
164    shadow_dilation: Option<f32>,
165    shadow_offset: Option<Vector2<f32>>,
166}
167
168impl Run {
169    /// Create a run that sets no formatting values across the given range.
170    pub fn new(range: Range<u32>) -> Self {
171        Self {
172            range,
173            font: None,
174            brush: None,
175            font_size: None,
176            shadow: None,
177            shadow_brush: None,
178            shadow_dilation: None,
179            shadow_offset: None,
180        }
181    }
182    /// The font of the characters in this run, or None if the font is unmodified.
183    pub fn font(&self) -> Option<&FontResource> {
184        self.font.as_ref()
185    }
186    /// The brush of the characters in this run, or None if the brush is unmodified.
187    pub fn brush(&self) -> Option<&Brush> {
188        self.brush.as_ref()
189    }
190    /// The size of the characters in this run, or None if the size is unmodified.
191    pub fn font_size(&self) -> Option<f32> {
192        self.font_size
193    }
194    /// True if the characters in this run should have a shadow. None if this run does not change
195    /// whether the characters are shadowed.
196    pub fn shadow(&self) -> Option<bool> {
197        self.shadow
198    }
199    /// The brush for the shadow of the characters in this run, or None if the brush is unmodified.
200    pub fn shadow_brush(&self) -> Option<&Brush> {
201        self.shadow_brush.as_ref()
202    }
203    /// The dilation for the shadow in this run, or None if the dilation is unmodified.
204    pub fn shadow_dilation(&self) -> Option<f32> {
205        self.shadow_dilation
206    }
207    /// The offset for the shadow in this run, or None if the offset is unmodified.
208    pub fn shadow_offset(&self) -> Option<Vector2<f32>> {
209        self.shadow_offset
210    }
211    #[deprecated]
212    pub fn build(self) -> Self {
213        self
214    }
215    /// Set this run to match the values set in the given run, overwriting the values
216    /// in this run only if the corresponding value is set in the given run.
217    pub fn with_values_from(self, run: Run) -> Self {
218        Self {
219            range: self.range,
220            font: run.font.or(self.font),
221            brush: run.brush.or(self.brush),
222            font_size: run.font_size.or(self.font_size),
223            shadow: run.shadow.or(self.shadow),
224            shadow_brush: run.shadow_brush.or(self.shadow_brush),
225            shadow_dilation: run.shadow_dilation.or(self.shadow_dilation),
226            shadow_offset: run.shadow_offset.or(self.shadow_offset),
227        }
228    }
229    /// Set this run to modify the font of the text within the range.
230    pub fn with_font(mut self, font: FontResource) -> Self {
231        self.font = Some(font);
232        self
233    }
234    /// Set this run to modify the brush of the text within the range.
235    pub fn with_brush(mut self, brush: Brush) -> Self {
236        self.brush = Some(brush);
237        self
238    }
239    /// Set this run to modify the size of the text within the range.
240    pub fn with_size(mut self, size: f32) -> Self {
241        self.font_size = Some(size);
242        self
243    }
244    /// Set this run to enable or disable the shadow of the text within the range.
245    pub fn with_shadow(mut self, shadow: bool) -> Self {
246        self.shadow = Some(shadow);
247        self
248    }
249    /// Set this run to modify the brush of the shadow within the range.
250    pub fn with_shadow_brush(mut self, brush: Brush) -> Self {
251        self.shadow_brush = Some(brush);
252        self
253    }
254    /// Set this run to modify the dilation of the shadow within the range.
255    pub fn with_shadow_dilation(mut self, size: f32) -> Self {
256        self.shadow_dilation = Some(size);
257        self
258    }
259    /// Set this run to modify the offset of the shadow within the range.
260    pub fn with_shadow_offset(mut self, offset: Vector2<f32>) -> Self {
261        self.shadow_offset = Some(offset);
262        self
263    }
264}
265
266#[derive(Clone, Copy, Eq, PartialEq)]
267pub enum DrawValueLayer {
268    Main,
269    Shadow,
270}
271
272#[derive(Clone, PartialEq, Debug)]
273pub struct GlyphDrawValues {
274    pub atlas_page_index: usize,
275    pub font: FontResource,
276    pub brush: Brush,
277    /// Font size scaled by super sampling scaling to pick the correct atlas page.
278    pub height: FontHeight,
279}