mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
Make servo build again
This commit is contained in:
parent
56bf2aaafe
commit
00cd6f8909
50 changed files with 746 additions and 593 deletions
|
@ -7,14 +7,13 @@ export ContentTask;
|
|||
export ControlMsg, ExecuteMsg, ParseMsg, ExitMsg, Timer;
|
||||
export PingMsg, PongMsg;
|
||||
|
||||
import std::arc::{arc, clone};
|
||||
import comm::{Port, Chan, port, chan, listen, select2};
|
||||
import std::arc::{ARC, clone};
|
||||
import comm::{Port, Chan, listen, select2};
|
||||
import task::{spawn, spawn_listener};
|
||||
import io::{read_whole_file, println};
|
||||
import result::{ok, err};
|
||||
|
||||
import dom::base::{Document, Node, NodeScope, Window, define_bindings};
|
||||
import dom::event::{Event, ResizeEvent};
|
||||
import dom::event::{Event, ResizeEvent, ReflowEvent};
|
||||
import dom::style;
|
||||
import dom::style::Stylesheet;
|
||||
import gfx::compositor::Compositor;
|
||||
|
@ -88,28 +87,28 @@ struct Content<C:Compositor> {
|
|||
let jsrt: jsrt;
|
||||
let cx: cx;
|
||||
|
||||
let mut document: option<@Document>;
|
||||
let mut window: option<@Window>;
|
||||
let mut doc_url: option<url>;
|
||||
let mut document: Option<@Document>;
|
||||
let mut window: Option<@Window>;
|
||||
let mut doc_url: Option<url>;
|
||||
|
||||
let resource_task: ResourceTask;
|
||||
|
||||
let compartment: option<compartment>;
|
||||
let compartment: Option<compartment>;
|
||||
|
||||
new(layout_task: LayoutTask, +compositor: C, from_master: Port<ControlMsg>,
|
||||
resource_task: ResourceTask) {
|
||||
self.layout_task = layout_task;
|
||||
self.compositor = compositor;
|
||||
self.from_master = from_master;
|
||||
self.event_port = port();
|
||||
self.event_port = Port();
|
||||
|
||||
self.scope = NodeScope();
|
||||
self.jsrt = jsrt();
|
||||
self.cx = self.jsrt.cx();
|
||||
|
||||
self.document = none;
|
||||
self.window = none;
|
||||
self.doc_url = none;
|
||||
self.document = None;
|
||||
self.window = None;
|
||||
self.doc_url = None;
|
||||
|
||||
self.compositor.add_event_listener(self.event_port.chan());
|
||||
|
||||
|
@ -118,8 +117,8 @@ struct Content<C:Compositor> {
|
|||
self.cx.set_default_options_and_version();
|
||||
self.cx.set_logging_error_reporter();
|
||||
self.compartment = match self.cx.new_compartment(global_class) {
|
||||
ok(c) => some(c),
|
||||
err(()) => none
|
||||
Ok(c) => Some(c),
|
||||
Err(()) => None
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -166,9 +165,9 @@ struct Content<C:Compositor> {
|
|||
let document = Document(root, self.scope, css_rules);
|
||||
let window = Window(self.from_master);
|
||||
self.relayout(document, &url);
|
||||
self.document = some(@document);
|
||||
self.window = some(@window);
|
||||
self.doc_url = some(copy url);
|
||||
self.document = Some(@document);
|
||||
self.window = Some(@window);
|
||||
self.doc_url = Some(copy url);
|
||||
|
||||
let compartment = option::expect(self.compartment, ~"TODO error checking");
|
||||
compartment.define_functions(debug_fns);
|
||||
|
@ -202,11 +201,11 @@ struct Content<C:Compositor> {
|
|||
ExecuteMsg(url) => {
|
||||
#debug["content: Received url `%s` to execute", url_to_str(url)];
|
||||
|
||||
match read_whole_file(url.path) {
|
||||
err(msg) => {
|
||||
match read_whole_file(&Path(url.path)) {
|
||||
Err(msg) => {
|
||||
println(#fmt["Error opening %s: %s", url_to_str(url), msg]);
|
||||
}
|
||||
ok(bytes) => {
|
||||
Ok(bytes) => {
|
||||
let compartment = option::expect(self.compartment, ~"TODO error checking");
|
||||
compartment.define_functions(debug_fns);
|
||||
self.cx.evaluate_script(compartment.global_obj, bytes, url.path, 1u);
|
||||
|
@ -243,10 +242,10 @@ struct Content<C:Compositor> {
|
|||
ResizeEvent(new_width, new_height) => {
|
||||
#debug("content got resize event: %d, %d", new_width, new_height);
|
||||
match copy self.document {
|
||||
none => {
|
||||
None => {
|
||||
// Nothing to do.
|
||||
}
|
||||
some(document) => {
|
||||
Some(document) => {
|
||||
assert self.doc_url.is_some();
|
||||
self.relayout(*document, &self.doc_url.get());
|
||||
}
|
||||
|
@ -256,10 +255,10 @@ struct Content<C:Compositor> {
|
|||
ReflowEvent => {
|
||||
#debug("content got reflow event");
|
||||
match copy self.document {
|
||||
none => {
|
||||
None => {
|
||||
// Nothing to do.
|
||||
}
|
||||
some(document) => {
|
||||
Some(document) => {
|
||||
assert self.doc_url.is_some();
|
||||
self.relayout(*document, &self.doc_url.get());
|
||||
}
|
||||
|
|
|
@ -9,10 +9,10 @@ import js::jsapi::{JSClass, JSObject, JSPropertySpec, JSContext, jsid, jsval, JS
|
|||
import js::{JSPROP_ENUMERATE, JSPROP_SHARED};
|
||||
import js::crust::*;
|
||||
import js::glue::bindgen::RUST_OBJECT_TO_JSVAL;
|
||||
import dvec::{DVec, dvec};
|
||||
import dvec::DVec;
|
||||
import ptr::null;
|
||||
import bindings;
|
||||
import std::arc::arc;
|
||||
import std::arc::ARC;
|
||||
import style::Stylesheet;
|
||||
import comm::{Port, Chan};
|
||||
import content::content_task::{ControlMsg, Timer};
|
||||
|
@ -26,7 +26,7 @@ struct Window {
|
|||
let timer_chan: Chan<TimerControlMsg>;
|
||||
|
||||
new(content_port: Port<ControlMsg>) {
|
||||
let content_chan = chan(content_port);
|
||||
let content_chan = Chan(content_port);
|
||||
|
||||
self.timer_chan = do task::spawn_listener |timer_port: Port<TimerControlMsg>| {
|
||||
loop {
|
||||
|
@ -47,12 +47,12 @@ struct Window {
|
|||
struct Document {
|
||||
let root: Node;
|
||||
let scope: NodeScope;
|
||||
let css_rules: arc<Stylesheet>;
|
||||
let css_rules: ARC<Stylesheet>;
|
||||
|
||||
new(root: Node, scope: NodeScope, -css_rules: Stylesheet) {
|
||||
self.root = root;
|
||||
self.scope = scope;
|
||||
self.css_rules = arc(css_rules);
|
||||
self.css_rules = ARC(css_rules);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,19 +74,19 @@ struct ElementData {
|
|||
new(-tag_name: ~str, -kind: ~ElementKind) {
|
||||
self.tag_name = tag_name;
|
||||
self.kind = kind;
|
||||
self.attrs = dvec();
|
||||
self.attrs = DVec();
|
||||
}
|
||||
|
||||
fn get_attr(attr_name: ~str) -> option<~str> {
|
||||
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);
|
||||
return Some(copy self.attrs[i].value);
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
|
||||
none
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ impl NodeScope : tree::ReadMethods<Node> {
|
|||
tree::each_child(self, node, f)
|
||||
}
|
||||
|
||||
fn get_parent(node: Node) -> option<Node> {
|
||||
fn get_parent(node: Node) -> Option<Node> {
|
||||
tree::get_parent(self, node)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,11 @@ import js::jsapi::bindgen::{JS_ValueToString, JS_GetStringCharsZAndLength, JS_Re
|
|||
import js::glue::bindgen::*;
|
||||
import js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB};
|
||||
import js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub, JS_ResolveStub};
|
||||
import result::{result, ok, err};
|
||||
import ptr::null;
|
||||
import libc::c_uint;
|
||||
import utils::{DOMString, domstring_to_jsval, rust_box, squirrel_away, str};
|
||||
import bindings::node::create;
|
||||
import base::Document;
|
||||
import option::{some, none};
|
||||
|
||||
enum DOMException {
|
||||
INVALID_CHARACTER_ERR
|
||||
|
@ -90,7 +88,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
|
|||
}
|
||||
|
||||
fn init(compartment: bare_compartment, doc: @Document) {
|
||||
let obj = utils::define_empty_prototype(~"Document", none, compartment);
|
||||
let obj = utils::define_empty_prototype(~"Document", None, compartment);
|
||||
|
||||
let attrs = @~[
|
||||
{name: compartment.add_name(~"documentElement"),
|
||||
|
|
|
@ -28,7 +28,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
|
|||
}
|
||||
|
||||
fn init(compartment: bare_compartment) {
|
||||
let obj = utils::define_empty_prototype(~"Element", some(~"Node"), compartment);
|
||||
let obj = utils::define_empty_prototype(~"Element", Some(~"Node"), compartment);
|
||||
let attrs = @~[
|
||||
{name: compartment.add_name(~"tagName"),
|
||||
tinyid: 0,
|
||||
|
@ -43,12 +43,12 @@ fn init(compartment: bare_compartment) {
|
|||
compartment.register_class(utils::instance_jsclass(~"GenericElementInstance",
|
||||
finalize));
|
||||
|
||||
let _ = utils::define_empty_prototype(~"HTMLElement", some(~"Element"), compartment);
|
||||
let _ = utils::define_empty_prototype(~"HTMLDivElement", some(~"HTMLElement"), compartment);
|
||||
let _ = utils::define_empty_prototype(~"HTMLScriptElement", some(~"HTMLElement"), compartment);
|
||||
let _ = utils::define_empty_prototype(~"HTMLHeadElement", some(~"HTMLElement"), compartment);
|
||||
let _ = utils::define_empty_prototype(~"HTMLElement", Some(~"Element"), compartment);
|
||||
let _ = utils::define_empty_prototype(~"HTMLDivElement", Some(~"HTMLElement"), compartment);
|
||||
let _ = utils::define_empty_prototype(~"HTMLScriptElement", Some(~"HTMLElement"), compartment);
|
||||
let _ = utils::define_empty_prototype(~"HTMLHeadElement", Some(~"HTMLElement"), compartment);
|
||||
|
||||
let obj = utils::define_empty_prototype(~"HTMLImageElement", some(~"HTMLElement"), compartment);
|
||||
let obj = utils::define_empty_prototype(~"HTMLImageElement", Some(~"HTMLElement"), compartment);
|
||||
let attrs = @~[
|
||||
{name: compartment.add_name(~"width"),
|
||||
tinyid: 0,
|
||||
|
|
|
@ -15,7 +15,7 @@ import libc::c_uint;
|
|||
import ptr::null;
|
||||
|
||||
fn init(compartment: bare_compartment) {
|
||||
let obj = utils::define_empty_prototype(~"Node", none, compartment);
|
||||
let obj = utils::define_empty_prototype(~"Node", None, compartment);
|
||||
|
||||
let attrs = @~[
|
||||
{name: compartment.add_name(~"firstChild"),
|
||||
|
@ -44,11 +44,11 @@ fn init(compartment: bare_compartment) {
|
|||
fn create(cx: *JSContext, node: Node, scope: NodeScope) -> jsobj unsafe {
|
||||
do scope.write(node) |nd| {
|
||||
match nd.kind {
|
||||
~Element(ed) => {
|
||||
~Element(*) => {
|
||||
element::create(cx, node, scope)
|
||||
}
|
||||
|
||||
~Text(s) => {
|
||||
~Text(*) => {
|
||||
fail ~"no text node bindings yet";
|
||||
}
|
||||
}
|
||||
|
@ -80,11 +80,11 @@ extern fn getFirstChild(cx: *JSContext, _argc: c_uint, vp: *mut jsval) -> JSBool
|
|||
let bundle = unwrap(obj);
|
||||
do (*bundle).payload.scope.write((*bundle).payload.node) |nd| {
|
||||
match nd.tree.first_child {
|
||||
some(n) => {
|
||||
Some(n) => {
|
||||
let obj = create(cx, n, (*bundle).payload.scope).ptr;
|
||||
*vp = RUST_OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
none => {
|
||||
None => {
|
||||
*vp = JSVAL_NULL;
|
||||
}
|
||||
}
|
||||
|
@ -103,11 +103,11 @@ extern fn getNextSibling(cx: *JSContext, _argc: c_uint, vp: *mut jsval) -> JSBoo
|
|||
let bundle = unwrap(obj);
|
||||
do (*bundle).payload.scope.write((*bundle).payload.node) |nd| {
|
||||
match nd.tree.next_sibling {
|
||||
some(n) => {
|
||||
Some(n) => {
|
||||
let obj = create(cx, n, (*bundle).payload.scope).ptr;
|
||||
*vp = RUST_OBJECT_TO_JSVAL(obj);
|
||||
}
|
||||
none => {
|
||||
None => {
|
||||
*vp = JSVAL_NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import js::glue::{PROPERTY_STUB, STRICT_PROPERTY_STUB, ENUMERATE_STUB, CONVERT_S
|
|||
RESOLVE_STUB};
|
||||
import js::glue::bindgen::*;
|
||||
import ptr::null;
|
||||
import result::{result, ok, err};
|
||||
|
||||
enum DOMString {
|
||||
str(~str),
|
||||
|
@ -34,25 +33,25 @@ unsafe fn squirrel_away_unique<T>(+x: ~T) -> *rust_box<T> {
|
|||
}
|
||||
|
||||
//XXX very incomplete
|
||||
fn jsval_to_str(cx: *JSContext, v: jsval) -> result<~str, ()> {
|
||||
fn jsval_to_str(cx: *JSContext, v: jsval) -> Result<~str, ()> {
|
||||
let jsstr;
|
||||
if RUST_JSVAL_IS_STRING(v) == 1 {
|
||||
jsstr = RUST_JSVAL_TO_STRING(v)
|
||||
} else {
|
||||
jsstr = JS_ValueToString(cx, v);
|
||||
if jsstr.is_null() {
|
||||
return err(());
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
||||
let len = 0;
|
||||
let chars = JS_GetStringCharsZAndLength(cx, jsstr, ptr::addr_of(len));
|
||||
return if chars.is_null() {
|
||||
err(())
|
||||
Err(())
|
||||
} else {
|
||||
unsafe {
|
||||
let buf = vec::unsafe::from_buf(chars as *u8, len as uint);
|
||||
ok(str::from_bytes(buf))
|
||||
Ok(str::from_bytes(buf))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,16 +151,16 @@ fn instance_jsclass(name: ~str, finalize: *u8)
|
|||
};
|
||||
}
|
||||
|
||||
fn define_empty_prototype(name: ~str, proto: option<~str>, compartment: bare_compartment)
|
||||
fn define_empty_prototype(name: ~str, proto: Option<~str>, compartment: bare_compartment)
|
||||
-> js::rust::jsobj {
|
||||
compartment.register_class(utils::prototype_jsclass(name));
|
||||
|
||||
//TODO error checking
|
||||
let obj = result::unwrap(
|
||||
match proto {
|
||||
some(s) => compartment.new_object_with_proto(name, s,
|
||||
Some(s) => compartment.new_object_with_proto(name, s,
|
||||
compartment.global_obj.ptr),
|
||||
none => compartment.new_object(name, null(), compartment.global_obj.ptr)
|
||||
None => compartment.new_object(name, null(), compartment.global_obj.ptr)
|
||||
});
|
||||
|
||||
compartment.define_property(name, RUST_OBJECT_TO_JSVAL(obj.ptr),
|
||||
|
|
|
@ -9,13 +9,12 @@ import js::glue::bindgen::*;
|
|||
import js::global::jsval_to_rust_str;
|
||||
import js::crust::{JS_PropertyStub, JS_StrictPropertyStub, JS_EnumerateStub, JS_ConvertStub, JS_ResolveStub};
|
||||
import js::glue::bindgen::RUST_JSVAL_TO_INT;
|
||||
import result::{result, ok, err};
|
||||
import ptr::null;
|
||||
import libc::c_uint;
|
||||
import utils::{rust_box, squirrel_away, jsval_to_str};
|
||||
import bindings::node::create;
|
||||
import base::{Node, Window};
|
||||
import dvec::{DVec, dvec};
|
||||
import dvec::DVec;
|
||||
|
||||
extern fn alert(cx: *JSContext, argc: c_uint, vp: *jsval) -> JSBool {
|
||||
unsafe {
|
||||
|
@ -38,7 +37,7 @@ struct TimerData {
|
|||
let args: DVec<jsval>;
|
||||
new(argc: c_uint, argv: *jsval) unsafe {
|
||||
self.funval = *argv;
|
||||
self.args = dvec();
|
||||
self.args = DVec();
|
||||
let mut i = 2;
|
||||
while i < argc as uint {
|
||||
self.args.push(*ptr::offset(argv, i));
|
||||
|
@ -78,7 +77,7 @@ extern fn finalize(_fop: *JSFreeOp, obj: *JSObject) {
|
|||
}
|
||||
|
||||
fn init(compartment: bare_compartment, win: @Window) {
|
||||
let proto = utils::define_empty_prototype(~"Window", none, compartment);
|
||||
let proto = utils::define_empty_prototype(~"Window", None, compartment);
|
||||
compartment.register_class(utils::instance_jsclass(~"WindowInstance", finalize));
|
||||
|
||||
let obj = result::unwrap(
|
||||
|
|
|
@ -201,7 +201,9 @@ impl<T:copy send,A> Scope<T,A> {
|
|||
}
|
||||
|
||||
fn write<U>(h: Handle<T,A>, f: fn(T) -> U) -> U unsafe {
|
||||
if self.d.layout_active && h.read_ptr() == h.write_ptr() {
|
||||
let const_read_ptr = ptr::const_offset(h.read_ptr(), 0);
|
||||
let const_write_ptr = ptr::const_offset(h.write_ptr(), 0);
|
||||
if self.d.layout_active && const_read_ptr == const_write_ptr {
|
||||
#debug["marking handle %? as dirty", h];
|
||||
h.set_write_ptr(unsafe::reinterpret_cast(self.clone(h.read_ptr())));
|
||||
h.set_next_dirty(self.d.first_dirty);
|
||||
|
@ -273,8 +275,8 @@ mod test {
|
|||
|
||||
let iter1 = 3u;
|
||||
let iter2 = 22u;
|
||||
let read_port = comm::port();
|
||||
let read_chan = comm::chan(read_port);
|
||||
let read_port = comm::Port();
|
||||
let read_chan = comm::Chan(read_port);
|
||||
|
||||
// fire up a reader task
|
||||
for uint::range(0u, iter1) |i| {
|
||||
|
|
|
@ -62,3 +62,83 @@ pure fn PtToPx(u : Unit) -> Unit {
|
|||
_ => fail ~"Calling PtToPx on a unit that is not a Pt"
|
||||
}
|
||||
}
|
||||
|
||||
impl DisplayType: cmp::Eq {
|
||||
pure fn eq(&&other: DisplayType) -> bool {
|
||||
self as uint == other as uint
|
||||
}
|
||||
}
|
||||
|
||||
impl Unit: cmp::Eq {
|
||||
pure fn eq(&&other: Unit) -> bool {
|
||||
match (self, other) {
|
||||
(Auto, Auto) => true,
|
||||
(Auto, _) => false,
|
||||
(Percent(a), Percent(b)) => a == b,
|
||||
(Percent(*), _) => false,
|
||||
(Mm(a), Mm(b)) => a == b,
|
||||
(Mm(*), _) => false,
|
||||
(Pt(a), Pt(b)) => a == b,
|
||||
(Pt(*), _) => false,
|
||||
(Px(a), Px(b)) => a == b,
|
||||
(Px(*), _) => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StyleDeclaration: cmp::Eq {
|
||||
pure fn eq(&&other: StyleDeclaration) -> bool {
|
||||
match (self, other) {
|
||||
(BackgroundColor(a), BackgroundColor(b)) => a == b,
|
||||
(Display(a), Display(b)) => a == b,
|
||||
(FontSize(a), FontSize(b)) => a == b,
|
||||
(Height(a), Height(b)) => a == b,
|
||||
(TextColor(a), TextColor(b)) => a == b,
|
||||
(Width(a), Width(b)) => a == b,
|
||||
|
||||
(BackgroundColor(*), _)
|
||||
| (Display(*), _)
|
||||
| (FontSize(*), _)
|
||||
| (Height(*), _)
|
||||
| (TextColor(*), _)
|
||||
| (Width(*), _) => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Attr: cmp::Eq {
|
||||
pure fn eq(&&other: Attr) -> bool {
|
||||
match (self, other) {
|
||||
(Exists(a), Exists(b)) => a == b,
|
||||
|
||||
(Exact(a, aa), Exact(b, bb))
|
||||
| (Includes(a, aa), Includes(b, bb))
|
||||
| (StartsWith(a, aa), StartsWith(b, bb)) => a == b && aa == bb,
|
||||
|
||||
(Exists(*), _)
|
||||
| (Exact(*), _)
|
||||
| (Includes(*), _)
|
||||
| (StartsWith(*), _) => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Selector: cmp::Eq {
|
||||
pure fn eq(&&other: Selector) -> bool {
|
||||
// FIXME: Lots of copying here
|
||||
match (self, other) {
|
||||
(Element(s_a, attrs_a), Element(s_b, attrs_b)) => s_a == s_b && attrs_a == attrs_b,
|
||||
|
||||
(Child(s1a, s2a), Child(s1b, s2b))
|
||||
| (Descendant(s1a, s2a), Descendant(s1b, s2b))
|
||||
| (Sibling(s1a, s2a), Sibling(s1b, s2b)) => {
|
||||
s1a == s1b && s2a == s2b
|
||||
}
|
||||
|
||||
(Element(*), _) => false,
|
||||
(Child(*), _) => false,
|
||||
(Descendant(*), _) => false,
|
||||
(Sibling(*), _) => false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ import std::net::url::url;
|
|||
import resource::image_cache_task;
|
||||
import image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
|
||||
|
||||
import pipes::{port, chan};
|
||||
import pipes::{Port, Chan};
|
||||
|
||||
fn macros() {
|
||||
include!("macros.rs");
|
||||
|
|
|
@ -6,8 +6,8 @@ The interface used to by the renderer to aquire draw targets for
|
|||
each rendered frame and submit them to be drawn to the display
|
||||
"]
|
||||
trait Compositor {
|
||||
fn begin_drawing(+next_dt: pipes::chan<DrawTarget>);
|
||||
fn draw(+next_dt: pipes::chan<DrawTarget>, +draw_me: DrawTarget);
|
||||
fn begin_drawing(+next_dt: pipes::Chan<DrawTarget>);
|
||||
fn draw(+next_dt: pipes::Chan<DrawTarget>, +draw_me: DrawTarget);
|
||||
fn add_event_listener(listener: comm::Chan<Event>);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,12 @@ impl au : Num {
|
|||
}
|
||||
}
|
||||
|
||||
impl au : cmp::Eq {
|
||||
pure fn eq(&&other: au) -> bool {
|
||||
*self == *other
|
||||
}
|
||||
}
|
||||
|
||||
fn box<A:copy Num>(x: A, y: A, w: A, h: A) -> Rect<A> {
|
||||
Rect(Point2D(x, y), Size2D(w, h))
|
||||
}
|
||||
|
|
|
@ -20,28 +20,28 @@ import cairo_bg::{cairo_image_surface_create, cairo_surface_destroy,
|
|||
import compositor::Compositor;
|
||||
import render_task::{RenderTask, RenderMsg};
|
||||
import task::spawn_listener;
|
||||
import comm::{Chan, Port, chan, port};
|
||||
import comm::{Chan, Port};
|
||||
import unsafe::reinterpret_cast;
|
||||
import vec_from_buf = vec::unsafe::from_buf;
|
||||
import ptr::addr_of;
|
||||
import dom::event::Event;
|
||||
import dvec::dvec;
|
||||
import dvec::DVec;
|
||||
import layout::display_list::display_list;
|
||||
import std::cell::Cell;
|
||||
|
||||
type PngCompositor = Chan<Msg>;
|
||||
|
||||
enum Msg {
|
||||
BeginDrawing(pipes::chan<DrawTarget>),
|
||||
Draw(pipes::chan<DrawTarget>, DrawTarget),
|
||||
BeginDrawing(pipes::Chan<DrawTarget>),
|
||||
Draw(pipes::Chan<DrawTarget>, DrawTarget),
|
||||
Exit
|
||||
}
|
||||
|
||||
impl Chan<Msg> : Compositor {
|
||||
fn begin_drawing(+next_dt: pipes::chan<DrawTarget>) {
|
||||
fn begin_drawing(+next_dt: pipes::Chan<DrawTarget>) {
|
||||
self.send(BeginDrawing(next_dt))
|
||||
}
|
||||
fn draw(+next_dt: pipes::chan<DrawTarget>, +draw_me: DrawTarget) {
|
||||
fn draw(+next_dt: pipes::Chan<DrawTarget>, +draw_me: DrawTarget) {
|
||||
self.send(Draw(next_dt, draw_me))
|
||||
}
|
||||
fn add_event_listener(_listener: Chan<Event>) {
|
||||
|
@ -70,7 +70,7 @@ fn PngCompositor(output: Chan<~[u8]>) -> PngCompositor {
|
|||
}
|
||||
}
|
||||
|
||||
fn do_draw(sender: pipes::chan<DrawTarget>,
|
||||
fn do_draw(sender: pipes::Chan<DrawTarget>,
|
||||
+dt: DrawTarget,
|
||||
output: Chan<~[u8]>,
|
||||
cairo_surface: ImageSurface) {
|
||||
|
@ -89,7 +89,7 @@ fn sanity_check() {
|
|||
let compositor = PngCompositor(self_channel);
|
||||
let renderer = RenderTask(compositor);
|
||||
|
||||
let dlist : display_list = dvec();
|
||||
let dlist : display_list = DVec();
|
||||
renderer.send(RenderMsg(dlist));
|
||||
let (exit_chan, exit_response_from_engine) = pipes::stream();
|
||||
renderer.send(render_task::ExitMsg(exit_chan));
|
||||
|
|
|
@ -14,18 +14,18 @@ import geom::point::Point2D;
|
|||
import azure_hl::{AsAzureRect, B8G8R8A8, Color, ColorPattern, DrawOptions, DrawSurfaceOptions};
|
||||
import azure_hl::{DrawTarget, Linear};
|
||||
import ptr::addr_of;
|
||||
import std::arc::arc;
|
||||
import std::arc::ARC;
|
||||
import azure::cairo::{cairo_font_face_t, cairo_scaled_font_t};
|
||||
import std::cell::Cell;
|
||||
import compositor::Compositor;
|
||||
|
||||
import pipes::{port, chan};
|
||||
import pipes::{Port, Chan};
|
||||
|
||||
type Renderer = comm::Chan<Msg>;
|
||||
|
||||
enum Msg {
|
||||
RenderMsg(dl::display_list),
|
||||
ExitMsg(pipes::chan<()>)
|
||||
ExitMsg(pipes::Chan<()>)
|
||||
}
|
||||
|
||||
type RenderTask = comm::Chan<Msg>;
|
||||
|
@ -46,11 +46,11 @@ fn RenderTask<C: Compositor send>(+compositor: C) -> RenderTask {
|
|||
#debug("renderer: got render request");
|
||||
let draw_target = Cell(draw_target_po.recv());
|
||||
let (ch, po) = pipes::stream();
|
||||
let mut draw_target_ch_ = some(ch);
|
||||
let mut draw_target_ch_ = Some(ch);
|
||||
draw_target_po = po;
|
||||
#debug("renderer: rendering");
|
||||
do util::time::time(~"rendering") {
|
||||
let mut draw_target_ch = none;
|
||||
let mut draw_target_ch = None;
|
||||
draw_target_ch_ <-> draw_target_ch;
|
||||
let draw_target_ch = option::unwrap(draw_target_ch);
|
||||
|
||||
|
@ -115,7 +115,7 @@ fn draw_solid_color(draw_target: &DrawTarget, item: dl::display_item, r: u8, g:
|
|||
draw_target.fill_rect(item.bounds.to_azure_rect(), ColorPattern(color));
|
||||
}
|
||||
|
||||
fn draw_image(draw_target: &DrawTarget, item: dl::display_item, image: arc<~Image>) unsafe {
|
||||
fn draw_image(draw_target: &DrawTarget, item: dl::display_item, image: ARC<~Image>) unsafe {
|
||||
let image = std::arc::get(&image);
|
||||
let size = Size2D(image.width as i32, image.height as i32);
|
||||
let stride = image.width * 4;
|
||||
|
|
|
@ -5,6 +5,14 @@ enum format {
|
|||
// TODO: RGB 565, others?
|
||||
}
|
||||
|
||||
impl format: cmp::Eq {
|
||||
pure fn eq(&&other: format) -> bool {
|
||||
match (self, other) {
|
||||
(fo_rgba_8888, fo_rgba_8888) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type image_surface = {
|
||||
size: Size2D<int>,
|
||||
format: format,
|
||||
|
|
|
@ -21,7 +21,7 @@ fn test_image_bin() -> ~[u8] {
|
|||
return vec::from_fn(4962, |i| TEST_IMAGE[i]);
|
||||
}
|
||||
|
||||
fn load_from_memory(buffer: &[u8]) -> option<Image> {
|
||||
fn load_from_memory(buffer: &[u8]) -> Option<Image> {
|
||||
do stb_image::load_from_memory(buffer).map |image| {
|
||||
|
||||
assert image.depth == 4;
|
||||
|
|
|
@ -20,7 +20,7 @@ import std::net::url::url;
|
|||
import resource::image_cache_task;
|
||||
import image_cache_task::ImageCacheTask;
|
||||
import core::to_str::ToStr;
|
||||
import std::arc::{arc, clone};
|
||||
import std::arc::{ARC, clone};
|
||||
import task::spawn;
|
||||
|
||||
enum BoxKind {
|
||||
|
@ -30,14 +30,23 @@ enum BoxKind {
|
|||
TextBoxKind(@TextBox)
|
||||
}
|
||||
|
||||
impl BoxKind : cmp::Eq {
|
||||
pure fn eq(&&other: BoxKind) -> bool {
|
||||
match (self, other) {
|
||||
(BlockBox, BlockBox) => true,
|
||||
_ => fail ~"unimplemented case in BoxKind.eq"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Appearance {
|
||||
let mut background_image: option<ImageHolder>;
|
||||
let mut background_image: Option<ImageHolder>;
|
||||
let mut background_color: Color;
|
||||
let mut width: Unit;
|
||||
let mut height: Unit;
|
||||
|
||||
new(kind: NodeKind) {
|
||||
self.background_image = none;
|
||||
self.background_image = None;
|
||||
self.background_color = kind.default_color();
|
||||
self.width = kind.default_width();
|
||||
self.height = kind.default_height();
|
||||
|
@ -45,18 +54,18 @@ struct Appearance {
|
|||
|
||||
// This will be very unhappy if it is getting run in parallel with
|
||||
// anything trying to read the background image
|
||||
fn get_image() -> option<~arc<~Image>> {
|
||||
let mut image = none;
|
||||
fn get_image() -> Option<~ARC<~Image>> {
|
||||
let mut image = None;
|
||||
|
||||
// Do a dance where we swap the ImageHolder out before we can
|
||||
// get the image out of it because we can't match against it
|
||||
// because holder.get_image() is not pure.
|
||||
if (self.background_image).is_some() {
|
||||
let mut temp = none;
|
||||
let mut temp = None;
|
||||
temp <-> self.background_image;
|
||||
let holder <- option::unwrap(temp);
|
||||
image = holder.get_image();
|
||||
self.background_image = some(holder);
|
||||
self.background_image = Some(holder);
|
||||
}
|
||||
|
||||
return image;
|
||||
|
@ -85,14 +94,14 @@ struct Box {
|
|||
struct ImageHolder {
|
||||
// Invariant: at least one of url and image is not none, except
|
||||
// occasionally while get_image is being called
|
||||
let mut url : option<url>;
|
||||
let mut image : option<arc<~Image>>;
|
||||
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, reflow: fn~()) {
|
||||
self.url = some(copy url);
|
||||
self.image = none;
|
||||
self.url = Some(copy url);
|
||||
self.image = None;
|
||||
self.image_cache_task = image_cache_task;
|
||||
self.reflow = copy reflow;
|
||||
|
||||
|
@ -106,26 +115,26 @@ struct ImageHolder {
|
|||
}
|
||||
|
||||
// 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>> {
|
||||
// If this is the first time we've called this function, load
|
||||
// the image and store it for the future
|
||||
if self.image.is_none() {
|
||||
assert self.url.is_some();
|
||||
|
||||
let mut temp = none;
|
||||
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 = match response_port.recv() {
|
||||
image_cache_task::ImageReady(image) => some(clone(&image)),
|
||||
image_cache_task::ImageReady(image) => Some(clone(&image)),
|
||||
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();
|
||||
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(),
|
||||
|
@ -133,12 +142,12 @@ struct ImageHolder {
|
|||
image_cache_task::ImageFailed => ()
|
||||
}
|
||||
}
|
||||
none
|
||||
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
|
||||
None
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -147,21 +156,21 @@ struct ImageHolder {
|
|||
// Temporarily swap out the arc of the image so we can clone
|
||||
// it without breaking purity, then put it back and return the
|
||||
// clone. This is not threadsafe.
|
||||
let mut temp = none;
|
||||
let mut temp = None;
|
||||
temp <-> self.image;
|
||||
let im_arc = option::unwrap(temp);
|
||||
self.image = some(clone(&im_arc));
|
||||
self.image = Some(clone(&im_arc));
|
||||
|
||||
return some(~im_arc);
|
||||
return Some(~im_arc);
|
||||
} else {
|
||||
return none;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum LayoutData = {
|
||||
mut specified_style: ~SpecifiedStyle,
|
||||
mut box: option<@Box>
|
||||
mut box: Option<@Box>
|
||||
};
|
||||
|
||||
// FIXME: This is way too complex! Why do these have to have dummy receivers? --pcw
|
||||
|
|
|
@ -23,14 +23,14 @@ enum ctxt = {
|
|||
// See CSS2 9.2.1.1.
|
||||
//
|
||||
|
||||
mut anon_box: option<@Box>
|
||||
mut anon_box: Option<@Box>
|
||||
};
|
||||
|
||||
fn create_context(parent_node: Node, parent_box: @Box) -> ctxt {
|
||||
return ctxt({
|
||||
parent_node: parent_node,
|
||||
parent_box: parent_box,
|
||||
mut anon_box: none
|
||||
mut anon_box: None
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -46,16 +46,16 @@ impl ctxt {
|
|||
|
||||
// Determine the child's display.
|
||||
let disp = kid.get_specified_style().display_type;
|
||||
if disp != some(DisInline) {
|
||||
if disp != Some(DisInline) {
|
||||
self.finish_anonymous_box_if_necessary();
|
||||
}
|
||||
|
||||
// Add the child's box to the current enclosing box or the current anonymous box.
|
||||
match kid.get_specified_style().display_type {
|
||||
some(DisBlock) => BTree.add_child(self.parent_box, kid_box),
|
||||
some(DisInline) => {
|
||||
Some(DisBlock) => BTree.add_child(self.parent_box, kid_box),
|
||||
Some(DisInline) => {
|
||||
let anon_box = match self.anon_box {
|
||||
none => {
|
||||
None => {
|
||||
//
|
||||
// The anonymous box inherits the attributes of its parents for now, so
|
||||
// that properties of intrinsic boxes are not spread to their parenting
|
||||
|
@ -65,14 +65,14 @@ impl ctxt {
|
|||
//
|
||||
|
||||
let b = @Box(self.parent_node, InlineBox);
|
||||
self.anon_box = some(b);
|
||||
self.anon_box = Some(b);
|
||||
b
|
||||
}
|
||||
some(b) => b
|
||||
Some(b) => b
|
||||
};
|
||||
BTree.add_child(anon_box, kid_box);
|
||||
}
|
||||
some(DisNone) => {
|
||||
Some(DisNone) => {
|
||||
// Nothing to do.
|
||||
}
|
||||
_ => { //hack for now
|
||||
|
@ -93,21 +93,21 @@ impl ctxt {
|
|||
|
||||
// Determine the child's display.
|
||||
let disp = kid.get_specified_style().display_type;
|
||||
if disp != some(DisInline) {
|
||||
if disp != Some(DisInline) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Add the child's box to the current enclosing box.
|
||||
match kid.get_specified_style().display_type {
|
||||
some(DisBlock) => {
|
||||
Some(DisBlock) => {
|
||||
// TODO
|
||||
#warn("TODO: non-inline display found inside inline box");
|
||||
BTree.add_child(self.parent_box, kid_box);
|
||||
}
|
||||
some(DisInline) => {
|
||||
Some(DisInline) => {
|
||||
BTree.add_child(self.parent_box, kid_box);
|
||||
}
|
||||
some(DisNone) => {
|
||||
Some(DisNone) => {
|
||||
// Nothing to do.
|
||||
}
|
||||
_ => { //hack for now
|
||||
|
@ -122,9 +122,9 @@ impl ctxt {
|
|||
self.parent_node.dump();
|
||||
|
||||
match self.parent_node.get_specified_style().display_type {
|
||||
some(DisBlock) => self.construct_boxes_for_block_children(),
|
||||
some(DisInline) => self.construct_boxes_for_inline_children(),
|
||||
some(DisNone) => { /* Nothing to do. */ }
|
||||
Some(DisBlock) => self.construct_boxes_for_block_children(),
|
||||
Some(DisInline) => self.construct_boxes_for_inline_children(),
|
||||
Some(DisNone) => { /* Nothing to do. */ }
|
||||
_ => { //hack for now
|
||||
}
|
||||
}
|
||||
|
@ -139,10 +139,10 @@ impl ctxt {
|
|||
"]
|
||||
fn finish_anonymous_box_if_necessary() {
|
||||
match copy self.anon_box {
|
||||
none => { /* Nothing to do. */ }
|
||||
some(b) => BTree.add_child(self.parent_box, b)
|
||||
None => { /* Nothing to do. */ }
|
||||
Some(b) => BTree.add_child(self.parent_box, b)
|
||||
}
|
||||
self.anon_box = none;
|
||||
self.anon_box = None;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,13 +161,13 @@ impl Node : PrivBoxBuilder {
|
|||
~Element(element) => {
|
||||
match (copy *element.kind, self.get_specified_style().display_type) {
|
||||
(HTMLImageElement({size}), _) => IntrinsicBox(@size),
|
||||
(_, some(DisBlock)) => BlockBox,
|
||||
(_, some(DisInline)) => InlineBox,
|
||||
(_, some(DisNone)) => {
|
||||
(_, Some(DisBlock)) => BlockBox,
|
||||
(_, Some(DisInline)) => InlineBox,
|
||||
(_, Some(DisNone)) => {
|
||||
// TODO: don't have a box here at all?
|
||||
IntrinsicBox(@zero_size_au())
|
||||
}
|
||||
(_, none) => {
|
||||
(_, None) => {
|
||||
fail ~"The specified display style should be a default instead of none"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,12 @@ import geom::rect::Rect;
|
|||
import image::base::Image;
|
||||
import servo_text::text_run::TextRun;
|
||||
|
||||
import std::arc::arc;
|
||||
import std::arc::ARC;
|
||||
import dvec::DVec;
|
||||
|
||||
enum item_type {
|
||||
display_item_solid_color(u8, u8, u8),
|
||||
display_item_image(~arc<~Image>),
|
||||
display_item_image(~ARC<~Image>),
|
||||
display_item_text(TextRun),
|
||||
// FIXME: Shape code does not understand the alignment without this
|
||||
padding(u8, u8, u8, u8)
|
||||
|
|
|
@ -11,7 +11,7 @@ import geom::size::Size2D;
|
|||
import gfx::geometry::{au, au_to_px, box, px_to_au};
|
||||
import util::tree;
|
||||
|
||||
import dvec::dvec;
|
||||
import dvec::DVec;
|
||||
import vec::push;
|
||||
|
||||
#[doc = "
|
||||
|
@ -20,7 +20,7 @@ Builds a display list for a box and all its children
|
|||
|
||||
"]
|
||||
fn build_display_list(box : @Box) -> dl::display_list {
|
||||
let list = dvec();
|
||||
let list = DVec();
|
||||
build_display_list_from_origin(list, box, Point2D(au(0), au(0)));
|
||||
return list;
|
||||
}
|
||||
|
@ -113,10 +113,13 @@ fn should_convert_text_boxes_to_solid_color_background_items() {
|
|||
let n = s.new_node(Text(~"firecracker"));
|
||||
let b = n.construct_boxes();
|
||||
|
||||
let subbox = match check b.kind { TextBoxKind(subbox) => subbox };
|
||||
let subbox = match b.kind {
|
||||
TextBoxKind(subbox) => subbox,
|
||||
_ => fail
|
||||
};
|
||||
|
||||
b.reflow_text(subbox);
|
||||
let list = dvec();
|
||||
let list = DVec();
|
||||
box_to_display_items(list, b, Point2D(px_to_au(0), px_to_au(0)));
|
||||
|
||||
match list[0].item_type {
|
||||
|
@ -133,10 +136,13 @@ fn should_convert_text_boxes_to_text_items() {
|
|||
let n = s.new_node(Text(~"firecracker"));
|
||||
let b = n.construct_boxes();
|
||||
|
||||
let subbox = match check b.kind { TextBoxKind(subbox) => { subbox } };
|
||||
let subbox = match b.kind {
|
||||
TextBoxKind(subbox) => { subbox },
|
||||
_ => fail
|
||||
};
|
||||
|
||||
b.reflow_text(subbox);
|
||||
let list = dvec();
|
||||
let list = DVec();
|
||||
box_to_display_items(list, b, Point2D(px_to_au(0), px_to_au(0)));
|
||||
|
||||
match list[1].item_type {
|
||||
|
@ -153,10 +159,13 @@ fn should_calculate_the_bounds_of_the_text_box_background_color() {
|
|||
let n = s.new_node(Text(~"firecracker"));
|
||||
let b = n.construct_boxes();
|
||||
|
||||
let subbox = match check b.kind { TextBoxKind(subbox) => { subbox } };
|
||||
let subbox = match b.kind {
|
||||
TextBoxKind(subbox) => { subbox },
|
||||
_ => fail
|
||||
};
|
||||
|
||||
b.reflow_text(subbox);
|
||||
let list = dvec();
|
||||
let list = DVec();
|
||||
box_to_display_items(list, b, Point2D(px_to_au(0), px_to_au(0)));
|
||||
|
||||
let expected = Rect(
|
||||
|
@ -175,10 +184,13 @@ fn should_calculate_the_bounds_of_the_text_items() {
|
|||
let n = s.new_node(Text(~"firecracker"));
|
||||
let b = n.construct_boxes();
|
||||
|
||||
let subbox = match check b.kind { TextBoxKind(subbox) => { subbox } };
|
||||
let subbox = match b.kind {
|
||||
TextBoxKind(subbox) => { subbox },
|
||||
_ => fail
|
||||
};
|
||||
|
||||
b.reflow_text(subbox);
|
||||
let list = dvec();
|
||||
let list = DVec();
|
||||
box_to_display_items(list, b, Point2D(px_to_au(0), px_to_au(0)));
|
||||
|
||||
let expected = Rect(
|
||||
|
|
|
@ -30,7 +30,7 @@ impl @Box : InlineLayout {
|
|||
for tree::each_child(BTree, self) |kid| {
|
||||
kid.bounds.origin = Point2D(au(x), au(y));
|
||||
x += *kid.bounds.size.width;
|
||||
current_height = i32::max(current_height, *kid.bounds.size.height);
|
||||
current_height = i32::max(¤t_height, &*kid.bounds.size.height);
|
||||
}
|
||||
|
||||
let height = match self.appearance.height {
|
||||
|
@ -41,7 +41,7 @@ impl @Box : InlineLayout {
|
|||
|
||||
let width = match self.appearance.width {
|
||||
Px(p) => px_to_au(p.to_int()),
|
||||
Auto => au(i32::max(x, *self.bounds.size.width)),
|
||||
Auto => au(i32::max(&x, &*self.bounds.size.width)),
|
||||
_ => fail ~"inhereit_width failed, width is neither a Px or auto"
|
||||
};
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
rendered.
|
||||
"];
|
||||
|
||||
import std::arc::arc;
|
||||
import std::arc::ARC;
|
||||
import display_list_builder::build_display_list;
|
||||
import dom::base::Node;
|
||||
import dom::style::Stylesheet;
|
||||
|
@ -22,7 +22,7 @@ import comm::*;
|
|||
type LayoutTask = Chan<Msg>;
|
||||
|
||||
enum Msg {
|
||||
BuildMsg(Node, arc<Stylesheet>, url, Chan<Event>),
|
||||
BuildMsg(Node, ARC<Stylesheet>, url, Chan<Event>),
|
||||
PingMsg(Chan<content_task::PingMsg>),
|
||||
ExitMsg
|
||||
}
|
||||
|
|
|
@ -47,15 +47,15 @@ fn inhereit_height(box : @Box) {
|
|||
let style = box.node.get_specified_style();
|
||||
|
||||
box.appearance.height = match style.height {
|
||||
none => Auto,
|
||||
some(h) => match h {
|
||||
None => Auto,
|
||||
Some(h) => match h {
|
||||
Auto | Px(*) => h,
|
||||
Pt(*) => PtToPx(h),
|
||||
Mm(*) => MmToPx(h),
|
||||
Percent(em) => {
|
||||
match box.tree.parent {
|
||||
none => Auto,
|
||||
some(parent) => {
|
||||
None => Auto,
|
||||
Some(parent) => {
|
||||
match parent.appearance.height {
|
||||
//This is a poorly constrained case, so we ignore the percentage
|
||||
Auto => Auto,
|
||||
|
@ -77,15 +77,15 @@ fn inhereit_width(box : @Box) {
|
|||
let style = box.node.get_specified_style();
|
||||
|
||||
box.appearance.width = match style.width {
|
||||
none => Auto,
|
||||
some(h) => match h {
|
||||
None => Auto,
|
||||
Some(h) => match h {
|
||||
Auto | Px(*) => h,
|
||||
Pt(*) => PtToPx(h),
|
||||
Mm(*) => MmToPx(h),
|
||||
Percent(em) => {
|
||||
match box.tree.parent {
|
||||
none => Auto,
|
||||
some(parent) => {
|
||||
None => Auto,
|
||||
Some(parent) => {
|
||||
match parent.appearance.width {
|
||||
//This is a poorly constrained case, so we ignore the percentage
|
||||
Auto => Auto,
|
||||
|
@ -127,8 +127,8 @@ impl StyleApplicator {
|
|||
let style = self.box.node.get_specified_style();
|
||||
|
||||
self.box.appearance.background_color = match style.background_color {
|
||||
some(col) => col,
|
||||
none => node.kind.default_color()
|
||||
Some(col) => col,
|
||||
None => node.kind.default_color()
|
||||
};
|
||||
|
||||
match element.kind {
|
||||
|
@ -138,8 +138,8 @@ impl StyleApplicator {
|
|||
if url.is_some() {
|
||||
// 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.reflow))
|
||||
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.reflow))
|
||||
};
|
||||
}
|
||||
_ => { /* Ignore. */ }
|
||||
|
@ -155,7 +155,7 @@ impl StyleApplicator {
|
|||
mod test {
|
||||
import dom::base::{Attr, HTMLDivElement, HTMLHeadElement, HTMLImageElement, ElementData};
|
||||
import dom::base::{NodeScope, UnknownElement};
|
||||
import dvec::dvec;
|
||||
import dvec::DVec;
|
||||
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn new_node(scope: NodeScope, -name: ~str) -> Node {
|
||||
|
@ -179,11 +179,11 @@ mod test {
|
|||
scope.add_child(child, g2);
|
||||
let _handles = parent.initialize_style_for_subtree();
|
||||
|
||||
do parent.aux |aux| { aux.specified_style.height = some(Px(100.0)); }
|
||||
do child.aux |aux| { aux.specified_style.height = some(Auto); }
|
||||
do child2.aux |aux| { aux.specified_style.height = some(Percent(50.0)); }
|
||||
do g1.aux |aux| { aux.specified_style.height = some(Percent(50.0)); }
|
||||
do g2.aux |aux| { aux.specified_style.height = some(Px(10.0)); }
|
||||
do parent.aux |aux| { aux.specified_style.height = Some(Px(100.0)); }
|
||||
do child.aux |aux| { aux.specified_style.height = Some(Auto); }
|
||||
do child2.aux |aux| { aux.specified_style.height = Some(Percent(50.0)); }
|
||||
do g1.aux |aux| { aux.specified_style.height = Some(Percent(50.0)); }
|
||||
do g2.aux |aux| { aux.specified_style.height = Some(Px(10.0)); }
|
||||
|
||||
let parent_box = parent.construct_boxes();
|
||||
let child_box = parent_box.tree.first_child.get();
|
||||
|
|
|
@ -13,14 +13,14 @@ fn attrs_match(attr: Attr, elmt: ElementData) -> bool {
|
|||
match attr {
|
||||
Exists(name) => {
|
||||
match elmt.get_attr(name) {
|
||||
some(_) => true,
|
||||
none => false
|
||||
Some(_) => true,
|
||||
None => false
|
||||
}
|
||||
}
|
||||
Exact(name, val) => {
|
||||
match elmt.get_attr(name) {
|
||||
some(value) => value == val,
|
||||
none => false
|
||||
Some(value) => value == val,
|
||||
None => false
|
||||
}
|
||||
}
|
||||
Includes(name, val) => {
|
||||
|
@ -29,13 +29,13 @@ fn attrs_match(attr: Attr, elmt: ElementData) -> bool {
|
|||
if val == ~"" { return false; }
|
||||
|
||||
match elmt.get_attr(name) {
|
||||
some(value) => value.split_char(' ').contains(val),
|
||||
none => false
|
||||
Some(value) => value.split_char(' ').contains(val),
|
||||
None => false
|
||||
}
|
||||
}
|
||||
StartsWith(name, val) => {
|
||||
match elmt.get_attr(name) {
|
||||
some(value) => {
|
||||
Some(value) => {
|
||||
//check that there is only one attribute value and it
|
||||
//starts with the perscribed value
|
||||
if !value.starts_with(val) || value.contains(~" ") { return false; }
|
||||
|
@ -44,7 +44,7 @@ fn attrs_match(attr: Attr, elmt: ElementData) -> bool {
|
|||
if value.len() == val.len() { true }
|
||||
else { value.starts_with(val + ~"-") }
|
||||
}
|
||||
none => {
|
||||
None => {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ impl Node : PrivMatchingMethods {
|
|||
|
||||
return true;
|
||||
}
|
||||
Text(str) => { /*fall through, currently unsupported*/ }
|
||||
Text(*) => { /*fall through, currently unsupported*/ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,11 +92,11 @@ impl Node : PrivMatchingMethods {
|
|||
#[doc = "Checks if a generic CSS selector matches a given HTML element"]
|
||||
fn matches_selector(sel : ~Selector) -> bool {
|
||||
match *sel {
|
||||
Element(str, atts) => { return self.matches_element(sel); }
|
||||
Element(*) => { return self.matches_element(sel); }
|
||||
Child(sel1, sel2) => {
|
||||
return match self.read(|n| n.tree.parent) {
|
||||
some(parent) => self.matches_element(sel2) && parent.matches_selector(sel1),
|
||||
none => false
|
||||
Some(parent) => self.matches_element(sel2) && parent.matches_selector(sel1),
|
||||
None => false
|
||||
}
|
||||
}
|
||||
Descendant(sel1, sel2) => {
|
||||
|
@ -105,16 +105,16 @@ impl Node : PrivMatchingMethods {
|
|||
//loop over all ancestors to check if they are the person
|
||||
//we should be descended from.
|
||||
let mut cur_parent = match self.read(|n| n.tree.parent) {
|
||||
some(parent) => parent,
|
||||
none => return false
|
||||
Some(parent) => parent,
|
||||
None => return false
|
||||
};
|
||||
|
||||
loop {
|
||||
if cur_parent.matches_selector(sel1) { return true; }
|
||||
|
||||
cur_parent = match cur_parent.read(|n| n.tree.parent) {
|
||||
some(parent) => parent,
|
||||
none => return false
|
||||
Some(parent) => parent,
|
||||
None => return false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -123,34 +123,34 @@ impl Node : PrivMatchingMethods {
|
|||
|
||||
// Loop over this node's previous siblings to see if they match.
|
||||
match self.read(|n| n.tree.prev_sibling) {
|
||||
some(sib) => {
|
||||
Some(sib) => {
|
||||
let mut cur_sib = sib;
|
||||
loop {
|
||||
if cur_sib.matches_selector(sel1) { return true; }
|
||||
|
||||
cur_sib = match cur_sib.read(|n| n.tree.prev_sibling) {
|
||||
some(sib) => sib,
|
||||
none => { break; }
|
||||
Some(sib) => sib,
|
||||
None => { break; }
|
||||
};
|
||||
}
|
||||
}
|
||||
none => { }
|
||||
None => { }
|
||||
}
|
||||
|
||||
// check the rest of the siblings
|
||||
match self.read(|n| n.tree.next_sibling) {
|
||||
some(sib) => {
|
||||
Some(sib) => {
|
||||
let mut cur_sib = sib;
|
||||
loop {
|
||||
if cur_sib.matches_selector(sel1) { return true; }
|
||||
|
||||
cur_sib = match cur_sib.read(|n| n.tree.next_sibling) {
|
||||
some(sib) => sib,
|
||||
none => { break; }
|
||||
Some(sib) => sib,
|
||||
None => { break; }
|
||||
};
|
||||
}
|
||||
}
|
||||
none => { }
|
||||
None => { }
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -168,12 +168,12 @@ impl Node : PrivStyleMethods {
|
|||
fn update_style(decl : StyleDeclaration) {
|
||||
self.aux(|layout| {
|
||||
match decl {
|
||||
BackgroundColor(col) => layout.specified_style.background_color = some(col),
|
||||
Display(dis) => layout.specified_style.display_type = some(dis),
|
||||
FontSize(size) => layout.specified_style.font_size = some(size),
|
||||
Height(size) => layout.specified_style.height = some(size),
|
||||
TextColor(col) => layout.specified_style.text_color = some(col),
|
||||
Width(size) => layout.specified_style.width = some(size)
|
||||
BackgroundColor(col) => layout.specified_style.background_color = Some(col),
|
||||
Display(dis) => layout.specified_style.display_type = Some(dis),
|
||||
FontSize(size) => layout.specified_style.font_size = Some(size),
|
||||
Height(size) => layout.specified_style.height = Some(size),
|
||||
TextColor(col) => layout.specified_style.text_color = Some(col),
|
||||
Width(size) => layout.specified_style.width = Some(size)
|
||||
};
|
||||
})
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ impl Node : MatchingMethods {
|
|||
mod test {
|
||||
import dom::base::{Attr, HTMLDivElement, HTMLHeadElement, HTMLImageElement};
|
||||
import dom::base::{NodeScope, UnknownElement};
|
||||
import dvec::dvec;
|
||||
import dvec::DVec;
|
||||
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn new_node_from_attr(scope: NodeScope, -name: ~str, -val: ~str) -> Node {
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
#[doc="High-level interface to CSS selector matching."]
|
||||
|
||||
import std::arc::{arc, get, clone};
|
||||
import std::arc::{ARC, get, clone};
|
||||
|
||||
import dom::style::{DisplayType, DisBlock, DisInline, DisNone, Stylesheet, Unit, Auto};
|
||||
import dom::base::{Element, HTMLDivElement, HTMLHeadElement, HTMLImageElement, Node, NodeKind};
|
||||
import dom::base::{Element, HTMLDivElement, HTMLHeadElement, HTMLImageElement, Node, NodeKind, UnknownElement, HTMLScriptElement};
|
||||
import dom::base::{Text};
|
||||
import util::color::{Color, rgb};
|
||||
import util::color::css_colors::{white, black};
|
||||
import base::{LayoutData, NTree};
|
||||
|
||||
type SpecifiedStyle = {mut background_color : option<Color>,
|
||||
mut display_type : option<DisplayType>,
|
||||
mut font_size : option<Unit>,
|
||||
mut height : option<Unit>,
|
||||
mut text_color : option<Color>,
|
||||
mut width : option<Unit>
|
||||
type SpecifiedStyle = {mut background_color : Option<Color>,
|
||||
mut display_type : Option<DisplayType>,
|
||||
mut font_size : Option<Unit>,
|
||||
mut height : Option<Unit>,
|
||||
mut text_color : Option<Color>,
|
||||
mut width : Option<Unit>
|
||||
};
|
||||
|
||||
trait DefaultStyleMethods {
|
||||
|
@ -41,7 +41,8 @@ impl NodeKind : DefaultStyleMethods {
|
|||
HTMLDivElement => DisBlock,
|
||||
HTMLHeadElement => DisNone,
|
||||
HTMLImageElement(*) => DisInline,
|
||||
UnknownElement => DisInline
|
||||
HTMLScriptElement => DisNone,
|
||||
UnknownElement => DisInline,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,12 +67,12 @@ impl NodeKind : DefaultStyleMethods {
|
|||
fn empty_style_for_node_kind(kind: NodeKind) -> SpecifiedStyle {
|
||||
let display_type = kind.default_display_type();
|
||||
|
||||
{mut background_color : none,
|
||||
mut display_type : some(display_type),
|
||||
mut font_size : none,
|
||||
mut height : none,
|
||||
mut text_color : none,
|
||||
mut width : none}
|
||||
{mut background_color : None,
|
||||
mut display_type : Some(display_type),
|
||||
mut font_size : None,
|
||||
mut height : None,
|
||||
mut text_color : None,
|
||||
mut width : None}
|
||||
}
|
||||
|
||||
trait StylePriv {
|
||||
|
@ -94,7 +95,7 @@ impl Node : StylePriv {
|
|||
let node_kind = self.read(|n| copy *n.kind);
|
||||
let the_layout_data = @LayoutData({
|
||||
mut specified_style : ~empty_style_for_node_kind(node_kind),
|
||||
mut box : none
|
||||
mut box : None
|
||||
});
|
||||
|
||||
self.set_aux(the_layout_data);
|
||||
|
@ -109,7 +110,7 @@ impl Node : StylePriv {
|
|||
trait StyleMethods {
|
||||
fn initialize_style_for_subtree() -> ~[@LayoutData];
|
||||
fn get_specified_style() -> SpecifiedStyle;
|
||||
fn recompute_style_for_subtree(styles : arc<Stylesheet>);
|
||||
fn recompute_style_for_subtree(styles : ARC<Stylesheet>);
|
||||
}
|
||||
|
||||
impl Node : StyleMethods {
|
||||
|
@ -143,7 +144,7 @@ impl Node : StyleMethods {
|
|||
This is, importantly, the function that updates the layout data for the node (the reader-
|
||||
auxiliary box in the RCU model) with the computed style.
|
||||
"]
|
||||
fn recompute_style_for_subtree(styles : arc<Stylesheet>) {
|
||||
fn recompute_style_for_subtree(styles : ARC<Stylesheet>) {
|
||||
listen(|ack_chan| {
|
||||
let mut i = 0u;
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ import base::{Box, TextBoxKind};
|
|||
|
||||
struct TextBox {
|
||||
text: ~str;
|
||||
mut run: option<TextRun>;
|
||||
mut run: Option<TextRun>;
|
||||
|
||||
new(-text: ~str) {
|
||||
self.text = text;
|
||||
self.run = none;
|
||||
self.run = None;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ impl @Box : TextLayout {
|
|||
let font = flib.get_test_font();
|
||||
let run = TextRun(*font, subbox.text);
|
||||
self.bounds.size = run.size();
|
||||
subbox.run = some(run);
|
||||
subbox.run = Some(run);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,10 @@ fn should_calculate_the_size_of_the_text_box() {
|
|||
let n = s.new_node(Text(~"firecracker"));
|
||||
let b = n.construct_boxes();
|
||||
|
||||
let subbox = match check b.kind { TextBoxKind(subbox) => { subbox } };
|
||||
let subbox = match b.kind {
|
||||
TextBoxKind(subbox) => { subbox },
|
||||
_ => fail
|
||||
};
|
||||
b.reflow_text(subbox);
|
||||
let expected = Size2D(px_to_au(84), px_to_au(20));
|
||||
assert b.bounds.size == expected;
|
||||
|
|
|
@ -74,11 +74,11 @@ fn traverse_helper<T : copy send>(-root : @Box, returned : T, -top_down : fn~(+T
|
|||
let unwrapped = unwrap_box(copy kid);
|
||||
// Hide the box in an option so we can get it across the
|
||||
// task boundary without copying it
|
||||
let swappable : ~mut option<*shared_box<Box>> = ~mut some(unwrapped);
|
||||
let swappable : ~mut Option<*shared_box<Box>> = ~mut Some(unwrapped);
|
||||
|
||||
do task::spawn |copy top_down, copy bottom_up| {
|
||||
// Get the box out of the option and into the new task
|
||||
let mut swapped_in = none;
|
||||
let mut swapped_in = None;
|
||||
swapped_in <-> *swappable;
|
||||
|
||||
// Retrieve the original @Box and recurse
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
} => {
|
||||
if $index == $count {
|
||||
match move pipes::try_recv($port) {
|
||||
$(some($message($($(ref $x,)+)* ref next)) => {
|
||||
$(Some($message($($(ref $x,)+)* ref next)) => {
|
||||
// FIXME (#2329) we really want move out of enum here.
|
||||
let $next = move_ref!(next);
|
||||
$e
|
||||
|
|
|
@ -26,8 +26,8 @@ fn from_cmdline_args(args: ~[~str]) -> Opts {
|
|||
];
|
||||
|
||||
let opt_match = match getopts::getopts(args, opts) {
|
||||
result::ok(m) => { copy m }
|
||||
result::err(f) => { fail getopts::fail_str(f) }
|
||||
result::Ok(m) => { copy m }
|
||||
result::Err(f) => { fail getopts::fail_str(f) }
|
||||
};
|
||||
|
||||
let urls = if opt_match.free.is_empty() {
|
||||
|
@ -37,8 +37,8 @@ fn from_cmdline_args(args: ~[~str]) -> Opts {
|
|||
};
|
||||
|
||||
let render_mode = match getopts::opt_maybe_str(opt_match, ~"o") {
|
||||
some(output_file) => { Png(copy output_file) }
|
||||
none => { Screen }
|
||||
Some(output_file) => { Png(copy output_file) }
|
||||
None => { Screen }
|
||||
};
|
||||
|
||||
{
|
||||
|
|
|
@ -17,7 +17,7 @@ import parser::parser_util::{parse_display_type, parse_font_size, parse_size};
|
|||
import util::color::parsing::parse_color;
|
||||
import vec::push;
|
||||
|
||||
type TokenReader = {stream : pipes::port<Token>, mut lookahead : option<Token>};
|
||||
type TokenReader = {stream : pipes::Port<Token>, mut lookahead : Option<Token>};
|
||||
|
||||
trait TokenReaderMethods {
|
||||
fn get() -> Token;
|
||||
|
@ -27,30 +27,30 @@ trait TokenReaderMethods {
|
|||
impl TokenReader : TokenReaderMethods {
|
||||
fn get() -> Token {
|
||||
match copy self.lookahead {
|
||||
some(tok) => { self.lookahead = none; copy tok }
|
||||
none => { self.stream.recv() }
|
||||
Some(tok) => { self.lookahead = None; copy tok }
|
||||
None => { self.stream.recv() }
|
||||
}
|
||||
}
|
||||
|
||||
fn unget(-tok : Token) {
|
||||
assert is_none(self.lookahead);
|
||||
self.lookahead = some(tok);
|
||||
self.lookahead = Some(tok);
|
||||
}
|
||||
}
|
||||
|
||||
trait ParserMethods {
|
||||
fn parse_element() -> option<~style::Selector>;
|
||||
fn parse_selector() -> option<~[~Selector]>;
|
||||
fn parse_description() -> option<~[StyleDeclaration]>;
|
||||
fn parse_rule() -> option<~style::Rule>;
|
||||
fn parse_element() -> Option<~style::Selector>;
|
||||
fn parse_selector() -> Option<~[~Selector]>;
|
||||
fn parse_description() -> Option<~[StyleDeclaration]>;
|
||||
fn parse_rule() -> Option<~style::Rule>;
|
||||
}
|
||||
|
||||
impl TokenReader : ParserMethods {
|
||||
fn parse_element() -> option<~style::Selector> {
|
||||
fn parse_element() -> Option<~style::Selector> {
|
||||
// Get the current element type
|
||||
let elmt_name = match self.get() {
|
||||
Element(tag) => { copy tag }
|
||||
Eof => { return none; }
|
||||
Eof => { return None; }
|
||||
_ => { fail ~"Expected an element" }
|
||||
};
|
||||
|
||||
|
@ -65,16 +65,16 @@ impl TokenReader : ParserMethods {
|
|||
self.unget(tok);
|
||||
break;
|
||||
}
|
||||
Eof => { return none; }
|
||||
Eof => { return None; }
|
||||
Element(_) => fail ~"Unexpected second element without relation to first element",
|
||||
EndDescription => fail ~"Unexpected '}'",
|
||||
Description(_, _) => fail ~"Unexpected description"
|
||||
}
|
||||
}
|
||||
return some(~style::Element(elmt_name, attr_list));
|
||||
return Some(~style::Element(elmt_name, attr_list));
|
||||
}
|
||||
|
||||
fn parse_selector() -> option<~[~Selector]> {
|
||||
fn parse_selector() -> Option<~[~Selector]> {
|
||||
let mut sel_list = ~[];
|
||||
|
||||
// Collect all the selectors that this rule applies to
|
||||
|
@ -82,8 +82,8 @@ impl TokenReader : ParserMethods {
|
|||
let mut cur_sel;
|
||||
|
||||
match self.parse_element() {
|
||||
some(elmt) => { cur_sel = copy elmt; }
|
||||
none => { return none; } // we hit an eof in the middle of a rule
|
||||
Some(elmt) => { cur_sel = copy elmt; }
|
||||
None => { return None; } // we hit an eof in the middle of a rule
|
||||
}
|
||||
|
||||
loop {
|
||||
|
@ -93,29 +93,29 @@ impl TokenReader : ParserMethods {
|
|||
match tok {
|
||||
Descendant => {
|
||||
match self.parse_element() {
|
||||
some(elmt) => {
|
||||
Some(elmt) => {
|
||||
let new_sel = copy elmt;
|
||||
cur_sel <- ~style::Descendant(built_sel, new_sel)
|
||||
}
|
||||
none => { return none; }
|
||||
None => { return None; }
|
||||
}
|
||||
}
|
||||
Child => {
|
||||
match self.parse_element() {
|
||||
some(elmt) => {
|
||||
Some(elmt) => {
|
||||
let new_sel = copy elmt;
|
||||
cur_sel <- ~style::Child(built_sel, new_sel)
|
||||
}
|
||||
none => { return none; }
|
||||
None => { return None; }
|
||||
}
|
||||
}
|
||||
Sibling => {
|
||||
match self.parse_element() {
|
||||
some(elmt) => {
|
||||
Some(elmt) => {
|
||||
let new_sel = copy elmt;
|
||||
cur_sel <- ~style::Sibling(built_sel, new_sel)
|
||||
}
|
||||
none => { return none; }
|
||||
None => { return None; }
|
||||
}
|
||||
}
|
||||
StartDescription => {
|
||||
|
@ -131,7 +131,7 @@ impl TokenReader : ParserMethods {
|
|||
Attr(_) | EndDescription | Element(_) | Description(_, _) => {
|
||||
fail #fmt["Unexpected token %? in elements", tok];
|
||||
}
|
||||
Eof => { return none; }
|
||||
Eof => { return None; }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,10 +145,10 @@ impl TokenReader : ParserMethods {
|
|||
}
|
||||
}
|
||||
|
||||
return some(sel_list);
|
||||
return Some(sel_list);
|
||||
}
|
||||
|
||||
fn parse_description() -> option<~[StyleDeclaration]> {
|
||||
fn parse_description() -> Option<~[StyleDeclaration]> {
|
||||
let mut desc_list : ~[StyleDeclaration]= ~[];
|
||||
|
||||
// Get the description to be applied to the selector
|
||||
|
@ -165,49 +165,49 @@ impl TokenReader : ParserMethods {
|
|||
~"font-size" => parse_font_size(val).map(|res| FontSize(res)),
|
||||
~"height" => parse_size(val).map(|res| Height(res)),
|
||||
~"width" => parse_size(val).map(|res| Width(res)),
|
||||
_ => { #debug["Recieved unknown style property '%s'", val]; none }
|
||||
_ => { #debug["Recieved unknown style property '%s'", val]; None }
|
||||
};
|
||||
desc.map(|res| push(desc_list, res));
|
||||
}
|
||||
Eof => { return none; }
|
||||
Eof => { return None; }
|
||||
StartDescription | Descendant | Child | Sibling | Comma | Element(_) | Attr(_) => {
|
||||
fail #fmt["Unexpected token %? in description", tok];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return some(desc_list);
|
||||
return Some(desc_list);
|
||||
}
|
||||
|
||||
fn parse_rule() -> option<~style::Rule> {
|
||||
fn parse_rule() -> Option<~style::Rule> {
|
||||
// TODO: get rid of copies once match move works
|
||||
let sel_list = match self.parse_selector() {
|
||||
some(list) => { copy list }
|
||||
none => { return none; }
|
||||
Some(list) => { copy list }
|
||||
None => { return None; }
|
||||
};
|
||||
|
||||
#debug("sel_list: %?", sel_list);
|
||||
|
||||
// Get the description to be applied to the selector
|
||||
let desc_list = match self.parse_description() {
|
||||
some(list) => { copy list }
|
||||
none => { return none; }
|
||||
Some(list) => { copy list }
|
||||
None => { return None; }
|
||||
};
|
||||
|
||||
#debug("desc_list: %?", desc_list);
|
||||
|
||||
return some(~(sel_list, desc_list));
|
||||
return Some(~(sel_list, desc_list));
|
||||
}
|
||||
}
|
||||
|
||||
fn build_stylesheet(+stream : pipes::port<Token>) -> ~[~style::Rule] {
|
||||
fn build_stylesheet(+stream : pipes::Port<Token>) -> ~[~style::Rule] {
|
||||
let mut rule_list = ~[];
|
||||
let reader = {stream : stream, mut lookahead : none};
|
||||
let reader = {stream : stream, mut lookahead : None};
|
||||
|
||||
loop {
|
||||
match reader.parse_rule() {
|
||||
some(rule) => { push(rule_list, copy rule); }
|
||||
none => { break; }
|
||||
Some(rule) => { push(rule_list, copy rule); }
|
||||
None => { break; }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,12 @@ import option::is_none;
|
|||
import str::from_bytes;
|
||||
import vec::push;
|
||||
|
||||
import pipes::{port, chan};
|
||||
import pipes::{Port, Chan};
|
||||
|
||||
import lexer_util::*;
|
||||
|
||||
import std::net::url::url;
|
||||
import resource::resource_task::{ResourceTask, ProgressMsg, Load};
|
||||
import result::ok;
|
||||
|
||||
enum ParserState {
|
||||
CssElement,
|
||||
|
@ -230,7 +229,7 @@ impl CssLexer : CssLexerMethods {
|
|||
fn parser(input_port: comm::Port<ProgressMsg>, state : ParserState) -> CssLexer {
|
||||
return {
|
||||
input_state: {
|
||||
mut lookahead: none,
|
||||
mut lookahead: None,
|
||||
mut buffer: ~[],
|
||||
input_port: input_port,
|
||||
mut eof: false
|
||||
|
@ -239,12 +238,12 @@ fn parser(input_port: comm::Port<ProgressMsg>, state : ParserState) -> CssLexer
|
|||
};
|
||||
}
|
||||
|
||||
fn lex_css_from_bytes(+input_port: comm::Port<ProgressMsg>, result_chan : chan<Token>) {
|
||||
fn lex_css_from_bytes(+input_port: comm::Port<ProgressMsg>, result_chan : Chan<Token>) {
|
||||
let lexer = parser(input_port, CssElement);
|
||||
|
||||
loop {
|
||||
let token = lexer.parse_css();
|
||||
let should_break = (token == Eof);
|
||||
let should_break = match token { Eof => true, _ => false };
|
||||
|
||||
result_chan.send(token);
|
||||
|
||||
|
@ -254,13 +253,13 @@ fn lex_css_from_bytes(+input_port: comm::Port<ProgressMsg>, result_chan : chan<T
|
|||
}
|
||||
}
|
||||
|
||||
fn spawn_css_lexer_from_string(-content : ~str) -> pipes::port<Token> {
|
||||
fn spawn_css_lexer_from_string(-content : ~str) -> pipes::Port<Token> {
|
||||
let (result_chan, result_port) = pipes::stream();
|
||||
|
||||
do task::spawn {
|
||||
let input_port = comm::port();
|
||||
let input_port = comm::Port();
|
||||
input_port.send(Payload(str::to_bytes(content)));
|
||||
input_port.send(Done(ok(())));
|
||||
input_port.send(Done(Ok(())));
|
||||
|
||||
lex_css_from_bytes(input_port, result_chan);
|
||||
}
|
||||
|
@ -269,12 +268,12 @@ fn spawn_css_lexer_from_string(-content : ~str) -> pipes::port<Token> {
|
|||
}
|
||||
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn spawn_css_lexer_task(-url: url, resource_task: ResourceTask) -> pipes::port<Token> {
|
||||
fn spawn_css_lexer_task(-url: url, resource_task: ResourceTask) -> pipes::Port<Token> {
|
||||
let (result_chan, result_port) = pipes::stream();
|
||||
|
||||
do task::spawn || {
|
||||
assert url.path.ends_with(".css");
|
||||
let input_port = port();
|
||||
let input_port = Port();
|
||||
// TODO: change copy to move once the compiler permits it
|
||||
resource_task.send(Load(copy url, input_port.chan()));
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import dom::style::Stylesheet;
|
|||
import vec::{push, push_all_move, flat_map};
|
||||
import std::net::url::url;
|
||||
import resource::resource_task::{ResourceTask, Load, Payload, Done};
|
||||
import result::{ok, err};
|
||||
import to_str::ToStr;
|
||||
|
||||
enum CSSMessage {
|
||||
|
@ -35,18 +34,18 @@ fn link_up_attribute(scope: NodeScope, node: Node, -key: ~str, -value: ~str) {
|
|||
match *element.kind {
|
||||
HTMLImageElement(img) if key == ~"width" => {
|
||||
match int::from_str(value) {
|
||||
none => {
|
||||
None => {
|
||||
// Drop on the floor.
|
||||
}
|
||||
some(s) => { img.size.width = geometry::px_to_au(s); }
|
||||
Some(s) => { img.size.width = geometry::px_to_au(s); }
|
||||
}
|
||||
}
|
||||
HTMLImageElement(img) if key == ~"height" => {
|
||||
match int::from_str(value) {
|
||||
none => {
|
||||
None => {
|
||||
// Drop on the floor.
|
||||
}
|
||||
some(s) => {
|
||||
Some(s) => {
|
||||
img.size.height = geometry::px_to_au(s);
|
||||
}
|
||||
}
|
||||
|
@ -100,8 +99,8 @@ fn css_link_listener(to_parent : comm::Chan<Stylesheet>, from_parent : comm::Por
|
|||
loop {
|
||||
match from_parent.recv() {
|
||||
File(url) => {
|
||||
let result_port = comm::port();
|
||||
let result_chan = comm::chan(result_port);
|
||||
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(|| {
|
||||
|
@ -131,12 +130,12 @@ fn js_script_listener(to_parent : comm::Chan<~[~[u8]]>, from_parent : comm::Port
|
|||
loop {
|
||||
match from_parent.recv() {
|
||||
js_file(url) => {
|
||||
let result_port = comm::port();
|
||||
let result_chan = comm::chan(result_port);
|
||||
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();
|
||||
let input_port = Port();
|
||||
// TODO: change copy to move once we can move into closures
|
||||
resource_task.send(Load(copy url, input_port.chan()));
|
||||
|
||||
|
@ -146,11 +145,11 @@ fn js_script_listener(to_parent : comm::Chan<~[~[u8]]>, from_parent : comm::Port
|
|||
Payload(data) => {
|
||||
buf += data;
|
||||
}
|
||||
Done(ok(*)) => {
|
||||
Done(Ok(*)) => {
|
||||
result_chan.send(buf);
|
||||
break;
|
||||
}
|
||||
Done(err(*)) => {
|
||||
Done(Err(*)) => {
|
||||
#error("error loading script %s", url.to_str());
|
||||
}
|
||||
}
|
||||
|
@ -178,14 +177,14 @@ fn build_dom(scope: NodeScope, stream: comm::Port<Token>, url: url,
|
|||
// 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_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_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);
|
||||
});
|
||||
|
@ -216,15 +215,15 @@ fn build_dom(scope: NodeScope, stream: comm::Port<Token>, url: url,
|
|||
match *n.kind {
|
||||
Element(elmt) if elmt.tag_name == ~"link" => {
|
||||
match elmt.get_attr(~"rel") {
|
||||
some(r) if r == ~"stylesheet" => {
|
||||
Some(r) if r == ~"stylesheet" => {
|
||||
match elmt.get_attr(~"href") {
|
||||
some(filename) => {
|
||||
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));
|
||||
let new_url = make_url(filename, Some(copy url));
|
||||
style_chan.send(File(new_url));
|
||||
}
|
||||
none => { /* fall through*/ }
|
||||
None => { /* fall through*/ }
|
||||
}
|
||||
}
|
||||
_ => { /* fall through*/ }
|
||||
|
@ -235,18 +234,18 @@ fn build_dom(scope: NodeScope, stream: comm::Port<Token>, url: url,
|
|||
});
|
||||
cur_node = scope.get_parent(cur_node).get();
|
||||
}
|
||||
parser::EndTag(tag_name) => {
|
||||
parser::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) => {
|
||||
Some(filename) => {
|
||||
#debug["Linking to a js script named: %s", filename];
|
||||
let new_url = make_url(filename, some(copy url));
|
||||
let new_url = make_url(filename, Some(copy url));
|
||||
js_chan.send(js_file(new_url));
|
||||
}
|
||||
none => { /* fall through */ }
|
||||
None => { /* fall through */ }
|
||||
}
|
||||
}
|
||||
_ => { /* fall though */ }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import comm::{Port, Chan, port, chan};
|
||||
import comm::{Port, Chan};
|
||||
import dom::style;
|
||||
import option::is_none;
|
||||
import str::from_bytes;
|
||||
|
@ -121,23 +121,23 @@ impl HtmlLexer : HtmlLexerMethods {
|
|||
}
|
||||
|
||||
fn eat_until_end_of_comment() {
|
||||
let mut state = none;
|
||||
let mut state = None;
|
||||
|
||||
loop {
|
||||
match self.input_state.get() {
|
||||
CoeChar(c) => {
|
||||
match c {
|
||||
'-' as u8 if state == none => {
|
||||
state = some(~"-")
|
||||
'-' as u8 if state == None => {
|
||||
state = Some(~"-")
|
||||
}
|
||||
'-' as u8 if state == some(~"-") => {
|
||||
state = some(~"--")
|
||||
'-' as u8 if state == Some(~"-") => {
|
||||
state = Some(~"--")
|
||||
}
|
||||
'>' as u8 if state == some(~"--") => {
|
||||
'>' as u8 if state == Some(~"--") => {
|
||||
return
|
||||
}
|
||||
_ => {
|
||||
state = none
|
||||
state = None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ impl HtmlLexer : HtmlLexerMethods {
|
|||
fn lexer(+input_port: Port<resource_task::ProgressMsg>, state : ParseState) -> HtmlLexer {
|
||||
return {
|
||||
input_state: {
|
||||
mut lookahead: none,
|
||||
mut lookahead: None,
|
||||
mut buffer: ~[],
|
||||
input_port: input_port,
|
||||
mut eof: false
|
||||
|
@ -225,11 +225,11 @@ fn lexer(+input_port: Port<resource_task::ProgressMsg>, state : ParseState) -> H
|
|||
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn spawn_html_lexer_task(-url: url, resource_task: ResourceTask) -> Port<Token> {
|
||||
let html_port = port();
|
||||
let html_chan = chan(html_port);
|
||||
let html_port = Port();
|
||||
let html_chan = Chan(html_port);
|
||||
|
||||
task::spawn(|| {
|
||||
let input_port = port();
|
||||
let input_port = Port();
|
||||
// TODO: change copy to move once we can move into closures
|
||||
resource_task.send(Load(copy url, input_port.chan()));
|
||||
|
||||
|
@ -237,7 +237,7 @@ fn spawn_html_lexer_task(-url: url, resource_task: ResourceTask) -> Port<Token>
|
|||
|
||||
loop {
|
||||
let token = lexer.parse_html();
|
||||
let should_break = token == Eof;
|
||||
let should_break = match token { Eof => true, _ => false };
|
||||
html_chan.send(token);
|
||||
if should_break { break; }
|
||||
}
|
||||
|
|
|
@ -11,12 +11,9 @@ use JSExitMessage = parser::html_builder::js_exit;
|
|||
use JSFileMessage = parser::html_builder::js_file;
|
||||
use JSMessage = parser::html_builder::js_message;
|
||||
|
||||
use comm::{chan, port};
|
||||
use comm::{Chan, Port};
|
||||
use str::from_slice;
|
||||
use unsafe::reinterpret_cast;
|
||||
use Error = result::err;
|
||||
use OK = result::ok;
|
||||
use Result = result::result;
|
||||
use Url = std::net::url::url;
|
||||
|
||||
type JSResult = ~[~[u8]];
|
||||
|
@ -48,8 +45,8 @@ fn css_link_listener(to_parent : comm::Chan<Stylesheet>, from_parent : comm::Por
|
|||
loop {
|
||||
match from_parent.recv() {
|
||||
CSSFileMessage(url) => {
|
||||
let result_port = comm::port();
|
||||
let result_chan = comm::chan(result_port);
|
||||
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(|| {
|
||||
|
@ -79,12 +76,12 @@ fn js_script_listener(to_parent : comm::Chan<~[~[u8]]>, from_parent : comm::Port
|
|||
loop {
|
||||
match from_parent.recv() {
|
||||
JSFileMessage(url) => {
|
||||
let result_port = comm::port();
|
||||
let result_chan = comm::chan(result_port);
|
||||
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();
|
||||
let input_port = Port();
|
||||
// TODO: change copy to move once we can move into closures
|
||||
resource_task.send(Load(copy url, input_port.chan()));
|
||||
|
||||
|
@ -94,11 +91,11 @@ fn js_script_listener(to_parent : comm::Chan<~[~[u8]]>, from_parent : comm::Port
|
|||
Payload(data) => {
|
||||
buf += data;
|
||||
}
|
||||
Done(OK(*)) => {
|
||||
Done(Ok(*)) => {
|
||||
result_chan.send(buf);
|
||||
break;
|
||||
}
|
||||
Done(Error(*)) => {
|
||||
Done(Err(*)) => {
|
||||
#error("error loading script %s", url.to_str());
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +159,7 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa
|
|||
create_doctype: |_doctype| {
|
||||
debug!("create doctype");
|
||||
let new_node = scope.new_node(Element(ElementData(~"doctype", ~UnknownElement)));
|
||||
reinterpret_cast(new_node)
|
||||
unsafe { reinterpret_cast(new_node) }
|
||||
},
|
||||
create_element: |tag| {
|
||||
debug!("create element");
|
||||
|
@ -177,14 +174,14 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa
|
|||
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 = px_to_au(s)
|
||||
None => {} // Drop on the floor.
|
||||
Some(s) => img.size.width = px_to_au(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 = px_to_au(s)
|
||||
None => {} // Drop on the floor.
|
||||
Some(s) => img.size.height = px_to_au(s)
|
||||
}
|
||||
}
|
||||
HTMLDivElement | HTMLImageElement(*) | HTMLHeadElement |
|
||||
|
@ -202,9 +199,9 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa
|
|||
match *node_contents.kind {
|
||||
Element(element) if element.tag_name == ~"link" => {
|
||||
match (element.get_attr(~"rel"), element.get_attr(~"href")) {
|
||||
(some(rel), some(href)) if rel == ~"stylesheet" => {
|
||||
(Some(rel), Some(href)) if rel == ~"stylesheet" => {
|
||||
debug!("found CSS stylesheet: %s", href);
|
||||
css_chan.send(CSSFileMessage(make_url(href, some(copy *url))));
|
||||
css_chan.send(CSSFileMessage(make_url(href, Some(copy *url))));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -213,12 +210,12 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa
|
|||
}
|
||||
}
|
||||
|
||||
reinterpret_cast(node)
|
||||
unsafe { reinterpret_cast(node) }
|
||||
},
|
||||
create_text: |data| {
|
||||
debug!("create text");
|
||||
let new_node = scope.new_node(Text(from_slice(data)));
|
||||
reinterpret_cast(new_node)
|
||||
unsafe { reinterpret_cast(new_node) }
|
||||
},
|
||||
ref_node: |_node| {},
|
||||
unref_node: |_node| {},
|
||||
|
@ -268,12 +265,12 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa
|
|||
match *node_contents.kind {
|
||||
Element(element) if element.tag_name == ~"script" => {
|
||||
match element.get_attr(~"src") {
|
||||
some(src) => {
|
||||
Some(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));
|
||||
}
|
||||
none => {}
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -284,7 +281,7 @@ fn parse_html(scope: NodeScope, url: Url, resource_task: ResourceTask) -> HtmlPa
|
|||
});
|
||||
debug!("set tree handler");
|
||||
|
||||
let input_port = port();
|
||||
let input_port = Port();
|
||||
resource_task.send(Load(copy *url, input_port.chan()));
|
||||
debug!("loaded page");
|
||||
loop {
|
||||
|
|
|
@ -11,8 +11,18 @@ enum CharOrEof {
|
|||
CoeEof
|
||||
}
|
||||
|
||||
impl CharOrEof: cmp::Eq {
|
||||
pure fn eq(&&other: CharOrEof) -> bool {
|
||||
match (self, other) {
|
||||
(CoeChar(a), CoeChar(b)) => a == b,
|
||||
(CoeChar(*), _) | (_, CoeChar(*)) => false,
|
||||
(CoeEof, CoeEof) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type InputState = {
|
||||
mut lookahead: option<CharOrEof>,
|
||||
mut lookahead: Option<CharOrEof>,
|
||||
mut buffer: ~[u8],
|
||||
input_port: Port<ProgressMsg>,
|
||||
mut eof: bool
|
||||
|
@ -47,12 +57,12 @@ trait InputStateUtil {
|
|||
impl InputState : InputStateUtil {
|
||||
fn get() -> CharOrEof {
|
||||
match copy self.lookahead {
|
||||
some(coe) => {
|
||||
Some(coe) => {
|
||||
let rv = coe;
|
||||
self.lookahead = none;
|
||||
self.lookahead = None;
|
||||
return rv;
|
||||
}
|
||||
none => {
|
||||
None => {
|
||||
/* fall through */
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +92,7 @@ impl InputState : InputStateUtil {
|
|||
|
||||
fn unget(ch: u8) {
|
||||
assert is_none(self.lookahead);
|
||||
self.lookahead = some(CoeChar(ch));
|
||||
self.lookahead = Some(CoeChar(ch));
|
||||
}
|
||||
|
||||
fn parse_err(err: ~str) -> ! {
|
||||
|
|
|
@ -9,7 +9,7 @@ export parse_font_size;
|
|||
export parse_size;
|
||||
export parse_display_type;
|
||||
|
||||
fn parse_unit(str : ~str) -> option<Unit> {
|
||||
fn parse_unit(str : ~str) -> Option<Unit> {
|
||||
match str {
|
||||
s if s.ends_with(~"%") => from_str(str.substr(0, str.len() - 1)).map(|f| Percent(f)),
|
||||
s if s.ends_with(~"in") => from_str(str.substr(0, str.len() - 2)).map(|f| Pt(72.0*f)),
|
||||
|
@ -19,44 +19,44 @@ fn parse_unit(str : ~str) -> option<Unit> {
|
|||
s if s.ends_with(~"pc") => from_str(str.substr(0, str.len() - 2)).map(|f| Pt(12.0*f)),
|
||||
s if s.ends_with(~"px") => from_str(str.substr(0, str.len() - 2)).map(|f| Px(f)),
|
||||
s if s.ends_with(~"ex") | s.ends_with(~"em") => fail ~"Em and Ex sizes not yet supported",
|
||||
_ => none,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_font_size(str : ~str) -> option<Unit> {
|
||||
fn parse_font_size(str : ~str) -> Option<Unit> {
|
||||
// The default pixel size, not sure if this is accurate.
|
||||
let default = 16.0;
|
||||
|
||||
match str {
|
||||
~"xx-small" => some(Px(0.6*default)),
|
||||
~"x-small" => some(Px(0.75*default)),
|
||||
~"small" => some(Px(8.0/9.0*default)),
|
||||
~"medium" => some(Px(default)),
|
||||
~"large" => some(Px(1.2*default)),
|
||||
~"x-large" => some(Px(1.5*default)),
|
||||
~"xx-large" => some(Px(2.0*default)),
|
||||
~"smaller" => some(Percent(80.0)),
|
||||
~"larger" => some(Percent(125.0)),
|
||||
~"inherit" => some(Percent(100.0)),
|
||||
~"xx-small" => Some(Px(0.6*default)),
|
||||
~"x-small" => Some(Px(0.75*default)),
|
||||
~"small" => Some(Px(8.0/9.0*default)),
|
||||
~"medium" => Some(Px(default)),
|
||||
~"large" => Some(Px(1.2*default)),
|
||||
~"x-large" => Some(Px(1.5*default)),
|
||||
~"xx-large" => Some(Px(2.0*default)),
|
||||
~"smaller" => Some(Percent(80.0)),
|
||||
~"larger" => Some(Percent(125.0)),
|
||||
~"inherit" => Some(Percent(100.0)),
|
||||
_ => parse_unit(str),
|
||||
}
|
||||
}
|
||||
|
||||
// For width / height, and anything else with the same attribute values
|
||||
fn parse_size(str : ~str) -> option<Unit> {
|
||||
fn parse_size(str : ~str) -> Option<Unit> {
|
||||
match str {
|
||||
~"auto" => some(Auto),
|
||||
~"inherit" => some(Percent(100.0)),
|
||||
~"auto" => Some(Auto),
|
||||
~"inherit" => Some(Percent(100.0)),
|
||||
_ => parse_unit(str),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_display_type(str : ~str) -> option<DisplayType> {
|
||||
fn parse_display_type(str : ~str) -> Option<DisplayType> {
|
||||
match str {
|
||||
~"inline" => some(DisInline),
|
||||
~"block" => some(DisBlock),
|
||||
~"none" => some(DisNone),
|
||||
_ => { #debug["Recieved unknown display value '%s'", str]; none }
|
||||
~"inline" => Some(DisInline),
|
||||
~"block" => Some(DisBlock),
|
||||
~"none" => Some(DisNone),
|
||||
_ => { #debug["Recieved unknown display value '%s'", str]; None }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@ import azure::cairo;
|
|||
import azure::cairo::bindgen::*;
|
||||
import azure::cairo_hl::ImageSurface;
|
||||
import comm::*;
|
||||
import dvec::{DVec, dvec};
|
||||
import dvec::DVec;
|
||||
import azure::cairo::cairo_surface_t;
|
||||
import gfx::compositor::Compositor;
|
||||
import dom::event::{Event, ResizeEvent};
|
||||
import layers::ImageLayer;
|
||||
import geom::size::Size2D;
|
||||
import std::cmp::fuzzy_eq;
|
||||
import std::cmp::FuzzyEq;
|
||||
import task::TaskBuilder;
|
||||
import vec::push;
|
||||
|
||||
|
@ -23,9 +23,9 @@ import pipes::chan;
|
|||
type OSMain = comm::Chan<Msg>;
|
||||
|
||||
enum Msg {
|
||||
BeginDrawing(pipes::chan<DrawTarget>),
|
||||
Draw(pipes::chan<DrawTarget>, DrawTarget),
|
||||
AddKeyHandler(pipes::chan<()>),
|
||||
BeginDrawing(pipes::Chan<DrawTarget>),
|
||||
Draw(pipes::Chan<DrawTarget>, DrawTarget),
|
||||
AddKeyHandler(pipes::Chan<()>),
|
||||
AddEventListener(comm::Chan<Event>),
|
||||
Exit
|
||||
}
|
||||
|
@ -40,8 +40,8 @@ fn OSMain() -> OSMain {
|
|||
}
|
||||
|
||||
fn mainloop(po: Port<Msg>) {
|
||||
let key_handlers: @DVec<pipes::chan<()>> = @dvec();
|
||||
let event_listeners: @DVec<comm::Chan<Event>> = @dvec();
|
||||
let key_handlers: @DVec<pipes::Chan<()>> = @DVec();
|
||||
let event_listeners: @DVec<comm::Chan<Event>> = @DVec();
|
||||
|
||||
glut::init();
|
||||
glut::init_display_mode(glut::DOUBLE);
|
||||
|
@ -85,7 +85,7 @@ fn mainloop(po: Port<Msg>) {
|
|||
let image = @layers::layers::Image(800, 600, layers::layers::ARGB32Format, buffer);
|
||||
image_layer.set_image(image);
|
||||
}
|
||||
exit => {
|
||||
Exit => {
|
||||
*done = true;
|
||||
}
|
||||
}
|
||||
|
@ -125,10 +125,10 @@ Implementation to allow the osmain channel to be used as a graphics
|
|||
compositor for the renderer
|
||||
"]
|
||||
impl OSMain : Compositor {
|
||||
fn begin_drawing(+next_dt: pipes::chan<DrawTarget>) {
|
||||
fn begin_drawing(+next_dt: pipes::Chan<DrawTarget>) {
|
||||
self.send(BeginDrawing(next_dt))
|
||||
}
|
||||
fn draw(+next_dt: pipes::chan<DrawTarget>, +draw_me: DrawTarget) {
|
||||
fn draw(+next_dt: pipes::Chan<DrawTarget>, +draw_me: DrawTarget) {
|
||||
self.send(Draw(next_dt, draw_me))
|
||||
}
|
||||
fn add_event_listener(listener: comm::Chan<Event>) {
|
||||
|
@ -141,7 +141,7 @@ struct SurfaceSet {
|
|||
mut back: Surface;
|
||||
}
|
||||
|
||||
fn lend_surface(surfaces: SurfaceSet, receiver: pipes::chan<DrawTarget>) {
|
||||
fn lend_surface(surfaces: SurfaceSet, receiver: pipes::Chan<DrawTarget>) {
|
||||
// We are in a position to lend out the surface?
|
||||
assert surfaces.front.have;
|
||||
// Ok then take it
|
||||
|
|
|
@ -4,8 +4,7 @@ import comm::Chan;
|
|||
import task::spawn;
|
||||
import resource_task::{ProgressMsg, Payload, Done};
|
||||
import std::net::url::url;
|
||||
import io::file_reader;
|
||||
import result::{result, ok, err};
|
||||
import io::{file_reader, ReaderUtil};
|
||||
|
||||
const READ_SIZE: uint = 1024;
|
||||
|
||||
|
@ -13,16 +12,16 @@ fn factory(+url: url, progress_chan: Chan<ProgressMsg>) {
|
|||
assert url.scheme == ~"file";
|
||||
|
||||
do spawn {
|
||||
match file_reader(url.path) {
|
||||
ok(reader) => {
|
||||
match file_reader(&Path(url.path)) {
|
||||
Ok(reader) => {
|
||||
while !reader.eof() {
|
||||
let data = reader.read_bytes(READ_SIZE);
|
||||
progress_chan.send(Payload(data));
|
||||
}
|
||||
progress_chan.send(Done(ok(())));
|
||||
progress_chan.send(Done(Ok(())));
|
||||
}
|
||||
err(*) => {
|
||||
progress_chan.send(Done(err(())));
|
||||
Err(*) => {
|
||||
progress_chan.send(Done(Err(())));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import task::spawn;
|
|||
import resource_task::{ProgressMsg, Payload, Done};
|
||||
import std::net::url::url;
|
||||
import http_client::{uv_http_request};
|
||||
import result::{ok, err};
|
||||
|
||||
fn factory(+url: url, progress_chan: Chan<ProgressMsg>) {
|
||||
assert url.scheme == ~"http";
|
||||
|
@ -22,20 +21,20 @@ fn factory(+url: url, progress_chan: Chan<ProgressMsg>) {
|
|||
http_client::Status(*) => { }
|
||||
http_client::Payload(data) => {
|
||||
#debug("http_loader: got data from %?", url);
|
||||
let mut crap = none;
|
||||
let mut crap = None;
|
||||
*data <-> crap;
|
||||
progress_chan.send(Payload(option::unwrap(crap)));
|
||||
}
|
||||
http_client::Error(*) => {
|
||||
#debug("http_loader: error loading %?", url);
|
||||
*errored = true;
|
||||
progress_chan.send(Done(err(())));
|
||||
progress_chan.send(Done(Err(())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !*errored {
|
||||
progress_chan.send(Done(ok(())));
|
||||
progress_chan.send(Done(Ok(())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,13 @@ export SyncImageCacheTask;
|
|||
import image::base::{Image, load_from_memory, test_image_bin};
|
||||
import std::net::url::url;
|
||||
import util::url::{make_url, UrlMap, url_map};
|
||||
import comm::{Chan, Port, chan, port};
|
||||
import comm::{Chan, Port};
|
||||
import task::{spawn, spawn_listener};
|
||||
import resource::resource_task;
|
||||
import resource_task::ResourceTask;
|
||||
import std::arc::arc;
|
||||
import std::arc::ARC;
|
||||
import clone_arc = std::arc::clone;
|
||||
import std::cell::Cell;
|
||||
import result::{result, ok, err};
|
||||
import to_str::ToStr;
|
||||
|
||||
enum Msg {
|
||||
|
@ -23,13 +22,13 @@ enum Msg {
|
|||
Prefetch(url),
|
||||
|
||||
/// Used be the prefetch tasks to post back image binaries
|
||||
/*priv*/ StorePrefetchedImageData(url, result<Cell<~[u8]>, ()>),
|
||||
/*priv*/ StorePrefetchedImageData(url, Result<Cell<~[u8]>, ()>),
|
||||
|
||||
/// Tell the cache to decode an image. Must be posted before GetImage/WaitForImage
|
||||
Decode(url),
|
||||
|
||||
/// Used by the decoder tasks to post decoded images back to the cache
|
||||
/*priv*/ StoreImage(url, option<arc<~Image>>),
|
||||
/*priv*/ StoreImage(url, Option<ARC<~Image>>),
|
||||
|
||||
/// Request an Image object for a URL. If the image is not is not immediately
|
||||
/// available then ImageNotReady is returned.
|
||||
|
@ -46,14 +45,39 @@ enum Msg {
|
|||
}
|
||||
|
||||
enum ImageResponseMsg {
|
||||
ImageReady(arc<~Image>),
|
||||
ImageReady(ARC<~Image>),
|
||||
ImageNotReady,
|
||||
ImageFailed
|
||||
}
|
||||
|
||||
impl ImageResponseMsg {
|
||||
pure fn clone() -> ImageResponseMsg {
|
||||
match self {
|
||||
ImageReady(img) => ImageReady(unchecked { clone_arc(&img) }),
|
||||
ImageNotReady => ImageNotReady,
|
||||
ImageFailed => ImageFailed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ImageResponseMsg: cmp::Eq {
|
||||
pure fn eq(&&other: ImageResponseMsg) -> bool {
|
||||
// FIXME: Bad copies
|
||||
match (self.clone(), other.clone()) {
|
||||
(ImageReady(*), ImageReady(*)) => fail ~"unimplemented comparison",
|
||||
(ImageNotReady, ImageNotReady) => true,
|
||||
(ImageFailed, ImageFailed) => true,
|
||||
|
||||
(ImageReady(*), _)
|
||||
| (ImageNotReady, _)
|
||||
| (ImageFailed, _) => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ImageCacheTask = Chan<Msg>;
|
||||
|
||||
type DecoderFactory = ~fn() -> ~fn(~[u8]) -> option<Image>;
|
||||
type DecoderFactory = ~fn() -> ~fn(~[u8]) -> Option<Image>;
|
||||
|
||||
fn ImageCacheTask(resource_task: ResourceTask) -> ImageCacheTask {
|
||||
ImageCacheTask_(resource_task, default_decoder_factory)
|
||||
|
@ -71,7 +95,7 @@ fn ImageCacheTask_(resource_task: ResourceTask, +decoder_factory: DecoderFactory
|
|||
from_client: from_client,
|
||||
state_map: url_map(),
|
||||
wait_map: url_map(),
|
||||
need_exit: none
|
||||
need_exit: None
|
||||
}.run();
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +130,7 @@ struct ImageCache {
|
|||
state_map: UrlMap<ImageState>;
|
||||
/// List of clients waiting on a WaitForImage response
|
||||
wait_map: UrlMap<@mut ~[Chan<ImageResponseMsg>]>;
|
||||
mut need_exit: option<Chan<()>>;
|
||||
mut need_exit: Option<Chan<()>>;
|
||||
}
|
||||
|
||||
enum ImageState {
|
||||
|
@ -114,7 +138,7 @@ enum ImageState {
|
|||
Prefetching(AfterPrefetch),
|
||||
Prefetched(@Cell<~[u8]>),
|
||||
Decoding,
|
||||
Decoded(@arc<~Image>),
|
||||
Decoded(@ARC<~Image>),
|
||||
Failed
|
||||
}
|
||||
|
||||
|
@ -148,12 +172,12 @@ impl ImageCache {
|
|||
OnMsg(handler) => msg_handlers += [copy handler],
|
||||
Exit(response) => {
|
||||
assert self.need_exit.is_none();
|
||||
self.need_exit = some(response);
|
||||
self.need_exit = Some(response);
|
||||
}
|
||||
}
|
||||
|
||||
match copy self.need_exit {
|
||||
some(response) => {
|
||||
Some(response) => {
|
||||
// Wait until we have no outstanding requests and subtasks
|
||||
// before exiting
|
||||
let mut can_exit = true;
|
||||
|
@ -174,15 +198,15 @@ impl ImageCache {
|
|||
break;
|
||||
}
|
||||
}
|
||||
none => ()
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*priv*/ fn get_state(+url: url) -> ImageState {
|
||||
match self.state_map.find(url) {
|
||||
some(state) => state,
|
||||
none => Init
|
||||
Some(state) => state,
|
||||
None => Init
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,9 +228,9 @@ impl ImageCache {
|
|||
let image = load_image_data(copy url, resource_task);
|
||||
|
||||
let result = if image.is_ok() {
|
||||
ok(Cell(result::unwrap(image)))
|
||||
Ok(Cell(result::unwrap(image)))
|
||||
} else {
|
||||
err(())
|
||||
Err(())
|
||||
};
|
||||
to_cache.send(StorePrefetchedImageData(copy url, result));
|
||||
#debug("image_cache_task: ended fetch for %s", (copy url).to_str());
|
||||
|
@ -225,18 +249,19 @@ impl ImageCache {
|
|||
}
|
||||
}
|
||||
|
||||
/*priv*/ fn store_prefetched_image_data(+url: url, data: &result<Cell<~[u8]>, ()>) {
|
||||
/*priv*/ fn store_prefetched_image_data(+url: url, data: &Result<Cell<~[u8]>, ()>) {
|
||||
match self.get_state(copy url) {
|
||||
Prefetching(next_step) => {
|
||||
match *data {
|
||||
ok(data_cell) => {
|
||||
Ok(data_cell) => {
|
||||
let data = data_cell.take();
|
||||
self.set_state(copy url, Prefetched(@Cell(data)));
|
||||
if next_step == DoDecode {
|
||||
self.decode(url);
|
||||
match next_step {
|
||||
DoDecode => self.decode(url),
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
err(*) => {
|
||||
Err(*) => {
|
||||
self.set_state(copy url, Failed);
|
||||
self.purge_waiters(url, || ImageFailed);
|
||||
}
|
||||
|
@ -280,9 +305,9 @@ impl ImageCache {
|
|||
#debug("image_cache_task: started image decode for %s", url.to_str());
|
||||
let image = decode(data);
|
||||
let image = if image.is_some() {
|
||||
some(arc(~option::unwrap(image)))
|
||||
Some(ARC(~option::unwrap(image)))
|
||||
} else {
|
||||
none
|
||||
None
|
||||
};
|
||||
to_cache.send(StoreImage(copy url, move image));
|
||||
#debug("image_cache_task: ended image decode for %s", url.to_str());
|
||||
|
@ -299,16 +324,16 @@ impl ImageCache {
|
|||
}
|
||||
}
|
||||
|
||||
/*priv*/ fn store_image(+url: url, image: &option<arc<~Image>>) {
|
||||
/*priv*/ fn store_image(+url: url, image: &Option<ARC<~Image>>) {
|
||||
|
||||
match self.get_state(copy url) {
|
||||
Decoding => {
|
||||
match *image {
|
||||
some(image) => {
|
||||
Some(image) => {
|
||||
self.set_state(copy url, Decoded(@clone_arc(&image)));
|
||||
self.purge_waiters(url, || ImageReady(clone_arc(&image)) );
|
||||
}
|
||||
none => {
|
||||
None => {
|
||||
self.set_state(copy url, Failed);
|
||||
self.purge_waiters(url, || ImageFailed );
|
||||
}
|
||||
|
@ -328,13 +353,13 @@ impl ImageCache {
|
|||
|
||||
/*priv*/ fn purge_waiters(+url: url, f: fn() -> ImageResponseMsg) {
|
||||
match self.wait_map.find(copy url) {
|
||||
some(@waiters) => {
|
||||
Some(@waiters) => {
|
||||
for waiters.each |response| {
|
||||
response.send(f());
|
||||
}
|
||||
self.wait_map.remove(url);
|
||||
}
|
||||
none => ()
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -377,10 +402,10 @@ impl ImageCache {
|
|||
| Decoding => {
|
||||
// We don't have this image yet
|
||||
match self.wait_map.find(copy url) {
|
||||
some(waiters) => {
|
||||
Some(waiters) => {
|
||||
vec::push(*waiters, response);
|
||||
}
|
||||
none => {
|
||||
None => {
|
||||
self.wait_map.insert(url, @mut ~[response]);
|
||||
}
|
||||
}
|
||||
|
@ -406,15 +431,15 @@ trait ImageCacheTaskClient {
|
|||
impl ImageCacheTask: ImageCacheTaskClient {
|
||||
|
||||
fn exit() {
|
||||
let response = port();
|
||||
let response = Port();
|
||||
self.send(Exit(response.chan()));
|
||||
response.recv();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn load_image_data(+url: url, resource_task: ResourceTask) -> result<~[u8], ()> {
|
||||
let response_port = port();
|
||||
fn load_image_data(+url: url, resource_task: ResourceTask) -> Result<~[u8], ()> {
|
||||
let response_port = Port();
|
||||
resource_task.send(resource_task::Load(url, response_port.chan()));
|
||||
|
||||
let mut image_data = ~[];
|
||||
|
@ -424,18 +449,18 @@ fn load_image_data(+url: url, resource_task: ResourceTask) -> result<~[u8], ()>
|
|||
resource_task::Payload(data) => {
|
||||
image_data += data;
|
||||
}
|
||||
resource_task::Done(result::ok(*)) => {
|
||||
return ok(image_data);
|
||||
resource_task::Done(result::Ok(*)) => {
|
||||
return Ok(image_data);
|
||||
}
|
||||
resource_task::Done(result::err(*)) => {
|
||||
return err(());
|
||||
resource_task::Done(result::Err(*)) => {
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_decoder_factory() -> ~fn(~[u8]) -> option<Image> {
|
||||
fn~(data: ~[u8]) -> option<Image> { load_from_memory(data) }
|
||||
fn default_decoder_factory() -> ~fn(~[u8]) -> Option<Image> {
|
||||
fn~(data: ~[u8]) -> Option<Image> { load_from_memory(data) }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -462,7 +487,7 @@ fn should_exit_on_request() {
|
|||
let mock_resource_task = mock_resource_task(|_response| () );
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let _url = make_url(~"file", none);
|
||||
let _url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.exit();
|
||||
mock_resource_task.send(resource_task::Exit);
|
||||
|
@ -475,25 +500,25 @@ fn should_fail_if_unprefetched_image_is_requested() {
|
|||
let mock_resource_task = mock_resource_task(|_response| () );
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
let request = port();
|
||||
let request = Port();
|
||||
image_cache_task.send(GetImage(url, request.chan()));
|
||||
request.recv();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_request_url_from_resource_task_on_prefetch() {
|
||||
let url_requested = port();
|
||||
let url_requested = Port();
|
||||
let url_requested_chan = url_requested.chan();
|
||||
|
||||
let mock_resource_task = do mock_resource_task |response| {
|
||||
url_requested_chan.send(());
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.send(Prefetch(url));
|
||||
url_requested.recv();
|
||||
|
@ -509,7 +534,7 @@ fn should_fail_if_requesting_decode_of_an_unprefetched_image() {
|
|||
let mock_resource_task = mock_resource_task(|_response| () );
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.send(Decode(url));
|
||||
image_cache_task.exit();
|
||||
|
@ -520,16 +545,16 @@ fn should_fail_if_requesting_decode_of_an_unprefetched_image() {
|
|||
fn should_fail_if_requesting_image_before_requesting_decode() {
|
||||
|
||||
let mock_resource_task = do mock_resource_task |response| {
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.send(Prefetch(copy url));
|
||||
// no decode message
|
||||
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(GetImage(url, response_port.chan()));
|
||||
|
||||
image_cache_task.exit();
|
||||
|
@ -538,16 +563,16 @@ fn should_fail_if_requesting_image_before_requesting_decode() {
|
|||
|
||||
#[test]
|
||||
fn should_not_request_url_from_resource_task_on_multiple_prefetches() {
|
||||
let url_requested = port();
|
||||
let url_requested = Port();
|
||||
let url_requested_chan = url_requested.chan();
|
||||
|
||||
let mock_resource_task = do mock_resource_task |response| {
|
||||
url_requested_chan.send(());
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.send(Prefetch(copy url));
|
||||
image_cache_task.send(Prefetch(url));
|
||||
|
@ -567,15 +592,15 @@ fn should_return_image_not_ready_if_data_has_not_arrived() {
|
|||
// the image
|
||||
wait_port.recv();
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.send(Prefetch(copy url));
|
||||
image_cache_task.send(Decode(copy url));
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(GetImage(url, response_port.chan()));
|
||||
assert response_port.recv() == ImageNotReady;
|
||||
wait_chan.send(());
|
||||
|
@ -588,13 +613,13 @@ fn should_return_decoded_image_data_if_data_has_arrived() {
|
|||
|
||||
let mock_resource_task = do mock_resource_task |response| {
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
let wait_for_image = port();
|
||||
let wait_for_image = Port();
|
||||
let wait_for_image_chan = wait_for_image.chan();
|
||||
|
||||
image_cache_task.send(OnMsg(|msg| {
|
||||
|
@ -610,7 +635,7 @@ fn should_return_decoded_image_data_if_data_has_arrived() {
|
|||
// Wait until our mock resource task has sent the image to the image cache
|
||||
wait_for_image_chan.recv();
|
||||
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(GetImage(url, response_port.chan()));
|
||||
match response_port.recv() {
|
||||
ImageReady(_) => (),
|
||||
|
@ -626,13 +651,13 @@ fn should_return_decoded_image_data_for_multiple_requests() {
|
|||
|
||||
let mock_resource_task = do mock_resource_task |response| {
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
let wait_for_image = port();
|
||||
let wait_for_image = Port();
|
||||
let wait_for_image_chan = wait_for_image.chan();
|
||||
|
||||
image_cache_task.send(OnMsg(|msg| {
|
||||
|
@ -649,7 +674,7 @@ fn should_return_decoded_image_data_for_multiple_requests() {
|
|||
wait_for_image.recv();
|
||||
|
||||
for iter::repeat(2) {
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(GetImage(copy url, response_port.chan()));
|
||||
match response_port.recv() {
|
||||
ImageReady(_) => (),
|
||||
|
@ -664,10 +689,10 @@ fn should_return_decoded_image_data_for_multiple_requests() {
|
|||
#[test]
|
||||
fn should_not_request_image_from_resource_task_if_image_is_already_available() {
|
||||
|
||||
let image_bin_sent = port();
|
||||
let image_bin_sent = Port();
|
||||
let image_bin_sent_chan = image_bin_sent.chan();
|
||||
|
||||
let resource_task_exited = port();
|
||||
let resource_task_exited = Port();
|
||||
let resource_task_exited_chan = resource_task_exited.chan();
|
||||
|
||||
let mock_resource_task = do spawn_listener |from_client| {
|
||||
|
@ -679,7 +704,7 @@ fn should_not_request_image_from_resource_task_if_image_is_already_available() {
|
|||
match from_client.recv() {
|
||||
resource_task::Load(_, response) => {
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
image_bin_sent_chan.send(());
|
||||
}
|
||||
resource_task::Exit => {
|
||||
|
@ -691,7 +716,7 @@ fn should_not_request_image_from_resource_task_if_image_is_already_available() {
|
|||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.send(Prefetch(copy url));
|
||||
|
||||
|
@ -713,10 +738,10 @@ fn should_not_request_image_from_resource_task_if_image_is_already_available() {
|
|||
#[test]
|
||||
fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() {
|
||||
|
||||
let image_bin_sent = port();
|
||||
let image_bin_sent = Port();
|
||||
let image_bin_sent_chan = image_bin_sent.chan();
|
||||
|
||||
let resource_task_exited = port();
|
||||
let resource_task_exited = Port();
|
||||
let resource_task_exited_chan = resource_task_exited.chan();
|
||||
|
||||
let mock_resource_task = do spawn_listener |from_client| {
|
||||
|
@ -728,7 +753,7 @@ fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() {
|
|||
match from_client.recv() {
|
||||
resource_task::Load(_, response) => {
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
response.send(resource_task::Done(result::err(())));
|
||||
response.send(resource_task::Done(result::Err(())));
|
||||
image_bin_sent_chan.send(());
|
||||
}
|
||||
resource_task::Exit => {
|
||||
|
@ -740,7 +765,7 @@ fn should_not_request_image_from_resource_task_if_image_fetch_already_failed() {
|
|||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.send(Prefetch(copy url));
|
||||
image_cache_task.send(Decode(copy url));
|
||||
|
@ -767,13 +792,13 @@ fn should_return_failed_if_image_bin_cannot_be_fetched() {
|
|||
let mock_resource_task = do mock_resource_task |response| {
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
// ERROR fetching image
|
||||
response.send(resource_task::Done(result::err(())));
|
||||
response.send(resource_task::Done(result::Err(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
let wait_for_prefetech = port();
|
||||
let wait_for_prefetech = Port();
|
||||
let wait_for_prefetech_chan = wait_for_prefetech.chan();
|
||||
|
||||
image_cache_task.send(OnMsg(|msg| {
|
||||
|
@ -789,7 +814,7 @@ fn should_return_failed_if_image_bin_cannot_be_fetched() {
|
|||
// Wait until our mock resource task has sent the image to the image cache
|
||||
wait_for_prefetech.recv();
|
||||
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(GetImage(url, response_port.chan()));
|
||||
match response_port.recv() {
|
||||
ImageFailed => (),
|
||||
|
@ -806,13 +831,13 @@ fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_f
|
|||
let mock_resource_task = do mock_resource_task |response | {
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
// ERROR fetching image
|
||||
response.send(resource_task::Done(result::err(())));
|
||||
response.send(resource_task::Done(result::Err(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
let wait_for_prefetech = port();
|
||||
let wait_for_prefetech = Port();
|
||||
let wait_for_prefetech_chan = wait_for_prefetech.chan();
|
||||
|
||||
image_cache_task.send(OnMsg(|msg| {
|
||||
|
@ -828,7 +853,7 @@ fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_f
|
|||
// Wait until our mock resource task has sent the image to the image cache
|
||||
wait_for_prefetech.recv();
|
||||
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(GetImage(copy url, response_port.chan()));
|
||||
match response_port.recv() {
|
||||
ImageFailed => (),
|
||||
|
@ -836,7 +861,7 @@ fn should_return_failed_for_multiple_get_image_requests_if_image_bin_cannot_be_f
|
|||
}
|
||||
|
||||
// And ask again, we should get the same response
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(GetImage(url, response_port.chan()));
|
||||
match response_port.recv() {
|
||||
ImageFailed => (),
|
||||
|
@ -854,13 +879,13 @@ fn should_return_not_ready_if_image_is_still_decoding() {
|
|||
|
||||
let mock_resource_task = do mock_resource_task |response| {
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let wait_to_decode_port_cell = Cell(wait_to_decode_port);
|
||||
let decoder_factory = fn~(move wait_to_decode_port_cell) -> ~fn(~[u8]) -> option<Image> {
|
||||
let decoder_factory = fn~(move wait_to_decode_port_cell) -> ~fn(~[u8]) -> Option<Image> {
|
||||
let wait_to_decode_port = wait_to_decode_port_cell.take();
|
||||
fn~(data: ~[u8], move wait_to_decode_port) -> option<Image> {
|
||||
fn~(data: ~[u8], move wait_to_decode_port) -> Option<Image> {
|
||||
// Don't decode until after the client requests the image
|
||||
wait_to_decode_port.recv();
|
||||
load_from_memory(data)
|
||||
|
@ -868,9 +893,9 @@ fn should_return_not_ready_if_image_is_still_decoding() {
|
|||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask_(mock_resource_task, decoder_factory);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
let wait_for_prefetech = port();
|
||||
let wait_for_prefetech = Port();
|
||||
let wait_for_prefetech_chan = wait_for_prefetech.chan();
|
||||
|
||||
image_cache_task.send(OnMsg(|msg| {
|
||||
|
@ -887,7 +912,7 @@ fn should_return_not_ready_if_image_is_still_decoding() {
|
|||
wait_for_prefetech.recv();
|
||||
|
||||
// Make the request
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(GetImage(url, response_port.chan()));
|
||||
|
||||
match response_port.recv() {
|
||||
|
@ -908,13 +933,13 @@ fn should_return_failed_if_image_decode_fails() {
|
|||
let mock_resource_task = do mock_resource_task |response| {
|
||||
// Bogus data
|
||||
response.send(resource_task::Payload(~[]));
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
let wait_for_decode = port();
|
||||
let wait_for_decode = Port();
|
||||
let wait_for_decode_chan = wait_for_decode.chan();
|
||||
|
||||
image_cache_task.send(OnMsg(|msg| {
|
||||
|
@ -931,7 +956,7 @@ fn should_return_failed_if_image_decode_fails() {
|
|||
wait_for_decode.recv();
|
||||
|
||||
// Make the request
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(GetImage(url, response_port.chan()));
|
||||
|
||||
match response_port.recv() {
|
||||
|
@ -948,13 +973,13 @@ fn should_return_image_on_wait_if_image_is_already_loaded() {
|
|||
|
||||
let mock_resource_task = do mock_resource_task |response| {
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
let wait_for_decode = port();
|
||||
let wait_for_decode = Port();
|
||||
let wait_for_decode_chan = wait_for_decode.chan();
|
||||
|
||||
image_cache_task.send(OnMsg(|msg| {
|
||||
|
@ -970,7 +995,7 @@ fn should_return_image_on_wait_if_image_is_already_loaded() {
|
|||
// Wait until our mock resource task has sent the image to the image cache
|
||||
wait_for_decode.recv();
|
||||
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(WaitForImage(url, response_port.chan()));
|
||||
match response_port.recv() {
|
||||
ImageReady(*) => (),
|
||||
|
@ -989,16 +1014,16 @@ fn should_return_image_on_wait_if_image_is_not_yet_loaded() {
|
|||
let mock_resource_task = do mock_resource_task |response| {
|
||||
wait_port.recv();
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.send(Prefetch(copy url));
|
||||
image_cache_task.send(Decode(copy url));
|
||||
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(WaitForImage(url, response_port.chan()));
|
||||
|
||||
wait_chan.send(());
|
||||
|
@ -1020,16 +1045,16 @@ fn should_return_image_failed_on_wait_if_image_fails_to_load() {
|
|||
let mock_resource_task = do mock_resource_task |response| {
|
||||
wait_port.recv();
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
response.send(resource_task::Done(result::err(())));
|
||||
response.send(resource_task::Done(result::Err(())));
|
||||
};
|
||||
|
||||
let image_cache_task = ImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.send(Prefetch(copy url));
|
||||
image_cache_task.send(Decode(copy url));
|
||||
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(WaitForImage(url, response_port.chan()));
|
||||
|
||||
wait_chan.send(());
|
||||
|
@ -1047,16 +1072,16 @@ fn should_return_image_failed_on_wait_if_image_fails_to_load() {
|
|||
fn sync_cache_should_wait_for_images() {
|
||||
let mock_resource_task = do mock_resource_task |response| {
|
||||
response.send(resource_task::Payload(test_image_bin()));
|
||||
response.send(resource_task::Done(result::ok(())));
|
||||
response.send(resource_task::Done(result::Ok(())));
|
||||
};
|
||||
|
||||
let image_cache_task = SyncImageCacheTask(mock_resource_task);
|
||||
let url = make_url(~"file", none);
|
||||
let url = make_url(~"file", None);
|
||||
|
||||
image_cache_task.send(Prefetch(copy url));
|
||||
image_cache_task.send(Decode(copy url));
|
||||
|
||||
let response_port = port();
|
||||
let response_port = Port();
|
||||
image_cache_task.send(GetImage(url, response_port.chan()));
|
||||
match response_port.recv() {
|
||||
ImageReady(_) => (),
|
||||
|
|
|
@ -8,11 +8,10 @@ export ControlMsg, Load, Exit;
|
|||
export ProgressMsg, Payload, Done;
|
||||
export ResourceTask, ResourceManager, LoaderTaskFactory;
|
||||
|
||||
import comm::{Chan, Port, chan, port};
|
||||
import comm::{Chan, Port};
|
||||
import task::{spawn, spawn_listener};
|
||||
import std::net::url;
|
||||
import std::net::url::url;
|
||||
import result::{result, ok, err};
|
||||
|
||||
enum ControlMsg {
|
||||
/// Request the data associated with a particular URL
|
||||
|
@ -25,7 +24,19 @@ enum ProgressMsg {
|
|||
/// Binary data - there may be multiple of these
|
||||
Payload(~[u8]),
|
||||
/// Indicates loading is complete, either successfully or not
|
||||
Done(result<(), ()>)
|
||||
Done(Result<(), ()>)
|
||||
}
|
||||
|
||||
impl ProgressMsg: cmp::Eq {
|
||||
pure fn eq(&&other: ProgressMsg) -> bool {
|
||||
match (self, other) {
|
||||
(Payload(a), Payload(b)) => a == b,
|
||||
(Done(a), Done(b)) => a == b,
|
||||
|
||||
(Payload(*), _)
|
||||
| (Done(*), _) => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle to a resource task
|
||||
|
@ -81,25 +92,25 @@ struct ResourceManager {
|
|||
fn load(+url: url, progress_chan: Chan<ProgressMsg>) {
|
||||
|
||||
match self.get_loader_factory(url) {
|
||||
some(loader_factory) => {
|
||||
Some(loader_factory) => {
|
||||
#debug("resource_task: loading url: %s", url::to_str(url));
|
||||
loader_factory(url, progress_chan);
|
||||
}
|
||||
none => {
|
||||
None => {
|
||||
#debug("resource_task: no loader for scheme %s", url.scheme);
|
||||
progress_chan.send(Done(err(())));
|
||||
progress_chan.send(Done(Err(())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_loader_factory(url: url) -> option<LoaderTaskFactory> {
|
||||
fn get_loader_factory(url: url) -> Option<LoaderTaskFactory> {
|
||||
for self.loaders.each |scheme_loader| {
|
||||
let (scheme, loader_factory) = copy scheme_loader;
|
||||
if scheme == url.scheme {
|
||||
return some(loader_factory);
|
||||
return Some(loader_factory);
|
||||
}
|
||||
}
|
||||
return none;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,10 +124,11 @@ fn test_exit() {
|
|||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn test_bad_scheme() {
|
||||
let resource_task = ResourceTask();
|
||||
let progress = port();
|
||||
let progress = Port();
|
||||
resource_task.send(Load(url::from_str(~"bogus://whatever").get(), progress.chan()));
|
||||
match check progress.recv() {
|
||||
match progress.recv() {
|
||||
Done(result) => { assert result.is_err() }
|
||||
_ => fail
|
||||
}
|
||||
resource_task.send(Exit);
|
||||
}
|
||||
|
@ -127,13 +139,13 @@ fn should_delegate_to_scheme_loader() {
|
|||
let payload = ~[1, 2, 3];
|
||||
let loader_factory = fn~(+_url: url, progress_chan: Chan<ProgressMsg>, copy payload) {
|
||||
progress_chan.send(Payload(copy payload));
|
||||
progress_chan.send(Done(ok(())));
|
||||
progress_chan.send(Done(Ok(())));
|
||||
};
|
||||
let loader_factories = ~[(~"snicklefritz", loader_factory)];
|
||||
let resource_task = create_resource_task_with_loaders(loader_factories);
|
||||
let progress = port();
|
||||
let progress = Port();
|
||||
resource_task.send(Load(url::from_str(~"snicklefritz://heya").get(), progress.chan()));
|
||||
assert progress.recv() == Payload(payload);
|
||||
assert progress.recv() == Done(ok(()));
|
||||
assert progress.recv() == Done(Ok(()));
|
||||
resource_task.send(Exit);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import engine::{EngineTask, EngineProto};
|
|||
import url_to_str = std::net::url::to_str;
|
||||
import util::url::make_url;
|
||||
|
||||
import pipes::{port, chan};
|
||||
import pipes::{Port, Chan};
|
||||
|
||||
fn main(args: ~[~str]) {
|
||||
run(opts::from_cmdline_args(args))
|
||||
|
@ -38,19 +38,19 @@ fn run_pipeline_screen(urls: ~[~str]) {
|
|||
osmain.send(AddKeyHandler(keypress_to_engine));
|
||||
|
||||
// Create a serve instance
|
||||
let mut engine_task = some(EngineTask(osmain));
|
||||
let mut engine_task = Some(EngineTask(osmain));
|
||||
|
||||
for urls.each |filename| {
|
||||
let url = make_url(filename, none);
|
||||
let url = make_url(filename, None);
|
||||
#debug["master: Sending url `%s`", url_to_str(url)];
|
||||
engine_task =
|
||||
some(EngineProto::client::LoadURL(swap_unwrap(&mut engine_task),
|
||||
Some(EngineProto::client::LoadURL(swap_unwrap(&mut engine_task),
|
||||
url));
|
||||
#debug["master: Waiting for keypress"];
|
||||
|
||||
match keypress_from_osmain.try_recv() {
|
||||
some(*) => { }
|
||||
none => { #error("keypress stream closed unexpectedly") }
|
||||
Some(*) => { }
|
||||
None => { #error("keypress stream closed unexpectedly") }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,6 @@ fn run_pipeline_png(-url: ~str, outfile: ~str) {
|
|||
// Use a PNG encoder as the graphics compositor
|
||||
import gfx::png_compositor;
|
||||
import png_compositor::PngCompositor;
|
||||
import result::{ok, err};
|
||||
import io::{Writer, buffered_file_writer};
|
||||
import resource::resource_task::ResourceTask;
|
||||
import resource::image_cache_task::SyncImageCacheTask;
|
||||
|
@ -81,11 +80,11 @@ fn run_pipeline_png(-url: ~str, outfile: ~str) {
|
|||
// render
|
||||
let image_cache_task = SyncImageCacheTask(resource_task);
|
||||
let engine_task = EngineTask_(compositor, resource_task, image_cache_task);
|
||||
let engine_task = EngineProto::client::LoadURL(engine_task, make_url(url, none));
|
||||
let engine_task = EngineProto::client::LoadURL(engine_task, make_url(url, None));
|
||||
|
||||
match buffered_file_writer(outfile) {
|
||||
ok(writer) => writer.write(pngdata_from_compositor.recv()),
|
||||
err(e) => fail e
|
||||
match buffered_file_writer(&Path(outfile)) {
|
||||
Ok(writer) => writer.write(pngdata_from_compositor.recv()),
|
||||
Err(e) => fail e
|
||||
}
|
||||
|
||||
let engine_task = EngineProto::client::Exit(engine_task);
|
||||
|
|
|
@ -24,14 +24,14 @@ struct Font {
|
|||
self.fontbuf
|
||||
}
|
||||
|
||||
fn glyph_index(codepoint: char) -> option<GlyphIndex> {
|
||||
fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
|
||||
self.native_font.glyph_index(codepoint)
|
||||
}
|
||||
|
||||
fn glyph_h_advance(glyph: GlyphIndex) -> int {
|
||||
match self.native_font.glyph_h_advance(glyph) {
|
||||
some(adv) => adv,
|
||||
none => /* FIXME: Need fallback strategy */ 10
|
||||
Some(adv) => adv,
|
||||
None => /* FIXME: Need fallback strategy */ 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ fn should_get_glyph_indexes() {
|
|||
let lib = FontLibrary();
|
||||
let font = lib.get_test_font();
|
||||
let glyph_idx = font.glyph_index('w');
|
||||
assert glyph_idx == some(40u);
|
||||
assert glyph_idx == Some(40u);
|
||||
}
|
||||
|
||||
fn should_get_glyph_advance() {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
export FontLibrary, native;
|
||||
|
||||
import font::{Font, test_font_bin};
|
||||
import result::{result, ok, err};
|
||||
|
||||
struct FontLibrary {
|
||||
let native_lib: native::NativeFontLibrary;
|
||||
|
@ -16,8 +15,8 @@ struct FontLibrary {
|
|||
|
||||
fn get_font() -> @Font {
|
||||
match create_font(&self.native_lib) {
|
||||
ok(font) => font,
|
||||
err(*) => /* FIXME */ fail
|
||||
Ok(font) => font,
|
||||
Err(*) => /* FIXME */ fail
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,15 +26,15 @@ struct FontLibrary {
|
|||
}
|
||||
|
||||
|
||||
fn create_font(native_lib: &native::NativeFontLibrary) -> result<@Font, ()> {
|
||||
fn create_font(native_lib: &native::NativeFontLibrary) -> Result<@Font, ()> {
|
||||
let font_bin = test_font_bin();
|
||||
let native_font = native_font::create(native_lib, &font_bin);
|
||||
let native_font = if native_font.is_ok() {
|
||||
result::unwrap(native_font)
|
||||
} else {
|
||||
return err(native_font.get_err());
|
||||
return Err(native_font.get_err());
|
||||
};
|
||||
return ok(@Font(font_bin, native_font));
|
||||
return Ok(@Font(font_bin, native_font));
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
|
|
@ -9,7 +9,6 @@ font resources needed by the graphics layer to draw glyphs.
|
|||
|
||||
export NativeFont, create;
|
||||
|
||||
import result::result;
|
||||
import font_library::native::NativeFontLibrary;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
@ -19,12 +18,12 @@ type NativeFont/& = quartz_native_font::QuartzNativeFont;
|
|||
type NativeFont/& = ft_native_font::FreeTypeNativeFont;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn create(_native_lib: &NativeFontLibrary, buf: &~[u8]) -> result<NativeFont, ()> {
|
||||
fn create(_native_lib: &NativeFontLibrary, buf: &~[u8]) -> Result<NativeFont, ()> {
|
||||
quartz_native_font::create(buf)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn create(native_lib: &NativeFontLibrary, buf: &~[u8]) -> result<NativeFont, ()> {
|
||||
fn create(native_lib: &NativeFontLibrary, buf: &~[u8]) -> Result<NativeFont, ()> {
|
||||
ft_native_font::create(*native_lib, buf)
|
||||
}
|
||||
|
||||
|
@ -43,7 +42,7 @@ fn with_test_native_font(f: fn@(nf: &NativeFont)) {
|
|||
fn should_get_glyph_indexes() {
|
||||
with_test_native_font(|font| {
|
||||
let idx = font.glyph_index('w');
|
||||
assert idx == some(40u);
|
||||
assert idx == Some(40u);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -52,7 +51,7 @@ fn should_get_glyph_indexes() {
|
|||
fn should_return_none_glyph_index_for_bad_codepoints() {
|
||||
with_test_native_font(|font| {
|
||||
let idx = font.glyph_index(0 as char);
|
||||
assert idx == none;
|
||||
assert idx == None;
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -61,7 +60,7 @@ fn should_return_none_glyph_index_for_bad_codepoints() {
|
|||
fn should_get_glyph_h_advance() {
|
||||
with_test_native_font(|font| {
|
||||
let adv = font.glyph_h_advance(40u);
|
||||
assert adv == some(15);
|
||||
assert adv == Some(15);
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -70,6 +69,6 @@ fn should_get_glyph_h_advance() {
|
|||
fn should_return_none_glyph_h_advance_for_bad_codepoints() {
|
||||
with_test_native_font(|font| {
|
||||
let adv = font.glyph_h_advance(-1 as uint);
|
||||
assert adv == none;
|
||||
assert adv == None;
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
export FreeTypeNativeFont, with_test_native_font, create;
|
||||
|
||||
import vec_as_buf = vec::as_buf;
|
||||
import result::{result, ok, err};
|
||||
import ptr::{addr_of, null};
|
||||
import unsafe::reinterpret_cast;
|
||||
import glyph::GlyphIndex;
|
||||
|
@ -32,19 +31,19 @@ struct FreeTypeNativeFont/& {
|
|||
}
|
||||
}
|
||||
|
||||
fn glyph_index(codepoint: char) -> option<GlyphIndex> {
|
||||
fn glyph_index(codepoint: char) -> Option<GlyphIndex> {
|
||||
assert self.face.is_not_null();
|
||||
let idx = FT_Get_Char_Index(self.face, codepoint as FT_ULong);
|
||||
return if idx != 0 as FT_UInt {
|
||||
some(idx as GlyphIndex)
|
||||
Some(idx as GlyphIndex)
|
||||
} else {
|
||||
#warn("Invalid codepoint: %?", codepoint);
|
||||
none
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
// FIXME: What unit is this returning? Let's have a custom type
|
||||
fn glyph_h_advance(glyph: GlyphIndex) -> option<int> {
|
||||
fn glyph_h_advance(glyph: GlyphIndex) -> Option<int> {
|
||||
assert self.face.is_not_null();
|
||||
let res = FT_Load_Glyph(self.face, glyph as FT_UInt, 0);
|
||||
if res.succeeded() {
|
||||
|
@ -56,16 +55,16 @@ struct FreeTypeNativeFont/& {
|
|||
#debug("h_advance for %? is %?", glyph, advance);
|
||||
// FIXME: Dividing by 64 converts to pixels, which
|
||||
// is not the unit we should be using
|
||||
return some((advance / 64) as int);
|
||||
return Some((advance / 64) as int);
|
||||
}
|
||||
} else {
|
||||
#warn("Unable to load glyph %?. reason: %?", glyph, res);
|
||||
return none;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create(lib: FT_Library, buf: &~[u8]) -> result<FreeTypeNativeFont, ()> {
|
||||
fn create(lib: FT_Library, buf: &~[u8]) -> Result<FreeTypeNativeFont, ()> {
|
||||
assert lib.is_not_null();
|
||||
let face: FT_Face = null();
|
||||
return vec_as_buf(*buf, |cbuf, _len| {
|
||||
|
@ -74,9 +73,9 @@ fn create(lib: FT_Library, buf: &~[u8]) -> result<FreeTypeNativeFont, ()> {
|
|||
// FIXME: These values are placeholders
|
||||
let res = FT_Set_Char_Size(face, 0, 20*64, 0, 72);
|
||||
if !res.succeeded() { fail ~"unable to set font char size" }
|
||||
ok(FreeTypeNativeFont(face))
|
||||
Ok(FreeTypeNativeFont(face))
|
||||
} else {
|
||||
err(())
|
||||
Err(())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -113,11 +113,11 @@ extern fn glyph_func(_font: *hb_font_t,
|
|||
assert font.is_not_null();
|
||||
|
||||
return match (*font).glyph_index(unicode as char) {
|
||||
some(g) => {
|
||||
Some(g) => {
|
||||
*glyph = g as hb_codepoint_t;
|
||||
true
|
||||
}
|
||||
none => {
|
||||
None => {
|
||||
false
|
||||
}
|
||||
} as hb_bool_t;
|
||||
|
|
|
@ -66,13 +66,13 @@ impl Color {
|
|||
mod parsing {
|
||||
export parse_color;
|
||||
|
||||
fn fail_unrecognized(col : ~str) -> option<Color> {
|
||||
fn fail_unrecognized(col : ~str) -> Option<Color> {
|
||||
#warn["Unrecognized color %s", col];
|
||||
return none;
|
||||
return None;
|
||||
}
|
||||
|
||||
#[doc="Match an exact color keyword."]
|
||||
fn parse_by_name(color : ~str) -> option<Color> {
|
||||
fn parse_by_name(color : ~str) -> Option<Color> {
|
||||
let col = match color.to_lower() {
|
||||
~"black" => black(),
|
||||
~"silver" => silver(),
|
||||
|
@ -94,11 +94,11 @@ mod parsing {
|
|||
_ => return fail_unrecognized(color)
|
||||
};
|
||||
|
||||
return some(col);
|
||||
return Some(col);
|
||||
}
|
||||
|
||||
#[doc="Parses a color specification in the form rgb(foo,bar,baz)"]
|
||||
fn parse_rgb(color : ~str) -> option<Color> {
|
||||
fn parse_rgb(color : ~str) -> Option<Color> {
|
||||
// Shave off the rgb( and the )
|
||||
let only_colors = color.substr(4u, color.len() - 5u);
|
||||
|
||||
|
@ -108,13 +108,13 @@ mod parsing {
|
|||
|
||||
match (u8::from_str(cols[0]), u8::from_str(cols[1]),
|
||||
u8::from_str(cols[2])) {
|
||||
(some(r), some(g), some(b)) => { some(rgb(r, g, b)) }
|
||||
(Some(r), Some(g), Some(b)) => { Some(rgb(r, g, b)) }
|
||||
_ => { fail_unrecognized(color) }
|
||||
}
|
||||
}
|
||||
|
||||
#[doc="Parses a color specification in the form rgba(foo,bar,baz,qux)"]
|
||||
fn parse_rgba(color : ~str) -> option<Color> {
|
||||
fn parse_rgba(color : ~str) -> Option<Color> {
|
||||
// Shave off the rgba( and the )
|
||||
let only_vals = color.substr(5u, color.len() - 6u);
|
||||
|
||||
|
@ -124,13 +124,13 @@ mod parsing {
|
|||
|
||||
match (u8::from_str(cols[0]), u8::from_str(cols[1]),
|
||||
u8::from_str(cols[2]), float::from_str(cols[3])) {
|
||||
(some(r), some(g), some(b), some(a)) => { some(rgba(r, g, b, a)) }
|
||||
(Some(r), Some(g), Some(b), Some(a)) => { Some(rgba(r, g, b, a)) }
|
||||
_ => { fail_unrecognized(color) }
|
||||
}
|
||||
}
|
||||
|
||||
#[doc="Parses a color specification in the form hsl(foo,bar,baz)"]
|
||||
fn parse_hsl(color : ~str) -> option<Color> {
|
||||
fn parse_hsl(color : ~str) -> Option<Color> {
|
||||
// Shave off the hsl( and the )
|
||||
let only_vals = color.substr(4u, color.len() - 5u);
|
||||
|
||||
|
@ -140,13 +140,13 @@ mod parsing {
|
|||
|
||||
match (float::from_str(vals[0]), float::from_str(vals[1]),
|
||||
float::from_str(vals[2])) {
|
||||
(some(h), some(s), some(l)) => { some(hsl(h, s, l)) }
|
||||
(Some(h), Some(s), Some(l)) => { Some(hsl(h, s, l)) }
|
||||
_ => { fail_unrecognized(color) }
|
||||
}
|
||||
}
|
||||
|
||||
#[doc="Parses a color specification in the form hsla(foo,bar,baz,qux)"]
|
||||
fn parse_hsla(color : ~str) -> option<Color> {
|
||||
fn parse_hsla(color : ~str) -> Option<Color> {
|
||||
// Shave off the hsla( and the )
|
||||
let only_vals = color.substr(5u, color.len() - 6u);
|
||||
|
||||
|
@ -155,7 +155,7 @@ mod parsing {
|
|||
|
||||
match (float::from_str(vals[0]), float::from_str(vals[1]),
|
||||
float::from_str(vals[2]), float::from_str(vals[3])) {
|
||||
(some(h), some(s), some(l), some(a)) => { some(hsla(h, s, l, a)) }
|
||||
(Some(h), Some(s), Some(l), Some(a)) => { Some(hsla(h, s, l, a)) }
|
||||
_ => { fail_unrecognized(color) }
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ mod parsing {
|
|||
// Currently colors are supported in rgb(a,b,c) form and also by
|
||||
// keywords for several common colors.
|
||||
// TODO: extend this
|
||||
fn parse_color(color : ~str) -> option<Color> {
|
||||
fn parse_color(color : ~str) -> Option<Color> {
|
||||
match color {
|
||||
c if c.starts_with(~"rgb(") => parse_rgb(c),
|
||||
c if c.starts_with(~"rgba(") => parse_rgba(c),
|
||||
|
@ -198,7 +198,7 @@ mod test {
|
|||
assert navy().eq(unwrap(parse_color(~"NAVY")));
|
||||
assert teal().eq(unwrap(parse_color(~"Teal")));
|
||||
assert aqua().eq(unwrap(parse_color(~"Aqua")));
|
||||
assert none == parse_color(~"foobarbaz");
|
||||
assert None == parse_color(~"foobarbaz");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -210,7 +210,7 @@ mod test {
|
|||
assert rgb(1u8,2u8,3u8).eq(unwrap(parse_color(~"rgb(1,2,03)")));
|
||||
assert rgba(15u8,250u8,3u8,0.5).eq(unwrap(parse_color(~"rgba(15,250,3,.5)")));
|
||||
assert rgba(15u8,250u8,3u8,0.5).eq(unwrap(parse_color(~"rgba(15,250,3,0.5)")));
|
||||
assert none == parse_color(~"rbga(1,2,3)");
|
||||
assert None == parse_color(~"rbga(1,2,3)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -232,7 +232,7 @@ mod test {
|
|||
assert navy().eq(unwrap(parse_color(~"hsl(240.0,1.0,.25)")));
|
||||
assert teal().eq(unwrap(parse_color(~"hsl(180.0,1.0,.25)")));
|
||||
assert aqua().eq(unwrap(parse_color(~"hsl(180.0,1.0,.5)")));
|
||||
assert none == parse_color(~"hsl(1,2,3,.4)");
|
||||
assert None == parse_color(~"hsl(1,2,3,.4)");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
// TODO: Use traits.
|
||||
|
||||
type Tree<T> = {
|
||||
mut parent: option<T>,
|
||||
mut first_child: option<T>,
|
||||
mut last_child: option<T>,
|
||||
mut prev_sibling: option<T>,
|
||||
mut next_sibling: option<T>
|
||||
mut parent: Option<T>,
|
||||
mut first_child: Option<T>,
|
||||
mut last_child: Option<T>,
|
||||
mut prev_sibling: Option<T>,
|
||||
mut next_sibling: Option<T>
|
||||
};
|
||||
|
||||
trait ReadMethods<T> {
|
||||
|
@ -22,8 +22,8 @@ fn each_child<T:copy,O:ReadMethods<T>>(ops: O, node: T, f: fn(T) -> bool) {
|
|||
let mut p = ops.with_tree_fields(node, |f| f.first_child);
|
||||
loop {
|
||||
match copy p {
|
||||
none => { return; }
|
||||
some(c) => {
|
||||
None => { return; }
|
||||
Some(c) => {
|
||||
if !f(c) { return; }
|
||||
p = ops.with_tree_fields(c, |f| f.next_sibling);
|
||||
}
|
||||
|
@ -32,45 +32,45 @@ fn each_child<T:copy,O:ReadMethods<T>>(ops: O, node: T, f: fn(T) -> bool) {
|
|||
}
|
||||
|
||||
fn empty<T>() -> Tree<T> {
|
||||
{mut parent: none,
|
||||
mut first_child: none,
|
||||
mut last_child: none,
|
||||
mut prev_sibling: none,
|
||||
mut next_sibling: none}
|
||||
{mut parent: None,
|
||||
mut first_child: None,
|
||||
mut last_child: None,
|
||||
mut prev_sibling: None,
|
||||
mut next_sibling: None}
|
||||
}
|
||||
|
||||
fn add_child<T:copy,O:WriteMethods<T>>(ops: O, parent: T, child: T) {
|
||||
|
||||
ops.with_tree_fields(child, |child_tf| {
|
||||
match child_tf.parent {
|
||||
some(_) => { fail ~"Already has a parent"; }
|
||||
none => { child_tf.parent = some(parent); }
|
||||
Some(_) => { fail ~"Already has a parent"; }
|
||||
None => { child_tf.parent = Some(parent); }
|
||||
}
|
||||
|
||||
assert child_tf.prev_sibling == none;
|
||||
assert child_tf.next_sibling == none;
|
||||
assert child_tf.prev_sibling.is_none();
|
||||
assert child_tf.next_sibling.is_none();
|
||||
|
||||
ops.with_tree_fields(parent, |parent_tf| {
|
||||
match copy parent_tf.last_child {
|
||||
none => {
|
||||
parent_tf.first_child = some(child);
|
||||
None => {
|
||||
parent_tf.first_child = Some(child);
|
||||
}
|
||||
some(lc) => {
|
||||
Some(lc) => {
|
||||
let lc = lc; // satisfy alias checker
|
||||
ops.with_tree_fields(lc, |lc_tf| {
|
||||
assert lc_tf.next_sibling == none;
|
||||
lc_tf.next_sibling = some(child);
|
||||
assert lc_tf.next_sibling.is_none();
|
||||
lc_tf.next_sibling = Some(child);
|
||||
});
|
||||
child_tf.prev_sibling = some(lc);
|
||||
child_tf.prev_sibling = Some(lc);
|
||||
}
|
||||
}
|
||||
|
||||
parent_tf.last_child = some(child);
|
||||
parent_tf.last_child = Some(child);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn get_parent<T:copy,O:ReadMethods<T>>(ops: O, node: T) -> option<T> {
|
||||
fn get_parent<T:copy,O:ReadMethods<T>>(ops: O, node: T) -> Option<T> {
|
||||
ops.with_tree_fields(node, |tf| tf.parent)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ export make_url, UrlMap, url_map;
|
|||
import std::net::url;
|
||||
import url::{get_scheme, url};
|
||||
import std::map::hashmap;
|
||||
import path::Path;
|
||||
|
||||
/**
|
||||
Create a URL object from a string. Does various helpful browsery things like
|
||||
|
@ -14,24 +15,24 @@ Create a URL object from a string. Does various helpful browsery things like
|
|||
|
||||
*/
|
||||
#[allow(non_implicitly_copyable_typarams)]
|
||||
fn make_url(str_url: ~str, current_url: option<url>) -> url {
|
||||
fn make_url(str_url: ~str, current_url: Option<url>) -> url {
|
||||
let mut schm = get_scheme(str_url);
|
||||
let str_url = if result::is_err(schm) {
|
||||
if current_url.is_none() {
|
||||
// If all we have is a filename, assume it's a local relative file
|
||||
// and build an absolute path with the cwd
|
||||
~"file://" + path::connect(os::getcwd(), str_url)
|
||||
~"file://" + os::getcwd().push(str_url).to_str()
|
||||
} else {
|
||||
let current_url = current_url.get();
|
||||
#debug("make_url: current_url: %?", current_url);
|
||||
if current_url.path.is_empty() || current_url.path.ends_with("/") {
|
||||
current_url.scheme + "://" + path::connect(current_url.host, str_url)
|
||||
current_url.scheme + "://" + current_url.host + "/" + str_url
|
||||
} else {
|
||||
let path = path::split(current_url.path);
|
||||
let path = str::split_char(current_url.path, '/');
|
||||
let path = path.init();
|
||||
let path = path::connect_many(path + ~[copy str_url]);
|
||||
let path = str::connect(path + ~[copy str_url], "/");
|
||||
|
||||
current_url.scheme + "://" + path::connect(current_url.host, path)
|
||||
current_url.scheme + "://" + current_url.host + "/" + path
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -47,18 +48,18 @@ mod make_url_tests {
|
|||
#[test]
|
||||
fn should_create_absolute_file_url_if_current_url_is_none_and_str_url_looks_filey() {
|
||||
let file = ~"local.html";
|
||||
let url = make_url(file, none);
|
||||
let url = make_url(file, None);
|
||||
#debug("url: %?", url);
|
||||
assert url.scheme == ~"file";
|
||||
assert url.path.contains(os::getcwd());
|
||||
assert url.path.contains(os::getcwd().to_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_create_url_based_on_old_url_1() {
|
||||
let old_str = ~"http://example.com";
|
||||
let old_url = make_url(old_str, none);
|
||||
let old_url = make_url(old_str, None);
|
||||
let new_str = ~"index.html";
|
||||
let new_url = make_url(new_str, some(old_url));
|
||||
let new_url = make_url(new_str, Some(old_url));
|
||||
assert new_url.scheme == ~"http";
|
||||
assert new_url.host == ~"example.com";
|
||||
assert new_url.path == ~"/index.html";
|
||||
|
@ -67,9 +68,9 @@ mod make_url_tests {
|
|||
#[test]
|
||||
fn should_create_url_based_on_old_url_2() {
|
||||
let old_str = ~"http://example.com/";
|
||||
let old_url = make_url(old_str, none);
|
||||
let old_url = make_url(old_str, None);
|
||||
let new_str = ~"index.html";
|
||||
let new_url = make_url(new_str, some(old_url));
|
||||
let new_url = make_url(new_str, Some(old_url));
|
||||
assert new_url.scheme == ~"http";
|
||||
assert new_url.host == ~"example.com";
|
||||
assert new_url.path == ~"/index.html";
|
||||
|
@ -78,9 +79,9 @@ mod make_url_tests {
|
|||
#[test]
|
||||
fn should_create_url_based_on_old_url_3() {
|
||||
let old_str = ~"http://example.com/index.html";
|
||||
let old_url = make_url(old_str, none);
|
||||
let old_url = make_url(old_str, None);
|
||||
let new_str = ~"crumpet.html";
|
||||
let new_url = make_url(new_str, some(old_url));
|
||||
let new_url = make_url(new_str, Some(old_url));
|
||||
assert new_url.scheme == ~"http";
|
||||
assert new_url.host == ~"example.com";
|
||||
assert new_url.path == ~"/crumpet.html";
|
||||
|
@ -89,9 +90,9 @@ mod make_url_tests {
|
|||
#[test]
|
||||
fn should_create_url_based_on_old_url_4() {
|
||||
let old_str = ~"http://example.com/snarf/index.html";
|
||||
let old_url = make_url(old_str, none);
|
||||
let old_url = make_url(old_str, None);
|
||||
let new_str = ~"crumpet.html";
|
||||
let new_url = make_url(new_str, some(old_url));
|
||||
let new_url = make_url(new_str, Some(old_url));
|
||||
assert new_url.scheme == ~"http";
|
||||
assert new_url.host == ~"example.com";
|
||||
assert new_url.path == ~"/snarf/crumpet.html";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue