mirror of
https://github.com/servo/servo.git
synced 2025-08-08 06:55:31 +01:00
Parse a bunch more tags; move ElementData enum to its own file; fix some UA style fakery; remove old DOM parser.
This commit is contained in:
parent
754bbeae41
commit
76a43555ac
13 changed files with 217 additions and 419 deletions
|
@ -16,7 +16,6 @@ use dom::base::{Document, Node, NodeScope, Window, define_bindings};
|
||||||
use dom::event::{Event, ResizeEvent, ReflowEvent};
|
use dom::event::{Event, ResizeEvent, ReflowEvent};
|
||||||
use gfx::compositor::Compositor;
|
use gfx::compositor::Compositor;
|
||||||
use html::lexer::spawn_html_lexer_task;
|
use html::lexer::spawn_html_lexer_task;
|
||||||
use html::dom_builder::build_dom;
|
|
||||||
use layout::layout_task;
|
use layout::layout_task;
|
||||||
use layout_task::{LayoutTask, BuildMsg};
|
use layout_task::{LayoutTask, BuildMsg};
|
||||||
|
|
||||||
|
@ -155,12 +154,6 @@ impl<C:Compositor> Content<C> {
|
||||||
|
|
||||||
// Note: we can parse the next document in parallel
|
// Note: we can parse the next document in parallel
|
||||||
// with any previous documents.
|
// 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,
|
let result = html::hubbub_html_parser::parse_html(self.scope,
|
||||||
url,
|
url,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#[doc="Applies the appropriate CSS style to boxes."]
|
#[doc="Applies the appropriate CSS style to boxes."]
|
||||||
|
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
|
use dom::element::*;
|
||||||
use layout::base::{RenderBox, SpecifiedStyle, RenderBoxTree};
|
use layout::base::{RenderBox, SpecifiedStyle, RenderBoxTree};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::traverse_parallel::top_down_traversal;
|
use layout::traverse_parallel::top_down_traversal;
|
||||||
|
@ -121,7 +122,7 @@ impl StyleApplicator {
|
||||||
match node.kind {
|
match node.kind {
|
||||||
~dom::base::Element(element) => {
|
~dom::base::Element(element) => {
|
||||||
match element.kind {
|
match element.kind {
|
||||||
~dom::base::HTMLImageElement(*) => {
|
~HTMLImageElement(*) => {
|
||||||
let url = element.get_attr(~"src");
|
let url = element.get_attr(~"src");
|
||||||
|
|
||||||
if url.is_some() {
|
if url.is_some() {
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
use dom::base::{LayoutData};
|
use dom::base::{LayoutData};
|
||||||
use dom::base;
|
use dom::base;
|
||||||
use base::{ElementData, Node, Text};
|
use dom::element::ElementData;
|
||||||
|
use base::{Node, Text};
|
||||||
|
|
||||||
use values::*;
|
use values::*;
|
||||||
use styles::{SpecifiedStyle};
|
use styles::{SpecifiedStyle};
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::arc::{ARC, get, clone};
|
||||||
|
|
||||||
use css::values::*;
|
use css::values::*;
|
||||||
use css::values::Stylesheet;
|
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::{Comment, Doctype, Element, Node, NodeKind, Text};
|
||||||
use dom::base::{LayoutData};
|
use dom::base::{LayoutData};
|
||||||
use util::color::{Color, rgb};
|
use util::color::{Color, rgb};
|
||||||
|
@ -37,6 +37,7 @@ impl NodeKind : DefaultStyleMethods {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: this belongs in the UA stylesheet */
|
||||||
fn default_display_type() -> CSSDisplay {
|
fn default_display_type() -> CSSDisplay {
|
||||||
match self {
|
match self {
|
||||||
Text(*) => { DisplayInline }
|
Text(*) => { DisplayInline }
|
||||||
|
@ -46,7 +47,7 @@ impl NodeKind : DefaultStyleMethods {
|
||||||
HTMLHeadElement => DisplayNone,
|
HTMLHeadElement => DisplayNone,
|
||||||
HTMLImageElement(*) => DisplayInline,
|
HTMLImageElement(*) => DisplayInline,
|
||||||
HTMLScriptElement => DisplayNone,
|
HTMLScriptElement => DisplayNone,
|
||||||
UnknownElement => DisplayInline,
|
_ => DisplayInline,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Comment(*) | Doctype(*) => DisplayNone
|
Comment(*) | Doctype(*) => DisplayNone
|
||||||
|
|
|
@ -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 comm::{Port, Chan};
|
||||||
use content::content_task::{ControlMsg, Timer};
|
use content::content_task::{ControlMsg, Timer};
|
||||||
use css::styles::SpecifiedStyle;
|
use css::styles::SpecifiedStyle;
|
||||||
use css::values::Stylesheet;
|
use css::values::Stylesheet;
|
||||||
|
use dom::element::{Attr, ElementData};
|
||||||
use dom::bindings;
|
use dom::bindings;
|
||||||
use dvec::DVec;
|
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::geometry::au;
|
use gfx::geometry::au;
|
||||||
use js::crust::*;
|
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,
|
fn define_bindings(compartment: bare_compartment, doc: @Document,
|
||||||
win: @Window) {
|
win: @Window) {
|
||||||
|
@ -182,14 +141,6 @@ fn define_bindings(compartment: bare_compartment, doc: @Document,
|
||||||
bindings::element::init(compartment);
|
bindings::element::init(compartment);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ElementKind {
|
|
||||||
UnknownElement,
|
|
||||||
HTMLDivElement,
|
|
||||||
HTMLHeadElement,
|
|
||||||
HTMLImageElement({mut size: Size2D<au>}),
|
|
||||||
HTMLScriptElement
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** The RCU rd_aux data is a (weak) pointer to the layout data,
|
/** The RCU rd_aux data is a (weak) pointer to the layout data,
|
||||||
defined by this `LayoutData` enum. It contains the CSS style object
|
defined by this `LayoutData` enum. It contains the CSS style object
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
|
use au::au;
|
||||||
use js::rust::{bare_compartment, methods, jsobj};
|
use js::rust::{bare_compartment, methods, jsobj};
|
||||||
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL,
|
use js::{JS_ARGV, JSCLASS_HAS_RESERVED_SLOTS, JSPROP_ENUMERATE, JSPROP_SHARED, JSVAL_NULL,
|
||||||
JS_THIS_OBJECT, JS_SET_RVAL, JSPROP_NATIVE_ACCESSORS};
|
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 js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub};
|
||||||
|
|
||||||
use dom::base::{Node, NodeScope, Element};
|
use dom::base::{Node, NodeScope, Element};
|
||||||
|
use dom::element::*;
|
||||||
use node::NodeBundle;
|
use node::NodeBundle;
|
||||||
use utils::{rust_box, squirrel_away_unique, get_compartment, domstring_to_jsval, str};
|
use utils::{rust_box, squirrel_away_unique, get_compartment, domstring_to_jsval, str};
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use ptr::null;
|
use ptr::null;
|
||||||
use node::unwrap;
|
use node::unwrap;
|
||||||
use dom::base::{HTMLImageElement, HTMLScriptElement, HTMLHeadElement, HTMLDivElement,
|
|
||||||
UnknownElement};
|
|
||||||
|
|
||||||
extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
|
extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
|
||||||
#debug("element finalize!");
|
#debug("element finalize!");
|
||||||
|
@ -71,13 +72,22 @@ extern fn HTMLImageElement_getWidth(cx: *JSContext, _argc: c_uint, vp: *mut jsva
|
||||||
let bundle = unwrap(obj);
|
let bundle = unwrap(obj);
|
||||||
let width = (*bundle).payload.scope.write((*bundle).payload.node, |nd| {
|
let width = (*bundle).payload.scope.write((*bundle).payload.node, |nd| {
|
||||||
match nd.kind {
|
match nd.kind {
|
||||||
~Element(ed) => {
|
~Element(ed) => {
|
||||||
match ed.kind {
|
match ed.kind {
|
||||||
~HTMLImageElement(img) => img.size.width,
|
~HTMLImageElement(*) => {
|
||||||
_ => fail ~"why is this not an image element?"
|
// TODO: this should actually come from rendered dimensions!
|
||||||
}
|
match ed.get_attr(~"width") {
|
||||||
}
|
Some(s) => match int::from_str(s) {
|
||||||
_ => fail ~"why is this not an element?"
|
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(
|
*vp = RUST_INT_TO_JSVAL(
|
||||||
|
@ -97,9 +107,9 @@ extern fn HTMLImageElement_setWidth(cx: *JSContext, _argc: c_uint, vp: *mut jsva
|
||||||
match nd.kind {
|
match nd.kind {
|
||||||
~Element(ed) => {
|
~Element(ed) => {
|
||||||
match ed.kind {
|
match ed.kind {
|
||||||
~HTMLImageElement(img) => {
|
~HTMLImageElement(*) => {
|
||||||
let arg = ptr::offset(JS_ARGV(cx, cast::reinterpret_cast(&vp)), 0);
|
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?"
|
_ => fail ~"why is this not an image element?"
|
||||||
}
|
}
|
||||||
|
@ -144,7 +154,7 @@ fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj unsafe {
|
||||||
~HTMLHeadElement(*) => ~"HTMLHeadElement",
|
~HTMLHeadElement(*) => ~"HTMLHeadElement",
|
||||||
~HTMLImageElement(*) => ~"HTMLImageElement",
|
~HTMLImageElement(*) => ~"HTMLImageElement",
|
||||||
~HTMLScriptElement(*) => ~"HTMLScriptElement",
|
~HTMLScriptElement(*) => ~"HTMLScriptElement",
|
||||||
~UnknownElement(*) => ~"HTMLElement"
|
_ => ~"HTMLElement"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => fail ~"element::create only handles elements"
|
_ => fail ~"element::create only handles elements"
|
||||||
|
|
96
src/servo/dom/element.rs
Normal file
96
src/servo/dom/element.rs
Normal file
|
@ -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<au>}),
|
||||||
|
HTMLInputElement,
|
||||||
|
HTMLItalicElement,
|
||||||
|
HTMLLinkElement,
|
||||||
|
HTMLListItemElement,
|
||||||
|
HTMLMetaElement,
|
||||||
|
HTMLOListElement,
|
||||||
|
HTMLOptionElement,
|
||||||
|
HTMLParagraphElement,
|
||||||
|
HTMLScriptElement,
|
||||||
|
HTMLSectionElement,
|
||||||
|
HTMLSelectElement,
|
||||||
|
HTMLSmallElement,
|
||||||
|
HTMLSpanElement,
|
||||||
|
HTMLStyleElement,
|
||||||
|
HTMLTableBodyElement,
|
||||||
|
HTMLTableCellElement,
|
||||||
|
HTMLTableElement,
|
||||||
|
HTMLTableRowElement,
|
||||||
|
HTMLTitleElement,
|
||||||
|
HTMLUListElement,
|
||||||
|
UnknownElement,
|
||||||
|
}
|
|
@ -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<Stylesheet>, from_parent : comm::Port<CSSMessage>,
|
|
||||||
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<js_message>,
|
|
||||||
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<Token>, url: Url,
|
|
||||||
resource_task: ResourceTask) -> (Node, comm::Port<Stylesheet>, 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);
|
|
||||||
}
|
|
|
@ -1,16 +1,10 @@
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use dom::base::{Attr, Comment, Doctype, DoctypeData, Element, ElementData, ElementKind};
|
use dom::base::{Comment, Doctype, DoctypeData, Element};
|
||||||
use dom::base::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, HTMLScriptElement};
|
use dom::element::*;
|
||||||
use dom::base::{Node, NodeScope, Text, UnknownElement};
|
use dom::base::{Node, NodeScope, Text, UnknownElement};
|
||||||
use css::values::Stylesheet;
|
use css::values::Stylesheet;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use html::dom_builder::CSSMessage;
|
|
||||||
use resource::resource_task::{Done, Load, Payload, ResourceTask};
|
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 comm::{Chan, Port};
|
||||||
use str::from_slice;
|
use str::from_slice;
|
||||||
|
@ -19,6 +13,16 @@ use std::net::url::Url;
|
||||||
|
|
||||||
type JSResult = ~[~[u8]];
|
type JSResult = ~[~[u8]];
|
||||||
|
|
||||||
|
enum CSSMessage {
|
||||||
|
CSSTaskNewFile(Url),
|
||||||
|
CSSTaskExit
|
||||||
|
}
|
||||||
|
|
||||||
|
enum JSMessage {
|
||||||
|
JSTaskNewFile(Url),
|
||||||
|
JSTaskExit
|
||||||
|
}
|
||||||
|
|
||||||
struct HtmlParserResult {
|
struct HtmlParserResult {
|
||||||
root: Node,
|
root: Node,
|
||||||
style_port: comm::Port<Stylesheet>,
|
style_port: comm::Port<Stylesheet>,
|
||||||
|
@ -45,7 +49,7 @@ fn css_link_listener(to_parent : comm::Chan<Stylesheet>, from_parent : comm::Por
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match from_parent.recv() {
|
match from_parent.recv() {
|
||||||
CSSFileMessage(url) => {
|
CSSTaskNewFile(url) => {
|
||||||
let result_port = comm::Port();
|
let result_port = comm::Port();
|
||||||
let result_chan = comm::Chan(result_port);
|
let result_chan = comm::Chan(result_port);
|
||||||
// TODO: change copy to move once we have match move
|
// TODO: change copy to move once we have match move
|
||||||
|
@ -59,7 +63,7 @@ fn css_link_listener(to_parent : comm::Chan<Stylesheet>, from_parent : comm::Por
|
||||||
|
|
||||||
vec::push(result_vec, result_port);
|
vec::push(result_vec, result_port);
|
||||||
}
|
}
|
||||||
CSSExitMessage => {
|
CSSTaskExit => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +80,7 @@ fn js_script_listener(to_parent : comm::Chan<~[~[u8]]>, from_parent : comm::Port
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match from_parent.recv() {
|
match from_parent.recv() {
|
||||||
JSFileMessage(url) => {
|
JSTaskNewFile(url) => {
|
||||||
let result_port = comm::Port();
|
let result_port = comm::Port();
|
||||||
let result_chan = comm::Chan(result_port);
|
let result_chan = comm::Chan(result_port);
|
||||||
// TODO: change copy to move once we have match move
|
// 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);
|
vec::push(result_vec, result_port);
|
||||||
}
|
}
|
||||||
JSExitMessage => {
|
JSTaskExit => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,18 +118,47 @@ fn js_script_listener(to_parent : comm::Chan<~[~[u8]]>, from_parent : comm::Port
|
||||||
to_parent.send(js_scripts);
|
to_parent.send(js_scripts);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_element_kind(tag_name: &str) -> ~ElementKind {
|
fn build_element_kind(tag: &str) -> ~ElementKind {
|
||||||
if tag_name == "div" {
|
// TODO: use atoms
|
||||||
~HTMLDivElement
|
if tag == ~"a" { ~HTMLAnchorElement }
|
||||||
} else if tag_name == "img" {
|
else if tag == ~"aside" { ~HTMLAsideElement }
|
||||||
~HTMLImageElement({ mut size: Size2D(au::from_px(100), au::from_px(100)) })
|
else if tag == ~"br" { ~HTMLBRElement }
|
||||||
} else if tag_name == "script" {
|
else if tag == ~"body" { ~HTMLBodyElement }
|
||||||
~HTMLScriptElement
|
else if tag == ~"bold" { ~HTMLBoldElement }
|
||||||
} else if tag_name == "head" {
|
else if tag == ~"div" { ~HTMLDivElement }
|
||||||
~HTMLHeadElement
|
else if tag == ~"font" { ~HTMLFontElement }
|
||||||
} else {
|
else if tag == ~"form" { ~HTMLFormElement }
|
||||||
~UnknownElement
|
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 {
|
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| {
|
create_element: |tag: &hubbub::Tag| {
|
||||||
debug!("create element");
|
debug!("create element");
|
||||||
let element_kind = build_element_kind(tag.name);
|
let elem_kind = build_element_kind(tag.name);
|
||||||
let node = scope.new_node(Element(ElementData(from_slice(tag.name), element_kind)));
|
let elem = ElementData(from_slice(tag.name), elem_kind);
|
||||||
|
debug!("attach attrs");
|
||||||
for tag.attributes.each |attribute| {
|
for tag.attributes.each |attribute| {
|
||||||
do scope.read(node) |node_contents| {
|
elem.attrs.push(~Attr(from_slice(attribute.name),
|
||||||
match *node_contents.kind {
|
from_slice(attribute.value)));
|
||||||
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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle CSS style sheet links.
|
// Spawn additional parsing, network loads, etc. from opening tag
|
||||||
do scope.read(node) |node_contents| {
|
match elem.tag_name {
|
||||||
match *node_contents.kind {
|
//Handle CSS style sheets from <link> elements
|
||||||
Element(element) if element.tag_name == ~"link" => {
|
~"link" => {
|
||||||
match (element.get_attr(~"rel"), element.get_attr(~"href")) {
|
match (elem.get_attr(~"rel"), elem.get_attr(~"href")) {
|
||||||
(Some(rel), Some(href)) if rel == ~"stylesheet" => {
|
(Some(rel), Some(href)) if rel == ~"stylesheet" => {
|
||||||
debug!("found CSS stylesheet: %s", href);
|
debug!("found CSS stylesheet: %s", href);
|
||||||
css_chan.send(CSSFileMessage(make_url(href, Some(copy *url))));
|
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) }
|
unsafe { reinterpret_cast(&node) }
|
||||||
},
|
},
|
||||||
create_text: |data| {
|
create_text: |data| {
|
||||||
|
@ -280,7 +290,7 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa
|
||||||
Some(src) => {
|
Some(src) => {
|
||||||
debug!("found script: %s", src);
|
debug!("found script: %s", src);
|
||||||
let new_url = make_url(src, Some(copy *url));
|
let new_url = make_url(src, Some(copy *url));
|
||||||
js_chan.send(JSFileMessage(new_url));
|
js_chan.send(JSTaskNewFile(new_url));
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
@ -308,8 +318,8 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
css_chan.send(CSSExitMessage);
|
css_chan.send(CSSTaskExit);
|
||||||
js_chan.send(JSExitMessage);
|
js_chan.send(JSTaskExit);
|
||||||
|
|
||||||
return HtmlParserResult { root: root, style_port: css_port, js_port: js_port };
|
return HtmlParserResult { root: root, style_port: css_port, js_port: js_port };
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,8 @@ use core::rand;
|
||||||
use css::styles::SpecifiedStyle;
|
use css::styles::SpecifiedStyle;
|
||||||
use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgTransparent};
|
use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgTransparent};
|
||||||
use dl = gfx::display_list;
|
use dl = gfx::display_list;
|
||||||
use dom::base::{Element, ElementKind, HTMLDivElement, HTMLImageElement};
|
use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement};
|
||||||
use dom::base::{Node, NodeData, NodeKind, NodeTree};
|
use dom::base::{Element, Node, NodeData, NodeKind, NodeTree};
|
||||||
use dom::rcu;
|
use dom::rcu;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
|
|
@ -4,7 +4,8 @@ use core::dvec::DVec;
|
||||||
use css::styles::SpecifiedStyle;
|
use css::styles::SpecifiedStyle;
|
||||||
use css::values::{CSSDisplay, DisplayBlock, DisplayInline, DisplayInlineBlock, DisplayNone};
|
use css::values::{CSSDisplay, DisplayBlock, DisplayInline, DisplayInlineBlock, DisplayNone};
|
||||||
use css::values::{Inherit, Initial, Specified};
|
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::{RenderBox, BoxData, GenericBox, ImageBox, TextBox, RenderBoxTree};
|
||||||
use layout::base::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree};
|
use layout::base::{FlowContext, FlowContextData, BlockFlow, InlineFlow, InlineBlockFlow, RootFlow, FlowTree};
|
||||||
use layout::block::BlockFlowData;
|
use layout::block::BlockFlowData;
|
||||||
|
|
|
@ -87,7 +87,7 @@ impl @FlowContext : InlineLayout {
|
||||||
/* Recursively (top-down) determines the actual width of child
|
/* Recursively (top-down) determines the actual width of child
|
||||||
contexts and boxes. When called on this context, the context has
|
contexts and boxes. When called on this context, the context has
|
||||||
had its width set by the parent context. */
|
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();
|
assert self.starts_inline_flow();
|
||||||
|
|
||||||
/* Perform inline flow with the available width. */
|
/* Perform inline flow with the available width. */
|
||||||
|
@ -107,6 +107,13 @@ impl @FlowContext : InlineLayout {
|
||||||
where its chunks ended up.
|
where its chunks ended up.
|
||||||
|
|
||||||
- Save the dvec of this context's lineboxes. */
|
- 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 {
|
box.data.position.size.width = match box.kind {
|
||||||
ImageBox(sz) => sz.width,
|
ImageBox(sz) => sz.width,
|
||||||
|
|
|
@ -31,6 +31,7 @@ mod dom {
|
||||||
mod node;
|
mod node;
|
||||||
mod window;
|
mod window;
|
||||||
}
|
}
|
||||||
|
mod element;
|
||||||
mod event;
|
mod event;
|
||||||
mod rcu;
|
mod rcu;
|
||||||
}
|
}
|
||||||
|
@ -88,7 +89,6 @@ mod image {
|
||||||
mod html {
|
mod html {
|
||||||
mod lexer;
|
mod lexer;
|
||||||
mod lexer_util;
|
mod lexer_util;
|
||||||
mod dom_builder;
|
|
||||||
mod hubbub_html_parser;
|
mod hubbub_html_parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue