CamelCase node kinds. Also fix shape glue problem in CSS color comparison.

This commit is contained in:
Patrick Walton 2012-06-14 16:38:05 -07:00
parent d2455c7bb6
commit c348486140
8 changed files with 130 additions and 130 deletions

View file

@ -11,11 +11,11 @@ enum node_data = {
};
enum node_kind {
nk_element(element),
nk_text(str)
Element(ElementData),
Text(str)
}
class element {
class ElementData {
let tag_name: str;
let subclass: ~element_subclass;
let attrs: dvec<~attr>;
@ -34,7 +34,8 @@ class element {
}
i += 1u;
}
ret none;
none
}
}

View file

@ -1,6 +1,6 @@
#[doc="Fundamental layout structures and algorithms."]
import dom::base::{element, es_div, es_img, node_data, node_kind, node};
import dom::base::{Element, es_div, es_img, node_data, node_kind, node};
import dom::rcu;
import dom::rcu::reader_methods;
import gfx::geometry;
@ -145,8 +145,8 @@ impl node_methods for node {
#[cfg(test)]
mod test {
import dom::base::{element, es_div, es_img, methods, nk_element, node_data,
node_kind, node, wr_tree_ops};
import dom::base::{ElementData, es_div, es_img, methods, Element, node_data, node_kind, node};
import dom::base::{wr_tree_ops};
import dom::rcu::scope;
import box_builder::{box_builder_methods};
@ -183,10 +183,10 @@ mod test {
~es_img({mut size: size})
}
let n0 = s.new_node(nk_element(element("img", mk_img(Size2D(au(10),au(10))))));
let n1 = s.new_node(nk_element(element("img", mk_img(Size2D(au(10),au(10))))));
let n2 = s.new_node(nk_element(element("img", mk_img(Size2D(au(10),au(20))))));
let n3 = s.new_node(nk_element(element("div", ~es_div)));
let n0 = s.new_node(Element(ElementData("img", mk_img(Size2D(au(10),au(10))))));
let n1 = s.new_node(Element(ElementData("img", mk_img(Size2D(au(10),au(10))))));
let n2 = s.new_node(Element(ElementData("img", mk_img(Size2D(au(10),au(20))))));
let n3 = s.new_node(Element(ElementData("div", ~es_div)));
tree::add_child(s, n3, n0);
tree::add_child(s, n3, n1);

View file

@ -1,6 +1,6 @@
#[doc="Creates CSS boxes from a DOM."]
import dom::base::{element, es_div, es_img, nk_element, nk_text, node};
import dom::base::{ElementData, es_div, es_img, Element, Text, node};
import dom::style::{display_type, di_block, di_inline, di_none};
import dom::rcu::reader_methods;
import gfx::geometry;
@ -20,8 +20,7 @@ enum ctxt = {
// The parent box that these boxes will be added to.
parent_box: @box,
// The current anonymous box that we're currently appending inline nodes
// to.
// The current anonymous box that we're currently appending inline nodes to.
//
// See CSS2 9.2.1.1.
mut anon_box: option<@box>
@ -61,8 +60,7 @@ impl methods for ctxt {
self.finish_anonymous_box_if_necessary();
}
// Add the child's box to the current enclosing box or the current
// anonymous box.
// Add the child's box to the current enclosing box or the current anonymous box.
alt kid.get_computed_style().display {
di_block {
btree.add_child(self.parent_box, kid_box);
@ -70,11 +68,14 @@ impl methods for ctxt {
di_inline {
let anon_box = alt self.anon_box {
none {
// the anonymous box inherits the attributes
// of its parents for now, so that
// properties of intrinsic boxes are not
// spread to their parenting anonymous box.
//
// the anonymous box inherits the attributes of its parents for now, so
// that properties of intrinsic boxes are not spread to their parenting
// anonymous box.
//
// TODO: check what css actually specifies
//
let b = new_box(self.parent_node, bk_inline);
self.anon_box = some(b);
b
@ -159,8 +160,8 @@ impl box_builder_priv for node {
"]
fn determine_box_kind() -> box_kind {
alt self.rd({ |n| copy n.kind }) {
~nk_text(string) { bk_text(@text_box(string)) }
~nk_element(element) {
~Text(string) { bk_text(@text_box(string)) }
~Element(element) {
alt *element.subclass {
es_div { bk_block }
es_img({size}) { bk_intrinsic(@size) }

View file

@ -1,5 +1,5 @@
#[doc="Applies style to boxes."]
import dom::base::{es_img, nk_element, node};
import dom::base::{es_img, Element, node};
import dom::rcu::reader_methods;
import image::base::load;
import layout::base::*;
@ -20,7 +20,7 @@ impl apply_style_methods for @box {
self.node.rd {
|node|
alt node.kind {
~nk_element(element) {
~Element(element) {
let style = self.node.get_computed_style();
self.appearance.background_color = some(style.back_color);
@ -34,8 +34,7 @@ impl apply_style_methods for @box {
// FIXME: Don't load synchronously!
#debug("loading image from %s", url);
let image = @load(url);
self.appearance.background_image =
some(image);
self.appearance.background_image = some(image);
}
none {
/* Ignore. */

View file

@ -1,17 +1,16 @@
#[doc="Perform css selector matching"]
import dom::base::{node, nk_element, nk_text};
import dom::style::{selector, style_decl, font_size, display, text_color,
background_color, stylesheet, element, child, descendant,
sibling, attr, exact, exists, includes, starts_with};
import dom::base::{node, Element, ElementData, Text};
import dom::style::{selector, style_decl, font_size, display, text_color, background_color,
stylesheet, element, child, descendant, sibling, attr, exact, exists, includes,
starts_with};
import dom::rcu::{reader_methods};
import style::{computed_style, default_style_for_node_kind};
import base::{layout_data};
export matching_methods;
#[doc="Update the computed style of an html element with a style specified
by css."]
#[doc="Update the computed style of an HTML element with a style specified by CSS."]
fn update_style(style : @computed_style, decl : style_decl) {
alt decl {
display(dis) { (*style).display = dis; }
@ -20,8 +19,8 @@ fn update_style(style : @computed_style, decl : style_decl) {
}
}
#[doc="Check if a css attribute matches the attribute of an html element."]
fn attrs_match(attr : attr, elmt : dom::base::element) -> bool {
#[doc="Check if a CSS attribute matches the attribute of an HTML element."]
fn attrs_match(attr: attr, elmt: ElementData) -> bool {
alt attr {
exists(name) {
alt elmt.get_attr(name) {
@ -56,22 +55,25 @@ fn attrs_match(attr : attr, elmt : dom::base::element) -> bool {
if value.len() == val.len() { ret true; }
else { ret value.starts_with(val + "-"); }
}
none { ret false; }
none {
ret false;
}
}
}
}
}
impl priv_matching_methods for node {
#[doc="Checks if the given css selector, which must describe a single
element with no relational information, describes the given
html element."]
#[doc="
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 {
alt *sel {
child(_, _) | descendant(_, _) | sibling(_, _) { ret false; }
element(tag, attrs) {
alt self.rd { |n| copy *n.kind } {
nk_element(elmt) {
Element(elmt) {
if !(tag == "*" || tag == elmt.tag_name) {
ret false;
}
@ -84,7 +86,7 @@ impl priv_matching_methods for node {
ret true;
}
nk_text(str) { /*fall through, currently unsupported*/ }
Text(str) { /*fall through, currently unsupported*/ }
}
}
}
@ -93,7 +95,7 @@ impl priv_matching_methods for node {
//unsupported.
}
#[doc = "Checks if a generic css selector matches a given html element"]
#[doc = "Checks if a generic CSS selector matches a given HTML element"]
fn matches_selector(sel : ~selector) -> bool {
alt *sel {
element(str, atts) { ret self.matches_element(sel); }
@ -202,17 +204,16 @@ impl matching_methods for node {
}
mod test {
import dom::base::{node_scope, methods, nk_element, attr, es_div,
es_img, es_unknown, es_head, wr_tree_ops};
import dom::base::{node_scope, methods, Element, attr, es_div, es_img, es_unknown, es_head};
import dom::base::{wr_tree_ops};
import dvec::{dvec, extensions};
import io::println;
fn new_node_from_attr(scope : node_scope, -name : str, -val : str) -> node
{
let elmt = dom::base::element("div", ~es_div);
fn new_node_from_attr(scope: node_scope, -name: str, -val: str) -> node {
let elmt = ElementData("div", ~es_div);
let attr = ~attr(name, val);
elmt.attrs.push(attr);
ret scope.new_node(nk_element(elmt));
ret scope.new_node(Element(elmt));
}
#[test]

View file

@ -1,9 +1,7 @@
#[doc="High-level interface to CSS selector matching."]
import dom::style::{display_type, di_block, di_inline, di_none,
stylesheet};
import dom::base::{element, es_div, es_head, es_img, nk_element, nk_text};
import dom::base::{node};
import dom::style::{display_type, di_block, di_inline, di_none, stylesheet};
import dom::base::{es_div, es_head, es_img, Element, Text, node};
import dom::base::node_kind;
import dom::rcu::reader_methods;
import layout::base::*; // FIXME: resolve bug requires *
@ -17,11 +15,11 @@ type computed_style = {mut display : display_type,
#[doc="Returns the default style for the given node kind."]
fn default_style_for_node_kind(kind: node_kind) -> computed_style {
alt kind {
nk_text(*) {
Text(*) {
{mut display: di_inline,
mut back_color: white()}
}
nk_element(element) {
Element(element) {
let r = rand::rng();
let rand_color = rgb(r.next() as u8, r.next() as u8, r.next() as u8);
@ -30,8 +28,7 @@ fn default_style_for_node_kind(kind: node_kind) -> computed_style {
mut back_color: rand_color} }
es_head { {mut display: di_none, mut back_color: rand_color} }
es_img(*) { {mut display: di_inline, mut back_color: rand_color} }
es_unknown { {mut display : di_inline, mut back_color :
rand_color} }
es_unknown { {mut display: di_inline, mut back_color: rand_color} }
}
}
}
@ -41,9 +38,8 @@ impl style_priv for node {
#[doc="
Performs CSS selector matching on a node.
This is, importantly, the function that creates the layout data for
the node (the reader-auxiliary box in the RCU model) and populates it
with the computed style.
This is, importantly, the function that creates the layout data for the node (the reader-
auxiliary box in the RCU model) and populates it with the computed style.
"]
fn recompute_style(styles : stylesheet) {
let style = self.match_css_style(styles);
@ -63,8 +59,8 @@ impl style_priv for node {
impl style_methods for node {
#[doc="
Returns the computed style for the given node. If CSS selector matching
has not yet been performed, fails.
Returns the computed style for the given node. If CSS selector matching has not yet been
performed, fails.
TODO: Return a safe reference; don't copy.
"]
@ -78,9 +74,8 @@ impl style_methods for node {
#[doc="
Performs CSS selector matching on a subtree.
This is, importantly, the function that creates the layout data for
the node (the reader-auxiliary box in the RCU model) and populates it
with the computed style.
This is, importantly, the function that creates the layout data for the node (the reader-
auxiliary box in the RCU model) and populates it with the computed style.
TODO: compute the style of multiple nodes in parallel.
"]

View file

@ -1,9 +1,8 @@
#[doc="Constructs a DOM tree from an incoming token stream."]
import dom::rcu::writer_methods;
import dom::base::{attr, element, element_subclass, es_div, es_head, es_img};
import dom::base::{es_unknown, methods, nk_element, nk_text, rd_tree_ops};
import dom::base::{wr_tree_ops};
import dom::base::{attr, element_subclass, es_div, es_head, es_img, es_unknown, methods, Element};
import dom::base::{ElementData, Text, rd_tree_ops, wr_tree_ops};
import dom = dom::base;
import dvec::extensions;
import geom::size::Size2D;
@ -12,14 +11,12 @@ import gfx::geometry::au;
import parser = parser::lexer::html;
import parser::token;
fn link_up_attribute(scope: dom::node_scope, node: dom::node, -key: str,
-value: str) {
// TODO: Implement atoms so that we don't always perform string
// comparisons.
fn link_up_attribute(scope: dom::node_scope, node: dom::node, -key: str, -value: str) {
// TODO: Implement atoms so that we don't always perform string comparisons.
scope.rd(node) {
|node_contents|
alt *node_contents.kind {
dom::nk_element(element) {
Element(element) {
element.attrs.push(~attr(copy key, copy value));
alt *element.subclass {
es_img(img) if key == "width" {
@ -45,7 +42,8 @@ fn link_up_attribute(scope: dom::node_scope, node: dom::node, -key: str,
}
}
}
dom::nk_text(*) {
Text(*) {
fail "attempt to link up an attribute to a text node"
}
}
@ -66,10 +64,9 @@ fn build_element_subclass(tag_name: str) -> ~element_subclass {
}
}
fn build_dom(scope: dom::node_scope,
stream: port<token>) -> dom::node {
fn build_dom(scope: dom::node_scope, stream: port<token>) -> dom::node {
// The current reference node.
let mut cur = scope.new_node(dom::nk_element(element("html", ~es_div)));
let mut cur = scope.new_node(Element(ElementData("html", ~es_div)));
loop {
let token = stream.recv();
alt token {
@ -77,9 +74,7 @@ fn build_dom(scope: dom::node_scope,
parser::to_start_opening_tag(tag_name) {
#debug["starting tag %s", tag_name];
let element_subclass = build_element_subclass(tag_name);
let new_node =
scope.new_node(dom::nk_element(element(tag_name,
element_subclass)));
let new_node = scope.new_node(Element(ElementData(tag_name, element_subclass)));
scope.add_child(cur, new_node);
cur = new_node;
}
@ -98,7 +93,7 @@ fn build_dom(scope: dom::node_scope,
}
parser::to_text(s) if !s.is_whitespace() {
let s <- s;
let new_node = scope.new_node(dom::nk_text(s));
let new_node = scope.new_node(Text(s));
scope.add_child(cur, new_node);
}
parser::to_text(_) {

View file

@ -7,9 +7,17 @@
import float::round;
import libc::types::os::arch::c95::c_double;
import css_colors::*;
import cmp::eq;
enum Color = {red : u8, green : u8, blue : u8, alpha : float};
impl Color of eq for Color {
fn eq(&&other: Color) -> bool {
ret self.red == other.red && self.green == other.green && self.blue == other.blue &&
self.alpha == other.alpha;
}
}
fn rgba(r : u8, g : u8, b : u8, a : float) -> Color {
Color({red : r, green : g, blue : b, alpha : a})
}
@ -172,54 +180,54 @@ mod test {
#[test]
fn test_parse_by_name() {
assert red() == parse_color("red");
assert lime() == parse_color("Lime");
assert blue() == parse_color("BLUE");
assert green() == parse_color("GreEN");
assert white() == parse_color("white");
assert black() == parse_color("Black");
assert gray() == parse_color("Gray");
assert silver() == parse_color("SiLvEr");
assert maroon() == parse_color("maroon");
assert purple() == parse_color("PURPLE");
assert fuschia() == parse_color("FUSCHIA");
assert olive() == parse_color("oLiVe");
assert yellow() == parse_color("yellow");
assert navy() == parse_color("NAVY");
assert teal() == parse_color("Teal");
assert aqua() == parse_color("Aqua");
assert red().eq(parse_color("red"));
assert lime().eq(parse_color("Lime"));
assert blue().eq(parse_color("BLUE"));
assert green().eq(parse_color("GreEN"));
assert white().eq(parse_color("white"));
assert black().eq(parse_color("Black"));
assert gray().eq(parse_color("Gray"));
assert silver().eq(parse_color("SiLvEr"));
assert maroon().eq(parse_color("maroon"));
assert purple().eq(parse_color("PURPLE"));
assert fuschia().eq(parse_color("FUSCHIA"));
assert olive().eq(parse_color("oLiVe"));
assert yellow().eq(parse_color("yellow"));
assert navy().eq(parse_color("NAVY"));
assert teal().eq(parse_color("Teal"));
assert aqua().eq(parse_color("Aqua"));
}
#[test]
fn test_parsing_rgb() {
assert red() == parse_color("rgb(255,0,0)");
assert red() == parse_color("rgba(255,0,0,1.0)");
assert red() == parse_color("rgba(255,0,0,1)");
assert lime() == parse_color("rgba(0,255,0,1.00)");
assert rgb(1u8,2u8,3u8) == parse_color("rgb(1,2,03)");
assert rgba(15u8,250u8,3u8,0.5) == parse_color("rgba(15,250,3,.5)");
assert rgba(15u8,250u8,3u8,0.5) == parse_color("rgba(15,250,3,0.5)");
assert red().eq(parse_color("rgb(255,0,0)"));
assert red().eq(parse_color("rgba(255,0,0,1.0)"));
assert red().eq(parse_color("rgba(255,0,0,1)"));
assert lime().eq(parse_color("rgba(0,255,0,1.00)"));
assert rgb(1u8,2u8,3u8).eq(parse_color("rgb(1,2,03)"));
assert rgba(15u8,250u8,3u8,0.5).eq(parse_color("rgba(15,250,3,.5)"));
assert rgba(15u8,250u8,3u8,0.5).eq(parse_color("rgba(15,250,3,0.5)"));
}
#[test]
fn test_parsing_hsl() {
assert red() == parse_color("hsl(0,1,.5)");
assert lime() == parse_color("hsl(120.0,1.0,.5)");
assert blue() == parse_color("hsl(240.0,1.0,.5)");
assert green() == parse_color("hsl(120.0,1.0,.25)");
assert white() == parse_color("hsl(1.0,1.,1.0)");
assert white() == parse_color("hsl(129.0,0.3,1.0)");
assert black() == parse_color("hsl(231.2,0.75,0.0)");
assert black() == parse_color("hsl(11.2,0.0,0.0)");
assert gray() == parse_color("hsl(0.0,0.0,0.5)");
assert maroon() == parse_color("hsl(0.0,1.0,0.25)");
assert purple() == parse_color("hsl(300.0,1.0,0.25)");
assert fuschia() == parse_color("hsl(300,1.0,0.5)");
assert olive() == parse_color("hsl(60.,1.0,0.25)");
assert yellow() == parse_color("hsl(60.,1.0,0.5)");
assert navy() == parse_color("hsl(240.0,1.0,.25)");
assert teal() == parse_color("hsl(180.0,1.0,.25)");
assert aqua() == parse_color("hsl(180.0,1.0,.5)");
assert red().eq(parse_color("hsl(0,1,.5)"));
assert lime().eq(parse_color("hsl(120.0,1.0,.5)"));
assert blue().eq(parse_color("hsl(240.0,1.0,.5)"));
assert green().eq(parse_color("hsl(120.0,1.0,.25)"));
assert white().eq(parse_color("hsl(1.0,1.,1.0)"));
assert white().eq(parse_color("hsl(129.0,0.3,1.0)"));
assert black().eq(parse_color("hsl(231.2,0.75,0.0)"));
assert black().eq(parse_color("hsl(11.2,0.0,0.0)"));
assert gray().eq(parse_color("hsl(0.0,0.0,0.5)"));
assert maroon().eq(parse_color("hsl(0.0,1.0,0.25)"));
assert purple().eq(parse_color("hsl(300.0,1.0,0.25)"));
assert fuschia().eq(parse_color("hsl(300,1.0,0.5)"));
assert olive().eq(parse_color("hsl(60.,1.0,0.25)"));
assert yellow().eq(parse_color("hsl(60.,1.0,0.5)"));
assert navy().eq(parse_color("hsl(240.0,1.0,.25)"));
assert teal().eq(parse_color("hsl(180.0,1.0,.25)"));
assert aqua().eq(parse_color("hsl(180.0,1.0,.5)"));
}
}