Reflow when images become available

This commit is contained in:
Brian Anderson 2012-08-17 16:56:29 -07:00
parent 5e379067e6
commit 7bf10c8e06
6 changed files with 55 additions and 16 deletions

View file

@ -88,7 +88,8 @@ struct Content<S:Sink send copy> {
let resource_task: ResourceTask;
new(layout: Layout, sink: S, from_master: Port<ControlMsg>, resource_task: ResourceTask) {
new(layout: Layout, sink: S, from_master: Port<ControlMsg>,
resource_task: ResourceTask) {
self.layout = layout;
self.sink = sink;
self.from_master = from_master;
@ -193,7 +194,7 @@ struct Content<S:Sink send copy> {
// Send new document and relevant styles to layout
// FIXME: Put CSS rules in an arc or something.
self.layout.send(BuildMsg(document.root, clone(&document.css_rules), copy *doc_url));
self.layout.send(BuildMsg(document.root, clone(&document.css_rules), copy *doc_url, self.event_port.chan()));
// Indicate that reader was forked so any further
// changes will be isolated.
@ -215,6 +216,19 @@ struct Content<S:Sink send copy> {
}
return true;
}
ReflowEvent => {
#debug("content got reflow event");
match copy self.document {
none => {
// Nothing to do.
}
some(document) => {
assert self.doc_url.is_some();
self.relayout(*document, &self.doc_url.get());
}
}
return true;
}
}
}
}

View file

@ -1,4 +1,5 @@
enum Event {
ResizeEvent(int, int)
ResizeEvent(int, int),
ReflowEvent
}

View file

@ -21,6 +21,7 @@ import resource::image_cache_task;
import image_cache_task::ImageCacheTask;
import core::to_str::ToStr;
import std::arc::{arc, clone};
import task::spawn;
enum BoxKind {
BlockBox,
@ -87,11 +88,13 @@ struct ImageHolder {
let mut url : option<url>;
let mut image : option<arc<~Image>>;
let image_cache_task: ImageCacheTask;
let reflow: fn~();
new(-url : url, image_cache_task: ImageCacheTask) {
new(-url : url, image_cache_task: ImageCacheTask, reflow: fn~()) {
self.url = some(copy url);
self.image = none;
self.image_cache_task = image_cache_task;
self.reflow = copy reflow;
// Tell the image cache we're going to be interested in this url
// FIXME: These two messages must be sent to prep an image for use
@ -117,8 +120,22 @@ struct ImageHolder {
self.image_cache_task.send(image_cache_task::GetImage(copy url, response_port.chan()));
self.image = match response_port.recv() {
image_cache_task::ImageReady(image) => some(clone(&image)),
image_cache_task::ImageNotReady
| image_cache_task::ImageFailed => {
image_cache_task::ImageNotReady => {
// Need to reflow when the image is available
let image_cache_task = self.image_cache_task;
let reflow = copy self.reflow;
do spawn |copy url, move reflow| {
let response_port = port();
image_cache_task.send(image_cache_task::WaitForImage(copy url, response_port.chan()));
match response_port.recv() {
image_cache_task::ImageReady(*) => reflow(),
image_cache_task::ImageNotReady => fail /*not possible*/,
image_cache_task::ImageFailed => ()
}
}
none
}
image_cache_task::ImageFailed => {
#info("image was not ready for %s", url.to_str());
// FIXME: Need to schedule another layout when the image is ready
none

View file

@ -12,6 +12,7 @@ import gfx::renderer::Renderer;
import resource::image_cache_task::ImageCacheTask;
import std::net::url::url;
import style::apply::apply_style;
import dom::event::{Event, ReflowEvent};
import task::*;
import comm::*;
@ -19,7 +20,7 @@ import comm::*;
type Layout = Chan<Msg>;
enum Msg {
BuildMsg(Node, arc<Stylesheet>, url),
BuildMsg(Node, arc<Stylesheet>, url, Chan<Event>),
PingMsg(Chan<content::PingMsg>),
ExitMsg
}
@ -33,7 +34,7 @@ fn Layout(renderer: Renderer, image_cache_task: ImageCacheTask) -> Layout {
#debug("layout: ExitMsg received");
break;
}
BuildMsg(node, styles, doc_url) => {
BuildMsg(node, styles, doc_url, event_chan) => {
#debug("layout: received layout request for:");
node.dump();
@ -44,7 +45,9 @@ fn Layout(renderer: Renderer, image_cache_task: ImageCacheTask) -> Layout {
let this_box = node.construct_boxes();
this_box.dump();
apply_style(this_box, &doc_url, image_cache_task);
let reflow: fn~() = || event_chan.send(ReflowEvent);
apply_style(this_box, &doc_url, image_cache_task, reflow);
this_box.reflow_subtree(px_to_au(800));

View file

@ -14,13 +14,15 @@ struct StyleApplicator {
box: @Box;
doc_url: &url;
image_cache_task: ImageCacheTask;
reflow: fn~();
}
fn apply_style(box: @Box, doc_url: &url, image_cache_task: ImageCacheTask) {
fn apply_style(box: @Box, doc_url: &url, image_cache_task: ImageCacheTask, reflow: fn~()) {
let applicator = StyleApplicator {
box: box,
doc_url: doc_url,
image_cache_task: image_cache_task
image_cache_task: image_cache_task,
reflow: reflow
};
applicator.apply_css_style();
@ -28,11 +30,12 @@ fn apply_style(box: @Box, doc_url: &url, image_cache_task: ImageCacheTask) {
#[doc="A wrapper around a set of functions that can be applied as a top-down traversal of layout
boxes."]
fn inheritance_wrapper(box : @Box, doc_url: &url, image_cache_task: ImageCacheTask) {
fn inheritance_wrapper(box : @Box, doc_url: &url, image_cache_task: ImageCacheTask, reflow: fn~()) {
let applicator = StyleApplicator {
box: box,
doc_url: doc_url,
image_cache_task: image_cache_task
image_cache_task: image_cache_task,
reflow: reflow
};
applicator.apply_style();
inhereit_height(box);
@ -103,8 +106,9 @@ impl StyleApplicator {
fn apply_css_style() {
let doc_url = copy *self.doc_url;
let image_cache_task = self.image_cache_task;
let reflow = copy self.reflow;
do top_down_traversal(self.box) |box, move doc_url| {
inheritance_wrapper(box, &doc_url, image_cache_task);
inheritance_wrapper(box, &doc_url, image_cache_task, reflow);
}
}
@ -136,7 +140,7 @@ impl StyleApplicator {
// FIXME: Some sort of BASE HREF support!
// FIXME: Parse URLs!
let new_url = make_url(option::unwrap(url), some(copy *self.doc_url));
self.box.appearance.background_image = some(ImageHolder(new_url, self.image_cache_task))
self.box.appearance.background_image = some(ImageHolder(new_url, self.image_cache_task, self.reflow))
};
}
_ => { /* Ignore. */ }

View file

@ -1,4 +1,4 @@
export Msg, Prefetch, Decode, GetImage, Exit;
export Msg, Prefetch, Decode, GetImage, WaitForImage, Exit;
export ImageResponseMsg, ImageReady, ImageNotReady, ImageFailed;
export ImageCacheTask;
export image_cache_task;