use std::fmt::Write;
use std::hash::{Hash, Hasher};
use super::ToCss;
macro_rules! enum_property {
(
$(#[$meta:meta])*
$vis:vis enum $name:ident {
$(
$(#[$variant_meta:meta])*
$variant:ident => $css:literal
),* $(,)?
}
) => {
$(#[$meta])*
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
$vis enum $name {
$(
$(#[$variant_meta])*
$variant,
)*
}
impl $name {
#[inline]
pub fn as_str(&self) -> &'static str {
match self {
$($name::$variant => $css,)*
}
}
#[inline]
pub fn from_css(s: &str) -> Option<Self> {
match s {
$($css => Some($name::$variant),)*
_ => None,
}
}
}
impl ToCss for $name {
fn to_css(&self, buf: &mut String) {
buf.push_str(self.as_str());
}
}
};
}
pub(crate) use enum_property;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct FontWeight(pub u16);
impl FontWeight {
pub const NORMAL: FontWeight = FontWeight(400);
pub const BOLD: FontWeight = FontWeight(700);
}
impl ToCss for FontWeight {
fn to_css(&self, buf: &mut String) {
match self.0 {
400 => buf.push_str("normal"),
700 => buf.push_str("bold"),
w => write!(buf, "{}", w).unwrap(),
}
}
}
enum_property! {
pub enum FontStyle {
#[default]
Normal => "normal",
Italic => "italic",
Oblique => "oblique",
}
}
enum_property! {
pub enum FontVariant {
#[default]
Normal => "normal",
SmallCaps => "small-caps",
}
}
enum_property! {
pub enum TextTransform {
#[default]
None => "none",
Uppercase => "uppercase",
Lowercase => "lowercase",
Capitalize => "capitalize",
}
}
enum_property! {
pub enum Hyphens {
Auto => "auto",
#[default]
Manual => "manual",
None => "none",
}
}
enum_property! {
pub enum DecorationStyle {
#[default]
None => "none",
Solid => "solid",
Dotted => "dotted",
Dashed => "dashed",
Double => "double",
}
}
enum_property! {
pub enum Float {
#[default]
None => "none",
Left => "left",
Right => "right",
}
}
enum_property! {
pub enum BreakValue {
#[default]
Auto => "auto",
Always => "always",
Avoid => "avoid",
Column => "column",
}
}
enum_property! {
pub enum BorderStyle {
#[default]
None => "none",
Solid => "solid",
Dotted => "dotted",
Dashed => "dashed",
Double => "double",
Groove => "groove",
Ridge => "ridge",
Inset => "inset",
Outset => "outset",
}
}
enum_property! {
pub enum ListStylePosition {
#[default]
Outside => "outside",
Inside => "inside",
}
}
enum_property! {
pub enum Visibility {
#[default]
Visible => "visible",
Hidden => "hidden",
Collapse => "collapse",
}
}
enum_property! {
pub enum BoxSizing {
#[default]
ContentBox => "content-box",
BorderBox => "border-box",
}
}
enum_property! {
pub enum Clear {
#[default]
None => "none",
Left => "left",
Right => "right",
Both => "both",
}
}
enum_property! {
pub enum WordBreak {
#[default]
Normal => "normal",
BreakAll => "break-all",
KeepAll => "keep-all",
BreakWord => "break-word",
}
}
enum_property! {
pub enum OverflowWrap {
#[default]
Normal => "normal",
BreakWord => "break-word",
Anywhere => "anywhere",
}
}
enum_property! {
pub enum WhiteSpace {
#[default]
Normal => "normal",
Nowrap => "nowrap",
Pre => "pre",
PreWrap => "pre-wrap",
PreLine => "pre-line",
}
}
enum_property! {
pub enum VerticalAlign {
#[default]
Baseline => "baseline",
Top => "top",
Middle => "middle",
Bottom => "bottom",
TextTop => "text-top",
TextBottom => "text-bottom",
Super => "super",
Sub => "sub",
}
}
enum_property! {
pub enum BorderCollapse {
#[default]
Separate => "separate",
Collapse => "collapse",
}
}
enum_property! {
pub enum TextAlign {
#[default]
Start => "start",
End => "end",
Left => "left",
Right => "right",
Center => "center",
Justify => "justify",
}
}
enum_property! {
pub enum Display {
#[default]
Block => "block",
Inline => "inline",
InlineBlock => "inline-block",
None => "none",
ListItem => "list-item",
TableCell => "table-cell",
TableRow => "table-row",
}
}
enum_property! {
pub enum ListStyleType {
None => "none",
#[default]
Disc => "disc",
Circle => "circle",
Square => "square",
Decimal => "decimal",
LowerAlpha => "lower-alpha",
UpperAlpha => "upper-alpha",
LowerRoman => "lower-roman",
UpperRoman => "upper-roman",
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Color {
pub r: u8,
pub g: u8,
pub b: u8,
pub a: u8,
}
impl Color {
pub const BLACK: Color = Color {
r: 0,
g: 0,
b: 0,
a: 255,
};
pub const WHITE: Color = Color {
r: 255,
g: 255,
b: 255,
a: 255,
};
pub const TRANSPARENT: Color = Color {
r: 0,
g: 0,
b: 0,
a: 0,
};
pub fn rgb(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b, a: 255 }
}
pub fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
Self { r, g, b, a }
}
}
impl ToCss for Color {
fn to_css(&self, buf: &mut String) {
if self.a == 255 {
write!(buf, "#{:02x}{:02x}{:02x}", self.r, self.g, self.b).unwrap();
} else if self.a == 0 {
buf.push_str("transparent");
} else {
let alpha = self.a as f32 / 255.0;
write!(buf, "rgba({},{},{},{:.2})", self.r, self.g, self.b, alpha).unwrap();
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub enum Length {
#[default]
Auto,
Px(f32),
Em(f32),
Rem(f32),
Percent(f32),
}
impl Eq for Length {}
impl Hash for Length {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Length::Auto => 0u8.hash(state),
Length::Px(v) => {
1u8.hash(state);
v.to_bits().hash(state);
}
Length::Em(v) => {
2u8.hash(state);
v.to_bits().hash(state);
}
Length::Rem(v) => {
3u8.hash(state);
v.to_bits().hash(state);
}
Length::Percent(v) => {
4u8.hash(state);
v.to_bits().hash(state);
}
}
}
}
impl ToCss for Length {
fn to_css(&self, buf: &mut String) {
match self {
Length::Auto => buf.push_str("auto"),
Length::Px(v) => {
if *v == 0.0 {
buf.push('0');
} else {
write!(buf, "{}px", v).unwrap();
}
}
Length::Em(v) => write!(buf, "{}em", v).unwrap(),
Length::Rem(v) => write!(buf, "{}rem", v).unwrap(),
Length::Percent(v) => write!(buf, "{}%", v).unwrap(),
}
}
}