diff --git a/src/servo/content/content_task.rs b/src/servo/content/content_task.rs index 46db1fbb6f5..0aaf7be2940 100644 --- a/src/servo/content/content_task.rs +++ b/src/servo/content/content_task.rs @@ -16,7 +16,6 @@ use dom::base::{Document, Node, NodeScope, Window, define_bindings}; use dom::event::{Event, ResizeEvent, ReflowEvent}; use gfx::compositor::Compositor; use html::lexer::spawn_html_lexer_task; -use html::dom_builder::build_dom; use layout::layout_task; use layout_task::{LayoutTask, BuildMsg}; @@ -155,12 +154,6 @@ impl Content { // Note: we can parse the next document in parallel // with any previous documents. - /*let stream = spawn_html_lexer_task(copy url, self.resource_task); - let (root, style_port, js_port) = build_dom(self.scope, stream, url, - self.resource_task); - - let css_rules = style_port.recv(); - let js_scripts = js_port.recv();*/ let result = html::hubbub_html_parser::parse_html(self.scope, url, diff --git a/src/servo/css/resolve/apply.rs b/src/servo/css/resolve/apply.rs index 0e4ee8a6dde..88a8bae79d5 100644 --- a/src/servo/css/resolve/apply.rs +++ b/src/servo/css/resolve/apply.rs @@ -1,6 +1,7 @@ #[doc="Applies the appropriate CSS style to boxes."] use au = gfx::geometry; +use dom::element::*; use layout::base::{RenderBox, SpecifiedStyle, RenderBoxTree}; use layout::context::LayoutContext; use layout::traverse_parallel::top_down_traversal; @@ -121,7 +122,7 @@ impl StyleApplicator { match node.kind { ~dom::base::Element(element) => { match element.kind { - ~dom::base::HTMLImageElement(*) => { + ~HTMLImageElement(*) => { let url = element.get_attr(~"src"); if url.is_some() { diff --git a/src/servo/css/resolve/matching.rs b/src/servo/css/resolve/matching.rs index fc49240e23f..611fce679ab 100644 --- a/src/servo/css/resolve/matching.rs +++ b/src/servo/css/resolve/matching.rs @@ -2,7 +2,8 @@ use dom::base::{LayoutData}; use dom::base; -use base::{ElementData, Node, Text}; +use dom::element::ElementData; +use base::{Node, Text}; use values::*; use styles::{SpecifiedStyle}; diff --git a/src/servo/css/styles.rs b/src/servo/css/styles.rs index f1fbb372760..4e598579720 100644 --- a/src/servo/css/styles.rs +++ b/src/servo/css/styles.rs @@ -4,7 +4,7 @@ use std::arc::{ARC, get, clone}; use css::values::*; use css::values::Stylesheet; -use dom::base::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, UnknownElement, HTMLScriptElement}; +use dom::element::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, UnknownElement, HTMLScriptElement}; use dom::base::{Comment, Doctype, Element, Node, NodeKind, Text}; use dom::base::{LayoutData}; use util::color::{Color, rgb}; @@ -37,6 +37,7 @@ impl NodeKind : DefaultStyleMethods { } } + /* TODO: this belongs in the UA stylesheet */ fn default_display_type() -> CSSDisplay { match self { Text(*) => { DisplayInline } @@ -46,7 +47,7 @@ impl NodeKind : DefaultStyleMethods { HTMLHeadElement => DisplayNone, HTMLImageElement(*) => DisplayInline, HTMLScriptElement => DisplayNone, - UnknownElement => DisplayInline, + _ => DisplayInline, } }, Comment(*) | Doctype(*) => DisplayNone diff --git a/src/servo/dom/base.rs b/src/servo/dom/base.rs index 3eb5a5e1a56..dc2e632d478 100644 --- a/src/servo/dom/base.rs +++ b/src/servo/dom/base.rs @@ -1,11 +1,10 @@ -#[doc="The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements."] - +/* The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. */ use comm::{Port, Chan}; use content::content_task::{ControlMsg, Timer}; use css::styles::SpecifiedStyle; use css::values::Stylesheet; +use dom::element::{Attr, ElementData}; use dom::bindings; -use dvec::DVec; use geom::size::Size2D; use gfx::geometry::au; use js::crust::*; @@ -132,47 +131,7 @@ fn DoctypeData(name: ~str, public_id: Option<~str>, } } -struct ElementData { - tag_name: ~str, - kind: ~ElementKind, - attrs: DVec<~Attr>, -} -impl ElementData { - fn get_attr(attr_name: ~str) -> Option<~str> { - let mut i = 0u; - while i < self.attrs.len() { - if attr_name == self.attrs[i].name { - return Some(copy self.attrs[i].value); - } - i += 1u; - } - - None - } -} - - -fn ElementData(tag_name: ~str, kind: ~ElementKind) -> ElementData { - ElementData { - tag_name : tag_name, - kind : kind, - attrs : DVec(), - } -} - - -struct Attr { - name: ~str, - value: ~str, -} - -fn Attr(name: ~str, value: ~str) -> Attr { - Attr { - name : name, - value : value, - } -} fn define_bindings(compartment: bare_compartment, doc: @Document, win: @Window) { @@ -182,14 +141,6 @@ fn define_bindings(compartment: bare_compartment, doc: @Document, bindings::element::init(compartment); } -enum ElementKind { - UnknownElement, - HTMLDivElement, - HTMLHeadElement, - HTMLImageElement({mut size: Size2D}), - HTMLScriptElement -} - /** The RCU rd_aux data is a (weak) pointer to the layout data, defined by this `LayoutData` enum. It contains the CSS style object diff --git a/src/servo/dom/bindings/element.rs b/src/servo/dom/bindings/element.rs index d991bc25f51..e0562b36a32 100644 --- a/src/servo/dom/bindings/element.rs +++ b/src/servo/dom/bindings/element.rs @@ -1,4 +1,5 @@ use au = gfx::geometry; +use au::au; use js::rust::{bare_compartment, methods, jsobj}; use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL, JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS}; @@ -11,13 +12,13 @@ use js::glue::bindgen::*; use js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub}; use dom::base::{Node, NodeScope, Element}; +use dom::element::*; use node::NodeBundle; use utils::{rust_box, squirrel_away_unique, get_compartment, domstring_to_jsval, str}; use libc::c_uint; use ptr::null; use node::unwrap; -use dom::base::{HTMLImageElement, HTMLScriptElement, HTMLHeadElement, HTMLDivElement, - UnknownElement}; + extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) { #debug("element finalize!"); @@ -71,13 +72,22 @@ extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut jsva let bundle = unwrap(obj); let width = (*bundle).payload.scope.write((*bundle).payload.node, |nd| { match nd.kind { - ~Element(ed) => { - match ed.kind { - ~HTMLImageElement(img) => img.size.width, - _ => fail ~"why is this not an image element?" - } - } - _ => fail ~"why is this not an element?" + ~Element(ed) => { + match ed.kind { + ~HTMLImageElement(*) => { + // TODO: this should actually come from rendered dimensions! + match ed.get_attr(~"width") { + Some(s) => match int::from_str(s) { + Some(w) => au::from_px(w), + None => au(0) /* failed to parse a number */ + }, + None => au(0) /* no width attr. */ + } + }, + _ => fail ~"why is this not an image element?" + } + }, + _ => fail ~"why is this not an element?" } }); *vp = RUST_INT_TO_JSVAL( @@ -97,9 +107,9 @@ extern fn HTMLImageElement_setWidth(cx: *JSContext, _argc: c_uint, vp: *mut jsva match nd.kind { ~Element(ed) => { match ed.kind { - ~HTMLImageElement(img) => { + ~HTMLImageElement(*) => { let arg = ptr::offset(JS_ARGV(cx, cast::reinterpret_cast(&vp)), 0); - img.size.width = au::from_px(RUST_JSVAL_TO_INT(*arg) as int) + ed.set_attr(~"width", int::str(RUST_JSVAL_TO_INT(*arg) as int)) }, _ => fail ~"why is this not an image element?" } @@ -144,7 +154,7 @@ fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj unsafe { ~HTMLHeadElement(*) => ~"HTMLHeadElement", ~HTMLImageElement(*) => ~"HTMLImageElement", ~HTMLScriptElement(*) => ~"HTMLScriptElement", - ~UnknownElement(*) => ~"HTMLElement" + _ => ~"HTMLElement" } } _ => fail ~"element::create only handles elements" diff --git a/src/servo/dom/element.rs b/src/servo/dom/element.rs new file mode 100644 index 00000000000..80370d26c4f --- /dev/null +++ b/src/servo/dom/element.rs @@ -0,0 +1,96 @@ +use au = gfx::geometry; +use au::au; +use dvec::DVec; +use geom::size::Size2D; + +struct ElementData { + tag_name: ~str, + kind: ~ElementKind, + attrs: DVec<~Attr>, +} + +impl ElementData { + fn get_attr(attr_name: ~str) -> Option<~str> { + let mut i = 0u; + while i < self.attrs.len() { + if attr_name == self.attrs[i].name { + return Some(copy self.attrs[i].value); + } + i += 1u; + } + + None + } + + fn set_attr(_attr_name: ~str, attr_value: ~str) { + // TODO: add new attr of name, or delete old one + } +} + +fn ElementData(tag_name: ~str, kind: ~ElementKind) -> ElementData { + ElementData { + tag_name : tag_name, + kind : kind, + attrs : DVec(), + } +} + +struct Attr { + name: ~str, + value: ~str, +} + +fn Attr(name: ~str, value: ~str) -> Attr { + Attr { + name : name, + value : value, + } +} + +enum HeadingLevel { + Heading1, + Heading2, + Heading3, + Heading4, + Heading5, + Heading6, +} + +enum ElementKind { + HTMLAnchorElement, + HTMLAsideElement, + HTMLBRElement, + HTMLBodyElement, + HTMLBoldElement, + HTMLDivElement, + HTMLFontElement, + HTMLFormElement, + HTMLHRElement, + HTMLHeadElement, + HTMLHeadingElement(HeadingLevel), + HTMLHtmlElement, + // TODO: should not take this as argument--it is fetched from + // layout task as requested. + HTMLImageElement({mut size: Size2D}), + HTMLInputElement, + HTMLItalicElement, + HTMLLinkElement, + HTMLListItemElement, + HTMLMetaElement, + HTMLOListElement, + HTMLOptionElement, + HTMLParagraphElement, + HTMLScriptElement, + HTMLSectionElement, + HTMLSelectElement, + HTMLSmallElement, + HTMLSpanElement, + HTMLStyleElement, + HTMLTableBodyElement, + HTMLTableCellElement, + HTMLTableElement, + HTMLTableRowElement, + HTMLTitleElement, + HTMLUListElement, + UnknownElement, +} diff --git a/src/servo/html/dom_builder.rs b/src/servo/html/dom_builder.rs deleted file mode 100644 index a1cb56e0684..00000000000 --- a/src/servo/html/dom_builder.rs +++ /dev/null @@ -1,273 +0,0 @@ -#[doc="Constructs a DOM tree from an incoming token stream."] - -use au = gfx::geometry; -use au::au; -use dom::base::{Attr, Element, ElementData, ElementKind, HTMLDivElement, HTMLHeadElement, - HTMLScriptElement}; -use dom::base::{HTMLImageElement, Node, NodeScope, Text, UnknownElement}; -use geom::size::Size2D; -use html::lexer; -use html::lexer::Token; -use css::values::Stylesheet; -use vec::{push, push_all_move, flat_map}; -use std::net::url::Url; -use resource::resource_task::{ResourceTask, Load, Payload, Done}; -use to_str::ToStr; - -enum CSSMessage { - File(Url), - Exit -} - -enum js_message { - js_file(Url), - js_exit -} - -#[allow(non_implicitly_copyable_typarams)] -fn link_up_attribute(scope: NodeScope, node: Node, -key: ~str, -value: ~str) { - // TODO: Implement atoms so that we don't always perform string comparisons. - scope.read(node, |node_contents| { - match *node_contents.kind { - Element(element) => { - element.attrs.push(~Attr(copy key, copy value)); - match *element.kind { - HTMLImageElement(img) if key == ~"width" => { - match int::from_str(value) { - None => { - // Drop on the floor. - } - Some(s) => { img.size.width = au::from_px(s); } - } - } - HTMLImageElement(img) if key == ~"height" => { - match int::from_str(value) { - None => { - // Drop on the floor. - } - Some(s) => { - img.size.height = au::from_px(s); - } - } - } - HTMLDivElement | HTMLImageElement(*) | HTMLHeadElement | - HTMLScriptElement | UnknownElement => { - // Drop on the floor. - } - } - } - - _ => { - fail ~"attempt to link up an attribute to an unstyleable node" - } - } - }) -} - -fn build_element_kind(tag_name: ~str) -> ~ElementKind { - match tag_name { - ~"div" => ~HTMLDivElement, - ~"img" => { - ~HTMLImageElement({ mut size: Size2D(au::from_px(100), - au::from_px(100)) - }) - } - ~"script" => ~HTMLScriptElement, - ~"head" => ~HTMLHeadElement, - _ => ~UnknownElement - } -} - -#[doc="Runs a task that coordinates parsing links to css stylesheets. - -This function should be spawned in a separate task and spins waiting -for the html builder to find links to css stylesheets and sends off -tasks to parse each link. When the html process finishes, it notifies -the listener, who then collects the css rules from each task it -spawned, collates them, and sends them to the given result channel. - -# Arguments - -* `to_parent` - A channel on which to send back the full set of rules. -* `from_parent` - A port on which to receive new links. - -"] -fn css_link_listener(to_parent : comm::Chan, from_parent : comm::Port, - resource_task: ResourceTask) { - let mut result_vec = ~[]; - - loop { - match from_parent.recv() { - File(url) => { - let result_port = comm::Port(); - let result_chan = comm::Chan(result_port); - // TODO: change copy to move once we have match move - let url = copy url; - task::spawn(|| { - // TODO: change copy to move once we can move into closures - let css_stream = css::lexer::spawn_css_lexer_task(copy url, resource_task); - let mut css_rules = css::parser::build_stylesheet(css_stream); - result_chan.send(css_rules); - }); - - push(result_vec, result_port); - } - Exit => { - break; - } - } - } - - let css_rules = flat_map(result_vec, |result_port| { result_port.recv() }); - - to_parent.send(css_rules); -} - -fn js_script_listener(to_parent : comm::Chan<~[~[u8]]>, from_parent : comm::Port, - resource_task: ResourceTask) { - let mut result_vec = ~[]; - - loop { - match from_parent.recv() { - js_file(url) => { - let result_port = comm::Port(); - let result_chan = comm::Chan(result_port); - // TODO: change copy to move once we have match move - let url = copy url; - do task::spawn || { - let input_port = Port(); - // TODO: change copy to move once we can move into closures - resource_task.send(Load(copy url, input_port.chan())); - - let mut buf = ~[]; - loop { - match input_port.recv() { - Payload(data) => { - buf += data; - } - Done(Ok(*)) => { - result_chan.send(buf); - break; - } - Done(Err(*)) => { - #error("error loading script %s", url.to_str()); - } - } - } - } - push(result_vec, result_port); - } - js_exit => { - break; - } - } - } - - let js_scripts = vec::map(result_vec, |result_port| result_port.recv()); - to_parent.send(js_scripts); -} - -#[allow(non_implicitly_copyable_typarams)] -fn build_dom(scope: NodeScope, stream: comm::Port, url: Url, - resource_task: ResourceTask) -> (Node, comm::Port, comm::Port<~[~[u8]]>) { - // The current reference node. - let mut cur_node = scope.new_node(Element(ElementData(~"html", ~HTMLDivElement))); - // We will spawn a separate task to parse any css that is - // encountered, each link to a stylesheet is sent to the waiting - // task. After the html sheet has been fully read, the spawned - // task will collect the results of all linked style data and send - // it along the returned port. - let style_port = comm::Port(); - let child_chan = comm::Chan(style_port); - let style_chan = task::spawn_listener(|child_port| { - css_link_listener(child_chan, child_port, resource_task); - }); - - let js_port = comm::Port(); - let child_chan = comm::Chan(js_port); - let js_chan = task::spawn_listener(|child_port| { - js_script_listener(child_chan, child_port, resource_task); - }); - - loop { - let token = stream.recv(); - match token { - lexer::Eof => { break; } - lexer::StartOpeningTag(tag_name) => { - #debug["starting tag %s", tag_name]; - let element_kind = build_element_kind(tag_name); - let new_node = scope.new_node(Element(ElementData(copy tag_name, element_kind))); - scope.add_child(cur_node, new_node); - cur_node = new_node; - } - lexer::Attr(key, value) => { - #debug["attr: %? = %?", key, value]; - link_up_attribute(scope, cur_node, copy key, copy value); - } - lexer::EndOpeningTag => { - #debug("end opening tag"); - } - // TODO: Fail more gracefully (i.e. according to the HTML5 - // spec) if we close more tags than we open. - lexer::SelfCloseTag => { - //TODO: check for things other than the link tag - scope.read(cur_node, |n| { - match *n.kind { - Element(elmt) if elmt.tag_name == ~"link" => { - match elmt.get_attr(~"rel") { - Some(r) if r == ~"stylesheet" => { - match elmt.get_attr(~"href") { - Some(filename) => { - #debug["Linking to a css sheet named: %s", filename]; - // FIXME: Need to base the new url on the current url - let new_url = make_url(filename, Some(copy url)); - style_chan.send(File(new_url)); - } - None => { /* fall through*/ } - } - } - _ => { /* fall through*/ } - } - } - _ => { /* fall through*/ } - } - }); - cur_node = scope.get_parent(cur_node).get(); - } - lexer::EndTag(*) => { - // TODO: Assert that the closing tag has the right name. - scope.read(cur_node, |n| { - match *n.kind { - Element(elmt) if elmt.tag_name == ~"script" => { - match elmt.get_attr(~"src") { - Some(filename) => { - #debug["Linking to a js script named: %s", filename]; - let new_url = make_url(filename, Some(copy url)); - js_chan.send(js_file(new_url)); - } - None => { /* fall through */ } - } - } - _ => { /* fall though */ } - } - }); - cur_node = scope.get_parent(cur_node).get(); - } - lexer::Text(s) if !s.is_whitespace() => { - let new_node = scope.new_node(Text(copy s)); - scope.add_child(cur_node, new_node); - } - lexer::Text(_) => { - // FIXME: Whitespace should not be ignored. - } - lexer::Doctype => { - // TODO: Do something here... - } - } - } - - style_chan.send(Exit); - js_chan.send(js_exit); - - return (cur_node, style_port, js_port); -} diff --git a/src/servo/html/hubbub_html_parser.rs b/src/servo/html/hubbub_html_parser.rs index 8c366e94109..0dc61abb8d8 100644 --- a/src/servo/html/hubbub_html_parser.rs +++ b/src/servo/html/hubbub_html_parser.rs @@ -1,16 +1,10 @@ use au = gfx::geometry; -use dom::base::{Attr, Comment, Doctype, DoctypeData, Element, ElementData, ElementKind}; -use dom::base::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, HTMLScriptElement}; +use dom::base::{Comment, Doctype, DoctypeData, Element}; +use dom::element::*; use dom::base::{Node, NodeScope, Text, UnknownElement}; use css::values::Stylesheet; use geom::size::Size2D; -use html::dom_builder::CSSMessage; use resource::resource_task::{Done, Load, Payload, ResourceTask}; -use CSSExitMessage = html::dom_builder::Exit; -use CSSFileMessage = html::dom_builder::File; -use JSExitMessage = html::dom_builder::js_exit; -use JSFileMessage = html::dom_builder::js_file; -use JSMessage = html::dom_builder::js_message; use comm::{Chan, Port}; use str::from_slice; @@ -19,6 +13,16 @@ use std::net::url::Url; type JSResult = ~[~[u8]]; +enum CSSMessage { + CSSTaskNewFile(Url), + CSSTaskExit +} + +enum JSMessage { + JSTaskNewFile(Url), + JSTaskExit +} + struct HtmlParserResult { root: Node, style_port: comm::Port, @@ -45,7 +49,7 @@ fn css_link_listener(to_parent : comm::Chan, from_parent : comm::Por loop { match from_parent.recv() { - CSSFileMessage(url) => { + CSSTaskNewFile(url) => { let result_port = comm::Port(); let result_chan = comm::Chan(result_port); // TODO: change copy to move once we have match move @@ -59,7 +63,7 @@ fn css_link_listener(to_parent : comm::Chan, from_parent : comm::Por vec::push(result_vec, result_port); } - CSSExitMessage => { + CSSTaskExit => { break; } } @@ -76,7 +80,7 @@ fn js_script_listener(to_parent : comm::Chan<~[~[u8]]>, from_parent : comm::Port loop { match from_parent.recv() { - JSFileMessage(url) => { + JSTaskNewFile(url) => { let result_port = comm::Port(); let result_chan = comm::Chan(result_port); // TODO: change copy to move once we have match move @@ -104,7 +108,7 @@ fn js_script_listener(to_parent : comm::Chan<~[~[u8]]>, from_parent : comm::Port } vec::push(result_vec, result_port); } - JSExitMessage => { + JSTaskExit => { break; } } @@ -114,18 +118,47 @@ fn js_script_listener(to_parent : comm::Chan<~[~[u8]]>, from_parent : comm::Port to_parent.send(js_scripts); } -fn build_element_kind(tag_name: &str) -> ~ElementKind { - if tag_name == "div" { - ~HTMLDivElement - } else if tag_name == "img" { - ~HTMLImageElement({ mut size: Size2D(au::from_px(100), au::from_px(100)) }) - } else if tag_name == "script" { - ~HTMLScriptElement - } else if tag_name == "head" { - ~HTMLHeadElement - } else { - ~UnknownElement - } +fn build_element_kind(tag: &str) -> ~ElementKind { + // TODO: use atoms + if tag == ~"a" { ~HTMLAnchorElement } + else if tag == ~"aside" { ~HTMLAsideElement } + else if tag == ~"br" { ~HTMLBRElement } + else if tag == ~"body" { ~HTMLBodyElement } + else if tag == ~"bold" { ~HTMLBoldElement } + else if tag == ~"div" { ~HTMLDivElement } + else if tag == ~"font" { ~HTMLFontElement } + else if tag == ~"form" { ~HTMLFormElement } + else if tag == ~"hr" { ~HTMLHRElement } + else if tag == ~"head" { ~HTMLHeadElement } + else if tag == ~"h1" { ~HTMLHeadingElement(Heading1) } + else if tag == ~"h2" { ~HTMLHeadingElement(Heading2) } + else if tag == ~"h3" { ~HTMLHeadingElement(Heading3) } + else if tag == ~"h4" { ~HTMLHeadingElement(Heading4) } + else if tag == ~"h5" { ~HTMLHeadingElement(Heading5) } + else if tag == ~"h6" { ~HTMLHeadingElement(Heading6) } + else if tag == ~"html" { ~HTMLHtmlElement } + else if tag == ~"img" { ~HTMLImageElement({ mut size: au::zero_size() }) } + else if tag == ~"input" { ~HTMLInputElement } + else if tag == ~"i" { ~HTMLItalicElement } + else if tag == ~"link" { ~HTMLLinkElement } + else if tag == ~"li" { ~HTMLListItemElement } + else if tag == ~"meta" { ~HTMLMetaElement } + else if tag == ~"ol" { ~HTMLOListElement } + else if tag == ~"option" { ~HTMLOptionElement } + else if tag == ~"p" { ~HTMLParagraphElement } + else if tag == ~"script" { ~HTMLScriptElement } + else if tag == ~"section" { ~HTMLSectionElement } + else if tag == ~"select" { ~HTMLSelectElement } + else if tag == ~"small" { ~HTMLSmallElement } + else if tag == ~"span" { ~HTMLSpanElement } + else if tag == ~"style" { ~HTMLStyleElement } + else if tag == ~"tbody" { ~HTMLTableBodyElement } + else if tag == ~"td" { ~HTMLTableCellElement } + else if tag == ~"table" { ~HTMLTableElement } + else if tag == ~"tr" { ~HTMLTableRowElement } + else if tag == ~"title" { ~HTMLTitleElement } + else if tag == ~"ul" { ~HTMLUListElement } + else { ~UnknownElement } } fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlParserResult unsafe { @@ -175,53 +208,30 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa }, create_element: |tag: &hubbub::Tag| { debug!("create element"); - let element_kind = build_element_kind(tag.name); - let node = scope.new_node(Element(ElementData(from_slice(tag.name), element_kind))); + let elem_kind = build_element_kind(tag.name); + let elem = ElementData(from_slice(tag.name), elem_kind); + debug!("attach attrs"); for tag.attributes.each |attribute| { - do scope.read(node) |node_contents| { - match *node_contents.kind { - Element(element) => { - element.attrs.push(~Attr(from_slice(attribute.name), - from_slice(attribute.value))); - match *element.kind { - HTMLImageElement(img) if attribute.name == "width" => { - match int::from_str(from_slice(attribute.value)) { - None => {} // Drop on the floor. - Some(s) => img.size.width = au::from_px(s) - } - } - HTMLImageElement(img) if attribute.name == "height" => { - match int::from_str(from_slice(attribute.value)) { - None => {} // Drop on the floor. - Some(s) => img.size.height = au::from_px(s) - } - } - HTMLDivElement | HTMLImageElement(*) | HTMLHeadElement | - HTMLScriptElement | UnknownElement => {} // Drop on the floor. - } - } - - _ => fail ~"can't happen: unexpected node type" - } - } + elem.attrs.push(~Attr(from_slice(attribute.name), + from_slice(attribute.value))); } - // Handle CSS style sheet links. - do scope.read(node) |node_contents| { - match *node_contents.kind { - Element(element) if element.tag_name == ~"link" => { - match (element.get_attr(~"rel"), element.get_attr(~"href")) { - (Some(rel), Some(href)) if rel == ~"stylesheet" => { - debug!("found CSS stylesheet: %s", href); - css_chan.send(CSSFileMessage(make_url(href, Some(copy *url)))); - } - _ => {} + // Spawn additional parsing, network loads, etc. from opening tag + match elem.tag_name { + //Handle CSS style sheets from elements + ~"link" => { + match (elem.get_attr(~"rel"), elem.get_attr(~"href")) { + (Some(rel), Some(href)) if rel == ~"stylesheet" => { + debug!("found CSS stylesheet: %s", href); + css_chan.send(CSSTaskNewFile(make_url(href, Some(copy *url)))); } + _ => {} } - _ => {} } + //TODO: handle inline styles ('style' attr) + _ => {} } - + let node = scope.new_node(Element(elem)); unsafe { reinterpret_cast(&node) } }, create_text: |data| { @@ -280,7 +290,7 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa Some(src) => { debug!("found script: %s", src); let new_url = make_url(src, Some(copy *url)); - js_chan.send(JSFileMessage(new_url)); + js_chan.send(JSTaskNewFile(new_url)); } None => {} } @@ -308,8 +318,8 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa } } - css_chan.send(CSSExitMessage); - js_chan.send(JSExitMessage); + css_chan.send(CSSTaskExit); + js_chan.send(JSTaskExit); return HtmlParserResult { root: root, style_port: css_port, js_port: js_port }; } diff --git a/src/servo/layout/base.rs b/src/servo/layout/base.rs index b8a810a3d13..71062a44f9f 100644 --- a/src/servo/layout/base.rs +++ b/src/servo/layout/base.rs @@ -10,8 +10,8 @@ use core::rand; use css::styles::SpecifiedStyle; use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgTransparent}; use dl = gfx::display_list; -use dom::base::{Element, ElementKind, HTMLDivElement, HTMLImageElement}; -use dom::base::{Node, NodeData, NodeKind, NodeTree}; +use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement}; +use dom::base::{Element, Node, NodeData, NodeKind, NodeTree}; use dom::rcu; use geom::rect::Rect; use geom::size::Size2D; diff --git a/src/servo/layout/box_builder.rs b/src/servo/layout/box_builder.rs index 0bac63c2fa2..1181964818f 100644 --- a/src/servo/layout/box_builder.rs +++ b/src/servo/layout/box_builder.rs @@ -4,7 +4,8 @@ use core::dvec::DVec; use css::styles::SpecifiedStyle; use css::values::{CSSDisplay, DisplayBlock, DisplayInline, DisplayInlineBlock, DisplayNone}; use css::values::{Inherit, Initial, Specified}; -use dom::base::*; +use dom::base::{Node, Comment, Text, Element, Doctype, NodeTree}; +use dom::element::*; use layout::base::{RenderBox, BoxData, GenericBox, ImageBox, TextBox, RenderBoxTree}; use layout::base::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree}; use layout::block::BlockFlowData; diff --git a/src/servo/layout/inline.rs b/src/servo/layout/inline.rs index e11dced4a67..af19b5bcc4b 100644 --- a/src/servo/layout/inline.rs +++ b/src/servo/layout/inline.rs @@ -87,7 +87,7 @@ impl @FlowContext : InlineLayout { /* Recursively (top-down) determines the actual width of child contexts and boxes. When called on this context, the context has had its width set by the parent context. */ - fn assign_widths_inline(_ctx: &LayoutContext) { + fn assign_widths_inline(ctx: &LayoutContext) { assert self.starts_inline_flow(); /* Perform inline flow with the available width. */ @@ -107,6 +107,13 @@ impl @FlowContext : InlineLayout { where its chunks ended up. - Save the dvec of this context's lineboxes. */ + + /* hack: until text box splitting is hoisted into this + function, force "reflow" on TextBoxes. */ + match box.kind { + TextBox(*) => box.reflow_text(ctx), + _ => {} + } box.data.position.size.width = match box.kind { ImageBox(sz) => sz.width, diff --git a/src/servo/servo.rc b/src/servo/servo.rc index 559dbca4ac2..f3e1eb62071 100755 --- a/src/servo/servo.rc +++ b/src/servo/servo.rc @@ -31,6 +31,7 @@ mod dom { mod node; mod window; } + mod element; mod event; mod rcu; } @@ -88,7 +89,6 @@ mod image { mod html { mod lexer; mod lexer_util; - mod dom_builder; mod hubbub_html_parser; }