Skip to content

Commit

Permalink
chore(innate): add tree leaf building children
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mendez committed Oct 7, 2023
1 parent 451612b commit cb9237c
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 81 deletions.
183 changes: 103 additions & 80 deletions kayle_innate/kayle_innate/src/engine/audit/tree.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,93 @@
use crate::console_log;
use scraper_forky::selector::Simple;
use scraper_forky::ElementRef;
use scraper_forky::Html;
use selectors::matching::MatchingContext;
use slotmap::DefaultKey;
use std::collections::BTreeMap;
use std::collections::HashSet;
use std::sync::Arc;
use taffy::prelude::*;
use victor_tree::style::values::Direction;
use victor_tree::style::values::WritingMode;
use victor_tree::style::ComputedValues;
use victor_tree::style::StyleSet;

lazy_static! {
static ref NODE_IGNORE: HashSet<&'static str> =
HashSet::from(["meta", "style", "link", "script", "head", "html"]);
HashSet::from(["meta", "style", "link", "script", "head", "html", "body"]);
}

/// layout style
pub fn node_layout_style(style: Arc<ComputedValues>) -> Style {
let physical_size = style.box_size().size_to_physical(style.writing_mode());
// todo: determine if all children at the top level have floats set to use flex-row
Style {
// compute the default layout from CDP
size: Size {
width: if physical_size.x.non_auto().is_none() {
Dimension::Auto
} else {
Dimension::Points(physical_size.x.inner_px())
},
height: if physical_size.y.non_auto().is_none() {
Dimension::Auto
} else {
Dimension::Points(physical_size.x.inner_px())
},
},
border: points(style.border_width().inner_px()),
padding: points(style.padding().inner_px()),
margin: points(style.margin().inner_px()),
..Default::default()
}
}

/// get a layout leaf a new leaf
pub fn leaf<'a, 'b, 'c>(
element: &ElementRef,
author: &StyleSet,
document: &'a Html,
mut matching_context: &mut MatchingContext<'c, Simple>,
taffy: &mut Taffy,
) -> DefaultKey {
let mut l_leafs: Vec<Node> = vec![];

for child in element.children() {
match ElementRef::wrap(child) {
Some(element) => {
let name = element.value().name();

if !NODE_IGNORE.contains(name) {
let style = victor_tree::style::cascade::style_for_element_ref(
&element,
&author,
&document,
&mut matching_context,
);
let leaf = taffy.new_leaf(node_layout_style(style));

l_leafs.push(leaf.unwrap())
}
}
_ => (),
}
}

let style = victor_tree::style::cascade::style_for_element_ref(
&element,
&author,
&document,
&mut matching_context,
);

let leaf_style = node_layout_style(style);

// build leaf with children
if l_leafs.len() > 0 {
taffy.new_with_children(leaf_style, &l_leafs)
} else {
taffy.new_leaf(leaf_style)
}
.unwrap()
}

