mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Revamp how images are handled. HTMLImageElement sends a prefetch message to the image cache during parsing. Other miscellaneous cleanup.
This commit is contained in:
parent
b7b3cc8bbb
commit
b5e0cee1ab
15 changed files with 174 additions and 131 deletions
|
@ -20,6 +20,7 @@ use gfx::compositor::Compositor;
|
||||||
use html::lexer::spawn_html_lexer_task;
|
use html::lexer::spawn_html_lexer_task;
|
||||||
use layout::layout_task;
|
use layout::layout_task;
|
||||||
use layout_task::{LayoutTask, BuildMsg};
|
use layout_task::{LayoutTask, BuildMsg};
|
||||||
|
use resource::image_cache_task::ImageCacheTask;
|
||||||
|
|
||||||
use css::styles::Stylesheet;
|
use css::styles::Stylesheet;
|
||||||
|
|
||||||
|
@ -59,9 +60,12 @@ enum PingMsg {
|
||||||
|
|
||||||
type ContentTask = Chan<ControlMsg>;
|
type ContentTask = Chan<ControlMsg>;
|
||||||
|
|
||||||
fn ContentTask<S: Compositor Send Copy>(layout_task: LayoutTask, +compositor: S, resource_task: ResourceTask) -> ContentTask {
|
fn ContentTask<S: Compositor Send Copy>(layout_task: LayoutTask,
|
||||||
|
+compositor: S,
|
||||||
|
resource_task: ResourceTask,
|
||||||
|
img_cache_task: ImageCacheTask) -> ContentTask {
|
||||||
do task().sched_mode(SingleThreaded).spawn_listener::<ControlMsg> |from_master| {
|
do task().sched_mode(SingleThreaded).spawn_listener::<ControlMsg> |from_master| {
|
||||||
Content(layout_task, compositor, from_master, resource_task).start();
|
Content(layout_task, compositor, from_master, resource_task, img_cache_task).start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +85,7 @@ fn join_layout(scope: NodeScope, layout_task: LayoutTask) {
|
||||||
struct Content<C:Compositor> {
|
struct Content<C:Compositor> {
|
||||||
compositor: C,
|
compositor: C,
|
||||||
layout_task: LayoutTask,
|
layout_task: LayoutTask,
|
||||||
|
image_cache_task: ImageCacheTask,
|
||||||
from_master: comm::Port<ControlMsg>,
|
from_master: comm::Port<ControlMsg>,
|
||||||
event_port: comm::Port<Event>,
|
event_port: comm::Port<Event>,
|
||||||
|
|
||||||
|
@ -100,7 +105,8 @@ struct Content<C:Compositor> {
|
||||||
fn Content<C:Compositor>(layout_task: LayoutTask,
|
fn Content<C:Compositor>(layout_task: LayoutTask,
|
||||||
compositor: C,
|
compositor: C,
|
||||||
from_master: Port<ControlMsg>,
|
from_master: Port<ControlMsg>,
|
||||||
resource_task: ResourceTask) -> Content<C> {
|
resource_task: ResourceTask,
|
||||||
|
img_cache_task: ImageCacheTask) -> Content<C> {
|
||||||
|
|
||||||
let jsrt = jsrt();
|
let jsrt = jsrt();
|
||||||
let cx = jsrt.cx();
|
let cx = jsrt.cx();
|
||||||
|
@ -117,6 +123,7 @@ fn Content<C:Compositor>(layout_task: LayoutTask,
|
||||||
|
|
||||||
Content {
|
Content {
|
||||||
layout_task : layout_task,
|
layout_task : layout_task,
|
||||||
|
image_cache_task : img_cache_task,
|
||||||
compositor : compositor,
|
compositor : compositor,
|
||||||
from_master : from_master,
|
from_master : from_master,
|
||||||
event_port : event_port,
|
event_port : event_port,
|
||||||
|
@ -159,7 +166,8 @@ impl<C:Compositor> Content<C> {
|
||||||
|
|
||||||
let result = html::hubbub_html_parser::parse_html(self.scope,
|
let result = html::hubbub_html_parser::parse_html(self.scope,
|
||||||
url,
|
url,
|
||||||
self.resource_task);
|
self.resource_task,
|
||||||
|
self.image_cache_task);
|
||||||
|
|
||||||
let root = result.root;
|
let root = result.root;
|
||||||
let css_rules = result.style_port.recv();
|
let css_rules = result.style_port.recv();
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#[doc="Applies the appropriate CSS style to boxes."]
|
/**
|
||||||
|
* Applies the appropriate CSS style to nodes.
|
||||||
|
*/
|
||||||
|
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
|
use dom::node::{Node, NodeTree};
|
||||||
use dom::element::*;
|
use dom::element::*;
|
||||||
use layout::base::{RenderBox, SpecifiedStyle, RenderBoxTree};
|
use layout::base::{RenderBox, SpecifiedStyle, RenderBoxTree};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
|
@ -16,7 +19,7 @@ trait ResolveMethods<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSValue<CSSBackgroundColor> : ResolveMethods<CSSBackgroundColor> {
|
impl CSSValue<CSSBackgroundColor> : ResolveMethods<CSSBackgroundColor> {
|
||||||
pure fn initial() -> CSSBackgroundColor { return BgTransparent; }
|
pure fn initial() -> CSSBackgroundColor { return BgColorTransparent; }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CSSValue<CSSDisplay> : ResolveMethods<CSSDisplay> {
|
impl CSSValue<CSSDisplay> : ResolveMethods<CSSDisplay> {
|
||||||
|
@ -33,14 +36,14 @@ impl CSSValue<CSSFontSize> : ResolveMethods<CSSFontSize> {
|
||||||
|
|
||||||
|
|
||||||
struct StyleApplicator {
|
struct StyleApplicator {
|
||||||
box: @RenderBox,
|
node: Node,
|
||||||
reflow: fn~(),
|
reflow: fn~(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: normalize this into a normal preorder tree traversal function
|
// TODO: normalize this into a normal preorder tree traversal function
|
||||||
fn apply_style(layout_ctx: &LayoutContext, box: @RenderBox, reflow: fn~()) {
|
fn apply_style(layout_ctx: &LayoutContext, node: Node, reflow: fn~()) {
|
||||||
let applicator = StyleApplicator {
|
let applicator = StyleApplicator {
|
||||||
box: box,
|
node: node,
|
||||||
reflow: reflow
|
reflow: reflow
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,14 +52,15 @@ fn apply_style(layout_ctx: &LayoutContext, box: @RenderBox, reflow: fn~()) {
|
||||||
|
|
||||||
// TODO: this is misleadingly-named. It is actually trying to resolve CSS 'inherit' values.
|
// TODO: this is misleadingly-named. It is actually trying to resolve CSS 'inherit' values.
|
||||||
|
|
||||||
#[doc="A wrapper around a set of functions that can be applied as a top-down traversal of layout
|
/** A wrapper around a set of functions that can be applied as a
|
||||||
boxes."]
|
* top-down traversal of layout boxes.
|
||||||
fn inheritance_wrapper(layout_ctx: &LayoutContext, box : @RenderBox, reflow: fn~()) {
|
*/
|
||||||
|
fn inheritance_wrapper(layout_ctx: &LayoutContext, node : Node, reflow: fn~()) {
|
||||||
let applicator = StyleApplicator {
|
let applicator = StyleApplicator {
|
||||||
box: box,
|
node: node,
|
||||||
reflow: reflow
|
reflow: reflow
|
||||||
};
|
};
|
||||||
applicator.apply_style(layout_ctx);
|
applicator.resolve_style(layout_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -103,41 +107,19 @@ impl StyleApplicator {
|
||||||
fn apply_css_style(layout_ctx: &LayoutContext) {
|
fn apply_css_style(layout_ctx: &LayoutContext) {
|
||||||
let reflow = copy self.reflow;
|
let reflow = copy self.reflow;
|
||||||
|
|
||||||
do RenderBoxTree.each_child(self.box) |child| {
|
do NodeTree.each_child(self.node) |child| {
|
||||||
inheritance_wrapper(layout_ctx, child, reflow); true
|
inheritance_wrapper(layout_ctx, child, reflow); true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="Applies CSS style to a layout box.
|
/**
|
||||||
|
* Convert the cascaded, specified style for this node into a resolved style:
|
||||||
Get the specified style and apply the existing traits to a
|
* one which additionally resolves the values of Initial, Inherit based on
|
||||||
layout box. If a trait does not exist, calculate the default
|
* defaults and node parent style. It also converts Node attributes into
|
||||||
value for the given type of element and use that instead.
|
* equivalent inline style declarations (TODO: where is this defined??)
|
||||||
|
*/
|
||||||
"]
|
fn resolve_style(_layout_ctx: &LayoutContext) {
|
||||||
fn apply_style(layout_ctx: &LayoutContext) {
|
// TODO: implement
|
||||||
|
|
||||||
// Right now, we only handle images.
|
|
||||||
do self.box.node.read |node| {
|
|
||||||
match node.kind {
|
|
||||||
~dom::node::Element(element) => {
|
|
||||||
match element.kind {
|
|
||||||
~HTMLImageElement(*) => {
|
|
||||||
let url = element.get_attr(~"src");
|
|
||||||
|
|
||||||
if url.is_some() {
|
|
||||||
// FIXME: Some sort of BASE HREF support!
|
|
||||||
// FIXME: Parse URLs!
|
|
||||||
let new_url = make_url(option::unwrap(url), Some(copy layout_ctx.doc_url));
|
|
||||||
self.box.data.background_image = Some(ImageHolder(new_url, layout_ctx.image_cache, self.reflow))
|
|
||||||
};
|
|
||||||
}
|
|
||||||
_ => { /* Ignore. */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => { /* Ignore. */ }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ use util::color::css_colors::{white, black};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
|
|
||||||
type SpecifiedStyle = {mut background_color : CSSValue<CSSBackgroundColor>,
|
type SpecifiedStyle = {mut background_color : CSSValue<CSSBackgroundColor>,
|
||||||
|
mut background_image : CSSValue<CSSBackgroundImage>,
|
||||||
mut display_type : CSSValue<CSSDisplay>,
|
mut display_type : CSSValue<CSSDisplay>,
|
||||||
mut font_size : CSSValue<CSSFontSize>,
|
mut font_size : CSSValue<CSSFontSize>,
|
||||||
mut height : CSSValue<BoxSizing>,
|
mut height : CSSValue<BoxSizing>,
|
||||||
|
@ -75,6 +76,7 @@ fn empty_style_for_node_kind(kind: NodeKind) -> SpecifiedStyle {
|
||||||
let display_type = kind.default_display_type();
|
let display_type = kind.default_display_type();
|
||||||
|
|
||||||
{mut background_color : Initial,
|
{mut background_color : Initial,
|
||||||
|
mut background_image: Initial,
|
||||||
mut display_type : Specified(display_type),
|
mut display_type : Specified(display_type),
|
||||||
mut font_size : Initial,
|
mut font_size : Initial,
|
||||||
mut height : Initial,
|
mut height : Initial,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use SharedColor = util::color::Color;
|
use SharedColor = util::color::Color;
|
||||||
use cmp::Eq;
|
use cmp::Eq;
|
||||||
|
use std::net::url::Url;
|
||||||
|
|
||||||
#[doc = "
|
#[doc = "
|
||||||
Defines how css rules, both selectors and style specifications, are
|
Defines how css rules, both selectors and style specifications, are
|
||||||
|
@ -101,7 +102,7 @@ enum CSSBackgroundAttachment {
|
||||||
|
|
||||||
enum CSSBackgroundColor {
|
enum CSSBackgroundColor {
|
||||||
BgColor(SharedColor),
|
BgColor(SharedColor),
|
||||||
BgTransparent
|
BgColorTransparent
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CSSBackgroundRepeat {
|
enum CSSBackgroundRepeat {
|
||||||
|
@ -111,6 +112,11 @@ enum CSSBackgroundRepeat {
|
||||||
BgNoRepeat
|
BgNoRepeat
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum CSSBackgroundImage {
|
||||||
|
BgImage(Url),
|
||||||
|
BgImageNone,
|
||||||
|
}
|
||||||
|
|
||||||
enum CSSColor {
|
enum CSSColor {
|
||||||
TextColor(SharedColor)
|
TextColor(SharedColor)
|
||||||
}
|
}
|
||||||
|
@ -232,7 +238,7 @@ impl CSSBackgroundColor: cmp::Eq {
|
||||||
pure fn eq(other: &CSSBackgroundColor) -> bool {
|
pure fn eq(other: &CSSBackgroundColor) -> bool {
|
||||||
match (self, *other) {
|
match (self, *other) {
|
||||||
(BgColor(a), BgColor(b)) => a == b,
|
(BgColor(a), BgColor(b)) => a == b,
|
||||||
(BgTransparent, BgTransparent) => true,
|
(BgColorTransparent, BgColorTransparent) => true,
|
||||||
(_, _) => false
|
(_, _) => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ use au = gfx::geometry;
|
||||||
use au::au;
|
use au::au;
|
||||||
use dvec::DVec;
|
use dvec::DVec;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
|
use std::net::url::Url;
|
||||||
|
|
||||||
struct ElementData {
|
struct ElementData {
|
||||||
tag_name: ~str,
|
tag_name: ~str,
|
||||||
|
@ -47,6 +48,16 @@ fn Attr(name: ~str, value: ~str) -> Attr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn HTMLImageData() -> HTMLImageData {
|
||||||
|
HTMLImageData {
|
||||||
|
image: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct HTMLImageData {
|
||||||
|
mut image: Option<Url>
|
||||||
|
}
|
||||||
|
|
||||||
enum HeadingLevel {
|
enum HeadingLevel {
|
||||||
Heading1,
|
Heading1,
|
||||||
Heading2,
|
Heading2,
|
||||||
|
@ -69,9 +80,7 @@ enum ElementKind {
|
||||||
HTMLHeadElement,
|
HTMLHeadElement,
|
||||||
HTMLHeadingElement(HeadingLevel),
|
HTMLHeadingElement(HeadingLevel),
|
||||||
HTMLHtmlElement,
|
HTMLHtmlElement,
|
||||||
// TODO: should not take this as argument--it is fetched from
|
HTMLImageElement(HTMLImageData),
|
||||||
// layout task as requested.
|
|
||||||
HTMLImageElement({mut size: Size2D<au>}),
|
|
||||||
HTMLInputElement,
|
HTMLInputElement,
|
||||||
HTMLItalicElement,
|
HTMLItalicElement,
|
||||||
HTMLLinkElement,
|
HTMLLinkElement,
|
||||||
|
|
|
@ -71,7 +71,7 @@ impl Node : DebugMethods {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn debug_str() -> ~str {
|
fn debug_str() -> ~str {
|
||||||
fmt!("%?", self.read(|n| copy n.kind ))
|
do self.read |n| { fmt!("%?", n.kind) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ fn EngineTask_<C: Compositor Send Copy>(
|
||||||
|
|
||||||
let render_task = RenderTask(compositor);
|
let render_task = RenderTask(compositor);
|
||||||
let layout_task = LayoutTask(render_task, image_cache_task);
|
let layout_task = LayoutTask(render_task, image_cache_task);
|
||||||
let content_task = ContentTask(layout_task, compositor, resource_task);
|
let content_task = ContentTask(layout_task, compositor, resource_task, image_cache_task);
|
||||||
|
|
||||||
Engine {
|
Engine {
|
||||||
compositor: compositor,
|
compositor: compositor,
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use dom::element::UnknownElement;
|
use content::content_task::ContentTask;
|
||||||
|
use css::values::Stylesheet;
|
||||||
|
use dom::element::*;
|
||||||
|
use dom::event::{Event, ReflowEvent};
|
||||||
use dom::node::{Comment, Doctype, DoctypeData, Text,
|
use dom::node::{Comment, Doctype, DoctypeData, Text,
|
||||||
Element, Node, NodeScope};
|
Element, Node, NodeScope};
|
||||||
use dom::element::*;
|
use resource::image_cache_task::ImageCacheTask;
|
||||||
use css::values::Stylesheet;
|
use resource::image_cache_task;
|
||||||
use geom::size::Size2D;
|
|
||||||
use resource::resource_task::{Done, Load, Payload, ResourceTask};
|
use resource::resource_task::{Done, Load, Payload, ResourceTask};
|
||||||
|
|
||||||
use comm::{Chan, Port};
|
use comm::{Chan, Port};
|
||||||
|
@ -138,7 +140,7 @@ fn build_element_kind(tag: &str) -> ~ElementKind {
|
||||||
else if tag == ~"h5" { ~HTMLHeadingElement(Heading5) }
|
else if tag == ~"h5" { ~HTMLHeadingElement(Heading5) }
|
||||||
else if tag == ~"h6" { ~HTMLHeadingElement(Heading6) }
|
else if tag == ~"h6" { ~HTMLHeadingElement(Heading6) }
|
||||||
else if tag == ~"html" { ~HTMLHtmlElement }
|
else if tag == ~"html" { ~HTMLHtmlElement }
|
||||||
else if tag == ~"img" { ~HTMLImageElement({ mut size: au::zero_size() }) }
|
else if tag == ~"img" { ~HTMLImageElement(HTMLImageData()) }
|
||||||
else if tag == ~"input" { ~HTMLInputElement }
|
else if tag == ~"input" { ~HTMLInputElement }
|
||||||
else if tag == ~"i" { ~HTMLItalicElement }
|
else if tag == ~"i" { ~HTMLItalicElement }
|
||||||
else if tag == ~"link" { ~HTMLLinkElement }
|
else if tag == ~"link" { ~HTMLLinkElement }
|
||||||
|
@ -162,7 +164,10 @@ fn build_element_kind(tag: &str) -> ~ElementKind {
|
||||||
else { ~UnknownElement }
|
else { ~UnknownElement }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlParserResult unsafe {
|
fn parse_html(scope: NodeScope,
|
||||||
|
url: Url,
|
||||||
|
resource_task: ResourceTask,
|
||||||
|
image_cache_task: ImageCacheTask) -> HtmlParserResult unsafe {
|
||||||
// Spawn a CSS parser to receive links to CSS style sheets.
|
// Spawn a CSS parser to receive links to CSS style sheets.
|
||||||
let (css_port, css_chan): (comm::Port<Stylesheet>, comm::Chan<CSSMessage>) =
|
let (css_port, css_chan): (comm::Port<Stylesheet>, comm::Chan<CSSMessage>) =
|
||||||
do task::spawn_conversation |css_port: comm::Port<CSSMessage>,
|
do task::spawn_conversation |css_port: comm::Port<CSSMessage>,
|
||||||
|
@ -217,10 +222,10 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa
|
||||||
from_slice(attribute.value)));
|
from_slice(attribute.value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn additional parsing, network loads, etc. from opening tag
|
// Spawn additional parsing, network loads, etc. from tag and attrs
|
||||||
match elem.tag_name {
|
match elem.kind {
|
||||||
//Handle CSS style sheets from <link> elements
|
//Handle CSS style sheets from <link> elements
|
||||||
~"link" => {
|
~HTMLLinkElement => {
|
||||||
match (elem.get_attr(~"rel"), elem.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);
|
||||||
|
@ -228,6 +233,14 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
~HTMLImageElement(d) => {
|
||||||
|
do elem.get_attr(~"src").iter |img_url_str| {
|
||||||
|
let img_url = make_url(copy img_url_str, Some(copy *url));
|
||||||
|
d.image = Some(copy img_url);
|
||||||
|
// inform the image cache to load this, but don't store a handle.
|
||||||
|
image_cache_task.send(image_cache_task::Prefetch(move img_url));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//TODO: handle inline styles ('style' attr)
|
//TODO: handle inline styles ('style' attr)
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use std::net::url::Url;
|
use std::net::url::Url;
|
||||||
use std::arc::{ARC, clone};
|
use std::arc::{ARC, clone, get};
|
||||||
use resource::image_cache_task::ImageCacheTask;
|
use resource::image_cache_task::ImageCacheTask;
|
||||||
use resource::image_cache_task;
|
use resource::image_cache_task;
|
||||||
|
use geom::size::Size2D;
|
||||||
|
|
||||||
/** A struct to store image data. The image will be loaded once, the
|
/** A struct to store image data. The image will be loaded once, the
|
||||||
first time it is requested, and an arc will be stored. Clones of
|
first time it is requested, and an arc will be stored. Clones of
|
||||||
|
@ -17,9 +18,10 @@ pub struct ImageHolder {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ImageHolder(-url : Url, image_cache_task: ImageCacheTask, cb: fn~()) -> ImageHolder {
|
fn ImageHolder(url : &Url, image_cache_task: ImageCacheTask, cb: fn~()) -> ImageHolder {
|
||||||
|
debug!("ImageHolder() %?", url.to_str());
|
||||||
let holder = ImageHolder {
|
let holder = ImageHolder {
|
||||||
url : Some(copy url),
|
url : Some(copy *url),
|
||||||
image : None,
|
image : None,
|
||||||
image_cache_task : image_cache_task,
|
image_cache_task : image_cache_task,
|
||||||
reflow_cb : copy cb,
|
reflow_cb : copy cb,
|
||||||
|
@ -30,23 +32,34 @@ fn ImageHolder(-url : Url, image_cache_task: ImageCacheTask, cb: fn~()) -> Image
|
||||||
// but they are intended to be spread out in time. Ideally prefetch
|
// but they are intended to be spread out in time. Ideally prefetch
|
||||||
// should be done as early as possible and decode only once we
|
// should be done as early as possible and decode only once we
|
||||||
// are sure that the image will be used.
|
// are sure that the image will be used.
|
||||||
image_cache_task.send(image_cache_task::Prefetch(copy url));
|
image_cache_task.send(image_cache_task::Prefetch(copy *url));
|
||||||
image_cache_task.send(image_cache_task::Decode(move url));
|
image_cache_task.send(image_cache_task::Decode(copy *url));
|
||||||
|
|
||||||
holder
|
holder
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageHolder {
|
impl ImageHolder {
|
||||||
|
fn get_size() -> Option<Size2D<int>> {
|
||||||
|
debug!("get_size() %?", self.url);
|
||||||
|
match self.get_image() {
|
||||||
|
Some(img) => {
|
||||||
|
let img_ref = get(&img);
|
||||||
|
Some(Size2D(img_ref.width as int,
|
||||||
|
img_ref.height as int))
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This function should not be called by two tasks at the same time
|
// This function should not be called by two tasks at the same time
|
||||||
fn get_image() -> Option<ARC<~Image>> {
|
fn get_image() -> Option<ARC<~Image>> {
|
||||||
|
debug!("get_image() %?", self.url);
|
||||||
|
|
||||||
// If this is the first time we've called this function, load
|
// If this is the first time we've called this function, load
|
||||||
// the image and store it for the future
|
// the image and store it for the future
|
||||||
if self.image.is_none() {
|
if self.image.is_none() {
|
||||||
assert self.url.is_some();
|
assert self.url.is_some();
|
||||||
|
let url = copy self.url.get();
|
||||||
let mut temp = None;
|
|
||||||
temp <-> self.url;
|
|
||||||
let url = option::unwrap(temp);
|
|
||||||
|
|
||||||
let response_port = Port();
|
let response_port = Port();
|
||||||
self.image_cache_task.send(image_cache_task::GetImage(copy url, response_port.chan()));
|
self.image_cache_task.send(image_cache_task::GetImage(copy url, response_port.chan()));
|
||||||
|
@ -68,7 +81,7 @@ impl ImageHolder {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
image_cache_task::ImageFailed => {
|
image_cache_task::ImageFailed => {
|
||||||
#info("image was not ready for %s", url.to_str());
|
debug!("image was not ready for %s", url.to_str());
|
||||||
// FIXME: Need to schedule another layout when the image is ready
|
// FIXME: Need to schedule another layout when the image is ready
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ 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::styles::SpecifiedStyle;
|
||||||
use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgTransparent};
|
use css::values::{BoxSizing, Length, Px, CSSDisplay, Specified, BgColor, BgColorTransparent};
|
||||||
use dl = gfx::display_list;
|
use dl = gfx::display_list;
|
||||||
use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement};
|
use dom::element::{ElementKind, HTMLDivElement, HTMLImageElement};
|
||||||
use dom::node::{Element, Node, NodeData, NodeKind, NodeTree};
|
use dom::node::{Element, Node, NodeData, NodeKind, NodeTree};
|
||||||
|
@ -121,6 +121,7 @@ enum FlowContextData {
|
||||||
struct FlowContext {
|
struct FlowContext {
|
||||||
kind: FlowContextData,
|
kind: FlowContextData,
|
||||||
data: FlowLayoutData,
|
data: FlowLayoutData,
|
||||||
|
mut node: Option<Node>,
|
||||||
/* reference to parent, children flow contexts */
|
/* reference to parent, children flow contexts */
|
||||||
tree: tree::Tree<@FlowContext>,
|
tree: tree::Tree<@FlowContext>,
|
||||||
/* TODO: debug only */
|
/* TODO: debug only */
|
||||||
|
@ -131,6 +132,7 @@ fn FlowContext(id: int, kind: FlowContextData, tree: tree::Tree<@FlowContext>) -
|
||||||
FlowContext {
|
FlowContext {
|
||||||
kind: kind,
|
kind: kind,
|
||||||
data: FlowLayoutData(),
|
data: FlowLayoutData(),
|
||||||
|
node: None,
|
||||||
tree: tree,
|
tree: tree,
|
||||||
id: id
|
id: id
|
||||||
}
|
}
|
||||||
|
@ -230,7 +232,7 @@ fn BoxLayoutData() -> BoxLayoutData {
|
||||||
|
|
||||||
enum BoxData {
|
enum BoxData {
|
||||||
GenericBox,
|
GenericBox,
|
||||||
ImageBox(Size2D<au>),
|
ImageBox(ImageHolder),
|
||||||
TextBox(TextBoxData)
|
TextBox(TextBoxData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +272,11 @@ impl @RenderBox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pure fn get_min_width() -> au {
|
/** In general, these functions are transitively impure because they
|
||||||
|
* may cause glyphs to be allocated. For now, it's impure because of
|
||||||
|
* holder.get_image()
|
||||||
|
*/
|
||||||
|
fn get_min_width() -> au {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
// TODO: this should account for min/pref widths of the
|
// TODO: this should account for min/pref widths of the
|
||||||
// box element in isolation. That includes
|
// box element in isolation. That includes
|
||||||
|
@ -279,18 +285,15 @@ impl @RenderBox {
|
||||||
// that of its children to arrive at the context width.
|
// that of its children to arrive at the context width.
|
||||||
GenericBox => au(0),
|
GenericBox => au(0),
|
||||||
// TODO: consult CSS 'width', margin, border.
|
// TODO: consult CSS 'width', margin, border.
|
||||||
// TODO: If image isn't available, consult Node
|
// TODO: If image isn't available, consult 'width'.
|
||||||
// attrs, etc. to determine intrinsic dimensions. These
|
ImageBox(i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),
|
||||||
// dimensions are not defined by CSS 2.1, but are defined
|
|
||||||
// by the HTML5 spec in Section 4.8.1
|
|
||||||
ImageBox(size) => size.width,
|
|
||||||
TextBox(d) => d.runs.foldl(au(0), |sum, run| {
|
TextBox(d) => d.runs.foldl(au(0), |sum, run| {
|
||||||
au::max(sum, run.min_break_width())
|
au::max(sum, run.min_break_width())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pure fn get_pref_width() -> au {
|
fn get_pref_width() -> au {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
// TODO: this should account for min/pref widths of the
|
// TODO: this should account for min/pref widths of the
|
||||||
// box element in isolation. That includes
|
// box element in isolation. That includes
|
||||||
|
@ -298,11 +301,7 @@ impl @RenderBox {
|
||||||
// FlowContext will combine the width of this element and
|
// FlowContext will combine the width of this element and
|
||||||
// that of its children to arrive at the context width.
|
// that of its children to arrive at the context width.
|
||||||
GenericBox => au(0),
|
GenericBox => au(0),
|
||||||
// TODO: If image isn't available, consult Node
|
ImageBox(i) => au::from_px(i.get_size().get_default(Size2D(0,0)).width),
|
||||||
// attrs, etc. to determine intrinsic dimensions. These
|
|
||||||
// dimensions are not defined by CSS 2.1, but are defined
|
|
||||||
// by the HTML5 spec in Section 4.8.1
|
|
||||||
ImageBox(size) => size.width,
|
|
||||||
// TODO: account for line breaks, etc. The run should know
|
// TODO: account for line breaks, etc. The run should know
|
||||||
// how to compute its own min and pref widths, and should
|
// how to compute its own min and pref widths, and should
|
||||||
// probably cache them.
|
// probably cache them.
|
||||||
|
@ -330,6 +329,7 @@ impl @RenderBox {
|
||||||
(au(0), au(0))
|
(au(0), au(0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This will be very unhappy if it is getting run in parallel with
|
// This will be very unhappy if it is getting run in parallel with
|
||||||
// anything trying to read the background image
|
// anything trying to read the background image
|
||||||
fn get_image() -> Option<ARC<~Image>> {
|
fn get_image() -> Option<ARC<~Image>> {
|
||||||
|
@ -408,7 +408,7 @@ impl @RenderBox {
|
||||||
let boxed_color = self.node.style().background_color;
|
let boxed_color = self.node.style().background_color;
|
||||||
let color = match boxed_color {
|
let color = match boxed_color {
|
||||||
Specified(BgColor(c)) => c,
|
Specified(BgColor(c)) => c,
|
||||||
Specified(BgTransparent) | _ => util::color::rgba(0,0,0,0.0)
|
Specified(BgColorTransparent) | _ => util::color::rgba(0,0,0,0.0)
|
||||||
};
|
};
|
||||||
list.push(~dl::SolidColor(bounds, color.red, color.green, color.blue));
|
list.push(~dl::SolidColor(bounds, color.red, color.green, color.blue));
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ use css::values::{CSSDisplay, DisplayBlock, DisplayInline, DisplayInlineBlock, D
|
||||||
use css::values::{Inherit, Initial, Specified};
|
use css::values::{Inherit, Initial, Specified};
|
||||||
use dom::element::*;
|
use dom::element::*;
|
||||||
use dom::node::{Comment, Doctype, Element, Text, Node, NodeTree, LayoutData};
|
use dom::node::{Comment, Doctype, Element, Text, Node, NodeTree, LayoutData};
|
||||||
|
use image::holder::ImageHolder;
|
||||||
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;
|
||||||
|
@ -21,7 +22,6 @@ use servo_text::font_cache::FontCache;
|
||||||
export LayoutTreeBuilder;
|
export LayoutTreeBuilder;
|
||||||
|
|
||||||
struct LayoutTreeBuilder {
|
struct LayoutTreeBuilder {
|
||||||
mut root_box: Option<@RenderBox>,
|
|
||||||
mut root_ctx: Option<@FlowContext>,
|
mut root_ctx: Option<@FlowContext>,
|
||||||
mut next_bid: int,
|
mut next_bid: int,
|
||||||
mut next_cid: int
|
mut next_cid: int
|
||||||
|
@ -29,7 +29,6 @@ struct LayoutTreeBuilder {
|
||||||
|
|
||||||
fn LayoutTreeBuilder() -> LayoutTreeBuilder {
|
fn LayoutTreeBuilder() -> LayoutTreeBuilder {
|
||||||
LayoutTreeBuilder {
|
LayoutTreeBuilder {
|
||||||
root_box: None,
|
|
||||||
root_ctx: None,
|
root_ctx: None,
|
||||||
next_bid: -1,
|
next_bid: -1,
|
||||||
next_cid: -1
|
next_cid: -1
|
||||||
|
@ -43,7 +42,9 @@ impl LayoutTreeBuilder {
|
||||||
|
|
||||||
/** Creates necessary box(es) and flow context(s) for the current DOM node,
|
/** Creates necessary box(es) and flow context(s) for the current DOM node,
|
||||||
and recurses on its children. */
|
and recurses on its children. */
|
||||||
fn construct_recursively(layout_ctx: &LayoutContext, cur_node: Node, parent_ctx: @FlowContext, parent_box: @RenderBox) {
|
fn construct_recursively(layout_ctx: &LayoutContext, cur_node: Node,
|
||||||
|
parent_ctx: @FlowContext, parent_box: Option<@RenderBox>) {
|
||||||
|
|
||||||
let style = cur_node.style();
|
let style = cur_node.style();
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
|
@ -58,10 +59,7 @@ impl LayoutTreeBuilder {
|
||||||
};
|
};
|
||||||
|
|
||||||
// first, create the proper box kind, based on node characteristics
|
// first, create the proper box kind, based on node characteristics
|
||||||
let box_data = match self.create_box_data(layout_ctx, cur_node, simulated_display) {
|
let box_data = self.create_box_data(layout_ctx, cur_node, simulated_display);
|
||||||
None => return,
|
|
||||||
Some(data) => data
|
|
||||||
};
|
|
||||||
|
|
||||||
// then, figure out its proper context, possibly reorganizing.
|
// then, figure out its proper context, possibly reorganizing.
|
||||||
let next_ctx: @FlowContext = match box_data {
|
let next_ctx: @FlowContext = match box_data {
|
||||||
|
@ -94,27 +92,40 @@ impl LayoutTreeBuilder {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// store reference to the flow context which contains any boxes
|
||||||
|
// that correspond to cur_node
|
||||||
|
assert cur_node.has_aux();
|
||||||
|
do cur_node.aux |data| { data.flow = Some(next_ctx) }
|
||||||
|
|
||||||
// make box, add box to any context-specific list.
|
// make box, add box to any context-specific list.
|
||||||
let mut new_box = self.make_box(cur_node, parent_ctx, box_data);
|
let mut new_box = self.make_box(cur_node, parent_ctx, box_data);
|
||||||
debug!("Assign ^box to flow: %?", next_ctx.debug_str());
|
debug!("Assign ^box to flow: %?", next_ctx.debug_str());
|
||||||
|
|
||||||
match next_ctx.kind {
|
match next_ctx.kind {
|
||||||
InlineFlow(d) => { d.boxes.push(new_box) }
|
InlineFlow(d) => {
|
||||||
|
d.boxes.push(new_box);
|
||||||
|
|
||||||
|
if (parent_box.is_some()) {
|
||||||
|
let parent = parent_box.get();
|
||||||
|
|
||||||
|
// connect the box to its parent box
|
||||||
|
debug!("In inline flow f%?, set child b%? of parent b%?", next_ctx.id, parent.id, new_box.id);
|
||||||
|
RenderBoxTree.add_child(parent, new_box);
|
||||||
|
}
|
||||||
|
}
|
||||||
BlockFlow(d) => { d.box = Some(new_box) }
|
BlockFlow(d) => { d.box = Some(new_box) }
|
||||||
_ => {} // TODO: float lists, etc.
|
_ => {} // TODO: float lists, etc.
|
||||||
};
|
};
|
||||||
|
|
||||||
// connect the box to its parent box
|
|
||||||
debug!("Adding child box b%? of b%?", parent_box.id, new_box.id);
|
|
||||||
RenderBoxTree.add_child(parent_box, new_box);
|
|
||||||
|
|
||||||
if (!next_ctx.eq(&parent_ctx)) {
|
if (!next_ctx.eq(&parent_ctx)) {
|
||||||
debug!("Adding child flow f%? of f%?", parent_ctx.id, next_ctx.id);
|
debug!("Adding child flow f%? of f%?", parent_ctx.id, next_ctx.id);
|
||||||
FlowTree.add_child(parent_ctx, next_ctx);
|
FlowTree.add_child(parent_ctx, next_ctx);
|
||||||
}
|
}
|
||||||
// recurse
|
// recurse
|
||||||
|
// TODO: don't set parent box unless this is an inline flow?
|
||||||
do NodeTree.each_child(cur_node) |child_node| {
|
do NodeTree.each_child(cur_node) |child_node| {
|
||||||
self.construct_recursively(layout_ctx, child_node, next_ctx, new_box); true
|
self.construct_recursively(layout_ctx, child_node, next_ctx, Some(new_box)); true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixup any irregularities, such as split inlines (CSS 2.1 Section 9.2.1.1)
|
// Fixup any irregularities, such as split inlines (CSS 2.1 Section 9.2.1.1)
|
||||||
|
@ -164,12 +175,11 @@ impl LayoutTreeBuilder {
|
||||||
|
|
||||||
/** entry point for box creation. Should only be
|
/** entry point for box creation. Should only be
|
||||||
called on root DOM element. */
|
called on root DOM element. */
|
||||||
fn construct_trees(layout_ctx: &LayoutContext, root: Node) -> Result<@RenderBox, ()> {
|
fn construct_trees(layout_ctx: &LayoutContext, root: Node) -> Result<@FlowContext, ()> {
|
||||||
self.root_ctx = Some(self.make_ctx(RootFlow(RootFlowData()), tree::empty()));
|
self.root_ctx = Some(self.make_ctx(RootFlow(RootFlowData()), tree::empty()));
|
||||||
self.root_box = Some(self.make_box(root, self.root_ctx.get(), GenericBox));
|
|
||||||
|
|
||||||
self.construct_recursively(layout_ctx, root, self.root_ctx.get(), self.root_box.get());
|
self.construct_recursively(layout_ctx, root, self.root_ctx.get(), None);
|
||||||
return Ok(self.root_box.get())
|
return Ok(self.root_ctx.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_ctx(kind : FlowContextData, tree: tree::Tree<@FlowContext>) -> @FlowContext {
|
fn make_ctx(kind : FlowContextData, tree: tree::Tree<@FlowContext>) -> @FlowContext {
|
||||||
|
@ -185,22 +195,27 @@ impl LayoutTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Based on the DOM node type, create a specific type of box */
|
/* Based on the DOM node type, create a specific type of box */
|
||||||
fn create_box_data(layout_ctx: &LayoutContext, node: Node, display: CSSDisplay) -> Option<BoxData> {
|
fn create_box_data(layout_ctx: &LayoutContext, node: Node, display: CSSDisplay) -> BoxData {
|
||||||
// TODO: handle more types of nodes.
|
// TODO: handle more types of nodes.
|
||||||
do node.read |n| {
|
do node.read |n| {
|
||||||
match n.kind {
|
match n.kind {
|
||||||
~Doctype(*) | ~Comment(*) => None,
|
~Doctype(*) | ~Comment(*) => fail ~"Hey, doctypes and comments shouldn't get here! They are display:none!",
|
||||||
~Text(string) => {
|
~Text(string) => {
|
||||||
// TODO: clean this up. Fonts should not be created here.
|
// TODO: clean this up. Fonts should not be created here.
|
||||||
let font = layout_ctx.font_cache.get_test_font();
|
let font = layout_ctx.font_cache.get_test_font();
|
||||||
let run = TextRun(font, string);
|
let run = TextRun(font, string);
|
||||||
Some(TextBox(TextBoxData(copy string, ~[move run])))
|
TextBox(TextBoxData(copy string, ~[move run]))
|
||||||
}
|
}
|
||||||
~Element(element) => {
|
~Element(element) => {
|
||||||
match (element.kind, display) {
|
match (element.kind, display) {
|
||||||
(~HTMLImageElement({size}), _) => Some(ImageBox(size)),
|
(~HTMLImageElement(d), _) if d.image.is_some() => {
|
||||||
// (_, Specified(_)) => Some(GenericBox),
|
let holder = ImageHolder(&d.image.get(),
|
||||||
(_, _) => Some(GenericBox) // TODO: replace this with the commented lines
|
layout_ctx.image_cache,
|
||||||
|
copy layout_ctx.reflow_cb);
|
||||||
|
ImageBox(holder)
|
||||||
|
},
|
||||||
|
// (_, Specified(_)) => GenericBox,
|
||||||
|
(_, _) => GenericBox // TODO: replace this with the commented lines
|
||||||
// (_, _) => fail ~"Can't create box for Node with non-specified 'display' type"
|
// (_, _) => fail ~"Can't create box for Node with non-specified 'display' type"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,6 @@ struct LayoutContext {
|
||||||
font_cache: @FontCache,
|
font_cache: @FontCache,
|
||||||
image_cache: ImageCacheTask,
|
image_cache: ImageCacheTask,
|
||||||
doc_url: Url,
|
doc_url: Url,
|
||||||
|
reflow_cb: fn~(),
|
||||||
screen_size: Rect<au>
|
screen_size: Rect<au>
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ export DisplayListBuilder;
|
||||||
|
|
||||||
use au = gfx::geometry;
|
use au = gfx::geometry;
|
||||||
use base::{RenderBox, RenderBoxTree};
|
use base::{RenderBox, RenderBoxTree};
|
||||||
use css::values::{BgColor, BgTransparent, Specified};
|
use css::values::{BgColor, BgColorTransparent, Specified};
|
||||||
use dl = gfx::display_list;
|
use dl = gfx::display_list;
|
||||||
use dom::node::{Text, NodeScope};
|
use dom::node::{Text, NodeScope};
|
||||||
use dom::rcu::Scope;
|
use dom::rcu::Scope;
|
||||||
|
|
|
@ -116,14 +116,14 @@ impl @FlowContext : InlineLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
box.data.position.size.width = match box.kind {
|
box.data.position.size.width = match box.kind {
|
||||||
ImageBox(sz) => sz.width,
|
ImageBox(img) => au::from_px(img.get_size().get_default(Size2D(0,0)).width),
|
||||||
TextBox(d) => d.runs[0].size().width,
|
TextBox(d) => d.runs[0].size().width,
|
||||||
// TODO: this should be set to the extents of its children
|
// TODO: this should be set to the extents of its children
|
||||||
GenericBox(*) => au(0)
|
GenericBox(*) => au(0)
|
||||||
};
|
};
|
||||||
|
|
||||||
box.data.position.size.height = match box.kind {
|
box.data.position.size.height = match box.kind {
|
||||||
ImageBox(sz) => sz.height,
|
ImageBox(img) => au::from_px(img.get_size().get_default(Size2D(0,0)).height),
|
||||||
TextBox(d) => d.runs[0].size().height,
|
TextBox(d) => d.runs[0].size().height,
|
||||||
// TODO: this should be set to the extents of its children
|
// TODO: this should be set to the extents of its children
|
||||||
GenericBox(*) => au(0)
|
GenericBox(*) => au(0)
|
||||||
|
|
|
@ -60,37 +60,31 @@ fn LayoutTask(render_task: RenderTask, image_cache_task: ImageCacheTask) -> Layo
|
||||||
image_cache: image_cache_task,
|
image_cache: image_cache_task,
|
||||||
font_cache: font_cache,
|
font_cache: font_cache,
|
||||||
doc_url: doc_url,
|
doc_url: doc_url,
|
||||||
|
reflow_cb: || event_chan.send(ReflowEvent),
|
||||||
// TODO: obtain screen size from a real data source
|
// TODO: obtain screen size from a real data source
|
||||||
screen_size: Rect(Point2D(au(0), au(0)), Size2D(au::from_px(800), au::from_px(600)))
|
screen_size: Rect(Point2D(au(0), au(0)), Size2D(au::from_px(800), au::from_px(600)))
|
||||||
};
|
};
|
||||||
|
|
||||||
do util::time::time(~"layout") {
|
do util::time::time(~"layout") {
|
||||||
|
// TODO: this is dumb. we don't need 3 separate traversals.
|
||||||
node.initialize_style_for_subtree(&layout_ctx, &layout_data_refs);
|
node.initialize_style_for_subtree(&layout_ctx, &layout_data_refs);
|
||||||
node.recompute_style_for_subtree(&layout_ctx, styles);
|
node.recompute_style_for_subtree(&layout_ctx, styles);
|
||||||
|
/* resolve styles (convert relative values) down the node tree */
|
||||||
// TODO: this should care about root flow, not root box.
|
apply_style(&layout_ctx, node, layout_ctx.reflow_cb);
|
||||||
let root_box: @RenderBox;
|
|
||||||
let builder = LayoutTreeBuilder();
|
let builder = LayoutTreeBuilder();
|
||||||
match builder.construct_trees(&layout_ctx, node) {
|
let layout_root: @FlowContext = match builder.construct_trees(&layout_ctx, node) {
|
||||||
Ok(root) => root_box = root,
|
Ok(root) => root,
|
||||||
Err(*) => fail ~"Root node should always exist"
|
Err(*) => fail ~"Root flow should always exist"
|
||||||
}
|
};
|
||||||
|
|
||||||
debug!("layout: constructed RenderBox tree");
|
|
||||||
root_box.dump();
|
|
||||||
|
|
||||||
debug!("layout: constructed Flow tree");
|
debug!("layout: constructed Flow tree");
|
||||||
root_box.ctx.dump();
|
layout_root.dump();
|
||||||
|
|
||||||
/* resolve styles (convert relative values) down the box tree */
|
|
||||||
let reflow_cb: fn~() = || event_chan.send(ReflowEvent);
|
|
||||||
apply_style(&layout_ctx, root_box, reflow_cb);
|
|
||||||
|
|
||||||
/* perform layout passes over the flow tree */
|
/* perform layout passes over the flow tree */
|
||||||
let root_flow = root_box.ctx;
|
do layout_root.traverse_postorder |f| { f.bubble_widths(&layout_ctx) }
|
||||||
do root_flow.traverse_postorder |f| { f.bubble_widths(&layout_ctx) }
|
do layout_root.traverse_preorder |f| { f.assign_widths(&layout_ctx) }
|
||||||
do root_flow.traverse_preorder |f| { f.assign_widths(&layout_ctx) }
|
do layout_root.traverse_postorder |f| { f.assign_height(&layout_ctx) }
|
||||||
do root_flow.traverse_postorder |f| { f.assign_height(&layout_ctx) }
|
|
||||||
|
|
||||||
let dlist = DVec();
|
let dlist = DVec();
|
||||||
let builder = dl::DisplayListBuilder {
|
let builder = dl::DisplayListBuilder {
|
||||||
|
@ -98,7 +92,7 @@ fn LayoutTask(render_task: RenderTask, image_cache_task: ImageCacheTask) -> Layo
|
||||||
};
|
};
|
||||||
// TODO: set options on the builder before building
|
// TODO: set options on the builder before building
|
||||||
// TODO: be smarter about what needs painting
|
// TODO: be smarter about what needs painting
|
||||||
root_flow.build_display_list(&builder, © root_flow.data.position, &dlist);
|
layout_root.build_display_list(&builder, © layout_root.data.position, &dlist);
|
||||||
render_task.send(render_task::RenderMsg(dlist));
|
render_task.send(render_task::RenderMsg(dlist));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue