use std::collections::HashMap;
use std::fmt;
#[derive(Debug, Clone)]
pub struct Pango<'a> {
content: &'a str,
options: HashMap<&'static str, &'a str>,
}
impl<'a> Pango<'a> {
pub fn new(content: &'a str) -> Pango<'_> {
Pango {
content,
options: HashMap::new(),
}
}
pub fn with_capacity(content: &'a str, size: usize) -> Pango<'_> {
Pango {
content,
options: HashMap::with_capacity(size),
}
}
pub fn build(&mut self) -> String {
self.to_string()
}
pub fn build_content(&self, content: &str) -> String {
self.to_string_with_content(content)
}
pub fn font_description(&mut self, font: &'a str) -> &mut Self {
self.options.insert("font_desc", font);
self
}
pub fn font_family(&mut self, family: FontFamily) -> &mut Self {
self.options.insert(
"face",
match family {
FontFamily::Normal => "normal",
FontFamily::Sans => "sans",
FontFamily::Serif => "serif",
FontFamily::Monospace => "monospace",
},
);
self
}
pub fn size(&mut self, size: FontSize) -> &mut Self {
self.options.insert(
"size",
match size {
FontSize::VeryTiny => "xx-small",
FontSize::Tiny => "x-small",
FontSize::Small => "small",
FontSize::Normal => "medium",
FontSize::Large => "large",
FontSize::Huge => "x-large",
FontSize::VeryHuge => "xx-large",
FontSize::Smaller => "smaller",
FontSize::Larger => "larger",
},
);
self
}
pub fn slant_style(&mut self, style: SlantStyle) -> &mut Self {
self.options.insert(
"style",
match style {
SlantStyle::Normal => "normal",
SlantStyle::Oblique => "oblique",
SlantStyle::Italic => "italic",
},
);
self
}
pub fn weight(&mut self, weight: Weight) -> &mut Self {
self.options.insert(
"weight",
match weight {
Weight::Thin => "100",
Weight::UltraLight => "ultralight",
Weight::Light => "light",
Weight::Normal => "normal",
Weight::Medium => "500",
Weight::SemiBold => "600",
Weight::Bold => "bold",
Weight::UltraBold => "ultrabold",
Weight::Heavy => "heavy",
Weight::UltraHeavy => "1000",
},
);
self
}
pub fn alpha(&mut self, alpha: &'a str) -> &mut Self {
self.options.insert("alpha", alpha);
self
}
pub fn small_caps(&mut self) -> &mut Self {
self.options.insert("variant", "smallcaps");
self
}
pub fn stretch(&mut self, stretch: FontStretch) -> &mut Self {
self.options.insert(
"stretch",
match stretch {
FontStretch::UltraCondensed => "ultracondensed",
FontStretch::ExtraCondensed => "extracondensed",
FontStretch::Condensed => "condensed",
FontStretch::SemiCondensed => "semicondensed",
FontStretch::Normal => "normal",
FontStretch::SemiExpanded => "semiexpanded",
FontStretch::Expanded => "expanded",
FontStretch::ExtraExpanded => "extraexpanded",
FontStretch::UltraExpanded => "ultraexpanded",
},
);
self
}
pub fn fg_color(&mut self, color: &'a str) -> &mut Self {
self.options.insert("foreground", color);
self
}
pub fn bg_color(&mut self, color: &'a str) -> &mut Self {
self.options.insert("background", color);
self
}
pub fn underline(&mut self, underline: Underline) -> &mut Self {
self.options.insert(
"underline",
match underline {
Underline::None => "none",
Underline::Single => "single",
Underline::Double => "double",
Underline::Low => "low",
},
);
self
}
pub fn strike_through(&mut self) -> &mut Self {
self.options.insert("strikethrough", "true");
self
}
fn to_string_with_content(&self, content: &str) -> String {
if self.options.is_empty() {
content.to_string()
} else {
format!(
"<span {}>{}</span>",
self.options
.iter()
.map(|(k, v)| format!("{}='{}'", k, v))
.collect::<Vec<String>>()
.join(" "),
content
)
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum FontFamily {
Normal,
Sans,
Serif,
Monospace,
}
#[derive(Debug, Clone, Copy)]
pub enum FontSize {
VeryTiny,
Tiny,
Small,
Normal,
Large,
Huge,
VeryHuge,
Smaller,
Larger,
}
#[derive(Debug, Clone, Copy)]
pub enum SlantStyle {
Normal,
Oblique,
Italic,
}
#[derive(Debug, Clone, Copy)]
pub enum Weight {
Thin,
UltraLight,
Light,
Normal,
Medium,
SemiBold,
Bold,
UltraBold,
Heavy,
UltraHeavy,
}
#[derive(Debug, Clone, Copy)]
pub enum FontStretch {
UltraCondensed,
ExtraCondensed,
Condensed,
SemiCondensed,
Normal,
SemiExpanded,
Expanded,
ExtraExpanded,
UltraExpanded,
}
#[derive(Debug, Clone, Copy)]
pub enum Underline {
None,
Single,
Double,
Low,
}
impl<'a> fmt::Display for Pango<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.options.is_empty() {
write!(f, "{}", self.content)
} else {
write!(f, "<span")?;
for (k, v) in self.options.iter() {
write!(f, " {}='{}'", k, v)?;
}
write!(f, ">{}</span>", self.content)
}
}
}