/// try to fix all possible issues using a spec against the tree.
Expand All @@ -25,91 +100,34 @@ pub fn parse_accessibility_tree<'a, 'b, 'c>(
Taffy,
MatchingContext<'c, Simple>,
) {
// // todo: use optional variable for clips or layout creation
// TODO: make layout optional
let mut taffy = Taffy::new();

// let header_node: DefaultKey = taffy
// .new_leaf(Style {
// size: Size {
// width: points(800.0),
// height: points(100.0),
// },
// ..Default::default()
// })
// .unwrap();

// let body_node = taffy
// .new_leaf(Style {
// size: Size {
// width: points(800.0),
// height: auto(),
// },
// flex_grow: 1.0,
// ..Default::default()
// })
// .unwrap();

// We can get the x,y, and height, width of the element on proper tree insert

// parse doc will start from html downwards
// accessibility tree for ordered element mappings
let mut accessibility_tree: BTreeMap<&str, Vec<(ElementRef<'_>, DefaultKey)>> =
BTreeMap::from([("title".into(), Default::default())]);

let mut layout_leafs: Vec<Node> = vec![];

// let mut _match_context = match_context;

let mut matching_context = match_context;
let writing_direction = (WritingMode::HorizontalTb, Direction::Ltr);
let mut layout_leafs: Vec<Node> = vec![];

// push taffy layout in order from elements
for node in document.tree.nodes() {
match scraper_forky::element_ref::ElementRef::wrap(node) {
match ElementRef::wrap(node) {
Some(element) => {
let name = element.value().name();
// TODO: determine if children are found to get entire layout of children to vector first
let layout_leaf = taffy
.new_leaf(Style {
// make nodes optional but, for now max out perf drawbacks
size: if NODE_IGNORE.contains(name) {
Size {
width: points(0.0),
height: points(0.0),
}
} else {
let style = victor_tree::style::cascade::style_for_element_ref(
&element,
&author,
&document,
&mut matching_context,
);
let style = style.as_ref();
let _physical_size =
style.box_size().size_to_physical(writing_direction);
// TODO: Build physical styles of each element as needed
// crate::console_log!("{name} {:?}", physical_size);
// crate::console_log!("{name} Margin {:?}", style.margin());
// crate::console_log!("{name} Padding {:?}", style.padding());
let padding_insent = style.padding().block_start;
// todo: make method to get entire size
let _padding_pxs = padding_insent.inner_px();
// crate::console_log!("{name} Padding Top {:?}", padding_pxs);
// IF the x and y is empty get the height based on the padding.
// If img has no height get the inherited from style width
// We may have to build the width/height if empty from paddings and margins
// TODO: use flex if element has a x or y but, not both to flex out entire layout.

Size {
width: points(800.0),
height: points(100.0),
}
},
// todo: get entire styles up front
flex_grow: if name == "body" { 1.0 } else { 0.0 },
..Default::default()
})
.unwrap();
let layout_leaf = {
if NODE_IGNORE.contains(name) {
taffy.new_leaf(Default::default()).unwrap()
} else {
// all leafs created must be put into the body node at the end
console_log!("{name}");
leaf(
&element,
&author,
document,
&mut matching_context,
&mut taffy,
)
}
};

layout_leafs.push(layout_leaf.clone());

Expand All @@ -122,7 +140,6 @@ pub fn parse_accessibility_tree<'a, 'b, 'c>(
};
}

// this is slow at the moment for large leafs being mocked
let root_node = taffy
.new_with_children(
Style {
Expand All @@ -138,8 +155,14 @@ pub fn parse_accessibility_tree<'a, 'b, 'c>(
)
.unwrap();

console_log!("Layout leafs {:?}", layout_leafs.len());

// TODO: set the root node to html, body in the accessibility_tree
taffy.compute_layout(root_node, Size::MAX_CONTENT).unwrap();
// crate::console_log!("Last Element Position {:?}", taffy.layout(layout_leafs[layout_leafs.len() - 1]).unwrap());

for lea in layout_leafs {
crate::console_log!("Leaf Position {:?}", taffy.layout(lea).unwrap());
}
// console_log!("Getting tree links {:?}", accessibility_tree.get("a"));
// console_log!("Tree {:?}", accessibility_tree);

Expand Down
44 changes: 44 additions & 0 deletions kayle_innate/kayle_victor/victor/src/geom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ pub use crate::style::values::Length;
use crate::style::values::{LengthOrAuto, LengthOrPercentage, LengthOrPercentageOrAuto};

pub mod physical {
use crate::style::values::LengthOrPercentage;

#[derive(Debug, Clone)]
pub struct Vec2<T> {
pub x: T,
Expand All @@ -21,6 +23,24 @@ pub mod physical {
pub bottom: T,
pub right: T,
}

impl Sides<LengthOrPercentage> {
pub fn inner_px(&self) -> f32 {
let b = Self::get_px::<LengthOrPercentage>(self.bottom);
let t = Self::get_px::<LengthOrPercentage>(self.top);
let l = Self::get_px::<LengthOrPercentage>(self.left);
let r = Self::get_px::<LengthOrPercentage>(self.left);

b + t + l + r
}

pub fn get_px<T>(v: LengthOrPercentage) -> f32 {
match v {
LengthOrPercentage::Length(l) => l.px,
LengthOrPercentage::Percentage(l) => l.unit_value,
}
}
}
}

pub mod flow_relative {
Expand All @@ -43,6 +63,30 @@ pub mod flow_relative {
pub block_start: T,
pub block_end: T,
}

impl Sides<crate::style::values::LengthOrPercentage> {
/// inner pxs added up
pub fn inner_px(&self) -> f32 {
let is = self.inline_start.inner_px();
let ie = self.inline_end.inner_px();
let bs = self.block_start.inner_px();
let be = self.block_end.inner_px();

is + ie + bs + be
}
}

impl Sides<crate::style::values::LengthOrPercentageOrAuto> {
/// inner pxs added up
pub fn inner_px(&self) -> f32 {
let is = self.inline_start.inner_px();
let ie = self.inline_end.inner_px();
let bs = self.block_start.inner_px();
let be = self.block_end.inner_px();

is + ie + bs + be
}
}
}

use crate::style::values::{Direction, WritingMode};
Expand Down
10 changes: 9 additions & 1 deletion kayle_innate/kayle_victor/victor/src/style/values/length.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub struct Length {
#[repr(transparent)]
#[derive(Copy, Clone, SpecifiedAsComputed)]
pub struct Percentage {
unit_value: f32,
pub unit_value: f32,
}

/// <https://drafts.csswg.org/css-values/#lengths>
Expand Down Expand Up @@ -235,6 +235,14 @@ impl From<LengthOrPercentage> for LengthOrPercentageOrAuto {
}

impl LengthOrPercentageOrAuto {
pub fn inner_px(&self) -> f32 {
match self {
LengthOrPercentageOrAuto::Length(l) => l.px,
LengthOrPercentageOrAuto::Percentage(l) => l.unit_value,
LengthOrPercentageOrAuto::Auto => 0.0,
}
}

pub fn non_auto(&self) -> Option<LengthOrPercentage> {
match *self {
LengthOrPercentageOrAuto::Length(l) => Some(LengthOrPercentage::Length(l)),
Expand Down

0 comments on commit cb9237c

Please sign in to comment.