Delete unused old CSS code

This commit is contained in:
Brian Anderson 2012-10-31 19:02:36 -07:00
parent 3fb6cc439d
commit 85293b61ca
7 changed files with 12 additions and 519 deletions

View file

@ -1,79 +0,0 @@
/**
* Applies the appropriate CSS style to nodes.
*/
use au = gfx::geometry;
use css::styles::SpecifiedStyle;
use dom::node::{Node, NodeTree};
use dom::element::*;
use layout::context::LayoutContext;
use image::ImageHolder;
use resource::image_cache_task::ImageCacheTask;
use std::net::url::Url;
use newcss::values::*;
trait ResolveMethods<T> {
pure fn initial() -> T;
}
impl CSSValue<CSSBackgroundColor> : ResolveMethods<CSSBackgroundColor> {
pure fn initial() -> CSSBackgroundColor { return BgColorTransparent; }
}
impl CSSValue<CSSDisplay> : ResolveMethods<CSSDisplay> {
pure fn initial() -> CSSDisplay { return DisplayInline; }
}
impl CSSValue<BoxSizing> : ResolveMethods<BoxSizing> {
pure fn initial() -> BoxSizing { return BoxAuto; }
}
impl CSSValue<CSSFontSize> : ResolveMethods<CSSFontSize> {
pure fn initial() -> CSSFontSize { return AbsoluteSize(Medium); }
}
struct StyleApplicator {
node: Node,
}
// TODO: normalize this into a normal preorder tree traversal function
pub fn apply_style(layout_ctx: &LayoutContext, node: Node) {
let applicator = StyleApplicator {
node: node,
};
applicator.apply_css_style(layout_ctx);
}
// TODO: this is misleadingly-named. It is actually trying to resolve CSS 'inherit' values.
/** A wrapper around a set of functions that can be applied as a
* top-down traversal of layout boxes.
*/
fn inheritance_wrapper(layout_ctx: &LayoutContext, node : Node) {
let applicator = StyleApplicator {
node: node,
};
applicator.resolve_style(layout_ctx);
}
impl StyleApplicator {
fn apply_css_style(layout_ctx: &LayoutContext) {
for NodeTree.each_child(&self.node) |child| {
inheritance_wrapper(layout_ctx, *child)
}
}
/**
* Convert the cascaded, specified style for this node into a resolved style:
* one which additionally resolves the values of Initial, Inherit based on
* defaults and node parent style. It also converts Node attributes into
* equivalent inline style declarations (TODO: where is this defined??)
*/
fn resolve_style(_layout_ctx: &LayoutContext) {
// TODO: implement
}
}

View file

