summaryrefslogtreecommitdiff
path: root/src/layout/text.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2019-06-21 21:37:29 +0200
committerLaurenz <laurmaedje@gmail.com>2019-06-21 21:41:02 +0200
commit968e121697a96a2e3b05a560176c34f4bb6693c3 (patch)
treeb937cf208d7a8bfb318227a46e44f91da4ef7a49 /src/layout/text.rs
parentb53ad6b1ec8b2fd05566a83c9b895f265e61d281 (diff)
Implement flex and box layouting 📏
Diffstat (limited to 'src/layout/text.rs')
-rw-r--r--src/layout/text.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/src/layout/text.rs b/src/layout/text.rs
new file mode 100644
index 00000000..8aa76c4c
--- /dev/null
+++ b/src/layout/text.rs
@@ -0,0 +1,62 @@
+//! Layouting of text into boxes.
+
+use crate::doc::TextAction;
+use crate::font::FontQuery;
+use crate::size::{Size, Size2D};
+use super::*;
+
+
+/// The context for text layouting.
+#[derive(Debug, Clone)]
+pub struct TextContext<'a, 'p> {
+ /// Loads fonts matching queries.
+ pub loader: &'a FontLoader<'p>,
+ /// Base style to set text with.
+ pub style: TextStyle,
+}
+
+/// Layout one piece of text without any breaks as one continous box.
+pub fn layout(text: &str, ctx: &TextContext) -> LayoutResult<BoxLayout> {
+ let mut actions = Vec::new();
+ let mut active_font = std::usize::MAX;
+ let mut buffer = String::new();
+ let mut width = Size::zero();
+
+ // Walk the characters.
+ for character in text.chars() {
+ // Retrieve the best font for this character.
+ let (index, font) = ctx.loader.get(FontQuery {
+ families: ctx.style.font_families.clone(),
+ italic: ctx.style.italic,
+ bold: ctx.style.bold,
+ character,
+ }).ok_or_else(|| LayoutError::NoSuitableFont(character))?;
+
+ // Add the char width to the total box width.
+ let char_width = font.widths[font.map(character) as usize] * ctx.style.font_size;
+ width += char_width;
+
+ // Change the font if necessary.
+ if active_font != index {
+ if !buffer.is_empty() {
+ actions.push(TextAction::WriteText(buffer));
+ buffer = String::new();
+ }
+
+ actions.push(TextAction::SetFont(index, ctx.style.font_size));
+ active_font = index;
+ }
+
+ buffer.push(character);
+ }
+
+ // Write the remaining characters.
+ if !buffer.is_empty() {
+ actions.push(TextAction::WriteText(buffer));
+ }
+
+ Ok(BoxLayout {
+ dimensions: Size2D::new(width, Size::points(ctx.style.font_size)),
+ actions,
+ })
+}