mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
Load images through the image cache
This commit is contained in:
parent
b31da68ef2
commit
38321d9b70
4 changed files with 86 additions and 35 deletions
|
@ -84,6 +84,7 @@ class Content<S:Sink send copy> {
|
||||||
let jsrt: jsrt;
|
let jsrt: jsrt;
|
||||||
|
|
||||||
let mut document: option<@Document>;
|
let mut document: option<@Document>;
|
||||||
|
let mut doc_url: option<url>;
|
||||||
|
|
||||||
let resource_task: ResourceTask;
|
let resource_task: ResourceTask;
|
||||||
|
|
||||||
|
@ -97,6 +98,7 @@ class Content<S:Sink send copy> {
|
||||||
self.jsrt = jsrt();
|
self.jsrt = jsrt();
|
||||||
|
|
||||||
self.document = none;
|
self.document = none;
|
||||||
|
self.doc_url = none;
|
||||||
|
|
||||||
self.sink.add_event_listener(self.event_port.chan());
|
self.sink.add_event_listener(self.event_port.chan());
|
||||||
|
|
||||||
|
@ -135,8 +137,9 @@ class Content<S:Sink send copy> {
|
||||||
#debug["%?", js_scripts];
|
#debug["%?", js_scripts];
|
||||||
|
|
||||||
let document = Document(root, css_rules);
|
let document = Document(root, css_rules);
|
||||||
self.relayout(document);
|
self.relayout(document, &url);
|
||||||
self.document = some(@document);
|
self.document = some(@document);
|
||||||
|
self.doc_url = some(copy url);
|
||||||
|
|
||||||
//XXXjdm it was easier to duplicate the relevant ExecuteMsg code;
|
//XXXjdm it was easier to duplicate the relevant ExecuteMsg code;
|
||||||
// they should be merged somehow in the future.
|
// they should be merged somehow in the future.
|
||||||
|
@ -181,7 +184,7 @@ class Content<S:Sink send copy> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn relayout(document: Document) {
|
fn relayout(document: Document, doc_url: &url) {
|
||||||
#debug("content: performing relayout");
|
#debug("content: performing relayout");
|
||||||
|
|
||||||
// Now, join the layout so that they will see the latest
|
// Now, join the layout so that they will see the latest
|
||||||
|
@ -190,7 +193,7 @@ class Content<S:Sink send copy> {
|
||||||
|
|
||||||
// Send new document and relevant styles to layout
|
// Send new document and relevant styles to layout
|
||||||
// FIXME: Put CSS rules in an arc or something.
|
// FIXME: Put CSS rules in an arc or something.
|
||||||
self.layout.send(BuildMsg(document.root, clone(&document.css_rules)));
|
self.layout.send(BuildMsg(document.root, clone(&document.css_rules), copy *doc_url));
|
||||||
|
|
||||||
// Indicate that reader was forked so any further
|
// Indicate that reader was forked so any further
|
||||||
// changes will be isolated.
|
// changes will be isolated.
|
||||||
|
@ -206,7 +209,8 @@ class Content<S:Sink send copy> {
|
||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
some(document) => {
|
some(document) => {
|
||||||
self.relayout(*document);
|
assert self.doc_url.is_some();
|
||||||
|
self.relayout(*document, &self.doc_url.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -16,7 +16,10 @@ import text::TextBox;
|
||||||
import traverse::extended_full_traversal;
|
import traverse::extended_full_traversal;
|
||||||
import style::style::{SpecifiedStyle};
|
import style::style::{SpecifiedStyle};
|
||||||
import vec::{push, push_all};
|
import vec::{push, push_all};
|
||||||
|
import std::net::url::url;
|
||||||
|
import resource::image_cache_task;
|
||||||
|
import image_cache_task::ImageCacheTask;
|
||||||
|
import core::to_str::to_str;
|
||||||
import arc::{arc, clone};
|
import arc::{arc, clone};
|
||||||
|
|
||||||
enum BoxKind {
|
enum BoxKind {
|
||||||
|
@ -51,7 +54,7 @@ class Appearance {
|
||||||
let mut temp = none;
|
let mut temp = none;
|
||||||
temp <-> self.background_image;
|
temp <-> self.background_image;
|
||||||
let holder <- option::unwrap(temp);
|
let holder <- option::unwrap(temp);
|
||||||
image = some(holder.get_image());
|
image = holder.get_image();
|
||||||
self.background_image = some(holder);
|
self.background_image = some(holder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,16 +84,21 @@ class Box {
|
||||||
class ImageHolder {
|
class ImageHolder {
|
||||||
// Invariant: at least one of url and image is not none, except
|
// Invariant: at least one of url and image is not none, except
|
||||||
// occasionally while get_image is being called
|
// occasionally while get_image is being called
|
||||||
let mut url : option<~str>;
|
let mut url : option<url>;
|
||||||
let mut image : option<arc<~Image>>;
|
let mut image : option<arc<~Image>>;
|
||||||
|
let image_cache_task: ImageCacheTask;
|
||||||
|
|
||||||
new(-url : ~str) {
|
new(-url : url, image_cache_task: ImageCacheTask) {
|
||||||
self.url = some(url);
|
self.url = some(copy url);
|
||||||
self.image = none;
|
self.image = none;
|
||||||
|
self.image_cache_task = image_cache_task;
|
||||||
|
|
||||||
|
// Tell the image cache we're going to be interested in this url
|
||||||
|
image_cache_task.send(image_cache_task::Prefetch(move url));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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() -> ~arc<~Image> {
|
fn get_image() -> option<~arc<~Image>> {
|
||||||
// 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() {
|
||||||
|
@ -99,11 +107,20 @@ class ImageHolder {
|
||||||
let mut temp = none;
|
let mut temp = none;
|
||||||
temp <-> self.url;
|
temp <-> self.url;
|
||||||
let url = option::unwrap(temp);
|
let url = option::unwrap(temp);
|
||||||
let image = load(url);
|
|
||||||
|
|
||||||
self.image = some(arc(~image));
|
let response_port = port();
|
||||||
|
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 => {
|
||||||
|
#info("image was not ready for %s", url.to_str());
|
||||||
|
// FIXME: Need to schedule another layout when the image is ready
|
||||||
|
none
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.image.is_some() {
|
||||||
// Temporarily swap out the arc of the image so we can clone
|
// Temporarily swap out the arc of the image so we can clone
|
||||||
// it without breaking purity, then put it back and return the
|
// it without breaking purity, then put it back and return the
|
||||||
// clone. This is not threadsafe.
|
// clone. This is not threadsafe.
|
||||||
|
@ -112,7 +129,10 @@ class ImageHolder {
|
||||||
let im_arc = option::unwrap(temp);
|
let im_arc = option::unwrap(temp);
|
||||||
self.image = some(clone(&im_arc));
|
self.image = some(clone(&im_arc));
|
||||||
|
|
||||||
return ~im_arc;
|
return some(~im_arc);
|
||||||
|
} else {
|
||||||
|
return none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ import dom::style::Stylesheet;
|
||||||
import gfx::geometry::px_to_au;
|
import gfx::geometry::px_to_au;
|
||||||
import gfx::renderer::Renderer;
|
import gfx::renderer::Renderer;
|
||||||
import resource::image_cache_task::ImageCacheTask;
|
import resource::image_cache_task::ImageCacheTask;
|
||||||
|
import std::net::url::url;
|
||||||
|
import style::apply::apply_style;
|
||||||
|
|
||||||
import task::*;
|
import task::*;
|
||||||
import comm::*;
|
import comm::*;
|
||||||
|
@ -17,12 +19,12 @@ import comm::*;
|
||||||
type Layout = chan<Msg>;
|
type Layout = chan<Msg>;
|
||||||
|
|
||||||
enum Msg {
|
enum Msg {
|
||||||
BuildMsg(Node, arc<Stylesheet>),
|
BuildMsg(Node, arc<Stylesheet>, url),
|
||||||
PingMsg(chan<content::PingMsg>),
|
PingMsg(chan<content::PingMsg>),
|
||||||
ExitMsg
|
ExitMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Layout(renderer: Renderer, _image_cache_task: ImageCacheTask) -> Layout {
|
fn Layout(renderer: Renderer, image_cache_task: ImageCacheTask) -> Layout {
|
||||||
do spawn_listener::<Msg>|request| {
|
do spawn_listener::<Msg>|request| {
|
||||||
loop {
|
loop {
|
||||||
match request.recv() {
|
match request.recv() {
|
||||||
|
@ -31,7 +33,7 @@ fn Layout(renderer: Renderer, _image_cache_task: ImageCacheTask) -> Layout {
|
||||||
#debug("layout: ExitMsg received");
|
#debug("layout: ExitMsg received");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BuildMsg(node, styles) => {
|
BuildMsg(node, styles, doc_url) => {
|
||||||
#debug("layout: received layout request for:");
|
#debug("layout: received layout request for:");
|
||||||
node.dump();
|
node.dump();
|
||||||
|
|
||||||
|
@ -42,7 +44,8 @@ fn Layout(renderer: Renderer, _image_cache_task: ImageCacheTask) -> Layout {
|
||||||
let this_box = node.construct_boxes();
|
let this_box = node.construct_boxes();
|
||||||
this_box.dump();
|
this_box.dump();
|
||||||
|
|
||||||
this_box.apply_css_style();
|
apply_style(this_box, &doc_url, image_cache_task);
|
||||||
|
|
||||||
this_box.reflow_subtree(px_to_au(800));
|
this_box.reflow_subtree(px_to_au(800));
|
||||||
|
|
||||||
let dlist = build_display_list(this_box);
|
let dlist = build_display_list(this_box);
|
||||||
|
|
|
@ -7,16 +7,34 @@ import image::base::load;
|
||||||
import base::{Box, BTree, NTree, LayoutData, SpecifiedStyle, ImageHolder,
|
import base::{Box, BTree, NTree, LayoutData, SpecifiedStyle, ImageHolder,
|
||||||
BlockBox, InlineBox, IntrinsicBox, TextBox};
|
BlockBox, InlineBox, IntrinsicBox, TextBox};
|
||||||
import traverse::{top_down_traversal};
|
import traverse::{top_down_traversal};
|
||||||
|
import std::net::url::url;
|
||||||
|
import resource::image_cache_task::ImageCacheTask;
|
||||||
|
|
||||||
trait ApplyStyleBoxMethods {
|
struct StyleApplicator {
|
||||||
fn apply_css_style();
|
box: @Box;
|
||||||
fn apply_style();
|
doc_url: &url;
|
||||||
|
image_cache_task: ImageCacheTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_style(box: @Box, doc_url: &url, image_cache_task: ImageCacheTask) {
|
||||||
|
let applicator = StyleApplicator {
|
||||||
|
box: box,
|
||||||
|
doc_url: doc_url,
|
||||||
|
image_cache_task: image_cache_task
|
||||||
|
};
|
||||||
|
|
||||||
|
applicator.apply_css_style();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="A wrapper around a set of functions that can be applied as a top-down traversal of layout
|
#[doc="A wrapper around a set of functions that can be applied as a top-down traversal of layout
|
||||||
boxes."]
|
boxes."]
|
||||||
fn inheritance_wrapper(box : @Box) {
|
fn inheritance_wrapper(box : @Box, doc_url: &url, image_cache_task: ImageCacheTask) {
|
||||||
box.apply_style();
|
let applicator = StyleApplicator {
|
||||||
|
box: box,
|
||||||
|
doc_url: doc_url,
|
||||||
|
image_cache_task: image_cache_task
|
||||||
|
};
|
||||||
|
applicator.apply_style();
|
||||||
inhereit_height(box);
|
inhereit_height(box);
|
||||||
inhereit_width(box);
|
inhereit_width(box);
|
||||||
}
|
}
|
||||||
|
@ -81,9 +99,13 @@ fn inhereit_width(box : @Box) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl @Box : ApplyStyleBoxMethods {
|
impl StyleApplicator {
|
||||||
fn apply_css_style() {
|
fn apply_css_style() {
|
||||||
top_down_traversal(self, inheritance_wrapper);
|
let doc_url = copy *self.doc_url;
|
||||||
|
let image_cache_task = self.image_cache_task;
|
||||||
|
do top_down_traversal(self.box) |box, move doc_url| {
|
||||||
|
inheritance_wrapper(box, &doc_url, image_cache_task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc="Applies CSS style to a layout box.
|
#[doc="Applies CSS style to a layout box.
|
||||||
|
@ -94,13 +116,14 @@ impl @Box : ApplyStyleBoxMethods {
|
||||||
|
|
||||||
"]
|
"]
|
||||||
fn apply_style() {
|
fn apply_style() {
|
||||||
|
|
||||||
// Right now, we only handle images.
|
// Right now, we only handle images.
|
||||||
do self.node.read |node| {
|
do self.box.node.read |node| {
|
||||||
match node.kind {
|
match node.kind {
|
||||||
~Element(element) => {
|
~Element(element) => {
|
||||||
let style = self.node.get_specified_style();
|
let style = self.box.node.get_specified_style();
|
||||||
|
|
||||||
self.appearance.background_color = match style.background_color {
|
self.box.appearance.background_color = match style.background_color {
|
||||||
some(col) => col,
|
some(col) => col,
|
||||||
none => node.kind.default_color()
|
none => node.kind.default_color()
|
||||||
};
|
};
|
||||||
|
@ -112,7 +135,8 @@ impl @Box : ApplyStyleBoxMethods {
|
||||||
if url.is_some() {
|
if url.is_some() {
|
||||||
// FIXME: Some sort of BASE HREF support!
|
// FIXME: Some sort of BASE HREF support!
|
||||||
// FIXME: Parse URLs!
|
// FIXME: Parse URLs!
|
||||||
self.appearance.background_image = some(ImageHolder(option::unwrap(url)))
|
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))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
_ => { /* Ignore. */ }
|
_ => { /* Ignore. */ }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue