use super::length::{FontContext, Length, LengthContext, Viewport};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TextAlign {
Left,
Center,
Right,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FontWeight {
Normal,
Bold,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FontStyleKind {
Normal,
Italic,
Oblique,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TextDecoration {
None,
Underline,
LineThrough,
UnderlineLineThrough,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TextTransform {
#[default]
None,
Uppercase,
Lowercase,
Capitalize,
}
#[doc(hidden)]
pub fn parse_text_transform(s: &str) -> Option<TextTransform> {
match s.trim().to_ascii_lowercase().as_str() {
"none" => Some(TextTransform::None),
"uppercase" => Some(TextTransform::Uppercase),
"lowercase" => Some(TextTransform::Lowercase),
"capitalize" => Some(TextTransform::Capitalize),
_ => None,
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LineHeight {
Normal,
Number(f32),
Length(Length),
}
#[doc(hidden)]
pub fn parse_line_height(s: &str) -> Option<LineHeight> {
let s = s.trim();
if s.eq_ignore_ascii_case("normal") {
return Some(LineHeight::Normal);
}
if let Ok(n) = s.parse::<f32>() {
return Some(LineHeight::Number(n));
}
Length::parse(s).map(LineHeight::Length)
}
pub fn resolve_line_height_cells(
line_height: LineHeight,
font_size_cells: usize,
font_ctx: FontContext,
viewport: Viewport,
) -> usize {
let font = font_size_cells.max(1);
match line_height {
LineHeight::Normal => font,
LineHeight::Number(n) => (n * font as f32).round().max(1.0) as usize,
LineHeight::Length(len) => match len {
Length::Pct(p) => ((p / 100.0) * font as f32).round().max(1.0) as usize,
other => other
.resolve(LengthContext {
containing: 0,
font: font_ctx,
viewport,
})
.max(1),
},
}
}
pub fn glyph_row_within_line(font_cells: usize, line_height_cells: usize) -> usize {
let font = font_cells.max(1);
let line_h = line_height_cells.max(1);
if line_h > font {
(line_h - font) / 2
} else {
font.saturating_sub(1) / 2
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum WhiteSpace {
#[default]
Normal,
Pre,
NoWrap,
PreWrap,
PreLine,
}
impl WhiteSpace {
pub const fn preserves_whitespace(self) -> bool {
matches!(self, WhiteSpace::Pre | WhiteSpace::PreWrap)
}
pub const fn allows_wrap(self) -> bool {
matches!(
self,
WhiteSpace::Normal | WhiteSpace::PreWrap | WhiteSpace::PreLine
)
}
}
#[doc(hidden)]
pub fn parse_white_space(s: &str) -> Option<WhiteSpace> {
match s.trim().to_ascii_lowercase().as_str() {
"normal" => Some(WhiteSpace::Normal),
"pre" => Some(WhiteSpace::Pre),
"nowrap" => Some(WhiteSpace::NoWrap),
"pre-wrap" => Some(WhiteSpace::PreWrap),
"pre-line" => Some(WhiteSpace::PreLine),
_ => None,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum WordBreak {
#[default]
Normal,
BreakAll,
KeepAll,
}
#[doc(hidden)]
pub fn parse_word_break(s: &str) -> Option<WordBreak> {
match s.trim().to_ascii_lowercase().as_str() {
"normal" => Some(WordBreak::Normal),
"break-all" => Some(WordBreak::BreakAll),
"keep-all" => Some(WordBreak::KeepAll),
_ => None,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum OverflowWrap {
#[default]
Normal,
BreakWord,
Anywhere,
}
#[doc(hidden)]
pub fn parse_overflow_wrap(s: &str) -> Option<OverflowWrap> {
match s.trim().to_ascii_lowercase().as_str() {
"normal" => Some(OverflowWrap::Normal),
"break-word" => Some(OverflowWrap::BreakWord),
"anywhere" => Some(OverflowWrap::Anywhere),
_ => None,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum UserSelect {
#[default]
Auto,
None,
Text,
All,
Contain,
}
#[doc(hidden)]
pub fn parse_user_select(s: &str) -> Option<UserSelect> {
match s.trim().to_ascii_lowercase().as_str() {
"auto" => Some(UserSelect::Auto),
"none" => Some(UserSelect::None),
"text" => Some(UserSelect::Text),
"all" => Some(UserSelect::All),
"contain" => Some(UserSelect::Contain),
"element" => Some(UserSelect::Contain),
_ => None,
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TextOverflow {
#[default]
Clip,
Ellipsis,
}
pub fn parse_text_overflow(s: &str) -> Option<TextOverflow> {
match s.trim().to_ascii_lowercase().as_str() {
"clip" => Some(TextOverflow::Clip),
"ellipsis" => Some(TextOverflow::Ellipsis),
_ => None,
}
}