Skip to content

Commit

Permalink
up
Browse files Browse the repository at this point in the history
  • Loading branch information
jaytaph committed Mar 17, 2024
1 parent 9dbc585 commit d6e7a57
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 160 deletions.
112 changes: 74 additions & 38 deletions crates/gosub_styling/src/css_node_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub fn generate_css_node_tree(document: DocumentHandle) -> Result<CssNodeTree> {

// Selector matched, so we add all declared values to the map
for declaration in rule.declarations().iter() {
let property = declaration.property.clone();
let prop_name = declaration.property.clone();

let declaration = DeclarationProperty {
value: CssValue::String(declaration.value.clone()), // @TODO: parse the value into the correct CSSValue
Expand All @@ -46,13 +46,13 @@ pub fn generate_css_node_tree(document: DocumentHandle) -> Result<CssNodeTree> {
};

if let std::collections::hash_map::Entry::Vacant(e) =
css_map_entry.properties.entry(property.clone())
css_map_entry.properties.entry(prop_name.clone())
{
let mut entry = CssProperty::new();
let mut entry = CssProperty::new(prop_name.as_str());
entry.declared.push(declaration);
e.insert(entry);
} else {
let entry = css_map_entry.properties.get_mut(&property).unwrap();
let entry = css_map_entry.properties.get_mut(&prop_name).unwrap();
entry.declared.push(declaration);
}
}
Expand Down Expand Up @@ -302,6 +302,8 @@ impl Ord for DeclarationProperty {
/// all the computed values.
#[derive(Debug, Clone)]
pub struct CssProperty {
/// The name of the property
pub name: String,
/// True when this property needs to be recalculated
pub dirty: bool,
/// List of all declared values for this property
Expand All @@ -317,15 +319,10 @@ pub struct CssProperty {
pub actual: CssValue,
}

impl Default for CssProperty {
fn default() -> Self {
Self::new()
}
}

impl CssProperty {
pub fn new() -> Self {
pub fn new(prop_name: &str) -> Self {
Self {
name: prop_name.to_string(),
dirty: true,
declared: Vec::new(),
cascaded: None,
Expand Down Expand Up @@ -355,17 +352,58 @@ impl CssProperty {
}

fn calculate_value(&mut self) {
// Step 1: Find cascaded value
self.cascaded = self.find_cascaded_value();
self.specified = self.find_specified_value();
self.computed = self.find_computed_value();
self.used = self.find_used_value();
self.actual = self.find_actual_value();
}

fn find_cascaded_value(&self) -> Option<CssValue> {
let mut declared = self.declared.clone();

declared.sort();
declared.sort_by(|a, b| {
if a.priority() == b.priority() {
return Ordering::Equal;
}

a.specificity.cmp(&b.specificity)
});

declared.last().map(|d| d.value.clone())
}

// Step 2: Find specified value
fn find_specified_value(&self) -> CssValue {
match self.declared.iter().max() {
Some(decl) => decl.value.clone(),
None => CssValue::None,
}
}

// Step 3: Find computed value (needs viewport?)
fn find_computed_value(&self) -> CssValue {
if self.specified != CssValue::None {
return self.specified.clone();
}

// Step 4: Find used value (??)
if self.is_inheritable() {
while let Some(parent) = self.get_parent() {
if let Some(parent_value) = parent {
return parent_value.find_computed_value();
}
}
}

// Step 5: Find actual value by rounding numbers (when possible)
self.get_initial_value()
}

fn find_used_value(&self) -> CssValue {
self.computed.clone()
}

fn find_actual_value(&self) -> CssValue {
// @TODO: stuff like clipping and such should occur as well
self.actual = match &self.used {
match &self.used {
CssValue::Number(len) => {
CssValue::Number(len.round())
}
Expand All @@ -378,6 +416,24 @@ impl CssProperty {
_ => self.used.clone()
}
}


// Returns true when the property is inheritable, false otherwise
fn is_inheritable(&self) -> bool {
crate::property_list::PROPERTY_TABLE
.iter()
.find(|entry| entry.name == self.name)
.map(|entry| entry.inheritable)
.unwrap_or(false)
}

// Returns the initial value for the property, if any
fn get_initial_value(&self) -> Option<CssValue> {
crate::property_list::PROPERTY_TABLE
.iter()
.find(|entry| entry.name == self.name)
.map(|entry| entry.initial)
}
}

/// Map of all declared values for a single node. Note that these are only the defined properties, not
Expand All @@ -402,7 +458,7 @@ impl CssProperties {

/// Actual CSS value, can be a color, length, percentage, string or unit. Some relative values will be computed
/// from other values (ie: Percent(50) will convert to Length(100) when the parent width is 200)
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum CssValue {
None,
Color(RgbColor),
Expand Down Expand Up @@ -472,9 +528,6 @@ impl CssNodeTree {

/// Retrieves the property for the given node, or None when not found
pub fn get_property(&self, node_id: NodeId, prop_name: &str) -> Option<CssProperty> {
if node_id == NodeId::from(71) {
println!("get_property({:?}, {})", node_id, prop_name);
}
let props = self.nodes.get(&node_id);
if props.is_none() {
return None;
Expand All @@ -490,23 +543,6 @@ impl CssNodeTree {
pub fn get_all_properties(&self, node_id: NodeId) -> Option<&CssProperties> {
self.nodes.get(&node_id)
}

// Returns true when the property is inheritable, false otherwise
pub fn is_inheritable(&self, prop_name: &str) -> bool {
crate::property_list::PROPERTY_TABLE
.iter()
.find(|entry| entry.name == prop_name)
.map(|entry| entry.inheritable)
.unwrap_or(false)
}

// Returns the initial value for the property, if any
pub fn get_initial_value(&self, prop_name: &str) -> Option<&str> {
crate::property_list::PROPERTY_TABLE
.iter()
.find(|entry| entry.name == prop_name)
.map(|entry| entry.initial)
}
}

#[cfg(test)]
Expand Down
Loading

0 comments on commit d6e7a57

Please sign in to comment.