@ -1,329 +0,0 @@
/**
Performs CSS selector matching.
*/
use dom::node::{LayoutData, Node, Text};
use dom::element::ElementData;
use newcss::values::*;
use newcss::{SelectCtx, SelectResults};
use styles::{SpecifiedStyle};
use select_handler::NodeSelectHandler;
use node_util::NodeUtil;
/**
Check if a CSS attribute matches the attribute of an HTML element.
*/
fn attrs_match(attr: &Attr, elmt: &ElementData) -> bool {
match *attr {
Exists(name) => {
match elmt.get_attr(name) {
Some(_) => true,
None => false
}
}
Exact(name, val) => {
match elmt.get_attr(name) {
Some(value) => value == val,
None => false
}
}
Includes(name, val) => {
// Comply with css spec, if the specified attribute is empty
// it cannot match.
if val == ~"" { return false; }
match elmt.get_attr(name) {
Some(value) => value.split_char(' ').contains(&val),
None => false
}
}
StartsWith(name, val) => {
match elmt.get_attr(name) {
Some(value) => {
//check that there is only one attribute value and it
//starts with the perscribed value
if !value.starts_with(val) || value.contains(~" ") { return false; }
// We match on either the exact value or value-foo
if value.len() == val.len() { true }
else { value.starts_with(val + ~"-") }
}
None => {
false
}
}
}
}
}
trait PrivMatchingMethods {
fn matches_element(sel: &Selector) -> bool;
fn matches_selector(sel: &Selector) -> bool;
}
impl Node : PrivMatchingMethods {
/**
Checks if the given CSS selector, which must describe a single
element with no relational information, describes the given HTML
element.
*/
fn matches_element(sel: &Selector) -> bool {
match *sel {
Child(_, _) | Descendant(_, _) | Sibling(_, _) => { return false; }
Element(tag, attrs) => {
match self.read(|n| copy *n.kind) {
dom::node::Element(elmt) => {
if !(tag == ~"*" || tag == elmt.tag_name) {
return false;
}
let mut i = 0u;
while i < attrs.len() {
if !attrs_match(&attrs[i], &elmt) { return false; }
i += 1u;
}
return true;
}
_ => { /*fall through, currently unsupported*/ }
}
}
}
return false; //If we got this far it was because something was
//unsupported.
}
/**
Checks if a generic CSS selector matches a given HTML element
*/
fn matches_selector(sel : &Selector) -> bool {
match *sel {
Element(*) => { return self.matches_element(sel); }
Child(sel1, sel2) => {
return match self.read(|n| n.tree.parent) {
Some(parent) => self.matches_element(sel2) && parent.matches_selector(sel1),
None => false
}
}
Descendant(sel1, sel2) => {
if !self.matches_element(sel2) { return false; }
//loop over all ancestors to check if they are the person
//we should be descended from.
let mut cur_parent = match self.read(|n| n.tree.parent) {
Some(parent) => parent,
None => return false
};
loop {
if cur_parent.matches_selector(sel1) { return true; }
cur_parent = match cur_parent.read(|n| n.tree.parent) {
Some(parent) => parent,
None => return false
};
}
}
Sibling(sel1, sel2) => {
if !self.matches_element(sel2) { return false; }
// Loop over this node's previous siblings to see if they match.
match self.read(|n| n.tree.prev_sibling) {
Some(sib) => {
let mut cur_sib = sib;
loop {
if cur_sib.matches_selector(sel1) { return true; }
cur_sib = match cur_sib.read(|n| n.tree.prev_sibling) {
Some(sib) => sib,
None => { break; }
};
}
}
None => { }
}
// check the rest of the siblings
match self.read(|n| n.tree.next_sibling) {
Some(sib) => {
let mut cur_sib = sib;
loop {
if cur_sib.matches_selector(sel1) { return true; }
cur_sib = match cur_sib.read(|n| n.tree.next_sibling) {
Some(sib) => sib,
None => { break; }
};
}
}
None => { }
}
return false;
}
}
}
}
trait MatchingMethods {
fn match_css_style(select_ctx : &SelectCtx);
}
impl Node : MatchingMethods {
/**
Compare an html element to a list of css rules and update its
style according to the rules matching it.
*/
fn match_css_style(select_ctx : &SelectCtx) {
// Loop over each rule, see if our node matches what is
// described in the rule. If it matches, update its style. As
// we don't currently have priorities of style information,
// the latest rule takes precedence over the others. So we
// just overwrite style information as we go.
let select_handler = NodeSelectHandler {
node: self
};
let style = select_ctx.select_style(&self, &select_handler);
self.set_style(move style);
}
}
#[cfg(test)]
mod test {
use dom::element::{Attr, HTMLDivElement, HTMLHeadElement, HTMLImageElement, UnknownElement};
use dom::node::NodeScope;
use dvec::DVec;
#[allow(non_implicitly_copyable_typarams)]
fn new_node_from_attr(scope: &NodeScope, name: ~str, val: ~str) -> Node {
let elmt = ElementData(~"div", ~HTMLDivElement);
let attr = ~Attr(move name, move val);
elmt.attrs.push(move attr);
return scope.new_node(dom::node::Element(move elmt));
}
#[test]
fn test_match_pipe1() {
let scope = NodeScope();
let node = new_node_from_attr(&scope, ~"lang", ~"en-us");
let sel = Element(~"*", ~[StartsWith(~"lang", ~"en")]);
assert node.matches_selector(~move sel);
}
#[test]
fn test_match_pipe2() {
let scope = NodeScope();
let node = new_node_from_attr(&scope, ~"lang", ~"en");
let sel = Element(~"*", ~[StartsWith(~"lang", ~"en")]);
assert node.matches_selector(~move sel);
}
#[test]
fn test_not_match_pipe() {
let scope = NodeScope();
let node = new_node_from_attr(&scope, ~"lang", ~"english");
let sel = Element(~"*", ~[StartsWith(~"lang", ~"en")]);
assert !node.matches_selector(~move sel);
}
#[test]
fn test_match_includes() {
let scope = NodeScope();
let node = new_node_from_attr(&scope, ~"mad", ~"hatter cobler cooper");
let sel = Element(~"div", ~[Includes(~"mad", ~"hatter")]);
assert node.matches_selector(~move sel);
}
#[test]
fn test_match_exists() {
let scope = NodeScope();
let node = new_node_from_attr(&scope, ~"mad", ~"hatter cobler cooper");
let sel1 = Element(~"div", ~[Exists(~"mad")]);
let sel2 = Element(~"div", ~[Exists(~"hatter")]);
assert node.matches_selector(~move sel1);
assert !node.matches_selector(~move sel2);
}
#[test]
fn test_match_exact() {
let scope = NodeScope();
let node1 = new_node_from_attr(&scope, ~"mad", ~"hatter cobler cooper");
let node2 = new_node_from_attr(&scope, ~"mad", ~"hatter");
let sel = Element(~"div", ~[Exact(~"mad", ~"hatter")]);
assert !node1.matches_selector(~copy sel);
assert node2.matches_selector(~move sel);
}
#[test]
fn match_tree() {
let scope = NodeScope();
let root = new_node_from_attr(&scope, ~"class", ~"blue");
let child1 = new_node_from_attr(&scope, ~"id", ~"green");
let child2 = new_node_from_attr(&scope, ~"flag", ~"black");
let gchild = new_node_from_attr(&scope, ~"flag", ~"grey");
let ggchild = new_node_from_attr(&scope, ~"flag", ~"white");
let gggchild = new_node_from_attr(&scope, ~"flag", ~"purple");
scope.add_child(root, child1);
scope.add_child(root, child2);
scope.add_child(child2, gchild);
scope.add_child(gchild, ggchild);
scope.add_child(ggchild, gggchild);
let sel1 = Descendant(~Element(~"*", ~[Exact(~"class", ~"blue")]), ~Element(~"*", ~[]));
assert !root.matches_selector(~copy sel1);
assert child1.matches_selector(~copy sel1);
assert child2.matches_selector(~copy sel1);
assert gchild.matches_selector(~copy sel1);
assert ggchild.matches_selector(~copy sel1);
assert gggchild.matches_selector(~move sel1);
let sel2 = Descendant(~Child(~Element(~"*", ~[Exact(~"class", ~"blue")]),
~Element(~"*", ~[])),
~Element(~"div", ~[Exists(~"flag")]));
assert !root.matches_selector(~copy sel2);
assert !child1.matches_selector(~copy sel2);
assert !child2.matches_selector(~copy sel2);
assert gchild.matches_selector(~copy sel2);
assert ggchild.matches_selector(~copy sel2);
assert gggchild.matches_selector(~move sel2);
let sel3 = Sibling(~Element(~"*", ~[]), ~Element(~"*", ~[]));
assert !root.matches_selector(~copy sel3);
assert child1.matches_selector(~copy sel3);
assert child2.matches_selector(~copy sel3);
assert !gchild.matches_selector(~copy sel3);
assert !ggchild.matches_selector(~copy sel3);
assert !gggchild.matches_selector(~move sel3);
let sel4 = Descendant(~Child(~Element(~"*", ~[Exists(~"class")]), ~Element(~"*", ~[])),
~Element(~"*", ~[]));
assert !root.matches_selector(~copy sel4);
assert !child1.matches_selector(~copy sel4);
assert !child2.matches_selector(~copy sel4);
assert gchild.matches_selector(~copy sel4);
assert ggchild.matches_selector(~copy sel4);
assert gggchild.matches_selector(~move sel4);
}
}

