Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add render tree #414

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions crates/gosub_html5/src/parser/document.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
use core::fmt;
use core::fmt::Debug;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::Display;
use std::ops::{Deref, DerefMut};
use std::rc::{Rc, Weak};

use url::Url;

use gosub_css3::stylesheet::CssStylesheet;
use gosub_shared::types::Result;

use crate::element_class::ElementClass;
use crate::errors::Error;
use crate::node::arena::NodeArena;
Expand All @@ -11,16 +24,6 @@ use crate::parser::quirks::QuirksMode;
use crate::parser::tree_builder::TreeBuilder;
use crate::util::is_valid_id_attribute_value;
use crate::visit::Visitor;
use core::fmt;
use core::fmt::Debug;
use gosub_css3::stylesheet::CssStylesheet;
use gosub_shared::types::Result;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt::Display;
use std::ops::{Deref, DerefMut};
use std::rc::{Rc, Weak};
use url::Url;

/// Type of the given document
#[derive(PartialEq, Debug, Copy, Clone)]
Expand Down Expand Up @@ -276,6 +279,9 @@ impl Document {
}
}

pub fn count_nodes(&self) -> usize {
self.arena.count_nodes()
}
/// Returns a shared reference-counted handle for the document
pub fn shared(location: Option<Url>) -> DocumentHandle {
DocumentHandle(Rc::new(RefCell::new(Self::new(location))))
Expand Down Expand Up @@ -1019,12 +1025,13 @@ impl Iterator for TreeIterator {

#[cfg(test)]
mod tests {
use std::collections::HashMap;

use crate::node::{NodeTrait, NodeType, HTML_NAMESPACE};
use crate::parser::document::{DocumentBuilder, DocumentTaskQueue, TreeIterator};
use crate::parser::query::Query;
use crate::parser::tree_builder::TreeBuilder;
use crate::parser::{Node, NodeData, NodeId};
use std::collections::HashMap;

#[test]
fn relocate() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,91 +1,22 @@
use crate::css_colors::RgbColor;
use core::fmt::Debug;
use gosub_css3::stylesheet::{
CssOrigin, CssSelector, CssSelectorPart, CssSelectorType, MatcherType, Specificity,
};
use gosub_html5::node::NodeId;
use gosub_html5::parser::document::{DocumentHandle, TreeIterator};
use gosub_shared::types::Result;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::fmt::Display;

/// Generates a css node tree for the given document based on its loaded stylesheets
pub fn generate_css_node_tree(document: DocumentHandle) -> Result<CssNodeTree> {
// Restart css map
let mut css_node_tree = CssNodeTree::new(DocumentHandle::clone(&document));

// Iterate the complete document tree
let tree_iterator = TreeIterator::new(&document);
for current_node_id in tree_iterator {
let mut css_map_entry = CssProperties::new();

let binding = document.get();
let node = binding
.get_node_by_id(current_node_id)
.expect("node not found");
if !node.is_element() {
continue;
}

for sheet in document.get().stylesheets.iter() {
for rule in sheet.rules.iter() {
for selector in rule.selectors().iter() {
if !match_selector(DocumentHandle::clone(&document), current_node_id, selector)
{
continue;
}

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

let declaration = DeclarationProperty {
value: CssValue::String(declaration.value.clone()), // @TODO: parse the value into the correct CSSValue
origin: sheet.origin.clone(),
important: declaration.important,
location: sheet.location.clone(),
specificity: selector.specificity(),
};

if let std::collections::hash_map::Entry::Vacant(e) =
css_map_entry.properties.entry(prop_name.clone())
{
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(&prop_name).unwrap();
entry.declared.push(declaration);
}
}
}
}
}

css_node_tree.nodes.insert(current_node_id, css_map_entry);
}

for (node_id, props) in css_node_tree.nodes.iter() {
println!("Node: {:?}", node_id);
for (prop, values) in props.properties.iter() {
println!(" {}", prop);
if prop == "color" {
for decl in values.declared.iter() {
println!(
" {:?} {:?} {:?} {:?}",
decl.origin, decl.location, decl.value, decl.specificity
);
}
}
}
}
use gosub_css3::stylesheet::{
CssOrigin, CssSelector, CssSelectorPart, CssSelectorType, MatcherType, Specificity,
};
use gosub_html5::node::NodeId;
use gosub_html5::parser::document::DocumentHandle;

Ok(css_node_tree)
}
use crate::css_colors::RgbColor;

// Matches a complete selector (all parts) against the given node(id)
fn match_selector(document: DocumentHandle, node_id: NodeId, selector: &CssSelector) -> bool {
pub(crate) fn match_selector(
document: DocumentHandle,
node_id: NodeId,
selector: &CssSelector,
) -> bool {
let mut parts = selector.parts.clone();
parts.reverse();
match_selector_part(document, node_id, &mut parts)
Expand Down Expand Up @@ -451,7 +382,7 @@ impl CssProperty {
/// Map of all declared values for a single node. Note that these are only the defined properties, not
/// the non-existing properties.
pub struct CssProperties {
properties: HashMap<String, CssProperty>,
pub(crate) properties: HashMap<String, CssProperty>,
}

impl Default for CssProperties {
Expand Down Expand Up @@ -495,58 +426,6 @@ impl Display for CssValue {
}
}

/// Map of all declared values for all nodes in the document
pub struct CssNodeTree {
nodes: HashMap<NodeId, CssProperties>,
document: DocumentHandle,
}

impl CssNodeTree {
/// Creates a new CssNodeTree for the given document
pub fn new(doc: DocumentHandle) -> Self {
Self {
document: doc,
nodes: HashMap::new(),
}
}

/// Returns a clone of the document handle
pub fn get_document(&self) -> DocumentHandle {
DocumentHandle::clone(&self.document)
}

/// Mark the given node as dirty, so it will be recalculated
pub fn mark_dirty(&mut self, node_id: NodeId) {
if let Some(props) = self.nodes.get_mut(&node_id) {
for prop in props.properties.values_mut() {
prop.mark_dirty();
}
}
}

/// Mark the given node as clean, so it will not be recalculated
pub fn mark_clean(&mut self, node_id: NodeId) {
if let Some(props) = self.nodes.get_mut(&node_id) {
for prop in props.properties.values_mut() {
prop.mark_clean();
}
}
}

/// 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> {
let props = self.nodes.get(&node_id);
props?;

props.expect("props").properties.get(prop_name).cloned()
}

/// Retrieves the value for the given property for the given node, or None when not found
pub fn get_all_properties(&self, node_id: NodeId) -> Option<&CssProperties> {
self.nodes.get(&node_id)
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
6 changes: 4 additions & 2 deletions crates/gosub_styling/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
//! This crate connects CSS3 and HTML5 into a styling pipeline
//!

use std::fs;

use gosub_css3::convert::ast_converter::convert_ast_to_stylesheet;
use gosub_css3::parser_config::ParserConfig;
use gosub_css3::stylesheet::{CssOrigin, CssStylesheet};
use gosub_css3::Css3;
use std::fs;

pub mod css_colors;
pub mod css_node_tree;
pub mod css_values;
mod property_list;
pub mod render_tree;

/// Loads the default user agent stylesheet
pub fn load_default_useragent_stylesheet() -> anyhow::Result<CssStylesheet> {
Expand Down
3 changes: 2 additions & 1 deletion crates/gosub_styling/src/property_list.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::css_node_tree::CssValue;
use lazy_static::lazy_static;

use crate::css_values::CssValue;

// Values for this table is taken from https://www.w3.org/TR/CSS21/propidx.html
// Probably not the complete list, but it will do for now

Expand Down
Loading
Loading