Skip to main content

mos_layout/
support.rs

1use std::borrow::Cow;
2
3use mos_core::{AttrValue, Node};
4
5use crate::style::pt_to_f32;
6use crate::{Page, PageStyle};
7
8pub(crate) fn blank_page(number: u32, style: PageStyle) -> Page {
9    Page {
10        number,
11        width_pt: style.width_pt,
12        height_pt: style.height_pt,
13        runs: Vec::new(),
14        images: Vec::new(),
15    }
16}
17
18pub(crate) fn read_level(section: &Node) -> Option<u8> {
19    match section.attributes.get("level") {
20        Some(AttrValue::Int(n)) if *n >= 1 => u8::try_from((*n).clamp(1, 255)).ok(),
21        _ => None,
22    }
23}
24
25pub(crate) fn read_str_attr<'a>(node: &'a Node, key: &str) -> Option<&'a str> {
26    match node.attributes.get(key) {
27        Some(AttrValue::Str(s)) => Some(s.as_str()),
28        _ => None,
29    }
30}
31
32pub(crate) fn read_int_attr(node: &Node, key: &str) -> Option<i64> {
33    match node.attributes.get(key) {
34        Some(AttrValue::Int(n)) => Some(*n),
35        _ => None,
36    }
37}
38
39pub(crate) fn read_length_attr(node: &Node, key: &str) -> Option<f32> {
40    match node.attributes.get(key) {
41        Some(AttrValue::Length(pt)) => Some(pt_to_f32(*pt)),
42        _ => None,
43    }
44}
45
46pub(crate) fn expand_tabs(line: &str, tab_width: usize) -> Cow<'_, str> {
47    if !line.contains('\t') {
48        return Cow::Borrowed(line);
49    }
50
51    let tab_width = tab_width.max(1);
52    let mut out = String::with_capacity(line.len());
53    let mut col = 0_usize;
54    for ch in line.chars() {
55        if ch == '\t' {
56            let spaces = tab_width - (col % tab_width);
57            out.extend(std::iter::repeat_n(' ', spaces));
58            col += spaces;
59        } else {
60            out.push(ch);
61            col += 1;
62        }
63    }
64    Cow::Owned(out)
65}