View file

@ -2,110 +2,19 @@
* High-level interface to CSS selector matching. * High-level interface to CSS selector matching.
*/ */
use std::arc::{ARC, get, clone}; use std::arc::{ARC, get, clone};
use dom::node::{Node, LayoutData, NodeTree};
use core::dvec::DVec; use core::dvec::DVec;
use newcss::values::*; use newcss::values::*;
use newcss::{SelectCtx, SelectResults}; use newcss::{SelectCtx, SelectResults};
use dom::element::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, UnknownElement, HTMLScriptElement};
use dom::node::{Comment, Doctype, Element, Text,
Node, NodeKind, NodeTree, LayoutData};
use newcss::color::{Color, rgb}; use newcss::color::{Color, rgb};
use newcss::color::css_colors::{white, black}; use newcss::color::css_colors::{white, black};
use layout::context::LayoutContext; use layout::context::LayoutContext;
use select_handler::NodeSelectHandler;
#[allow(non_implicitly_copyable_typarams)]
type SpecifiedStyle = {mut background_color : CSSValue<CSSBackgroundColor>,
mut background_image : CSSValue<CSSBackgroundImage>,
mut display_type : CSSValue<CSSDisplay>,
mut font_size : CSSValue<CSSFontSize>,
mut height : CSSValue<BoxSizing>,
mut text_color : CSSValue<CSSColor>,
mut width : CSSValue<BoxSizing>,
mut border_color : CSSValue<CSSBorderColor>,
mut border_style : CSSValue<CSSBorderStyle>,
mut border_width : CSSValue<Length>,
mut position : CSSValue<CSSPosition>,
mut top : CSSValue<Length>,
mut right : CSSValue<Length>,
mut bottom : CSSValue<Length>,
mut left : CSSValue<Length>
};
trait DefaultStyleMethods {
fn default_color() -> Color;
fn default_display_type() -> CSSDisplay;
fn default_width() -> BoxSizing;
fn default_height() -> BoxSizing;
}
/// Default styles for various attributes in case they don't get initialized from CSS selectors.
impl NodeKind : DefaultStyleMethods {
fn default_color() -> Color {
match self {
Text(*) => white(),
Element(*) => white(),
_ => fail ~"unstyleable node type encountered"
}
}
/* TODO: this belongs in the UA stylesheet */
fn default_display_type() -> CSSDisplay {
match self {
Text(*) => DisplayInline,
Element(element) => {
match *element.kind {
HTMLDivElement => DisplayBlock,
HTMLHeadElement => DisplayNone,
HTMLImageElement(*) => DisplayInline,
HTMLScriptElement => DisplayNone,
_ => DisplayInline,
}
},
Comment(*) | Doctype(*) => DisplayNone
}
}
fn default_width() -> BoxSizing {
BoxAuto
}
fn default_height() -> BoxSizing {
BoxAuto
}
}
/**
* Create a specified style that can be used to initialize a node before selector matching.
*
* Everything is initialized to none except the display style. The default value of the display
* style is computed so that it can be used to short-circuit selector matching to avoid computing
* style for children of display:none objects.
*/
#[allow(non_implicitly_copyable_typarams)]
fn empty_style_for_node_kind(kind: &NodeKind) -> SpecifiedStyle {
let display_type = kind.default_display_type();
{mut background_color : Initial,
mut background_image: Initial,
mut display_type : Specified(display_type),
mut font_size : Initial,
mut height : Initial,
mut text_color : Initial,
mut width : Initial,
mut border_color : Initial,
mut border_style : Initial,
mut border_width : Initial,
mut position : Initial,
mut top : Initial,
mut right : Initial,
mut bottom : Initial,
mut left : Initial}
}
trait StyleMethods { trait StyleMethods {
fn initialize_layout_data() -> Option<@LayoutData>; fn initialize_layout_data() -> Option<@LayoutData>;
fn initialize_style_for_subtree(ctx: &LayoutContext, refs: &DVec<@LayoutData>); fn initialize_style_for_subtree(ctx: &LayoutContext, refs: &DVec<@LayoutData>);
fn recompute_style_for_subtree(ctx: &LayoutContext, styles : &SelectCtx); fn recompute_style_for_subtree(ctx: &LayoutContext, select_ctx: &SelectCtx);
} }
impl Node : StyleMethods { impl Node : StyleMethods {
@ -145,19 +54,18 @@ impl Node : StyleMethods {
* the node (the reader-auxiliary box in the COW model) with the * the node (the reader-auxiliary box in the COW model) with the
* computed style. * computed style.
*/ */
fn recompute_style_for_subtree(ctx: &LayoutContext, styles : &SelectCtx) { fn recompute_style_for_subtree(ctx: &LayoutContext, select_ctx: &SelectCtx) {
let mut i = 0u; let mut i = 0u;
// Compute the styles of each of our children in parallel
for NodeTree.each_child(&self) |kid| { for NodeTree.each_child(&self) |kid| {
i = i + 1u; i = i + 1u;
kid.recompute_style_for_subtree(ctx, styles); kid.recompute_style_for_subtree(ctx, select_ctx);
} }
self.match_css_style(styles); let select_handler = NodeSelectHandler {
node: self
};
let style = select_ctx.select_style(&self, &select_handler);
self.set_style(move style);
} }
} }
fn apply_style(layout_ctx: &LayoutContext, node: Node) {
apply::apply_style(layout_ctx, node)
}

View file

@ -8,7 +8,6 @@ use au::Au;
use core::dvec::DVec; use core::dvec::DVec;
use core::to_str::ToStr; use core::to_str::ToStr;
use core::rand; use core::rand;
use css::styles::SpecifiedStyle;
use css::compute::ComputeStyles; use css::compute::ComputeStyles;
use newcss::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColorTransparent}; use newcss::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColorTransparent};
use newcss::values::{BdrColor, PosAbsolute}; use newcss::values::{BdrColor, PosAbsolute};

View file

@ -1,7 +1,6 @@
/** Creates CSS boxes from a DOM. */ /** Creates CSS boxes from a DOM. */
use au = gfx::geometry; use au = gfx::geometry;
use core::dvec::DVec; use core::dvec::DVec;
use css::styles::{SpecifiedStyle, empty_style_for_node_kind};
use newcss::values::{CSSDisplay, DisplayBlock, DisplayInline, DisplayInlineBlock, DisplayNone}; use newcss::values::{CSSDisplay, DisplayBlock, DisplayInline, DisplayInlineBlock, DisplayNone};
use newcss::values::{Inherit, Initial, Specified}; use newcss::values::{Inherit, Initial, Specified};
use dom::element::*; use dom::element::*;

View file

@ -7,7 +7,6 @@ use au = gfx::geometry;
use au::Au; use au::Au;
use content::content_task; use content::content_task;
use core::dvec::DVec; use core::dvec::DVec;
use css::styles::apply_style;
use newcss::Stylesheet; use newcss::Stylesheet;
use dl = gfx::display_list; use dl = gfx::display_list;
use dom::event::{Event, ReflowEvent}; use dom::event::{Event, ReflowEvent};
@ -173,13 +172,11 @@ impl Layout {
}; };
let layout_root: @FlowContext = do time("layout: tree construction") { let layout_root: @FlowContext = do time("layout: tree construction") {
// TODO: this is dumb. we don't need 3 separate traversals. // TODO: this is dumb. we don't need 2 separate traversals.
node.initialize_style_for_subtree(&layout_ctx, &self.layout_refs); node.initialize_style_for_subtree(&layout_ctx, &self.layout_refs);
do self.css_select_ctx.borrow_imm |ctx| { do self.css_select_ctx.borrow_imm |ctx| {
node.recompute_style_for_subtree(&layout_ctx, ctx); node.recompute_style_for_subtree(&layout_ctx, ctx);
} }
/* resolve styles (convert relative values) down the node tree */
apply_style(&layout_ctx, *node);
let builder = LayoutTreeBuilder::new(); let builder = LayoutTreeBuilder::new();
let layout_root: @FlowContext = match builder.construct_trees(&layout_ctx, let layout_root: @FlowContext = match builder.construct_trees(&layout_ctx,

View file

@ -46,10 +46,8 @@ pub mod content {
pub mod css { pub mod css {
pub mod styles; pub mod styles;
mod apply;
mod matching;
priv mod select_handler;
pub mod compute; pub mod compute;
priv mod select_handler;
priv mod node_util; priv mod node_util;
} }