--- a/servo/cargo-nightly-build
+++ b/servo/cargo-nightly-build
@@ -1,1 +1,1 @@
-2014-12-18
+2015-01-09
--- a/servo/components/canvas/canvas_paint_task.rs
+++ b/servo/components/canvas/canvas_paint_task.rs
@@ -4,19 +4,19 @@
use azure::azure_hl::{DrawTarget, Color, SurfaceFormat, BackendType, StrokeOptions, DrawOptions};
use azure::azure_hl::{ColorPattern, PatternRef};
use geom::rect::Rect;
use geom::size::Size2D;
use servo_util::task::spawn_named;
use std::borrow::ToOwned;
-use std::comm;
+use std::sync::mpsc::{channel, Sender};
-#[deriving(Clone)]
+#[derive(Clone)]
pub enum CanvasMsg {
FillRect(Rect<f32>),
ClearRect(Rect<f32>),
StrokeRect(Rect<f32>),
Recreate(Size2D<i32>),
SendPixelContents(Sender<Vec<u8>>),
Close,
}
@@ -34,22 +34,22 @@ impl CanvasPaintTask {
drawtarget: CanvasPaintTask::create(size),
fill_color: ColorPattern::new(Color::new(0., 0., 0., 1.)),
stroke_color: ColorPattern::new(Color::new(0., 0., 0., 1.)),
stroke_opts: StrokeOptions::new(1.0, 1.0),
}
}
pub fn start(size: Size2D<i32>) -> Sender<CanvasMsg> {
- let (chan, port) = comm::channel::<CanvasMsg>();
- spawn_named("CanvasTask".to_owned(), proc() {
+ let (chan, port) = channel::<CanvasMsg>();
+ spawn_named("CanvasTask".to_owned(), move || {
let mut painter = CanvasPaintTask::new(size);
loop {
- match port.recv() {
+ match port.recv().unwrap() {
CanvasMsg::FillRect(ref rect) => painter.fill_rect(rect),
CanvasMsg::StrokeRect(ref rect) => painter.stroke_rect(rect),
CanvasMsg::ClearRect(ref rect) => painter.clear_rect(rect),
CanvasMsg::Recreate(size) => painter.recreate(size),
CanvasMsg::SendPixelContents(chan) => painter.send_pixel_contents(chan),
CanvasMsg::Close => break,
}
}
@@ -76,12 +76,12 @@ impl CanvasPaintTask {
}
fn recreate(&mut self, size: Size2D<i32>) {
self.drawtarget = CanvasPaintTask::create(size);
}
fn send_pixel_contents(&mut self, chan: Sender<Vec<u8>>) {
self.drawtarget.snapshot().get_data_surface().with_data(|element| {
- chan.send(element.to_vec());
+ chan.send(element.to_vec()).unwrap();
})
}
}
--- a/servo/components/compositing/Cargo.toml
+++ b/servo/components/compositing/Cargo.toml
@@ -38,22 +38,20 @@ git = "https://github.com/servo/rust-azu
git = "https://github.com/servo/rust-geom"
[dependencies.layers]
git = "https://github.com/servo/rust-layers"
[dependencies.png]
git = "https://github.com/servo/rust-png"
-[dependencies.url]
-git = "https://github.com/servo/rust-url"
-
[dependencies.core_graphics]
git = "https://github.com/servo/rust-core-graphics"
[dependencies.core_text]
git = "https://github.com/servo/rust-core-text"
[dependencies.gleam]
git = "https://github.com/servo/gleam"
-[dependencies.time]
-git = "https://github.com/rust-lang/time"
+[dependencies]
+url = "*"
+time = "*"
\ No newline at end of file
--- a/servo/components/compositing/compositor.rs
+++ b/servo/components/compositing/compositor.rs
@@ -36,21 +36,22 @@ use servo_msg::constellation_msg::Msg as
use servo_msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
use servo_msg::constellation_msg::{PipelineId, WindowSizeData};
use servo_util::geometry::{PagePx, ScreenPx, ViewportPx};
use servo_util::memory::MemoryProfilerChan;
use servo_util::opts;
use servo_util::time::{TimeProfilerCategory, profile, TimeProfilerChan};
use servo_util::{memory, time};
use std::collections::HashMap;
-use std::collections::hash_map::{Occupied, Vacant};
+use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::path::Path;
-use std::num::FloatMath;
+use std::num::Float;
use std::rc::Rc;
use std::slice::bytes::copy_memory;
+use std::sync::mpsc::Sender;
use time::{precise_time_ns, precise_time_s};
use url::Url;
/// NB: Never block on the constellation, because sometimes the constellation blocks on us.
pub struct IOCompositor<Window: WindowMethods> {
/// The application window.
window: Rc<Window>,
@@ -66,17 +67,17 @@ pub struct IOCompositor<Window: WindowMe
/// Tracks details about each active pipeline that the compositor knows about.
pipeline_details: HashMap<PipelineId, PipelineDetails>,
/// The canvas to paint a page.
scene: Scene<CompositorData>,
/// The application window size.
- window_size: TypedSize2D<DevicePixel, uint>,
+ window_size: TypedSize2D<DevicePixel, u32>,
/// "Mobile-style" zoom that does not reflow the page.
viewport_zoom: ScaleFactor<PagePx, ViewportPx, f32>,
/// "Desktop-style" zoom that resizes the viewport to fit the window.
/// See `ViewportPx` docs in util/geom.rs for details.
page_zoom: ScaleFactor<ViewportPx, ScreenPx, f32>,
@@ -129,24 +130,24 @@ pub struct IOCompositor<Window: WindowMe
pending_scroll_events: Vec<ScrollEvent>,
}
pub struct ScrollEvent {
delta: TypedPoint2D<DevicePixel,f32>,
cursor: TypedPoint2D<DevicePixel,i32>,
}
-#[deriving(PartialEq)]
+#[derive(PartialEq)]
enum CompositionRequest {
NoCompositingNecessary,
CompositeOnScrollTimeout(u64),
CompositeNow,
}
-#[deriving(Copy, PartialEq, Show)]
+#[derive(Copy, PartialEq, Show)]
enum ShutdownState {
NotShuttingDown,
ShuttingDown,
FinishedShuttingDown,
}
struct HitTestResult {
layer: Rc<Layer<CompositorData>>,
@@ -245,18 +246,18 @@ impl<Window: WindowMethods> IOCompositor
fn handle_browser_message(&mut self, msg: Msg) -> bool {
match (msg, self.shutdown_state) {
(_, ShutdownState::FinishedShuttingDown) =>
panic!("compositor shouldn't be handling messages after shutting down"),
(Msg::Exit(chan), _) => {
debug!("shutting down the constellation");
let ConstellationChan(ref con_chan) = self.constellation_chan;
- con_chan.send(ConstellationMsg::Exit);
- chan.send(());
+ con_chan.send(ConstellationMsg::Exit).unwrap();
+ chan.send(()).unwrap();
self.shutdown_state = ShutdownState::ShuttingDown;
}
(Msg::ShutdownComplete, _) => {
debug!("constellation completed shutdown");
self.shutdown_state = ShutdownState::FinishedShuttingDown;
return false;
}
@@ -287,36 +288,36 @@ impl<Window: WindowMethods> IOCompositor
response_chan,
new_constellation_chan);
self.send_viewport_rects_for_all_layers();
}
(Msg::ChangeLayerPipelineAndRemoveChildren(old_pipeline, new_pipeline, response_channel),
ShutdownState::NotShuttingDown) => {
self.handle_change_layer_pipeline_and_remove_children(old_pipeline, new_pipeline);
- response_channel.send(());
+ response_channel.send(()).unwrap();
}
(Msg::CreateRootLayerForPipeline(parent_pipeline, pipeline, rect, response_channel),
ShutdownState::NotShuttingDown) => {
self.handle_create_root_layer_for_pipeline(parent_pipeline, pipeline, rect);
- response_channel.send(());
+ response_channel.send(()).unwrap();
}
(Msg::CreateOrUpdateBaseLayer(layer_properties), ShutdownState::NotShuttingDown) => {
self.create_or_update_base_layer(layer_properties);
}
(Msg::CreateOrUpdateDescendantLayer(layer_properties),
ShutdownState::NotShuttingDown) => {
self.create_or_update_descendant_layer(layer_properties);
}
(Msg::GetGraphicsMetadata(chan), ShutdownState::NotShuttingDown) => {
- chan.send(Some(self.window.native_metadata()));
+ chan.send(Some(self.window.native_metadata())).unwrap();
}
(Msg::SetLayerOrigin(pipeline_id, layer_id, origin),
ShutdownState::NotShuttingDown) => {
self.set_layer_origin(pipeline_id, layer_id, origin);
}
(Msg::AssignPaintedBuffers(pipeline_id, epoch, replies), ShutdownState::NotShuttingDown) => {
@@ -414,22 +415,22 @@ impl<Window: WindowMethods> IOCompositor
return self.pipeline_details.get_mut(&pipeline_id).unwrap();
}
pub fn get_pipeline<'a>(&'a self, pipeline_id: PipelineId) -> &'a CompositionPipeline {
match self.pipeline_details.get(&pipeline_id) {
Some(ref details) => {
match details.pipeline {
Some(ref pipeline) => pipeline,
- None => panic!("Compositor layer has an unitialized pipeline ({}).",
+ None => panic!("Compositor layer has an unitialized pipeline ({:?}).",
pipeline_id),
}
}
- None => panic!("Compositor layer has an unknown pipeline ({}).", pipeline_id),
+ None => panic!("Compositor layer has an unknown pipeline ({:?}).", pipeline_id),
}
}
fn change_page_title(&mut self, _: PipelineId, title: Option<String>) {
self.window.set_page_title(title);
}
fn change_page_load_data(&mut self, _: FrameId, load_data: LoadData) {
@@ -454,17 +455,17 @@ impl<Window: WindowMethods> IOCompositor
self.has_paint_msg_tracking() && self.outstanding_paint_msgs > 0
}
fn add_outstanding_paint_msg(&mut self, count: uint) {
// return early if not tracking paint_msg's
if !self.has_paint_msg_tracking() {
return;
}
- debug!("add_outstanding_paint_msg {}", self.outstanding_paint_msgs);
+ debug!("add_outstanding_paint_msg {:?}", self.outstanding_paint_msgs);
self.outstanding_paint_msgs += count;
}
fn remove_outstanding_paint_msg(&mut self) {
if !self.has_paint_msg_tracking() {
return;
}
if self.outstanding_paint_msgs > 0 {
@@ -473,17 +474,17 @@ impl<Window: WindowMethods> IOCompositor
debug!("too many repaint msgs completed");
}
}
fn set_frame_tree(&mut self,
frame_tree: &SendableFrameTree,
response_chan: Sender<()>,
new_constellation_chan: ConstellationChan) {
- response_chan.send(());
+ response_chan.send(()).unwrap();
self.root_pipeline = Some(frame_tree.pipeline.clone());
// If we have an old root layer, release all old tiles before replacing it.
match self.scene.root {
Some(ref layer) => layer.clear_all_tiles(self),
None => { }
}
@@ -541,17 +542,18 @@ impl<Window: WindowMethods> IOCompositor
}
fn handle_change_layer_pipeline_and_remove_children(&mut self,
old_pipeline: CompositionPipeline,
new_pipeline: CompositionPipeline) {
let root_layer = match self.find_pipeline_root_layer(old_pipeline.id) {
Some(root_layer) => root_layer,
None => {
- debug!("Ignoring ChangeLayerPipelineAndRemoveChildren message for pipeline ({}) shutting down.",
+ debug!("Ignoring ChangeLayerPipelineAndRemoveChildren message \
+ for pipeline ({:?}) shutting down.",
old_pipeline.id);
return;
}
};
root_layer.clear_all_tiles(self);
root_layer.children().clear();
@@ -576,17 +578,18 @@ impl<Window: WindowMethods> IOCompositor
}
None => {}
}
let pipeline_id = parent_pipeline.id;
let parent_layer = match self.find_pipeline_root_layer(pipeline_id) {
Some(root_layer) => root_layer,
None => {
- debug!("Ignoring FrameTreeUpdate message for pipeline ({}) shutting down.",
+ debug!("Ignoring FrameTreeUpdate message for pipeline ({:?}) \
+ shutting down.",
pipeline_id);
return;
}
};
parent_layer.add_child(root_layer);
}
fn find_pipeline_root_layer(&self, pipeline_id: PipelineId) -> Option<Rc<Layer<CompositorData>>> {
@@ -606,17 +609,18 @@ impl<Window: WindowMethods> IOCompositor
}
}
fn create_or_update_base_layer(&mut self, layer_properties: LayerProperties) {
let pipeline_id = layer_properties.pipeline_id;
let root_layer = match self.find_pipeline_root_layer(pipeline_id) {
Some(root_layer) => root_layer,
None => {
- debug!("Ignoring CreateOrUpdateBaseLayer message for pipeline ({}) shutting down.",
+ debug!("Ignoring CreateOrUpdateBaseLayer message for pipeline \
+ ({:?}) shutting down.",
pipeline_id);
return;
}
};
let need_new_base_layer = !self.update_layer_if_exists(layer_properties);
if need_new_base_layer {
root_layer.update_layer_except_bounds(layer_properties);
@@ -664,17 +668,17 @@ impl<Window: WindowMethods> IOCompositor
let initial_viewport = self.window_size.as_f32() / dppx;
let visible_viewport = initial_viewport / self.viewport_zoom;
let ConstellationChan(ref chan) = self.constellation_chan;
chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
device_pixel_ratio: dppx,
initial_viewport: initial_viewport,
visible_viewport: visible_viewport,
- }));
+ })).unwrap()
}
pub fn move_layer(&self,
pipeline_id: PipelineId,
layer_id: LayerId,
origin: TypedPoint2D<LayerPixel, f32>)
-> bool {
match self.find_layer_with_pipeline_and_layer_id(pipeline_id, layer_id) {
@@ -718,17 +722,18 @@ impl<Window: WindowMethods> IOCompositor
fn set_layer_origin(&mut self,
pipeline_id: PipelineId,
layer_id: LayerId,
new_origin: Point2D<f32>) {
match self.find_layer_with_pipeline_and_layer_id(pipeline_id, layer_id) {
Some(ref layer) => {
layer.bounds.borrow_mut().origin = Point2D::from_untyped(&new_origin)
}
- None => panic!("Compositor received SetLayerOrigin for nonexistent layer: {}", pipeline_id),
+ None => panic!("Compositor received SetLayerOrigin for nonexistent \
+ layer: {:?}", pipeline_id),
};
self.send_buffer_requests_for_all_layers();
}
fn assign_painted_buffers(&mut self,
pipeline_id: PipelineId,
layer_id: LayerId,
@@ -739,24 +744,24 @@ impl<Window: WindowMethods> IOCompositor
self.assign_painted_buffers_to_layer(layer, new_layer_buffer_set, epoch);
return;
}
None => {}
}
let pipeline = self.get_pipeline(pipeline_id);
let message = PaintMsg::UnusedBuffer(new_layer_buffer_set.buffers);
- let _ = pipeline.paint_chan.send_opt(message);
+ let _ = pipeline.paint_chan.send(message);
}
fn assign_painted_buffers_to_layer(&mut self,
layer: Rc<Layer<CompositorData>>,
new_layer_buffer_set: Box<LayerBufferSet>,
epoch: Epoch) {
- debug!("compositor received new frame at size {}x{}",
+ debug!("compositor received new frame at size {:?}x{:?}",
self.window_size.width.get(),
self.window_size.height.get());
// From now on, if we destroy the buffers, they will leak.
let mut new_layer_buffer_set = new_layer_buffer_set;
new_layer_buffer_set.mark_will_leak();
// FIXME(pcwalton): This is going to cause problems with inconsistent frames since
@@ -824,24 +829,24 @@ impl<Window: WindowMethods> IOCompositor
WindowEvent::KeyEvent(key, state, modifiers) => {
self.on_key_event(key, state, modifiers);
}
WindowEvent::Quit => {
debug!("shutting down the constellation for WindowEvent::Quit");
let ConstellationChan(ref chan) = self.constellation_chan;
- chan.send(ConstellationMsg::Exit);
+ chan.send(ConstellationMsg::Exit).unwrap();
self.shutdown_state = ShutdownState::ShuttingDown;
}
}
}
- fn on_resize_window_event(&mut self, new_size: TypedSize2D<DevicePixel, uint>) {
- debug!("compositor resizing to {}", new_size.to_untyped());
+ fn on_resize_window_event(&mut self, new_size: TypedSize2D<DevicePixel, u32>) {
+ debug!("compositor resizing to {:?}", new_size.to_untyped());
// A size change could also mean a resolution change.
let new_hidpi_factor = self.window.hidpi_factor();
if self.hidpi_factor != new_hidpi_factor {
self.hidpi_factor = new_hidpi_factor;
self.update_zoom_transform();
}
@@ -862,17 +867,17 @@ impl<Window: WindowMethods> IOCompositor
Some(ref layer) => layer.get_pipeline_id(),
None => panic!("Compositor: Received WindowEvent::LoadUrl without initialized compositor \
layers"),
};
let msg = ConstellationMsg::LoadUrl(root_pipeline_id,
LoadData::new(Url::parse(url_string.as_slice()).unwrap()));
let ConstellationChan(ref chan) = self.constellation_chan;
- chan.send(msg);
+ chan.send(msg).unwrap()
}
fn on_mouse_window_event_class(&self, mouse_window_event: MouseWindowEvent) {
let point = match mouse_window_event {
MouseWindowEvent::Click(_, p) => p,
MouseWindowEvent::MouseDown(_, p) => p,
MouseWindowEvent::MouseUp(_, p) => p,
};
@@ -981,39 +986,39 @@ impl<Window: WindowMethods> IOCompositor
}
fn on_navigation_window_event(&self, direction: WindowNavigateMsg) {
let direction = match direction {
windowing::WindowNavigateMsg::Forward => NavigationDirection::Forward,
windowing::WindowNavigateMsg::Back => NavigationDirection::Back,
};
let ConstellationChan(ref chan) = self.constellation_chan;
- chan.send(ConstellationMsg::Navigate(direction))
+ chan.send(ConstellationMsg::Navigate(direction)).unwrap()
}
fn on_key_event(&self, key: Key, state: KeyState, modifiers: KeyModifiers) {
let ConstellationChan(ref chan) = self.constellation_chan;
- chan.send(ConstellationMsg::KeyEvent(key, state, modifiers))
+ chan.send(ConstellationMsg::KeyEvent(key, state, modifiers)).unwrap()
}
fn convert_buffer_requests_to_pipeline_requests_map(&self,
requests: Vec<(Rc<Layer<CompositorData>>,
Vec<BufferRequest>)>)
-> HashMap<PipelineId, Vec<PaintRequest>> {
let scale = self.device_pixels_per_page_px();
let mut results: HashMap<PipelineId, Vec<PaintRequest>> = HashMap::new();
for (layer, mut layer_requests) in requests.into_iter() {
let vec = match results.entry(layer.get_pipeline_id()) {
Occupied(mut entry) => {
*entry.get_mut() = Vec::new();
entry.into_mut()
}
Vacant(entry) => {
- entry.set(Vec::new())
+ entry.insert(Vec::new())
}
};
// All the BufferRequests are in layer/device coordinates, but the paint task
// wants to know the page coordinates. We scale them before sending them.
for request in layer_requests.iter_mut() {
request.page_rect = request.page_rect / scale.get();
}
@@ -1030,30 +1035,30 @@ impl<Window: WindowMethods> IOCompositor
}
fn send_back_unused_buffers(&mut self) {
match self.root_pipeline {
Some(ref pipeline) => {
let unused_buffers = self.scene.collect_unused_buffers();
if unused_buffers.len() != 0 {
let message = PaintMsg::UnusedBuffer(unused_buffers);
- let _ = pipeline.paint_chan.send_opt(message);
+ let _ = pipeline.paint_chan.send(message);
}
},
None => {}
}
}
fn send_viewport_rect_for_layer(&self, layer: Rc<Layer<CompositorData>>) {
if layer.extra_data.borrow().id == LayerId::null() {
let layer_rect = Rect(-layer.extra_data.borrow().scroll_offset.to_untyped(),
layer.bounds.borrow().size.to_untyped());
let pipeline = self.get_pipeline(layer.get_pipeline_id());
let ScriptControlChan(ref chan) = pipeline.script_chan;
- chan.send(ConstellationControlMsg::Viewport(pipeline.id.clone(), layer_rect));
+ chan.send(ConstellationControlMsg::Viewport(pipeline.id.clone(), layer_rect)).unwrap();
}
for kid in layer.children().iter() {
self.send_viewport_rect_for_layer(kid.clone());
}
}
fn send_viewport_rects_for_all_layers(&self) {
@@ -1079,17 +1084,17 @@ impl<Window: WindowMethods> IOCompositor
// We want to batch requests for each pipeline to avoid race conditions
// when handling the resulting BufferRequest responses.
let pipeline_requests =
self.convert_buffer_requests_to_pipeline_requests_map(layers_and_requests);
let mut num_paint_msgs_sent = 0;
for (pipeline_id, requests) in pipeline_requests.into_iter() {
num_paint_msgs_sent += 1;
- let _ = self.get_pipeline(pipeline_id).paint_chan.send_opt(PaintMsg::Paint(requests));
+ let _ = self.get_pipeline(pipeline_id).paint_chan.send(PaintMsg::Paint(requests));
}
self.add_outstanding_paint_msg(num_paint_msgs_sent);
true
}
fn is_ready_to_paint_image_output(&self) -> bool {
if !self.got_load_complete_message {
@@ -1120,17 +1125,17 @@ impl<Window: WindowMethods> IOCompositor
return
}
let output_image = opts::get().output_file.is_some() &&
self.is_ready_to_paint_image_output();
let mut framebuffer_ids = vec!();
let mut texture_ids = vec!();
- let (width, height) = (self.window_size.width.get(), self.window_size.height.get());
+ let (width, height) = (self.window_size.width.get() as usize, self.window_size.height.get() as usize);
if output_image {
framebuffer_ids = gl::gen_framebuffers(1);
gl::bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]);
texture_ids = gl::gen_textures(1);
gl::bind_texture(gl::TEXTURE_2D, texture_ids[0]);
@@ -1164,18 +1169,18 @@ impl<Window: WindowMethods> IOCompositor
}
}
}
None => {}
}
});
if output_image {
- let path =
- from_str::<Path>(opts::get().output_file.as_ref().unwrap().as_slice()).unwrap();
+ let path: Path =
+ opts::get().output_file.as_ref().unwrap().as_slice().parse().unwrap();
let mut pixels = gl::read_pixels(0, 0,
width as gl::GLsizei,
height as gl::GLsizei,
gl::RGB, gl::UNSIGNED_BYTE);
gl::bind_framebuffer(gl::FRAMEBUFFER, 0);
gl::delete_buffers(texture_ids.as_slice());
@@ -1196,17 +1201,17 @@ impl<Window: WindowMethods> IOCompositor
height: height as u32,
pixels: png::PixelsByColorType::RGB8(pixels),
};
let res = png::store_png(&mut img, &path);
assert!(res.is_ok());
debug!("shutting down the constellation after generating an output file");
let ConstellationChan(ref chan) = self.constellation_chan;
- chan.send(ConstellationMsg::Exit);
+ chan.send(ConstellationMsg::Exit).unwrap();
self.shutdown_state = ShutdownState::ShuttingDown;
}
// Perform the page flip. This will likely block for a while.
self.window.present();
self.last_composite_time = precise_time_ns();
@@ -1388,29 +1393,29 @@ impl<Window> CompositorEventListener for
}
// Drain compositor port, sometimes messages contain channels that are blocking
// another task from finishing (i.e. SetFrameTree).
while self.port.try_recv_compositor_msg().is_some() {}
// Tell the profiler, memory profiler, and scrolling timer to shut down.
let TimeProfilerChan(ref time_profiler_chan) = self.time_profiler_chan;
- time_profiler_chan.send(time::TimeProfilerMsg::Exit);
+ time_profiler_chan.send(time::TimeProfilerMsg::Exit).unwrap();
let MemoryProfilerChan(ref memory_profiler_chan) = self.memory_profiler_chan;
- memory_profiler_chan.send(memory::MemoryProfilerMsg::Exit);
+ memory_profiler_chan.send(memory::MemoryProfilerMsg::Exit).unwrap();
self.scrolling_timer.shutdown();
}
fn pinch_zoom_level(&self) -> f32 {
self.viewport_zoom.get() as f32
}
fn get_title_for_main_frame(&self) {
let root_pipeline_id = match self.root_pipeline {
None => return,
Some(ref root_pipeline) => root_pipeline.id,
};
let ConstellationChan(ref chan) = self.constellation_chan;
- chan.send(ConstellationMsg::GetPipelineTitle(root_pipeline_id));
+ chan.send(ConstellationMsg::GetPipelineTitle(root_pipeline_id)).unwrap();
}
}
--- a/servo/components/compositing/compositor_layer.rs
+++ b/servo/components/compositing/compositor_layer.rs
@@ -16,17 +16,16 @@ use gfx::paint_task::Msg as PaintMsg;
use layers::color::Color;
use layers::geometry::LayerPixel;
use layers::layers::{Layer, LayerBufferSet};
use script_traits::CompositorEvent::{ClickEvent, MouseDownEvent, MouseMoveEvent, MouseUpEvent};
use script_traits::{ScriptControlChan, ConstellationControlMsg};
use servo_msg::compositor_msg::{Epoch, LayerId, ScrollPolicy};
use servo_msg::constellation_msg::PipelineId;
use std::num::Float;
-use std::num::FloatMath;
use std::rc::Rc;
pub struct CompositorData {
/// This layer's pipeline id. The compositor can associate this id with an
/// actual CompositionPipeline.
pub pipeline_id: PipelineId,
/// The ID of this layer within the pipeline.
@@ -63,34 +62,35 @@ impl CompositorData {
Rc::new(Layer::new(Rect::from_untyped(&layer_properties.rect),
tile_size,
to_layers_color(&layer_properties.background_color),
new_compositor_data))
}
}
-pub trait CompositorLayer<Window: WindowMethods> {
+pub trait CompositorLayer {
fn update_layer_except_bounds(&self, layer_properties: LayerProperties);
fn update_layer(&self, layer_properties: LayerProperties);
- fn add_buffers(&self,
- compositor: &IOCompositor<Window>,
- new_buffers: Box<LayerBufferSet>,
- epoch: Epoch)
- -> bool;
+ fn add_buffers<Window>(&self,
+ compositor: &IOCompositor<Window>,
+ new_buffers: Box<LayerBufferSet>,
+ epoch: Epoch)
+ -> bool
+ where Window: WindowMethods;
/// Destroys all layer tiles, sending the buffers back to the painter to be destroyed or
/// reused.
- fn clear(&self, compositor: &IOCompositor<Window>);
+ fn clear<Window>(&self, compositor: &IOCompositor<Window>) where Window: WindowMethods;
/// Destroys tiles for this layer and all descendent layers, sending the buffers back to the
/// painter to be destroyed or reused.
- fn clear_all_tiles(&self, compositor: &IOCompositor<Window>);
+ fn clear_all_tiles<Window>(&self, compositor: &IOCompositor<Window>) where Window: WindowMethods;
/// Destroys all tiles of all layers, including children, *without* sending them back to the
/// painter. You must call this only when the paint task is destined to be going down;
/// otherwise, you will leak tiles.
///
/// This is used during shutdown, when we know the paint task is going away.
fn forget_all_tiles(&self);
@@ -102,41 +102,43 @@ pub trait CompositorLayer<Window: Window
fn handle_scroll_event(&self,
delta: TypedPoint2D<LayerPixel, f32>,
cursor: TypedPoint2D<LayerPixel, f32>)
-> ScrollEventResult;
// Takes in a MouseWindowEvent, determines if it should be passed to children, and
// sends the event off to the appropriate pipeline. NB: the cursor position is in
// page coordinates.
- fn send_mouse_event(&self,
- compositor: &IOCompositor<Window>,
- event: MouseWindowEvent,
- cursor: TypedPoint2D<LayerPixel, f32>);
+ fn send_mouse_event<Window>(&self,
+ compositor: &IOCompositor<Window>,
+ event: MouseWindowEvent,
+ cursor: TypedPoint2D<LayerPixel, f32>)
+ where Window: WindowMethods;
- fn send_mouse_move_event(&self,
- compositor: &IOCompositor<Window>,
- cursor: TypedPoint2D<LayerPixel, f32>);
+ fn send_mouse_move_event<Window>(&self,
+ compositor: &IOCompositor<Window>,
+ cursor: TypedPoint2D<LayerPixel, f32>)
+ where Window: WindowMethods;
fn clamp_scroll_offset_and_scroll_layer(&self,
new_offset: TypedPoint2D<LayerPixel, f32>)
-> ScrollEventResult;
fn scroll_layer_and_all_child_layers(&self,
new_offset: TypedPoint2D<LayerPixel, f32>)
-> bool;
/// Return a flag describing how this layer deals with scroll events.
fn wants_scroll_events(&self) -> WantsScrollEventsFlag;
/// Return the pipeline id associated with this layer.
fn get_pipeline_id(&self) -> PipelineId;
}
-#[deriving(Copy, PartialEq, Clone)]
+#[derive(Copy, PartialEq, Clone)]
pub enum WantsScrollEventsFlag {
WantsScrollEvents,
DoesntWantScrollEvents,
}
fn to_layers_color(color: &azure_hl::Color) -> Color {
Color { r: color.r, g: color.g, b: color.b, a: color.a }
}
@@ -162,24 +164,24 @@ impl Clampable for f32 {
fn calculate_content_size_for_layer(layer: &Layer<CompositorData>)
-> TypedSize2D<LayerPixel, f32> {
layer.children().iter().fold(Rect::zero(),
|unioned_rect, child_rect| {
unioned_rect.union(&*child_rect.bounds.borrow())
}).size
}
-#[deriving(PartialEq)]
+#[derive(PartialEq)]
pub enum ScrollEventResult {
ScrollEventUnhandled,
ScrollPositionChanged,
ScrollPositionUnchanged,
}
-impl<Window: WindowMethods> CompositorLayer<Window> for Layer<CompositorData> {
+impl CompositorLayer for Layer<CompositorData> {
fn update_layer_except_bounds(&self, layer_properties: LayerProperties) {
self.extra_data.borrow_mut().epoch = layer_properties.epoch;
self.extra_data.borrow_mut().scroll_policy = layer_properties.scroll_policy;
*self.background_color.borrow_mut() = to_layers_color(&layer_properties.background_color);
self.contents_changed();
}
@@ -194,63 +196,66 @@ impl<Window: WindowMethods> CompositorLa
}
// Add LayerBuffers to the specified layer. Returns the layer buffer set back if the layer that
// matches the given pipeline ID was not found; otherwise returns None and consumes the layer
// buffer set.
//
// If the epoch of the message does not match the layer's epoch, the message is ignored, the
// layer buffer set is consumed, and None is returned.
- fn add_buffers(&self,
- compositor: &IOCompositor<Window>,
- new_buffers: Box<LayerBufferSet>,
- epoch: Epoch)
- -> bool {
+ fn add_buffers<Window>(&self,
+ compositor: &IOCompositor<Window>,
+ new_buffers: Box<LayerBufferSet>,
+ epoch: Epoch)
+ -> bool
+ where Window: WindowMethods {
if self.extra_data.borrow().epoch != epoch {
- debug!("add_buffers: compositor epoch mismatch: {} != {}, id: {}",
+ debug!("add_buffers: compositor epoch mismatch: {:?} != {:?}, id: {:?}",
self.extra_data.borrow().epoch,
epoch,
self.get_pipeline_id());
let pipeline = compositor.get_pipeline(self.get_pipeline_id());
- let _ = pipeline.paint_chan.send_opt(PaintMsg::UnusedBuffer(new_buffers.buffers));
+ let _ = pipeline.paint_chan.send(PaintMsg::UnusedBuffer(new_buffers.buffers));
return false;
}
for buffer in new_buffers.buffers.into_iter().rev() {
self.add_buffer(buffer);
}
let unused_buffers = self.collect_unused_buffers();
if !unused_buffers.is_empty() { // send back unused buffers
let pipeline = compositor.get_pipeline(self.get_pipeline_id());
- let _ = pipeline.paint_chan.send_opt(PaintMsg::UnusedBuffer(unused_buffers));
+ let _ = pipeline.paint_chan.send(PaintMsg::UnusedBuffer(unused_buffers));
}
return true;
}
- fn clear(&self, compositor: &IOCompositor<Window>) {
+ fn clear<Window>(&self, compositor: &IOCompositor<Window>) where Window: WindowMethods {
let mut buffers = self.collect_buffers();
if !buffers.is_empty() {
// We have no way of knowing without a race whether the paint task is even up and
// running, but mark the buffers as not leaking. If the paint task died, then the
// buffers are going to be cleaned up.
for buffer in buffers.iter_mut() {
buffer.mark_wont_leak()
}
let pipeline = compositor.get_pipeline(self.get_pipeline_id());
- let _ = pipeline.paint_chan.send_opt(PaintMsg::UnusedBuffer(buffers));
+ let _ = pipeline.paint_chan.send(PaintMsg::UnusedBuffer(buffers));
}
}
/// Destroys tiles for this layer and all descendent layers, sending the buffers back to the
/// painter to be destroyed or reused.
- fn clear_all_tiles(&self, compositor: &IOCompositor<Window>) {
+ fn clear_all_tiles<Window>(&self,
+ compositor: &IOCompositor<Window>)
+ where Window: WindowMethods {
self.clear(compositor);
for kid in self.children().iter() {
kid.clear_all_tiles(compositor);
}
}
/// Destroys all tiles of all layers, including children, *without* sending them back to the
/// painter. You must call this only when the paint task is destined to be going down;
@@ -320,42 +325,44 @@ impl<Window: WindowMethods> CompositorLa
if result {
return ScrollEventResult::ScrollPositionChanged;
} else {
return ScrollEventResult::ScrollPositionUnchanged;
}
}
- fn send_mouse_event(&self,
- compositor: &IOCompositor<Window>,
- event: MouseWindowEvent,
- cursor: TypedPoint2D<LayerPixel, f32>) {
+ fn send_mouse_event<Window>(&self,
+ compositor: &IOCompositor<Window>,
+ event: MouseWindowEvent,
+ cursor: TypedPoint2D<LayerPixel, f32>)
+ where Window: WindowMethods {
let event_point = cursor.to_untyped();
let message = match event {
MouseWindowEvent::Click(button, _) =>
ClickEvent(button, event_point),
MouseWindowEvent::MouseDown(button, _) =>
MouseDownEvent(button, event_point),
MouseWindowEvent::MouseUp(button, _) =>
MouseUpEvent(button, event_point),
};
let pipeline = compositor.get_pipeline(self.get_pipeline_id());
let ScriptControlChan(ref chan) = pipeline.script_chan;
- let _ = chan.send_opt(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
+ let _ = chan.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
}
- fn send_mouse_move_event(&self,
- compositor: &IOCompositor<Window>,
- cursor: TypedPoint2D<LayerPixel, f32>) {
+ fn send_mouse_move_event<Window>(&self,
+ compositor: &IOCompositor<Window>,
+ cursor: TypedPoint2D<LayerPixel, f32>)
+ where Window: WindowMethods {
let message = MouseMoveEvent(cursor.to_untyped());
let pipeline = compositor.get_pipeline(self.get_pipeline_id());
let ScriptControlChan(ref chan) = pipeline.script_chan;
- let _ = chan.send_opt(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
+ let _ = chan.send(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message));
}
fn scroll_layer_and_all_child_layers(&self, new_offset: TypedPoint2D<LayerPixel, f32>)
-> bool {
let mut result = false;
// Only scroll this layer if it's not fixed-positioned.
if self.extra_data.borrow().scroll_policy != ScrollPolicy::FixedPosition {
--- a/servo/components/compositing/compositor_task.rs
+++ b/servo/components/compositing/compositor_task.rs
@@ -21,49 +21,49 @@ use pipeline::CompositionPipeline;
use servo_msg::compositor_msg::{Epoch, LayerId, LayerMetadata, ReadyState};
use servo_msg::compositor_msg::{PaintListener, PaintState, ScriptListener, ScrollPolicy};
use servo_msg::constellation_msg::{ConstellationChan, LoadData, PipelineId};
use servo_msg::constellation_msg::{Key, KeyState, KeyModifiers};
use servo_util::cursor::Cursor;
use servo_util::geometry::PagePx;
use servo_util::memory::MemoryProfilerChan;
use servo_util::time::TimeProfilerChan;
-use std::comm::{channel, Sender, Receiver};
+use std::sync::mpsc::{channel, Sender, Receiver};
use std::fmt::{Error, Formatter, Show};
use std::rc::Rc;
/// Sends messages to the compositor. This is a trait supplied by the port because the method used
/// to communicate with the compositor may have to kick OS event loops awake, communicate cross-
/// process, and so forth.
pub trait CompositorProxy : 'static + Send {
/// Sends a message to the compositor.
fn send(&mut self, msg: Msg);
/// Clones the compositor proxy.
fn clone_compositor_proxy(&self) -> Box<CompositorProxy+'static+Send>;
}
/// The port that the compositor receives messages on. As above, this is a trait supplied by the
/// Servo port.
-pub trait CompositorReceiver for Sized? : 'static {
+pub trait CompositorReceiver : 'static {
/// Receives the next message inbound for the compositor. This must not block.
fn try_recv_compositor_msg(&mut self) -> Option<Msg>;
/// Synchronously waits for, and returns, the next message inbound for the compositor.
fn recv_compositor_msg(&mut self) -> Msg;
}
/// A convenience implementation of `CompositorReceiver` for a plain old Rust `Receiver`.
impl CompositorReceiver for Receiver<Msg> {
fn try_recv_compositor_msg(&mut self) -> Option<Msg> {
match self.try_recv() {
Ok(msg) => Some(msg),
Err(_) => None,
}
}
fn recv_compositor_msg(&mut self) -> Msg {
- self.recv()
+ self.recv().unwrap()
}
}
/// Implementation of the abstract `ScriptListener` interface.
impl ScriptListener for Box<CompositorProxy+'static+Send> {
fn set_ready_state(&mut self, pipeline_id: PipelineId, ready_state: ReadyState) {
let msg = Msg::ChangeReadyState(pipeline_id, ready_state);
self.send(msg);
@@ -74,17 +74,17 @@ impl ScriptListener for Box<CompositorPr
layer_id: LayerId,
point: Point2D<f32>) {
self.send(Msg::ScrollFragmentPoint(pipeline_id, layer_id, point));
}
fn close(&mut self) {
let (chan, port) = channel();
self.send(Msg::Exit(chan));
- port.recv();
+ port.recv().unwrap();
}
fn dup(&mut self) -> Box<ScriptListener+'static> {
box self.clone_compositor_proxy() as Box<ScriptListener+'static>
}
fn set_title(&mut self, pipeline_id: PipelineId, title: Option<String>) {
self.send(Msg::ChangePageTitle(pipeline_id, title))
@@ -93,17 +93,17 @@ impl ScriptListener for Box<CompositorPr
fn send_key_event(&mut self, key: Key, state: KeyState, modifiers: KeyModifiers) {
if state == KeyState::Pressed {
self.send(Msg::KeyEvent(key, modifiers));
}
}
}
/// Information about each layer that the compositor keeps.
-#[deriving(Copy)]
+#[derive(Copy)]
pub struct LayerProperties {
pub pipeline_id: PipelineId,
pub epoch: Epoch,
pub id: LayerId,
pub rect: Rect<f32>,
pub background_color: Color,
pub scroll_policy: ScrollPolicy,
}
@@ -124,17 +124,17 @@ impl LayerProperties {
}
}
/// Implementation of the abstract `PaintListener` interface.
impl PaintListener for Box<CompositorProxy+'static+Send> {
fn get_graphics_metadata(&mut self) -> Option<NativeGraphicsMetadata> {
let (chan, port) = channel();
self.send(Msg::GetGraphicsMetadata(chan));
- port.recv()
+ port.recv().unwrap()
}
fn assign_painted_buffers(&mut self,
pipeline_id: PipelineId,
epoch: Epoch,
replies: Vec<(LayerId, Box<LayerBufferSet>)>) {
self.send(Msg::AssignPaintedBuffers(pipeline_id, epoch, replies));
}
--- a/servo/components/compositing/constellation.rs
+++ b/servo/components/compositing/constellation.rs
@@ -12,17 +12,17 @@ use geom::rect::{Rect, TypedRect};
use geom::scale_factor::ScaleFactor;
use gfx::font_cache_task::FontCacheTask;
use layers::geometry::DevicePixel;
use layout_traits::LayoutTaskFactory;
use libc;
use script_traits::{CompositorEvent, ConstellationControlMsg};
use script_traits::{ScriptControlChan, ScriptTaskFactory};
use servo_msg::compositor_msg::LayerId;
-use servo_msg::constellation_msg::{mod, ConstellationChan, Failure};
+use servo_msg::constellation_msg::{self, ConstellationChan, Failure};
use servo_msg::constellation_msg::{IFrameSandboxState, NavigationDirection};
use servo_msg::constellation_msg::{Key, KeyState, KeyModifiers};
use servo_msg::constellation_msg::{LoadData, NavigationType};
use servo_msg::constellation_msg::{PipelineExitType, PipelineId};
use servo_msg::constellation_msg::{SubpageId, WindowSizeData};
use servo_msg::constellation_msg::Msg as ConstellationMsg;
use servo_net::image_cache_task::{ImageCacheTask, ImageCacheTaskClient};
use servo_net::resource_task::ResourceTask;
@@ -34,16 +34,17 @@ use servo_util::opts;
use servo_util::task::spawn_named;
use servo_util::time::TimeProfilerChan;
use std::borrow::ToOwned;
use std::cell::{Cell, RefCell};
use std::collections::{HashMap, HashSet};
use std::io;
use std::mem::replace;
use std::rc::Rc;
+use std::sync::mpsc::{Receiver, channel};
use url::Url;
/// Maintains the pipelines and navigation context and grants permission to composite.
pub struct Constellation<LTF, STF> {
/// A channel through which messages can be sent to this object.
pub chan: ConstellationChan,
/// Receives messages.
@@ -86,17 +87,17 @@ pub struct Constellation<LTF, STF> {
/// A channel through which messages can be sent to the time profiler.
pub time_profiler_chan: TimeProfilerChan,
pub window_size: WindowSizeData,
}
/// A unique ID used to identify a frame.
-#[deriving(Copy)]
+#[derive(Copy)]
pub struct FrameId(u32);
/// One frame in the hierarchy.
struct FrameTree {
/// The ID of this frame.
pub id: FrameId,
/// The pipeline for this frame.
pub pipeline: RefCell<Rc<Pipeline>>,
@@ -120,17 +121,17 @@ impl FrameTree {
}
}
fn add_child(&self, new_child: ChildFrameTree) {
self.children.borrow_mut().push(new_child);
}
}
-#[deriving(Clone)]
+#[derive(Clone)]
struct ChildFrameTree {
frame_tree: Rc<FrameTree>,
/// Clipping rect representing the size and position, in page coordinates, of the visible
/// region of the child frame relative to the parent.
pub rect: Option<TypedRect<PagePx, f32>>,
}
impl ChildFrameTree {
@@ -229,17 +230,18 @@ impl ChildFrameTree {
/// An iterator over a frame tree, returning nodes in depth-first order.
/// Note that this iterator should _not_ be used to mutate nodes _during_
/// iteration. Mutating nodes once the iterator is out of scope is OK.
struct FrameTreeIterator {
stack: Vec<Rc<FrameTree>>,
}
-impl Iterator<Rc<FrameTree>> for FrameTreeIterator {
+impl Iterator for FrameTreeIterator {
+ type Item = Rc<FrameTree>;
fn next(&mut self) -> Option<Rc<FrameTree>> {
match self.stack.pop() {
Some(next) => {
for cft in next.children.borrow().iter() {
self.stack.push(cft.frame_tree.clone());
}
Some(next)
}
@@ -289,17 +291,17 @@ impl NavigationContext {
let next = self.next.pop().unwrap();
self.set_current(next.clone(), compositor_proxy);
next
}
/// Loads a new set of page frames, returning all evicted frame trees
fn load(&mut self, frame_tree: Rc<FrameTree>, compositor_proxy: &mut CompositorProxy)
-> Vec<Rc<FrameTree>> {
- debug!("navigating to {}", frame_tree.pipeline.borrow().id);
+ debug!("navigating to {:?}", frame_tree.pipeline.borrow().id);
let evicted = replace(&mut self.next, vec!());
match self.current.take() {
Some(current) => self.previous.push(current),
None => (),
}
self.set_current(frame_tree, compositor_proxy);
evicted
}
@@ -345,17 +347,17 @@ impl<LTF: LayoutTaskFactory, STF: Script
image_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
time_profiler_chan: TimeProfilerChan,
devtools_chan: Option<DevtoolsControlChan>,
storage_task: StorageTask)
-> ConstellationChan {
let (constellation_port, constellation_chan) = ConstellationChan::new();
let constellation_chan_clone = constellation_chan.clone();
- spawn_named("Constellation".to_owned(), proc() {
+ spawn_named("Constellation".to_owned(), move || {
let mut constellation: Constellation<LTF, STF> = Constellation {
chan: constellation_chan_clone,
request_port: constellation_port,
compositor_proxy: compositor_proxy,
devtools_chan: devtools_chan,
resource_task: resource_task,
image_cache_task: image_cache_task,
font_cache_task: font_cache_task,
@@ -375,17 +377,17 @@ impl<LTF: LayoutTaskFactory, STF: Script
};
constellation.run();
});
constellation_chan
}
fn run(&mut self) {
loop {
- let request = self.request_port.recv();
+ let request = self.request_port.recv().unwrap();
if !self.handle_request(request) {
break;
}
}
}
/// Helper function for creating a pipeline
fn new_pipeline(&mut self,
@@ -512,27 +514,27 @@ impl<LTF: LayoutTaskFactory, STF: Script
true
}
fn handle_exit(&mut self) {
for (_id, ref pipeline) in self.pipelines.iter() {
pipeline.exit(PipelineExitType::Complete);
}
self.image_cache_task.exit();
- self.resource_task.send(resource_task::ControlMsg::Exit);
+ self.resource_task.send(resource_task::ControlMsg::Exit).unwrap();
self.devtools_chan.as_ref().map(|chan| {
- chan.send(devtools_traits::ServerExitMsg);
+ chan.send(devtools_traits::ServerExitMsg).unwrap();
});
- self.storage_task.send(StorageTaskMsg::Exit);
+ self.storage_task.send(StorageTaskMsg::Exit).unwrap();
self.font_cache_task.exit();
self.compositor_proxy.send(CompositorMsg::ShutdownComplete);
}
fn handle_failure_msg(&mut self, pipeline_id: PipelineId, subpage_id: Option<SubpageId>) {
- debug!("handling failure message from pipeline {}, {}", pipeline_id, subpage_id);
+ debug!("handling failure message from pipeline {:?}, {:?}", pipeline_id, subpage_id);
if opts::get().hard_fail {
// It's quite difficult to make Servo exit cleanly if some tasks have failed.
// Hard fail exists for test runners so we crash and that's good enough.
let mut stderr = io::stderr();
stderr.write_str("Pipeline failed in hard-fail mode. Crashing!\n").unwrap();
stderr.flush().unwrap();
unsafe { libc::exit(1); }
@@ -599,21 +601,21 @@ impl<LTF: LayoutTaskFactory, STF: Script
self.browse(None,
Rc::new(FrameTree::new(next_frame_id, pipeline.clone(), None)),
NavigationType::Load);
self.pipelines.insert(pipeline.id, pipeline);
}
fn handle_frame_rect_msg(&mut self, pipeline_id: PipelineId, subpage_id: SubpageId,
rect: TypedRect<PagePx, f32>) {
- debug!("Received frame rect {} from {}, {}", rect, pipeline_id, subpage_id);
+ debug!("Received frame rect {:?} from {:?}, {:?}", rect, pipeline_id, subpage_id);
let mut already_sent = HashSet::new();
// Returns true if a child frame tree's subpage id matches the given subpage id
- let subpage_eq = |child_frame_tree: & &mut ChildFrameTree| {
+ let subpage_eq = |&:child_frame_tree: & &mut ChildFrameTree| {
child_frame_tree.frame_tree.pipeline.borrow().
subpage_id.expect("Constellation:
child frame does not have a subpage id. This should not be possible.")
== subpage_id
};
let frames = self.find_all(pipeline_id);
@@ -674,17 +676,17 @@ impl<LTF: LayoutTaskFactory, STF: Script
let pipeline = &*child_frame_tree.frame_tree.pipeline.borrow();
if !already_sent.contains(&pipeline.id) {
if is_active {
let ScriptControlChan(ref script_chan) = pipeline.script_chan;
script_chan.send(ConstellationControlMsg::Resize(pipeline.id, WindowSizeData {
visible_viewport: rect.size,
initial_viewport: rect.size * ScaleFactor(1.0),
device_pixel_ratio: device_pixel_ratio,
- }));
+ })).unwrap();
compositor_proxy.send(CompositorMsg::SetLayerOrigin(
pipeline.id,
LayerId::null(),
rect.to_untyped().origin));
} else {
already_sent.insert(pipeline.id);
}
};
@@ -692,17 +694,17 @@ impl<LTF: LayoutTaskFactory, STF: Script
}
fn update_child_pipeline(&mut self,
frame_tree: Rc<FrameTree>,
new_pipeline: Rc<Pipeline>,
old_subpage_id: SubpageId) {
let existing_tree = match frame_tree.find_with_subpage_id(Some(old_subpage_id)) {
Some(existing_tree) => existing_tree.clone(),
- None => panic!("Tried to update non-existing frame tree with pipeline={} subpage={}",
+ None => panic!("Tried to update non-existing frame tree with pipeline={:?} subpage={:?}",
new_pipeline.id,
old_subpage_id),
};
let old_pipeline = existing_tree.pipeline.borrow().clone();
*existing_tree.pipeline.borrow_mut() = new_pipeline.clone();
// If we have not yet sent this frame to the compositor for layer creation, we don't
@@ -711,17 +713,17 @@ impl<LTF: LayoutTaskFactory, STF: Script
return;
}
let (chan, port) = channel();
self.compositor_proxy.send(CompositorMsg::ChangeLayerPipelineAndRemoveChildren(
old_pipeline.to_sendable(),
new_pipeline.to_sendable(),
chan));
- let _ = port.recv_opt();
+ let _ = port.recv();
}
fn create_or_update_child_pipeline(&mut self,
frame_tree: Rc<FrameTree>,
new_pipeline: Rc<Pipeline>,
new_rect: Option<TypedRect<PagePx, f32>>,
old_subpage_id: Option<SubpageId>) {
match old_subpage_id {
@@ -765,20 +767,20 @@ impl<LTF: LayoutTaskFactory, STF: Script
let source_url = source_pipeline.load_data.url.clone();
let same_script = (source_url.host() == url.host() &&
source_url.port() == url.port()) &&
sandbox == IFrameSandboxState::IFrameUnsandboxed;
// FIXME(tkuehn): Need to follow the standardized spec for checking same-origin
// Reuse the script task if the URL is same-origin
let script_pipeline = if same_script {
- debug!("Constellation: loading same-origin iframe at {}", url);
+ debug!("Constellation: loading same-origin iframe at {:?}", url);
Some(source_pipeline.clone())
} else {
- debug!("Constellation: loading cross-origin iframe at {}", url);
+ debug!("Constellation: loading cross-origin iframe at {:?}", url);
None
};
let new_frame_pipeline_id = self.get_next_pipeline_id();
let pipeline = self.new_pipeline(
new_frame_pipeline_id,
Some(new_subpage_id),
script_pipeline,
@@ -796,17 +798,17 @@ impl<LTF: LayoutTaskFactory, STF: Script
}
fn handle_set_cursor_msg(&mut self, cursor: Cursor) {
self.compositor_proxy.send(CompositorMsg::SetCursor(cursor))
}
fn handle_load_url_msg(&mut self, source_id: PipelineId, load_data: LoadData) {
let url = load_data.url.to_string();
- debug!("Constellation: received message to load {}", url);
+ debug!("Constellation: received message to load {:?}", url);
// Make sure no pending page would be overridden.
let source_frame = self.current_frame().as_ref().unwrap().find(source_id).expect(
"Constellation: received a LoadUrl message from a pipeline_id associated
with a pipeline not in the active frame tree. This should be
impossible.");
for frame_change in self.pending_frames.iter() {
let old_id = frame_change.before.expect("Constellation: Received load msg
@@ -832,17 +834,17 @@ impl<LTF: LayoutTaskFactory, STF: Script
Rc::new(FrameTree::new(next_frame_id,
pipeline.clone(),
parent.borrow().clone())),
NavigationType::Load);
self.pipelines.insert(pipeline.id, pipeline);
}
fn handle_navigate_msg(&mut self, direction: constellation_msg::NavigationDirection) {
- debug!("received message to navigate {}", direction);
+ debug!("received message to navigate {:?}", direction);
// TODO(tkuehn): what is the "critical point" beyond which pending frames
// should not be cleared? Currently, the behavior is that forward/back
// navigation always has navigation priority, and after that new page loading is
// first come, first served.
let destination_frame = match direction {
NavigationDirection::Forward => {
if self.navigation_context.next.is_empty() {
@@ -881,32 +883,32 @@ impl<LTF: LayoutTaskFactory, STF: Script
self.current_frame().iter()
.any(|current_frame| current_frame.contains(pipeline_id))
}
fn handle_key_msg(&self, key: Key, state: KeyState, mods: KeyModifiers) {
self.current_frame().as_ref().map(|frame| {
let ScriptControlChan(ref chan) = frame.pipeline.borrow().script_chan;
chan.send(ConstellationControlMsg::SendEvent(
- frame.pipeline.borrow().id, CompositorEvent::KeyEvent(key, state, mods)));
+ frame.pipeline.borrow().id, CompositorEvent::KeyEvent(key, state, mods))).unwrap();
});
}
fn handle_get_pipeline_title_msg(&mut self, pipeline_id: PipelineId) {
match self.pipelines.get(&pipeline_id) {
None => self.compositor_proxy.send(CompositorMsg::ChangePageTitle(pipeline_id, None)),
Some(pipeline) => {
let ScriptControlChan(ref script_channel) = pipeline.script_chan;
- script_channel.send(ConstellationControlMsg::GetTitle(pipeline_id));
+ script_channel.send(ConstellationControlMsg::GetTitle(pipeline_id)).unwrap();
}
}
}
fn handle_painter_ready_msg(&mut self, pipeline_id: PipelineId) {
- debug!("Painter {} ready to send paint msg", pipeline_id);
+ debug!("Painter {:?} ready to send paint msg", pipeline_id);
// This message could originate from a pipeline in the navigation context or
// from a pending frame. The only time that we will grant paint permission is
// when the message originates from a pending frame or the current frame.
// Messages originating in the current frame are not navigations;
// they may come from a page load in a subframe.
if self.pipeline_is_in_current_frame(pipeline_id) {
self.create_compositor_layer_for_iframe_if_necessary(pipeline_id);
@@ -916,48 +918,48 @@ impl<LTF: LayoutTaskFactory, STF: Script
// Find the pending frame change whose new pipeline id is pipeline_id.
// If it is not found, it simply means that this pipeline will not receive
// permission to paint.
let pending_index = self.pending_frames.iter().rposition(|frame_change| {
frame_change.after.pipeline.borrow().id == pipeline_id
});
match pending_index {
Some(pending_index) => {
- let frame_change = self.pending_frames.swap_remove(pending_index).unwrap();
+ let frame_change = self.pending_frames.swap_remove(pending_index);
let to_add = frame_change.after.clone();
// Create the next frame tree that will be given to the compositor
let next_frame_tree = if to_add.parent.borrow().is_some() {
// NOTE: work around borrowchk issues
self.current_frame().as_ref().unwrap().clone()
} else {
to_add.clone()
};
// If there are frames to revoke permission from, do so now.
match frame_change.before {
Some(revoke_id) if self.current_frame().is_some() => {
- debug!("Constellation: revoking permission from {}", revoke_id);
+ debug!("Constellation: revoking permission from {:?}", revoke_id);
let current_frame = self.current_frame().as_ref().unwrap();
let to_revoke = current_frame.find(revoke_id).expect(
"Constellation: pending frame change refers to an old \
frame not contained in the current frame. This is a bug");
for frame in to_revoke.iter() {
frame.pipeline.borrow().revoke_paint_permission();
}
// If to_add is not the root frame, then replace revoked_frame with it.
// This conveniently keeps scissor rect size intact.
// NOTE: work around borrowchk issue
let mut flag = false;
{
if to_add.parent.borrow().is_some() {
- debug!("Constellation: replacing {} with {} in {}",
+ debug!("Constellation: replacing {:?} with {:?} in {:?}",
revoke_id, to_add.pipeline.borrow().id,
next_frame_tree.pipeline.borrow().id);
flag = true;
}
}
if flag {
next_frame_tree.replace_child(revoke_id, to_add);
}
@@ -989,39 +991,39 @@ impl<LTF: LayoutTaskFactory, STF: Script
/// Called when the window is resized.
fn handle_resized_window_msg(&mut self, new_size: WindowSizeData) {
let mut already_seen = HashSet::new();
for frame_tree in self.current_frame().iter() {
debug!("constellation sending resize message to active frame");
let pipeline = &*frame_tree.pipeline.borrow();;
let ScriptControlChan(ref chan) = pipeline.script_chan;
- let _ = chan.send_opt(ConstellationControlMsg::Resize(pipeline.id, new_size));
+ let _ = chan.send(ConstellationControlMsg::Resize(pipeline.id, new_size));
already_seen.insert(pipeline.id);
}
for frame_tree in self.navigation_context.previous.iter()
.chain(self.navigation_context.next.iter()) {
let pipeline = &*frame_tree.pipeline.borrow();
if !already_seen.contains(&pipeline.id) {
debug!("constellation sending resize message to inactive frame");
let ScriptControlChan(ref chan) = pipeline.script_chan;
- let _ = chan.send_opt(ConstellationControlMsg::ResizeInactive(pipeline.id, new_size));
+ let _ = chan.send(ConstellationControlMsg::ResizeInactive(pipeline.id, new_size));
already_seen.insert(pipeline.id);
}
}
// If there are any pending outermost frames, then tell them to resize. (This is how the
// initial window size gets sent to the first page loaded, giving it permission to reflow.)
for change in self.pending_frames.iter() {
let frame_tree = &change.after;
if frame_tree.parent.borrow().is_none() {
- debug!("constellation sending resize message to pending outer frame ({})",
+ debug!("constellation sending resize message to pending outer frame ({:?})",
frame_tree.pipeline.borrow().id);
let ScriptControlChan(ref chan) = frame_tree.pipeline.borrow().script_chan;
- let _ = chan.send_opt(ConstellationControlMsg::Resize(
+ let _ = chan.send(ConstellationControlMsg::Resize(
frame_tree.pipeline.borrow().id, new_size));
}
}
self.window_size = new_size;
}
// Close all pipelines at and beneath a given frame
@@ -1066,17 +1068,17 @@ impl<LTF: LayoutTaskFactory, STF: Script
// Grants a frame tree permission to paint; optionally updates navigation to reflect a new page
fn send_frame_tree_and_grant_paint_permission(&mut self, frame_tree: Rc<FrameTree>) {
debug!("Constellation sending SetFrameTree");
let (chan, port) = channel();
self.compositor_proxy.send(CompositorMsg::SetFrameTree(frame_tree.to_sendable(),
chan,
self.chan.clone()));
- if port.recv_opt().is_err() {
+ if port.recv().is_err() {
debug!("Compositor has discarded SetFrameTree");
return; // Our message has been discarded, probably shutting down.
}
let mut iter = frame_tree.iter();
for frame in iter {
frame.has_compositor_layer.set(true);
frame.pipeline.borrow().grant_paint_permission();
@@ -1121,17 +1123,17 @@ impl<LTF: LayoutTaskFactory, STF: Script
}
let (chan, port) = channel();
self.compositor_proxy.send(CompositorMsg::CreateRootLayerForPipeline(
parent.pipeline.borrow().to_sendable(),
child.frame_tree.pipeline.borrow().to_sendable(),
child.rect,
chan));
- match port.recv_opt() {
+ match port.recv() {
Ok(()) => {
child.frame_tree.has_compositor_layer.set(true);
child.frame_tree.pipeline.borrow().grant_paint_permission();
}
- Err(()) => {} // The message has been discarded, we are probably shutting down.
+ Err(_) => {} // The message has been discarded, we are probably shutting down.
}
}
}
--- a/servo/components/compositing/headless.rs
+++ b/servo/components/compositing/headless.rs
@@ -55,52 +55,52 @@ impl NullCompositor {
// Tell the constellation about the initial fake size.
{
let ConstellationChan(ref chan) = compositor.constellation_chan;
chan.send(ConstellationMsg::ResizedWindow(WindowSizeData {
initial_viewport: TypedSize2D(640_f32, 480_f32),
visible_viewport: TypedSize2D(640_f32, 480_f32),
device_pixel_ratio: ScaleFactor(1.0),
- }));
+ })).unwrap();
}
compositor
}
}
impl CompositorEventListener for NullCompositor {
fn handle_event(&mut self, _: WindowEvent) -> bool {
match self.port.recv_compositor_msg() {
Msg::Exit(chan) => {
debug!("shutting down the constellation");
let ConstellationChan(ref con_chan) = self.constellation_chan;
- con_chan.send(ConstellationMsg::Exit);
- chan.send(());
+ con_chan.send(ConstellationMsg::Exit).unwrap();
+ chan.send(()).unwrap();
}
Msg::ShutdownComplete => {
debug!("constellation completed shutdown");
return false
}
Msg::GetGraphicsMetadata(chan) => {
- chan.send(None);
+ chan.send(None).unwrap();
}
Msg::SetFrameTree(_, response_chan, _) => {
- response_chan.send(());
+ response_chan.send(()).unwrap();
}
Msg::ChangeLayerPipelineAndRemoveChildren(_, _, response_channel) => {
- response_channel.send(());
+ response_channel.send(()).unwrap();
}
Msg::CreateRootLayerForPipeline(_, _, _, response_channel) => {
- response_channel.send(());
+ response_channel.send(()).unwrap();
}
// Explicitly list ignored messages so that when we add a new one,
// we'll notice and think about whether it needs a response, like
// SetFrameTree.
Msg::CreateOrUpdateBaseLayer(..) |
Msg::CreateOrUpdateDescendantLayer(..) |
--- a/servo/components/compositing/lib.rs
+++ b/servo/components/compositing/lib.rs
@@ -1,32 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#![feature(globs, phase, macro_rules)]
+#![feature(box_syntax, plugin)]
+#![feature(int_uint)]
#![deny(unused_imports)]
#![deny(unused_variables)]
#![allow(missing_copy_implementations)]
+#![allow(unstable)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
extern crate azure;
extern crate devtools_traits;
extern crate geom;
extern crate gfx;
extern crate layers;
extern crate layout_traits;
extern crate png;
extern crate script_traits;
extern crate "msg" as servo_msg;
extern crate "net" as servo_net;
-#[phase(plugin, link)]
+#[macro_use]
extern crate "util" as servo_util;
extern crate gleam;
extern crate libc;
extern crate time;
extern crate url;
#[cfg(target_os="macos")]
--- a/servo/components/compositing/pipeline.rs
+++ b/servo/components/compositing/pipeline.rs
@@ -13,16 +13,17 @@ use gfx::paint_task::{PaintChan, PaintTa
use servo_msg::constellation_msg::{ConstellationChan, Failure, PipelineId, SubpageId};
use servo_msg::constellation_msg::{LoadData, WindowSizeData, PipelineExitType};
use servo_net::image_cache_task::ImageCacheTask;
use gfx::font_cache_task::FontCacheTask;
use servo_net::resource_task::ResourceTask;
use servo_net::storage_task::StorageTask;
use servo_util::time::TimeProfilerChan;
use std::rc::Rc;
+use std::sync::mpsc::{Receiver, channel};
/// A uniquely-identifiable pipeline of script task, layout task, and paint task.
pub struct Pipeline {
pub id: PipelineId,
pub subpage_id: Option<SubpageId>,
pub script_chan: ScriptControlChan,
pub layout_chan: LayoutControlChan,
pub paint_chan: PaintChan,
@@ -30,17 +31,17 @@ pub struct Pipeline {
pub paint_shutdown_port: Receiver<()>,
/// Load data corresponding to the most recently-loaded page.
pub load_data: LoadData,
/// The title of the most recently-loaded page.
pub title: Option<String>,
}
/// The subset of the pipeline that is needed for layer composition.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct CompositionPipeline {
pub id: PipelineId,
pub script_chan: ScriptControlChan,
pub paint_chan: PaintChan,
}
impl Pipeline {
/// Starts a paint task, layout task, and possibly a script task.
@@ -94,17 +95,17 @@ impl Pipeline {
let new_layout_info = NewLayoutInfo {
old_pipeline_id: spipe.id.clone(),
new_pipeline_id: id,
subpage_id: subpage_id.expect("script_pipeline != None but subpage_id == None"),
layout_chan: ScriptTaskFactory::clone_layout_channel(None::<&mut STF>, &layout_pair),
};
let ScriptControlChan(ref chan) = spipe.script_chan;
- chan.send(ConstellationControlMsg::AttachLayout(new_layout_info));
+ chan.send(ConstellationControlMsg::AttachLayout(new_layout_info)).unwrap();
spipe.script_chan.clone()
}
};
PaintTask::create(id,
paint_port,
compositor_proxy,
constellation_chan.clone(),
@@ -156,51 +157,52 @@ impl Pipeline {
paint_shutdown_port: paint_shutdown_port,
load_data: load_data,
title: None,
}
}
pub fn load(&self) {
let ScriptControlChan(ref chan) = self.script_chan;
- chan.send(ConstellationControlMsg::Load(self.id, self.load_data.clone()));
+ chan.send(ConstellationControlMsg::Load(self.id, self.load_data.clone())).unwrap();
}
pub fn grant_paint_permission(&self) {
- let _ = self.paint_chan.send_opt(PaintMsg::PaintPermissionGranted);
+ let _ = self.paint_chan.send(PaintMsg::PaintPermissionGranted);
}
pub fn revoke_paint_permission(&self) {
debug!("pipeline revoking paint channel paint permission");
- let _ = self.paint_chan.send_opt(PaintMsg::PaintPermissionRevoked);
+ let _ = self.paint_chan.send(PaintMsg::PaintPermissionRevoked);
}
pub fn exit(&self, exit_type: PipelineExitType) {
- debug!("pipeline {} exiting", self.id);
+ debug!("pipeline {:?} exiting", self.id);
// Script task handles shutting down layout, and layout handles shutting down the painter.
// For now, if the script task has failed, we give up on clean shutdown.
let ScriptControlChan(ref chan) = self.script_chan;
- if chan.send_opt(ConstellationControlMsg::ExitPipeline(self.id, exit_type)).is_ok() {
+ if chan.send(ConstellationControlMsg::ExitPipeline(self.id, exit_type)).is_ok() {
// Wait until all slave tasks have terminated and run destructors
// NOTE: We don't wait for script task as we don't always own it
- let _ = self.paint_shutdown_port.recv_opt();
- let _ = self.layout_shutdown_port.recv_opt();
+ let _ = self.paint_shutdown_port.recv();
+ let _ = self.layout_shutdown_port.recv();
}
}
pub fn force_exit(&self) {
let ScriptControlChan(ref script_channel) = self.script_chan;
- let _ = script_channel.send_opt(
+ let _ = script_channel.send(
ConstellationControlMsg::ExitPipeline(self.id,
- PipelineExitType::PipelineOnly));
- let _ = self.paint_chan.send_opt(PaintMsg::Exit(None, PipelineExitType::PipelineOnly));
+ PipelineExitType::PipelineOnly)).unwrap();
+ let _ = self.paint_chan.send(PaintMsg::Exit(None, PipelineExitType::PipelineOnly));
let LayoutControlChan(ref layout_channel) = self.layout_chan;
- let _ = layout_channel.send_opt(LayoutControlMsg::ExitNowMsg(PipelineExitType::PipelineOnly));
+ let _ = layout_channel.send(
+ LayoutControlMsg::ExitNowMsg(PipelineExitType::PipelineOnly)).unwrap();
}
pub fn to_sendable(&self) -> CompositionPipeline {
CompositionPipeline {
id: self.id.clone(),
script_chan: self.script_chan.clone(),
paint_chan: self.paint_chan.clone(),
}
--- a/servo/components/compositing/scrolling.rs
+++ b/servo/components/compositing/scrolling.rs
@@ -2,17 +2,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! A timer thread that gives the painting task a little time to catch up when the user scrolls.
use compositor_task::{CompositorProxy, Msg};
use std::io::timer;
-use std::task::TaskBuilder;
+use std::sync::mpsc::{Receiver, Sender, channel};
+use std::thread::Builder;
use std::time::duration::Duration;
use time;
/// The amount of time in nanoseconds that we give to the painting thread to paint new tiles upon
/// processing a scroll event that caused new tiles to be revealed. When this expires, we give up
/// and composite anyway (showing a "checkerboard") to avoid dropping the frame.
static TIMEOUT: i64 = 12_000_000;
@@ -28,41 +29,41 @@ pub struct ScrollingTimer {
enum ToScrollingTimerMsg {
ExitMsg,
ScrollEventProcessedMsg(u64),
}
impl ScrollingTimerProxy {
pub fn new(compositor_proxy: Box<CompositorProxy+Send>) -> ScrollingTimerProxy {
let (to_scrolling_timer_sender, to_scrolling_timer_receiver) = channel();
- TaskBuilder::new().spawn(proc() {
+ Builder::new().spawn(move || {
let mut scrolling_timer = ScrollingTimer {
compositor_proxy: compositor_proxy,
receiver: to_scrolling_timer_receiver,
};
scrolling_timer.run();
});
ScrollingTimerProxy {
sender: to_scrolling_timer_sender,
}
}
pub fn scroll_event_processed(&mut self, timestamp: u64) {
- self.sender.send(ToScrollingTimerMsg::ScrollEventProcessedMsg(timestamp))
+ self.sender.send(ToScrollingTimerMsg::ScrollEventProcessedMsg(timestamp)).unwrap()
}
pub fn shutdown(&mut self) {
- self.sender.send(ToScrollingTimerMsg::ExitMsg);
+ self.sender.send(ToScrollingTimerMsg::ExitMsg).unwrap()
}
}
impl ScrollingTimer {
pub fn run(&mut self) {
loop {
- match self.receiver.recv_opt() {
+ match self.receiver.recv() {
Ok(ToScrollingTimerMsg::ScrollEventProcessedMsg(timestamp)) => {
let target = timestamp as i64 + TIMEOUT;
let delta = target - (time::precise_time_ns() as i64);
timer::sleep(Duration::nanoseconds(delta));
self.compositor_proxy.send(Msg::ScrollTimeout(timestamp));
}
Ok(ToScrollingTimerMsg::ExitMsg) | Err(_) => break,
}
--- a/servo/components/compositing/windowing.rs
+++ b/servo/components/compositing/windowing.rs
@@ -13,47 +13,47 @@ use layers::geometry::DevicePixel;
use layers::platform::surface::NativeGraphicsMetadata;
use servo_msg::compositor_msg::{PaintState, ReadyState};
use servo_msg::constellation_msg::{Key, KeyState, KeyModifiers, LoadData};
use servo_util::cursor::Cursor;
use servo_util::geometry::ScreenPx;
use std::fmt::{Error, Formatter, Show};
use std::rc::Rc;
-#[deriving(Clone)]
+#[derive(Clone)]
pub enum MouseWindowEvent {
Click(uint, TypedPoint2D<DevicePixel, f32>),
MouseDown(uint, TypedPoint2D<DevicePixel, f32>),
MouseUp(uint, TypedPoint2D<DevicePixel, f32>),
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub enum WindowNavigateMsg {
Forward,
Back,
}
/// Events that the windowing system sends to Servo.
-#[deriving(Clone)]
+#[derive(Clone)]
pub enum WindowEvent {
/// Sent when no message has arrived, but the event loop was kicked for some reason (perhaps
/// by another Servo subsystem).
///
/// FIXME(pcwalton): This is kind of ugly and may not work well with multiprocess Servo.
/// It's possible that this should be something like
/// `CompositorMessageWindowEvent(compositor_task::Msg)` instead.
Idle,
/// Sent when part of the window is marked dirty and needs to be redrawn. Before sending this
/// message, the window must make the same GL context as in `PrepareRenderingEvent` current.
Refresh,
/// Sent to initialize the GL context. The windowing system must have a valid, current GL
/// context when this message is sent.
InitializeCompositing,
/// Sent when the window is resized.
- Resize(TypedSize2D<DevicePixel, uint>),
+ Resize(TypedSize2D<DevicePixel, u32>),
/// Sent when a new URL is to be loaded.
LoadUrl(String),
/// Sent when a mouse hit test is to be performed.
MouseWindowEventClass(MouseWindowEvent),
/// Sent when a mouse move.
MouseWindowMoveEventClass(TypedPoint2D<DevicePixel, f32>),
/// Sent when the user scrolls. The first point is the delta and the second point is the
/// origin.
@@ -87,17 +87,17 @@ impl Show for WindowEvent {
WindowEvent::Navigation(..) => write!(f, "Navigation"),
WindowEvent::Quit => write!(f, "Quit"),
}
}
}
pub trait WindowMethods {
/// Returns the size of the window in hardware pixels.
- fn framebuffer_size(&self) -> TypedSize2D<DevicePixel, uint>;
+ fn framebuffer_size(&self) -> TypedSize2D<DevicePixel, u32>;
/// Returns the size of the window in density-independent "px" units.
fn size(&self) -> TypedSize2D<ScreenPx, f32>;
/// Presents the window to the screen (perhaps by page flipping).
fn present(&self);
/// Sets the ready state of the current page.
fn set_ready_state(&self, ready_state: ReadyState);
/// Sets the paint state of the current page.
--- a/servo/components/devtools/actor.rs
+++ b/servo/components/devtools/actor.rs
@@ -1,75 +1,33 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/// General actor system infrastructure.
-use std::any::{Any, AnyRefExt, AnyMutRefExt};
+use std::any::Any;
use std::collections::HashMap;
use std::cell::{Cell, RefCell};
-use std::intrinsics::TypeId;
use std::io::TcpStream;
-use std::mem::{transmute, transmute_copy, replace};
-use std::raw::TraitObject;
+use std::mem::replace;
use serialize::json;
/// A common trait for all devtools actors that encompasses an immutable name
/// and the ability to process messages that are directed to particular actors.
/// TODO: ensure the name is immutable
pub trait Actor : Any {
fn handle_message(&self,
registry: &ActorRegistry,
msg_type: &String,
msg: &json::Object,
stream: &mut TcpStream) -> Result<bool, ()>;
fn name(&self) -> String;
}
-impl<'a> AnyMutRefExt<'a> for &'a mut (Actor + 'a) {
- fn downcast_mut<T: 'static>(self) -> Option<&'a mut T> {
- if self.is::<T>() {
- unsafe {
- // Get the raw representation of the trait object
- let to: TraitObject = transmute_copy(&self);
-
- // Extract the data pointer
- Some(transmute(to.data))
- }
- } else {
- None
- }
- }
-}
-
-impl<'a> AnyRefExt<'a> for &'a (Actor + 'a) {
- fn is<T: 'static>(self) -> bool {
- // This implementation is only needed so long as there's a Rust bug that
- // prevents downcast_ref from giving realistic return values.
- let t = TypeId::of::<T>();
- let boxed: TypeId = (*self).get_type_id();
- t == boxed
- }
-
- fn downcast_ref<T: 'static>(self) -> Option<&'a T> {
- if self.is::<T>() {
- unsafe {
- // Get the raw representation of the trait object
- let to: TraitObject = transmute_copy(&self);
-
- // Extract the data pointer
- Some(transmute(to.data))
- }
- } else {
- None
- }
- }
-}
-
/// A list of known, owned actors.
pub struct ActorRegistry {
actors: HashMap<String, Box<Actor+Send+Sized>>,
new_actors: RefCell<Vec<Box<Actor+Send+Sized>>>,
script_actors: RefCell<HashMap<String, String>>,
next: Cell<u32>,
}
@@ -125,30 +83,24 @@ impl ActorRegistry {
pub fn register_later(&self, actor: Box<Actor+Send+Sized>) {
let mut actors = self.new_actors.borrow_mut();
actors.push(actor);
}
/// Find an actor by registered name
pub fn find<'a, T: 'static>(&'a self, name: &str) -> &'a T {
- //FIXME: Rust bug forces us to implement bogus Any for Actor since downcast_ref currently
- // fails for unknown reasons.
- /*let actor: &Actor+Send+Sized = *self.actors.find(&name.to_string()).unwrap();
- (actor as &Any).downcast_ref::<T>().unwrap()*/
- self.actors.get(&name.to_string()).unwrap().downcast_ref::<T>().unwrap()
+ let actor: &Any = self.actors.get(&name.to_string()).unwrap();
+ actor.downcast_ref::<T>().unwrap()
}
/// Find an actor by registered name
pub fn find_mut<'a, T: 'static>(&'a mut self, name: &str) -> &'a mut T {
- //FIXME: Rust bug forces us to implement bogus Any for Actor since downcast_ref currently
- // fails for unknown reasons.
- /*let actor: &mut Actor+Send+Sized = *self.actors.find_mut(&name.to_string()).unwrap();
- (actor as &mut Any).downcast_mut::<T>().unwrap()*/
- self.actors.get_mut(&name.to_string()).unwrap().downcast_mut::<T>().unwrap()
+ let actor: &mut Any = self.actors.get_mut(&name.to_string()).unwrap();
+ actor.downcast_mut::<T>().unwrap()
}
/// Attempt to process a message as directed by its `to` property. If the actor is not
/// found or does not indicate that it knew how to process the message, ignore the failure.
pub fn handle_message(&mut self,
msg: &json::Object,
stream: &mut TcpStream)
-> Result<(), ()> {
--- a/servo/components/devtools/actors/console.rs
+++ b/servo/components/devtools/actors/console.rs
@@ -8,42 +8,43 @@
use actor::{Actor, ActorRegistry};
use protocol::JsonPacketStream;
use devtools_traits::{EvaluateJS, NullValue, VoidValue, NumberValue, StringValue, BooleanValue};
use devtools_traits::{ActorValue, DevtoolScriptControlMsg};
use servo_msg::constellation_msg::PipelineId;
-use collections::TreeMap;
+use collections::BTreeMap;
use core::cell::RefCell;
use serialize::json::{mod, Json, ToJson};
use std::io::TcpStream;
use std::num::Float;
+use std::sync::mpsc::{channel, Sender};
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct StartedListenersTraits {
customNetworkRequest: bool,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct StartedListenersReply {
from: String,
nativeConsoleAPI: bool,
startedListeners: Vec<String>,
traits: StartedListenersTraits,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
#[allow(dead_code)]
struct ConsoleAPIMessage {
_type: String, //FIXME: should this be __type__ instead?
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
#[allow(dead_code)]
struct PageErrorMessage {
_type: String, //FIXME: should this be __type__ instead?
errorMessage: String,
sourceName: String,
lineText: String,
lineNumber: uint,
columnNumber: uint,
@@ -51,52 +52,52 @@ struct PageErrorMessage {
timeStamp: uint,
warning: bool,
error: bool,
exception: bool,
strict: bool,
private: bool,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
#[allow(dead_code)]
struct LogMessage {
_type: String, //FIXME: should this be __type__ instead?
timeStamp: uint,
message: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
#[allow(dead_code)]
enum ConsoleMessageType {
ConsoleAPIType(ConsoleAPIMessage),
PageErrorType(PageErrorMessage),
LogMessageType(LogMessage),
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct GetCachedMessagesReply {
from: String,
messages: Vec<json::Object>,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct StopListenersReply {
from: String,
stoppedListeners: Vec<String>,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct AutocompleteReply {
from: String,
matches: Vec<String>,
matchProp: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct EvaluateJSReply {
from: String,
input: String,
result: Json,
timestamp: uint,
exception: Json,
exceptionMessage: String,
helperResult: Json,
@@ -215,75 +216,75 @@ impl Actor for ConsoleActor {
};
stream.write_json_packet(&msg);
true
}
"evaluateJS" => {
let input = msg.get(&"text".to_string()).unwrap().as_string().unwrap().to_string();
let (chan, port) = channel();
- self.script_chan.send(EvaluateJS(self.pipeline, input.clone(), chan));
+ self.script_chan.send(EvaluateJS(self.pipeline, input.clone(), chan)).unwrap();
//TODO: extract conversion into protocol module or some other useful place
- let result = match try!(port.recv_opt()) {
+ let result = match try!(port.recv().map_err(|_| ())) {
VoidValue => {
- let mut m = TreeMap::new();
+ let mut m = BTreeMap::new();
m.insert("type".to_string(), "undefined".to_string().to_json());
Json::Object(m)
}
NullValue => {
- let mut m = TreeMap::new();
+ let mut m = BTreeMap::new();
m.insert("type".to_string(), "null".to_string().to_json());
Json::Object(m)
}
BooleanValue(val) => val.to_json(),
NumberValue(val) => {
if val.is_nan() {
- let mut m = TreeMap::new();
+ let mut m = BTreeMap::new();
m.insert("type".to_string(), "NaN".to_string().to_json());
Json::Object(m)
} else if val.is_infinite() {
- let mut m = TreeMap::new();
+ let mut m = BTreeMap::new();
if val < 0. {
m.insert("type".to_string(), "-Infinity".to_string().to_json());
} else {
m.insert("type".to_string(), "Infinity".to_string().to_json());
}
Json::Object(m)
} else if val == Float::neg_zero() {
- let mut m = TreeMap::new();
+ let mut m = BTreeMap::new();
m.insert("type".to_string(), "-0".to_string().to_json());
Json::Object(m)
} else {
val.to_json()
}
}
StringValue(s) => s.to_json(),
ActorValue(s) => {
//TODO: make initial ActorValue message include these properties.
- let mut m = TreeMap::new();
+ let mut m = BTreeMap::new();
m.insert("type".to_string(), "object".to_string().to_json());
m.insert("class".to_string(), "???".to_string().to_json());
m.insert("actor".to_string(), s.to_json());
m.insert("extensible".to_string(), true.to_json());
m.insert("frozen".to_string(), false.to_json());
m.insert("sealed".to_string(), false.to_json());
Json::Object(m)
}
};
//TODO: catch and return exception values from JS evaluation
let msg = EvaluateJSReply {
from: self.name(),
input: input,
result: result,
timestamp: 0,
- exception: Json::Object(TreeMap::new()),
+ exception: Json::Object(BTreeMap::new()),
exceptionMessage: "".to_string(),
- helperResult: Json::Object(TreeMap::new()),
+ helperResult: Json::Object(BTreeMap::new()),
};
stream.write_json_packet(&msg);
true
}
_ => false
})
}
--- a/servo/components/devtools/actors/inspector.rs
+++ b/servo/components/devtools/actors/inspector.rs
@@ -5,59 +5,60 @@
/// Liberally derived from the [Firefox JS implementation](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/inspector.js).
use devtools_traits::{GetRootNode, GetDocumentElement, GetChildren, DevtoolScriptControlMsg};
use devtools_traits::{GetLayout, NodeInfo, ModifyAttribute};
use actor::{Actor, ActorRegistry};
use protocol::JsonPacketStream;
-use collections::TreeMap;
+use collections::BTreeMap;
use servo_msg::constellation_msg::PipelineId;
use serialize::json::{mod, Json, ToJson};
use std::cell::RefCell;
use std::io::TcpStream;
+use std::sync::mpsc::{channel, Sender};
use std::num::Float;
pub struct InspectorActor {
pub name: String,
pub walker: RefCell<Option<String>>,
pub pageStyle: RefCell<Option<String>>,
pub highlighter: RefCell<Option<String>>,
pub script_chan: Sender<DevtoolScriptControlMsg>,
pub pipeline: PipelineId,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct GetHighlighterReply {
highligter: HighlighterMsg, // sic.
from: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct HighlighterMsg {
actor: String,
}
struct HighlighterActor {
name: String,
}
pub struct NodeActor {
pub name: String,
script_chan: Sender<DevtoolScriptControlMsg>,
pipeline: PipelineId,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct ShowBoxModelReply {
from: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct HideBoxModelReply {
from: String,
}
impl Actor for HighlighterActor {
fn name(&self) -> String {
self.name.clone()
}
@@ -84,17 +85,17 @@ impl Actor for HighlighterActor {
true
}
_ => false,
})
}
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct ModifyAttributeReply{
from: String,
}
impl Actor for NodeActor {
fn name(&self) -> String {
self.name.clone()
}
@@ -109,49 +110,50 @@ impl Actor for NodeActor {
let target = msg.get(&"to".to_string()).unwrap().as_string().unwrap();
let mods = msg.get(&"modifications".to_string()).unwrap().as_array().unwrap();
let modifications = mods.iter().map(|json_mod| {
json::decode(json_mod.to_string().as_slice()).unwrap()
}).collect();
self.script_chan.send(ModifyAttribute(self.pipeline,
registry.actor_to_script(target.to_string()),
- modifications));
+ modifications))
+ .unwrap();
let reply = ModifyAttributeReply{
from: self.name(),
};
stream.write_json_packet(&reply);
true
}
_ => false,
})
}
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct GetWalkerReply {
from: String,
walker: WalkerMsg,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct WalkerMsg {
actor: String,
root: NodeActorMsg,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct AttrMsg {
namespace: String,
name: String,
value: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct NodeActorMsg {
actor: String,
baseURI: String,
parent: String,
nodeType: uint,
namespaceURI: String,
nodeName: String,
numChildren: uint,
@@ -238,33 +240,33 @@ impl NodeInfoToProtocol for NodeInfo {
}
struct WalkerActor {
name: String,
script_chan: Sender<DevtoolScriptControlMsg>,
pipeline: PipelineId,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct QuerySelectorReply {
from: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct DocumentElementReply {
from: String,
node: NodeActorMsg,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct ClearPseudoclassesReply {
from: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct ChildrenReply {
hasFirst: bool,
hasLast: bool,
nodes: Vec<NodeActorMsg>,
from: String,
}
impl Actor for WalkerActor {
@@ -283,18 +285,18 @@ impl Actor for WalkerActor {
from: self.name(),
};
stream.write_json_packet(&msg);
true
}
"documentElement" => {
let (tx, rx) = channel();
- self.script_chan.send(GetDocumentElement(self.pipeline, tx));
- let doc_elem_info = rx.recv();
+ self.script_chan.send(GetDocumentElement(self.pipeline, tx)).unwrap();
+ let doc_elem_info = rx.recv().unwrap();
let node = doc_elem_info.encode(registry, true, self.script_chan.clone(), self.pipeline);
let msg = DocumentElementReply {
from: self.name(),
node: node,
};
stream.write_json_packet(&msg);
true
@@ -308,18 +310,19 @@ impl Actor for WalkerActor {
true
}
"children" => {
let target = msg.get(&"node".to_string()).unwrap().as_string().unwrap();
let (tx, rx) = channel();
self.script_chan.send(GetChildren(self.pipeline,
registry.actor_to_script(target.to_string()),
- tx));
- let children = rx.recv();
+ tx))
+ .unwrap();
+ let children = rx.recv().unwrap();
let msg = ChildrenReply {
hasFirst: true,
hasLast: true,
nodes: children.into_iter().map(|child| {
child.encode(registry, true, self.script_chan.clone(), self.pipeline)
}).collect(),
from: self.name(),
@@ -328,87 +331,87 @@ impl Actor for WalkerActor {
true
}
_ => false,
})
}
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct GetPageStyleReply {
from: String,
pageStyle: PageStyleMsg,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct PageStyleMsg {
actor: String,
}
struct PageStyleActor {
name: String,
script_chan: Sender<DevtoolScriptControlMsg>,
pipeline: PipelineId,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct GetAppliedReply {
entries: Vec<AppliedEntry>,
rules: Vec<AppliedRule>,
sheets: Vec<AppliedSheet>,
from: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct GetComputedReply {
computed: Vec<uint>, //XXX all css props
from: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct AppliedEntry {
rule: String,
pseudoElement: Json,
isSystem: bool,
matchedSelectors: Vec<String>,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct AppliedRule {
actor: String,
__type__: uint,
href: String,
cssText: String,
line: uint,
column: uint,
parentStyleSheet: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct AppliedSheet {
actor: String,
href: String,
nodeHref: String,
disabled: bool,
title: String,
system: bool,
styleSheetIndex: int,
ruleCount: uint,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct GetLayoutReply {
width: int,
height: int,
autoMargins: Json,
from: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
#[allow(dead_code)]
struct AutoMargins {
top: String,
bottom: String,
left: String,
right: String,
}
@@ -445,30 +448,31 @@ impl Actor for PageStyleActor {
true
}
//TODO: query script for box layout properties of node (msg.node)
"getLayout" => {
let target = msg.get(&"node".to_string()).unwrap().as_string().unwrap();
let (tx, rx) = channel();
self.script_chan.send(GetLayout(self.pipeline,
- registry.actor_to_script(target.to_string()),
- tx));
- let (width, height) = rx.recv();
+ registry.actor_to_script(target.to_string()),
+ tx))
+ .unwrap();
+ let (width, height) = rx.recv().unwrap();
let auto_margins = msg.get(&"autoMargins".to_string()).unwrap().as_boolean().unwrap();
//TODO: the remaining layout properties (margin, border, padding, position)
// as specified in getLayout in http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/styles.js
let msg = GetLayoutReply {
width: width.round() as int,
height: height.round() as int,
autoMargins: if auto_margins {
//TODO: real values like processMargins in http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/styles.js
- let mut m = TreeMap::new();
+ let mut m = BTreeMap::new();
m.insert("top".to_string(), "auto".to_string().to_json());
m.insert("bottom".to_string(), "auto".to_string().to_json());
m.insert("left".to_string(), "auto".to_string().to_json());
m.insert("right".to_string(), "auto".to_string().to_json());
Json::Object(m)
} else {
Json::Null
},
@@ -502,18 +506,18 @@ impl Actor for InspectorActor {
pipeline: self.pipeline,
};
let mut walker_name = self.walker.borrow_mut();
*walker_name = Some(walker.name());
registry.register_later(box walker);
}
let (tx, rx) = channel();
- self.script_chan.send(GetRootNode(self.pipeline, tx));
- let root_info = rx.recv();
+ self.script_chan.send(GetRootNode(self.pipeline, tx)).unwrap();
+ let root_info = rx.recv().unwrap();
let node = root_info.encode(registry, false, self.script_chan.clone(), self.pipeline);
let msg = GetWalkerReply {
from: self.name(),
walker: WalkerMsg {
actor: self.walker.borrow().clone().unwrap(),
root: node,
--- a/servo/components/devtools/actors/root.rs
+++ b/servo/components/devtools/actors/root.rs
@@ -8,38 +8,38 @@
use actor::{Actor, ActorRegistry};
use actors::tab::{TabActor, TabActorMsg};
use protocol::JsonPacketStream;
use serialize::json;
use std::io::TcpStream;
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct ActorTraits {
sources: bool,
highlightable: bool,
customHighlighters: Vec<String>,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct ErrorReply {
from: String,
error: String,
message: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct ListTabsReply {
from: String,
selected: uint,
tabs: Vec<TabActorMsg>,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct RootActorMsg {
from: String,
applicationType: String,
traits: ActorTraits,
}
pub struct RootActor {
pub tabs: Vec<String>,
--- a/servo/components/devtools/actors/tab.rs
+++ b/servo/components/devtools/actors/tab.rs
@@ -8,55 +8,55 @@
use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use protocol::JsonPacketStream;
use serialize::json;
use std::io::TcpStream;
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct TabTraits;
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct TabAttachedReply {
from: String,
__type__: String,
threadActor: String,
cacheDisabled: bool,
javascriptEnabled: bool,
traits: TabTraits,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct TabDetachedReply {
from: String,
__type__: String,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct ReconfigureReply {
from: String
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct ListFramesReply {
from: String,
frames: Vec<FrameMsg>,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct FrameMsg {
id: uint,
url: String,
title: String,
parentID: uint,
}
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
pub struct TabActorMsg {
actor: String,
title: String,
url: String,
outerWindowID: uint,
consoleActor: String,
inspectorActor: String,
}
--- a/servo/components/devtools/lib.rs
+++ b/servo/components/devtools/lib.rs
@@ -5,27 +5,29 @@
//! An actor-based remote devtools server implementation. Only tested with
//! nightly Firefox versions at time of writing. Largely based on
//! reverse-engineering of Firefox chrome devtool logs and reading of
//! [code](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/).
#![crate_name = "devtools"]
#![crate_type = "rlib"]
+#![feature(int_uint, box_syntax)]
+
#![allow(non_snake_case)]
#![allow(missing_copy_implementations)]
+#![allow(unstable)]
-#![feature(phase)]
-
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
extern crate collections;
extern crate core;
extern crate devtools_traits;
+extern crate "serialize" as rustc_serialize;
extern crate serialize;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;
use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use actors::inspector::InspectorActor;
use actors::root::RootActor;
@@ -34,36 +36,36 @@ use protocol::JsonPacketStream;
use devtools_traits::{ServerExitMsg, DevtoolsControlMsg, NewGlobal, DevtoolScriptControlMsg, DevtoolsPageInfo};
use servo_msg::constellation_msg::PipelineId;
use servo_util::task::spawn_named;
use std::borrow::ToOwned;
use std::cell::RefCell;
use std::collections::HashMap;
-use std::comm;
-use std::comm::{Disconnected, Empty};
+use std::sync::mpsc::{channel, Receiver, Sender};
+use std::sync::mpsc::TryRecvError::{Disconnected, Empty};
use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener, TimedOut};
use std::sync::{Arc, Mutex};
mod actor;
/// Corresponds to http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/
mod actors {
pub mod console;
pub mod inspector;
pub mod root;
pub mod tab;
}
mod protocol;
/// Spin up a devtools server that listens for connections on the specified port.
pub fn start_server(port: u16) -> Sender<DevtoolsControlMsg> {
- let (sender, receiver) = comm::channel();
- spawn_named("Devtools".to_owned(), proc() {
+ let (sender, receiver) = channel();
+ spawn_named("Devtools".to_owned(), move || {
run_server(receiver, port)
});
sender
}
static POLL_TIMEOUT: u64 = 300;
fn run_server(receiver: Receiver<DevtoolsControlMsg>, port: u16) {
@@ -87,26 +89,27 @@ fn run_server(receiver: Receiver<Devtool
let mut accepted_connections: Vec<TcpStream> = Vec::new();
let mut actor_pipelines: HashMap<PipelineId, String> = HashMap::new();
/// Process the input from a single devtools client until EOF.
fn handle_client(actors: Arc<Mutex<ActorRegistry>>, mut stream: TcpStream) {
println!("connection established to {}", stream.peer_name().unwrap());
{
- let actors = actors.lock();
+ let actors = actors.lock().unwrap();
let msg = actors.find::<RootActor>("root").encodable();
stream.write_json_packet(&msg);
}
'outer: loop {
match stream.read_json_packet() {
Ok(json_packet) => {
- match actors.lock().handle_message(json_packet.as_object().unwrap(),
- &mut stream) {
+ let mut actors = actors.lock().unwrap();
+ match actors.handle_message(json_packet.as_object().unwrap(),
+ &mut stream) {
Ok(()) => {},
Err(()) => {
println!("error: devtools actor stopped responding");
let _ = stream.close_read();
let _ = stream.close_write();
break 'outer
}
}
@@ -122,17 +125,17 @@ fn run_server(receiver: Receiver<Devtool
// We need separate actor representations for each script global that exists;
// clients can theoretically connect to multiple globals simultaneously.
// TODO: move this into the root or tab modules?
fn handle_new_global(actors: Arc<Mutex<ActorRegistry>>,
pipeline: PipelineId,
sender: Sender<DevtoolScriptControlMsg>,
actor_pipelines: &mut HashMap<PipelineId, String>,
page_info: DevtoolsPageInfo) {
- let mut actors = actors.lock();
+ let mut actors = actors.lock().unwrap();
//TODO: move all this actor creation into a constructor method on TabActor
let (tab, console, inspector) = {
let console = ConsoleActor {
name: actors.new_name("console"),
script_chan: sender.clone(),
pipeline: pipeline,
streams: RefCell::new(Vec::new()),
@@ -180,17 +183,17 @@ fn run_server(receiver: Receiver<Devtool
Ok(NewGlobal(id, sender, pageinfo)) => handle_new_global(actors.clone(), id, sender, &mut actor_pipelines, pageinfo),
Err(Empty) => acceptor.set_timeout(Some(POLL_TIMEOUT)),
}
}
Err(_e) => { /* connection failed */ }
Ok(stream) => {
let actors = actors.clone();
accepted_connections.push(stream.clone());
- spawn_named("DevtoolsClientHandler".to_owned(), proc() {
+ spawn_named("DevtoolsClientHandler".to_owned(), move || {
// connection succeeded
handle_client(actors, stream.clone())
})
}
}
}
for connection in accepted_connections.iter_mut() {
--- a/servo/components/devtools/protocol.rs
+++ b/servo/components/devtools/protocol.rs
@@ -7,22 +7,22 @@
//! (https://wiki.mozilla.org/Remote_Debugging_Protocol_Stream_Transport#JSON_Packets).
use serialize::{json, Encodable};
use serialize::json::Json;
use std::io::{IoError, OtherIoError, EndOfFile, TcpStream, IoResult};
use std::num;
pub trait JsonPacketStream {
- fn write_json_packet<'a, T: Encodable<json::Encoder<'a>,IoError>>(&mut self, obj: &T);
+ fn write_json_packet<'a, T: Encodable>(&mut self, obj: &T);
fn read_json_packet(&mut self) -> IoResult<Json>;
}
impl JsonPacketStream for TcpStream {
- fn write_json_packet<'a, T: Encodable<json::Encoder<'a>,IoError>>(&mut self, obj: &T) {
+ fn write_json_packet<'a, T: Encodable>(&mut self, obj: &T) {
let s = json::encode(obj).replace("__type__", "type");
println!("<- {}", s);
self.write_str(s.len().to_string().as_slice()).unwrap();
self.write_u8(':' as u8).unwrap();
self.write_str(s.as_slice()).unwrap();
}
fn read_json_packet<'a>(&mut self) -> IoResult<Json> {
--- a/servo/components/devtools_traits/lib.rs
+++ b/servo/components/devtools_traits/lib.rs
@@ -4,34 +4,37 @@
//! This module contains shared types and messages for use by devtools/script.
//! The traits are here instead of in script so that the devtools crate can be
//! modified independently of the rest of Servo.
#![crate_name = "devtools_traits"]
#![crate_type = "rlib"]
+#![feature(int_uint)]
+
#![allow(non_snake_case)]
#![allow(missing_copy_implementations)]
-#![feature(globs)]
extern crate "msg" as servo_msg;
extern crate serialize;
extern crate url;
extern crate "util" as servo_util;
pub use self::DevtoolsControlMsg::*;
pub use self::DevtoolScriptControlMsg::*;
pub use self::EvaluateJSReply::*;
use serialize::{Decodable, Decoder};
use servo_msg::constellation_msg::PipelineId;
use servo_util::str::DOMString;
use url::Url;
+use std::sync::mpsc::{Sender, Receiver};
+
pub type DevtoolsControlChan = Sender<DevtoolsControlMsg>;
pub type DevtoolsControlPort = Receiver<DevtoolScriptControlMsg>;
// Information would be attached to NewGlobal to be received and show in devtools.
// Extend these fields if we need more information.
pub struct DevtoolsPageInfo {
pub title: DOMString,
pub url: Url
@@ -94,24 +97,24 @@ pub enum DevtoolScriptControlMsg {
/// Messages to instruct devtools server to update its state relating to a particular
/// tab.
pub enum ScriptDevtoolControlMsg {
/// Report a new JS error message
ReportConsoleMsg(String),
}
-#[deriving(Encodable)]
+#[derive(Encodable)]
pub struct Modification{
pub attributeName: String,
pub newValue: Option<String>,
}
-impl<D:Decoder<E>, E> Decodable<D, E> for Modification {
- fn decode(d: &mut D) -> Result<Modification, E> {
+impl Decodable for Modification {
+ fn decode<D: Decoder>(d: &mut D) -> Result<Modification, D::Error> {
d.read_struct("Modification", 2u, |d|
Ok(Modification {
attributeName: try!(d.read_struct_field("attributeName", 0u, |d| Decodable::decode(d))),
newValue: match d.read_struct_field("newValue", 1u, |d| Decodable::decode(d)) {
Ok(opt) => opt,
Err(_) => None
}
})
--- a/servo/components/gfx/Cargo.toml
+++ b/servo/components/gfx/Cargo.toml
@@ -33,19 +33,16 @@ git = "https://github.com/servo/rust-geo
git = "https://github.com/servo/rust-layers"
[dependencies.stb_image]
git = "https://github.com/servo/rust-stb-image"
[dependencies.png]
git = "https://github.com/servo/rust-png"
-[dependencies.url]
-git = "https://github.com/servo/rust-url"
-
[dependencies.harfbuzz]
git = "https://github.com/servo/rust-harfbuzz"
[dependencies.fontconfig]
git = "https://github.com/servo/rust-fontconfig"
[dependencies.freetype]
git = "https://github.com/servo/rust-freetype"
@@ -57,10 +54,11 @@ git = "https://github.com/servo/rust-cor
git = "https://github.com/servo/rust-core-graphics"
[dependencies.core_text]
git = "https://github.com/servo/rust-core-text"
[dependencies.script_traits]
path = "../script_traits"
-[dependencies.time]
-git = "https://github.com/rust-lang/time"
+[dependencies]
+url = "*"
+time = "*"
\ No newline at end of file
--- a/servo/components/gfx/buffer_map.rs
+++ b/servo/components/gfx/buffer_map.rs
@@ -1,19 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::collections::HashMap;
-use std::collections::hash_map::{Occupied, Vacant};
+use std::collections::hash_map::Entry::{Occupied, Vacant};
use geom::size::Size2D;
use layers::platform::surface::NativePaintingGraphicsContext;
use layers::layers::LayerBuffer;
-use std::hash::Hash;
-use std::hash::sip::SipState;
+use std::hash::{Hash, Hasher, Writer};
use std::mem;
/// This is a struct used to store buffers when they are not in use.
/// The paint task can quickly query for a particular size of buffer when it
/// needs it.
pub struct BufferMap {
/// A HashMap that stores the Buffers.
map: HashMap<BufferKey, BufferValue>,
@@ -22,21 +21,21 @@ pub struct BufferMap {
/// The maximum allowed memory. Unused buffers will be deleted
/// when this threshold is exceeded.
max_mem: uint,
/// A monotonically increasing counter to track how recently tile sizes were used.
counter: uint,
}
/// A key with which to store buffers. It is based on the size of the buffer.
-#[deriving(Eq, Copy)]
-struct BufferKey([uint, ..2]);
+#[derive(Eq, Copy)]
+struct BufferKey([uint; 2]);
-impl Hash for BufferKey {
- fn hash(&self, state: &mut SipState) {
+impl<H: Hasher+Writer> Hash<H> for BufferKey {
+ fn hash(&self, state: &mut H) {
let BufferKey(ref bytes) = *self;
bytes.as_slice().hash(state);
}
}
impl PartialEq for BufferKey {
fn eq(&self, other: &BufferKey) -> bool {
let BufferKey(s) = *self;
@@ -86,17 +85,17 @@ impl BufferMap {
self.mem += new_buffer.get_mem();
// use lazy insertion function to prevent unnecessary allocation
let counter = &self.counter;
match self.map.entry(new_key) {
Occupied(entry) => {
entry.into_mut().buffers.push(new_buffer);
}
Vacant(entry) => {
- entry.set(BufferValue {
+ entry.insert(BufferValue {
buffers: vec!(new_buffer),
last_action: *counter,
});
}
}
let mut opt_key: Option<BufferKey> = None;
while self.mem > self.max_mem {
--- a/servo/components/gfx/display_list/mod.rs
+++ b/servo/components/gfx/display_list/mod.rs
@@ -33,17 +33,17 @@ use paint_task::PaintLayer;
use servo_msg::compositor_msg::LayerId;
use servo_net::image::base::Image;
use servo_util::cursor::Cursor;
use servo_util::dlist as servo_dlist;
use servo_util::geometry::{mod, Au, MAX_RECT, ZERO_RECT};
use servo_util::range::Range;
use servo_util::smallvec::{SmallVec, SmallVec8};
use std::fmt;
-use std::slice::Items;
+use std::slice::Iter;
use std::sync::Arc;
use style::ComputedValues;
use style::computed_values::{border_style, cursor, filter, mix_blend_mode, pointer_events};
// It seems cleaner to have layout code not mention Azure directly, so let's just reexport this for
// layout to use.
pub use azure::azure_hl::GradientStop;
@@ -55,17 +55,17 @@ pub mod optimizer;
pub static BOX_SHADOW_INFLATION_FACTOR: i32 = 3;
/// An opaque handle to a node. The only safe operation that can be performed on this node is to
/// compare it to another opaque handle or to another node.
///
/// Because the script task's GC does not trace layout, node data cannot be safely stored in layout
/// data structures. Also, layout code tends to be faster when the DOM is not being accessed, for
/// locality reasons. Using `OpaqueNode` enforces this invariant.
-#[deriving(Clone, PartialEq, Copy)]
+#[derive(Clone, PartialEq, Copy)]
pub struct OpaqueNode(pub uintptr_t);
impl OpaqueNode {
/// Returns the address of this node, for debugging purposes.
pub fn id(&self) -> uintptr_t {
let OpaqueNode(pointer) = *self;
pointer
}
@@ -351,17 +351,17 @@ impl StackingContext {
pub fn hit_test(&self,
point: Point2D<Au>,
result: &mut Vec<DisplayItemMetadata>,
topmost_only: bool) {
fn hit_test_in_list<'a,I>(point: Point2D<Au>,
result: &mut Vec<DisplayItemMetadata>,
topmost_only: bool,
mut iterator: I)
- where I: Iterator<&'a DisplayItem> {
+ where I: Iterator<Item=&'a DisplayItem> {
for item in iterator {
// TODO(pcwalton): Use a precise algorithm here. This will allow us to properly hit
// test elements with `border-radius`, for example.
if !item.base().clip.might_intersect_point(&point) {
// Clipped out.
continue
}
if !geometry::rect_contains_point(item.bounds(), point) {
@@ -468,29 +468,29 @@ pub fn find_stacking_context_with_layer_
None => {}
}
}
None
}
/// One drawing command in the list.
-#[deriving(Clone)]
+#[derive(Clone)]
pub enum DisplayItem {
SolidColorClass(Box<SolidColorDisplayItem>),
TextClass(Box<TextDisplayItem>),
ImageClass(Box<ImageDisplayItem>),
BorderClass(Box<BorderDisplayItem>),
GradientClass(Box<GradientDisplayItem>),
LineClass(Box<LineDisplayItem>),
BoxShadowClass(Box<BoxShadowDisplayItem>),
}
/// Information common to all display items.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct BaseDisplayItem {
/// The boundaries of the display item, in layer coordinates.
pub bounds: Rect<Au>,
/// Metadata attached to this display item.
pub metadata: DisplayItemMetadata,
/// The region to clip to.
@@ -507,31 +507,31 @@ impl BaseDisplayItem {
clip: clip,
}
}
}
/// A clipping region for a display item. Currently, this can describe rectangles, rounded
/// rectangles (for `border-radius`), or arbitrary intersections of the two. Arbitrary transforms
/// are not supported because those are handled by the higher-level `StackingContext` abstraction.
-#[deriving(Clone, PartialEq, Show)]
+#[derive(Clone, PartialEq, Show)]
pub struct ClippingRegion {
/// The main rectangular region. This does not include any corners.
pub main: Rect<Au>,
/// Any complex regions.
///
/// TODO(pcwalton): Atomically reference count these? Not sure if it's worth the trouble.
/// Measure and follow up.
pub complex: Vec<ComplexClippingRegion>,
}
/// A complex clipping region. These don't as easily admit arbitrary intersection operations, so
/// they're stored in a list over to the side. Currently a complex clipping region is just a
/// rounded rectangle, but the CSS WGs will probably make us throw more stuff in here eventually.
-#[deriving(Clone, PartialEq, Show)]
+#[derive(Clone, PartialEq, Show)]
pub struct ComplexClippingRegion {
/// The boundaries of the rectangle.
pub rect: Rect<Au>,
/// Border radii of this rectangle.
pub radii: BorderRadii<Au>,
}
impl ClippingRegion {
@@ -632,17 +632,17 @@ impl ClippingRegion {
}).collect(),
}
}
}
/// Metadata attached to each display item. This is useful for performing auxiliary tasks with
/// the display list involving hit testing: finding the originating DOM node and determining the
/// cursor to use when the element is hovered over.
-#[deriving(Clone, Copy)]
+#[derive(Clone, Copy)]
pub struct DisplayItemMetadata {
/// The DOM node from which this display item originated.
pub node: OpaqueNode,
/// The value of the `cursor` property when the mouse hovers over this display item. If `None`,
/// this display item is ineligible for pointer events (`pointer-events: none`).
pub pointing: Option<Cursor>,
}
@@ -661,24 +661,24 @@ impl DisplayItemMetadata {
(pointer_events::T::auto, cursor::T::AutoCursor) => Some(default_cursor),
(pointer_events::T::auto, cursor::T::SpecifiedCursor(cursor)) => Some(cursor),
},
}
}
}
/// Paints a solid color.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct SolidColorDisplayItem {
pub base: BaseDisplayItem,
pub color: Color,
}
/// Paints text.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct TextDisplayItem {
/// Fields common to all display items.
pub base: BaseDisplayItem,
/// The text run.
pub text_run: Arc<Box<TextRun>>,
/// The range of text within the text run.
@@ -686,53 +686,53 @@ pub struct TextDisplayItem {
/// The color of the text.
pub text_color: Color,
pub baseline_origin: Point2D<Au>,
pub orientation: TextOrientation,
}
-#[deriving(Clone, Eq, PartialEq)]
+#[derive(Clone, Eq, PartialEq)]
pub enum TextOrientation {
Upright,
SidewaysLeft,
SidewaysRight,
}
/// Paints an image.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct ImageDisplayItem {
pub base: BaseDisplayItem,
pub image: Arc<Box<Image>>,
/// The dimensions to which the image display item should be stretched. If this is smaller than
/// the bounds of this display item, then the image will be repeated in the appropriate
/// direction to tile the entire bounds.
pub stretch_size: Size2D<Au>,
}
/// Paints a gradient.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct GradientDisplayItem {
/// Fields common to all display items.
pub base: BaseDisplayItem,
/// The start point of the gradient (computed during display list construction).
pub start_point: Point2D<Au>,
/// The end point of the gradient (computed during display list construction).
pub end_point: Point2D<Au>,
/// A list of color stops.
pub stops: Vec<GradientStop>,
}
/// Paints a border.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct BorderDisplayItem {
/// Fields common to all display items.
pub base: BaseDisplayItem,
/// Border widths.
pub border_widths: SideOffsets2D<Au>,
/// Border colors.
@@ -745,17 +745,17 @@ pub struct BorderDisplayItem {
///
/// TODO(pcwalton): Elliptical radii.
pub radius: BorderRadii<Au>,
}
/// Information about the border radii.
///
/// TODO(pcwalton): Elliptical radii.
-#[deriving(Clone, Default, PartialEq, Show, Copy)]
+#[derive(Clone, Default, PartialEq, Show, Copy)]
pub struct BorderRadii<T> {
pub top_left: T,
pub top_right: T,
pub bottom_right: T,
pub bottom_left: T,
}
impl<T> BorderRadii<T> where T: PartialEq + Zero {
@@ -763,29 +763,29 @@ impl<T> BorderRadii<T> where T: PartialE
pub fn is_square(&self) -> bool {
let zero = Zero::zero();
self.top_left == zero && self.top_right == zero && self.bottom_right == zero &&
self.bottom_left == zero
}
}
/// Paints a line segment.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct LineDisplayItem {
pub base: BaseDisplayItem,
/// The line segment color.
pub color: Color,
/// The line segment style.
pub style: border_style::T
}
/// Paints a box shadow per CSS-BACKGROUNDS.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct BoxShadowDisplayItem {
/// Fields common to all display items.
pub base: BaseDisplayItem,
/// The dimensions of the box that we're placing a shadow around.
pub box_bounds: Rect<Au>,
/// The offset of this shadow from the box.
@@ -801,20 +801,21 @@ pub struct BoxShadowDisplayItem {
pub spread_radius: Au,
/// True if this shadow is inset; false if it's outset.
pub inset: bool,
}
pub enum DisplayItemIterator<'a> {
Empty,
- Parent(dlist::Items<'a,DisplayItem>),
+ Parent(dlist::Iter<'a,DisplayItem>),
}
-impl<'a> Iterator<&'a DisplayItem> for DisplayItemIterator<'a> {
+impl<'a> Iterator for DisplayItemIterator<'a> {
+ type Item = &'a DisplayItem;
#[inline]
fn next(&mut self) -> Option<&'a DisplayItem> {
match *self {
DisplayItemIterator::Empty => None,
DisplayItemIterator::Parent(ref mut subiterator) => subiterator.next(),
}
}
}
@@ -831,24 +832,24 @@ impl DisplayItem {
}
match *self {
DisplayItem::SolidColorClass(ref solid_color) => {
paint_context.draw_solid_color(&solid_color.base.bounds, solid_color.color)
}
DisplayItem::TextClass(ref text) => {
- debug!("Drawing text at {}.", text.base.bounds);
+ debug!("Drawing text at {:?}.", text.base.bounds);
paint_context.draw_text(&**text);
}
DisplayItem::ImageClass(ref image_item) => {
// FIXME(pcwalton): This is a really inefficient way to draw a tiled image; use a
// brush instead.
- debug!("Drawing image at {}.", image_item.base.bounds);
+ debug!("Drawing image at {:?}.", image_item.base.bounds);
let mut y_offset = Au(0);
while y_offset < image_item.base.bounds.size.height {
let mut x_offset = Au(0);
while x_offset < image_item.base.bounds.size.width {
let mut bounds = image_item.base.bounds;
bounds.origin.x = bounds.origin.x + x_offset;
bounds.origin.y = bounds.origin.y + y_offset;
@@ -921,23 +922,23 @@ impl DisplayItem {
self.base().bounds
}
pub fn debug_with_level(&self, level: uint) {
let mut indent = String::new();
for _ in range(0, level) {
indent.push_str("| ")
}
- println!("{}+ {}", indent, self);
+ println!("{}+ {:?}", indent, self);
}
}
impl fmt::Show for DisplayItem {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{} @ {} ({:x})",
+ write!(f, "{} @ {:?} ({:x})",
match *self {
DisplayItem::SolidColorClass(_) => "SolidColor",
DisplayItem::TextClass(_) => "Text",
DisplayItem::ImageClass(_) => "Image",
DisplayItem::BorderClass(_) => "Border",
DisplayItem::GradientClass(_) => "Gradient",
DisplayItem::LineClass(_) => "Line",
DisplayItem::BoxShadowClass(_) => "BoxShadow",
--- a/servo/components/gfx/display_list/optimizer.rs
+++ b/servo/components/gfx/display_list/optimizer.rs
@@ -39,30 +39,30 @@ impl DisplayListOptimizer {
self.add_in_bounds_stacking_contexts(&mut result.children, display_list.children.iter());
result
}
/// Adds display items that intersect the visible rect to `result_list`.
fn add_in_bounds_display_items<'a,I>(&self,
result_list: &mut DList<DisplayItem>,
mut display_items: I)
- where I: Iterator<&'a DisplayItem> {
+ where I: Iterator<Item=&'a DisplayItem> {
for display_item in display_items {
if self.visible_rect.intersects(&display_item.base().bounds) &&
display_item.base().clip.might_intersect_rect(&self.visible_rect) {
result_list.push_back((*display_item).clone())
}
}
}
/// Adds child stacking contexts whose boundaries intersect the visible rect to `result_list`.
fn add_in_bounds_stacking_contexts<'a,I>(&self,
result_list: &mut DList<Arc<StackingContext>>,
mut stacking_contexts: I)
- where I: Iterator<&'a Arc<StackingContext>> {
+ where I: Iterator<Item=&'a Arc<StackingContext>> {
for stacking_context in stacking_contexts {
let overflow = stacking_context.overflow.translate(&stacking_context.bounds.origin);
if self.visible_rect.intersects(&overflow) {
result_list.push_back((*stacking_context).clone())
}
}
}
}
--- a/servo/components/gfx/filters.rs
+++ b/servo/components/gfx/filters.rs
@@ -4,17 +4,17 @@
//! CSS and SVG filter support.
use azure::AzFloat;
use azure::azure_hl::{ColorMatrixAttribute, ColorMatrixInput, CompositeInput, DrawTarget};
use azure::azure_hl::{FilterNode, FilterType, LinearTransferAttribute, LinearTransferInput};
use azure::azure_hl::{Matrix5x4, TableTransferAttribute, TableTransferInput};
-use std::num::FloatMath;
+use std::num::Float;
use style::computed_values::filter;
/// Creates a filter pipeline from a set of CSS filters. Returns the destination end of the filter
/// pipeline and the opacity.
pub fn create_filters(draw_target: &DrawTarget,
temporary_draw_target: &DrawTarget,
style_filters: &filter::T)
-> (FilterNode, AzFloat) {
--- a/servo/components/gfx/font.rs
+++ b/servo/components/gfx/font.rs
@@ -3,23 +3,23 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use geom::{Point2D, Rect, Size2D};
use std::borrow::ToOwned;
use std::mem;
use std::slice;
use std::rc::Rc;
use std::cell::RefCell;
-use servo_util::cache::{Cache, HashCache};
+use servo_util::cache::HashCache;
use servo_util::smallvec::{SmallVec, SmallVec8};
use style::computed_values::{font_variant, font_weight};
use style::style_structs::Font as FontStyle;
use std::sync::Arc;
-use collections::hash::Hash;
+use std::hash::Hash;
use platform::font_context::FontContextHandle;
use platform::font::{FontHandle, FontTable};
use servo_util::geometry::Au;
use text::glyph::{GlyphStore, GlyphId};
use text::shaping::ShaperMethods;
use text::{Shaper, TextRun};
use font_template::FontTemplateDescriptor;
use platform::font_template::FontTemplateData;
@@ -61,20 +61,20 @@ impl FontTableTagConversions for FontTab
let mut bytes = slice::from_raw_buf(&pointer, 4).to_vec();
bytes.reverse();
String::from_utf8_unchecked(bytes)
}
}
}
pub trait FontTableMethods {
- fn with_buffer(&self, |*const u8, uint|);
+ fn with_buffer<F>(&self, F) where F: FnOnce(*const u8, uint);
}
-#[deriving(Clone, Show)]
+#[derive(Clone, Show)]
pub struct FontMetrics {
pub underline_size: Au,
pub underline_offset: Au,
pub strikeout_size: Au,
pub strikeout_offset: Au,
pub leading: Au,
pub x_height: Au,
pub em_size: Au,
@@ -96,70 +96,58 @@ pub struct Font {
pub requested_pt_size: Au,
pub actual_pt_size: Au,
pub shaper: Option<Shaper>,
pub shape_cache: HashCache<ShapeCacheEntry,Arc<GlyphStore>>,
pub glyph_advance_cache: HashCache<u32,FractionalPixel>,
}
bitflags! {
- #[deriving(Copy)]
flags ShapingFlags: u8 {
#[doc="Set if the text is entirely whitespace."]
const IS_WHITESPACE_SHAPING_FLAG = 0x01,
#[doc="Set if we are to ignore ligatures."]
const IGNORE_LIGATURES_SHAPING_FLAG = 0x02,
#[doc="Set if we are to disable kerning."]
const DISABLE_KERNING_SHAPING_FLAG = 0x04
}
}
/// Various options that control text shaping.
-#[deriving(Clone, Eq, PartialEq, Hash, Copy)]
+#[derive(Clone, Eq, PartialEq, Hash, Copy)]
pub struct ShapingOptions {
/// Spacing to add between each letter. Corresponds to the CSS 2.1 `letter-spacing` property.
/// NB: You will probably want to set the `IGNORE_LIGATURES_SHAPING_FLAG` if this is non-null.
pub letter_spacing: Option<Au>,
/// Spacing to add between each word. Corresponds to the CSS 2.1 `word-spacing` property.
pub word_spacing: Au,
/// Various flags.
pub flags: ShapingFlags,
}
/// An entry in the shape cache.
-#[deriving(Clone, Eq, PartialEq, Hash)]
+#[derive(Clone, Eq, PartialEq, Hash)]
pub struct ShapeCacheEntry {
text: String,
options: ShapingOptions,
}
-#[deriving(Clone, Eq, PartialEq, Hash)]
-struct ShapeCacheEntryRef<'a> {
- text: &'a str,
- options: &'a ShapingOptions,
-}
-
-impl<'a> Equiv<ShapeCacheEntry> for ShapeCacheEntryRef<'a> {
- fn equiv(&self, other: &ShapeCacheEntry) -> bool {
- self.text == other.text.as_slice() && *self.options == other.options
- }
-}
-
impl Font {
pub fn shape_text(&mut self, text: &str, options: &ShapingOptions) -> Arc<GlyphStore> {
self.make_shaper(options);
+ //FIXME: find the equivalent of Equiv and the old ShapeCacheEntryRef
let shaper = &self.shaper;
- let lookup_key = ShapeCacheEntryRef {
- text: text,
- options: options,
+ let lookup_key = ShapeCacheEntry {
+ text: text.to_owned(),
+ options: options.clone(),
};
- match self.shape_cache.find_equiv(&lookup_key) {
+ match self.shape_cache.find(&lookup_key) {
None => {}
- Some(glyphs) => return (*glyphs).clone(),
+ Some(glyphs) => return glyphs.clone(),
}
let mut glyphs = GlyphStore::new(text.chars().count() as int,
options.flags.contains(IS_WHITESPACE_SHAPING_FLAG));
shaper.as_ref().unwrap().shape_text(text, options, &mut glyphs);
let glyphs = Arc::new(glyphs);
self.shape_cache.insert(ShapeCacheEntry {
--- a/servo/components/gfx/font_cache_task.rs
+++ b/servo/components/gfx/font_cache_task.rs
@@ -7,16 +7,17 @@ use platform::font_list::get_system_defa
use platform::font_list::get_variations_for_family;
use platform::font_list::get_last_resort_font_families;
use platform::font_context::FontContextHandle;
use collections::str::Str;
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::sync::Arc;
+use std::sync::mpsc::{Sender, Receiver, channel};
use font_template::{FontTemplate, FontTemplateDescriptor};
use platform::font_template::FontTemplateData;
use servo_net::resource_task::{ResourceTask, load_whole_resource};
use servo_util::task::spawn_named;
use servo_util::str::LowercaseString;
use style::Source;
/// A list of font templates that make up a given font family.
@@ -75,21 +76,25 @@ impl FontFamily {
/// Commands that the FontContext sends to the font cache task.
pub enum Command {
GetFontTemplate(String, FontTemplateDescriptor, Sender<Reply>),
GetLastResortFontTemplate(FontTemplateDescriptor, Sender<Reply>),
AddWebFont(String, Source, Sender<()>),
Exit(Sender<()>),
}
+unsafe impl Send for Command {}
+
/// Reply messages sent from the font cache task to the FontContext caller.
pub enum Reply {
GetFontTemplateReply(Option<Arc<FontTemplateData>>),
}
+unsafe impl Send for Reply {}
+
/// The font cache task itself. It maintains a list of reference counted
/// font templates that are currently in use.
struct FontCache {
port: Receiver<Command>,
generic_fonts: HashMap<LowercaseString, LowercaseString>,
local_families: HashMap<LowercaseString, FontFamily>,
web_families: HashMap<LowercaseString, FontFamily>,
font_context: FontContextHandle,
@@ -104,17 +109,17 @@ fn add_generic_font(generic_fonts: &mut
None => LowercaseString::new(mapped_name),
};
generic_fonts.insert(LowercaseString::new(generic_name), family_name);
}
impl FontCache {
fn run(&mut self) {
loop {
- let msg = self.port.recv();
+ let msg = self.port.recv().unwrap();
match msg {
Command::GetFontTemplate(family, descriptor, result) => {
let family = LowercaseString::new(family.as_slice());
let maybe_font_template = self.get_font_template(&family, &descriptor);
result.send(Reply::GetFontTemplateReply(maybe_font_template));
}
Command::GetLastResortFontTemplate(descriptor, result) => {
@@ -133,23 +138,23 @@ impl FontCache {
let url = &url_source.url;
let maybe_resource = load_whole_resource(&self.resource_task, url.clone());
match maybe_resource {
Ok((_, bytes)) => {
let family = &mut self.web_families[family_name];
family.add_template(url.to_string().as_slice(), Some(bytes));
},
Err(_) => {
- debug!("Failed to load web font: family={} url={}", family_name, url);
+ debug!("Failed to load web font: family={:?} url={}", family_name, url);
}
}
}
Source::Local(ref local_family_name) => {
let family = &mut self.web_families[family_name];
- get_variations_for_family(local_family_name.as_slice(), |path| {
+ get_variations_for_family(local_family_name.as_slice(), |&mut:path| {
family.add_template(path.as_slice(), None);
});
}
}
result.send(());
}
Command::Exit(result) => {
result.send(());
@@ -181,17 +186,17 @@ impl FontCache {
-> Option<Arc<FontTemplateData>> {
// TODO(Issue #188): look up localized font family names if canonical name not found
// look up canonical name
if self.local_families.contains_key(family_name) {
debug!("FontList: Found font family with name={}", family_name.as_slice());
let s = &mut self.local_families[*family_name];
if s.templates.len() == 0 {
- get_variations_for_family(family_name.as_slice(), |path| {
+ get_variations_for_family(family_name.as_slice(), |&mut:path| {
s.add_template(path.as_slice(), None);
});
}
// TODO(Issue #192: handle generic font families, like 'serif' and 'sans-serif'.
// if such family exists, try to match style to a font
let result = s.find_font_for_style(desc, &self.font_context);
if result.is_some() {
@@ -239,26 +244,26 @@ impl FontCache {
}
panic!("Unable to find any fonts that match (do you have fallback fonts installed?)");
}
}
/// The public interface to the font cache task, used exclusively by
/// the per-thread/task FontContext structures.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct FontCacheTask {
chan: Sender<Command>,
}
impl FontCacheTask {
pub fn new(resource_task: ResourceTask) -> FontCacheTask {
let (chan, port) = channel();
- spawn_named("FontCacheTask".to_owned(), proc() {
+ spawn_named("FontCacheTask".to_owned(), move || {
// TODO: Allow users to specify these.
let mut generic_fonts = HashMap::with_capacity(5);
add_generic_font(&mut generic_fonts, "serif", "Times New Roman");
add_generic_font(&mut generic_fonts, "sans-serif", "Arial");
add_generic_font(&mut generic_fonts, "cursive", "Apple Chancery");
add_generic_font(&mut generic_fonts, "fantasy", "Papyrus");
add_generic_font(&mut generic_fonts, "monospace", "Menlo");
@@ -281,32 +286,32 @@ impl FontCacheTask {
}
pub fn get_font_template(&self, family: String, desc: FontTemplateDescriptor)
-> Option<Arc<FontTemplateData>> {
let (response_chan, response_port) = channel();
self.chan.send(Command::GetFontTemplate(family, desc, response_chan));
- let reply = response_port.recv();
+ let reply = response_port.recv().unwrap();
match reply {
Reply::GetFontTemplateReply(data) => {
data
}
}
}
pub fn get_last_resort_font_template(&self, desc: FontTemplateDescriptor)
-> Arc<FontTemplateData> {
let (response_chan, response_port) = channel();
self.chan.send(Command::GetLastResortFontTemplate(desc, response_chan));
- let reply = response_port.recv();
+ let reply = response_port.recv().unwrap();
match reply {
Reply::GetFontTemplateReply(data) => {
data.unwrap()
}
}
}
--- a/servo/components/gfx/font_template.rs
+++ b/servo/components/gfx/font_template.rs
@@ -10,17 +10,17 @@ use platform::font_template::FontTemplat
use std::borrow::ToOwned;
use std::sync::{Arc, Weak};
use font::FontHandleMethods;
/// Describes how to select a font from a given family.
/// This is very basic at the moment and needs to be
/// expanded or refactored when we support more of the
/// font styling parameters.
-#[deriving(Clone, Copy)]
+#[derive(Clone, Copy)]
pub struct FontTemplateDescriptor {
pub weight: font_weight::T,
pub italic: bool,
}
impl FontTemplateDescriptor {
pub fn new(weight: font_weight::T, italic: bool) -> FontTemplateDescriptor {
FontTemplateDescriptor {
--- a/servo/components/gfx/lib.rs
+++ b/servo/components/gfx/lib.rs
@@ -1,37 +1,36 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#![feature(globs, macro_rules, phase, unsafe_destructor, default_type_params)]
+#![feature(unsafe_destructor, int_uint, plugin, box_syntax)]
#![deny(unused_imports)]
#![deny(unused_variables)]
#![allow(missing_copy_implementations)]
+#![allow(unstable)]
-#![feature(phase)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
extern crate azure;
extern crate collections;
extern crate geom;
extern crate layers;
extern crate libc;
-extern crate rustrt;
extern crate stb_image;
extern crate png;
extern crate script_traits;
-extern crate serialize;
+extern crate "serialize" as rustc_serialize;
extern crate unicode;
-#[phase(plugin)]
+#[no_link] #[plugin]
extern crate "plugins" as servo_plugins;
extern crate "net" as servo_net;
-#[phase(plugin, link)]
+#[macro_use]
extern crate "util" as servo_util;
extern crate "msg" as servo_msg;
extern crate style;
extern crate time;
extern crate url;
// Eventually we would like the shaper to be pluggable, as many operating systems have their own
// shapers. For now, however, this is a hard dependency.
--- a/servo/components/gfx/paint_context.rs
+++ b/servo/components/gfx/paint_context.rs
@@ -27,17 +27,17 @@ use libc::types::common::c99::{uint16_t,
use png::PixelsByColorType;
use servo_net::image::base::Image;
use servo_util::geometry::{Au, MAX_RECT};
use servo_util::opts;
use servo_util::range::Range;
use std::default::Default;
use std::f32;
use std::mem;
-use std::num::{Float, FloatMath};
+use std::num::Float;
use std::ptr;
use style::computed_values::{border_style, filter, mix_blend_mode};
use std::sync::Arc;
use text::TextRun;
use text::glyph::CharIndex;
pub struct PaintContext<'a> {
pub draw_target: DrawTarget,
@@ -49,25 +49,25 @@ pub struct PaintContext<'a> {
/// The clipping rect for the stacking context as a whole.
pub clip_rect: Option<Rect<Au>>,
/// The current transient clipping region, if any. A "transient clipping region" is the
/// clipping region used by the last display item. We cache the last value so that we avoid
/// pushing and popping clipping regions unnecessarily.
pub transient_clip: Option<ClippingRegion>,
}
-#[deriving(Copy)]
+#[derive(Copy)]
enum Direction {
Top,
Left,
Right,
Bottom
}
-#[deriving(Copy)]
+#[derive(Copy)]
enum DashSize {
DottedBorder = 1,
DashedBorder = 3
}
impl<'a> PaintContext<'a> {
pub fn get_draw_target(&self) -> &DrawTarget {
&self.draw_target
@@ -603,17 +603,17 @@ impl<'a> PaintContext<'a> {
direction: Direction,
bounds: &Rect<Au>,
border: &SideOffsets2D<f32>,
color: Color,
dash_size: DashSize) {
let rect = bounds.to_azure_rect();
let draw_opts = DrawOptions::new(1u as AzFloat, 0 as uint16_t);
let mut stroke_opts = StrokeOptions::new(0u as AzFloat, 10u as AzFloat);
- let mut dash: [AzFloat, ..2] = [0u as AzFloat, 0u as AzFloat];
+ let mut dash: [AzFloat; 2] = [0u as AzFloat, 0u as AzFloat];
stroke_opts.set_cap_style(AZ_CAP_BUTT as u8);
let border_width = match direction {
Direction::Top => border.top,
Direction::Left => border.left,
Direction::Right => border.right,
Direction::Bottom => border.bottom
--- a/servo/components/gfx/paint_task.rs
+++ b/servo/components/gfx/paint_task.rs
@@ -26,23 +26,23 @@ use servo_msg::constellation_msg::Msg as
use servo_msg::constellation_msg::{ConstellationChan, Failure, PipelineId};
use servo_msg::constellation_msg::PipelineExitType;
use servo_util::geometry::{Au, ZERO_POINT};
use servo_util::opts;
use servo_util::smallvec::SmallVec;
use servo_util::task::spawn_named_with_send_on_failure;
use servo_util::task_state;
use servo_util::time::{TimeProfilerChan, TimeProfilerCategory, profile};
-use std::comm::{Receiver, Sender, channel};
use std::mem;
-use std::task::TaskBuilder;
+use std::thread::Builder;
use std::sync::Arc;
+use std::sync::mpsc::{Receiver, Sender, channel};
/// Information about a hardware graphics layer that layout sends to the painting task.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct PaintLayer {
/// A per-pipeline ID describing this layer that should be stable across reflows.
pub id: LayerId,
/// The color of the background in this layer. Used for unpainted content.
pub background_color: Color,
/// The scrolling policy of this layer.
pub scroll_policy: ScrollPolicy,
}
@@ -69,33 +69,32 @@ pub enum Msg {
PaintInit(Arc<StackingContext>),
Paint(Vec<PaintRequest>),
UnusedBuffer(Vec<Box<LayerBuffer>>),
PaintPermissionGranted,
PaintPermissionRevoked,
Exit(Option<Sender<()>>, PipelineExitType),
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct PaintChan(Sender<Msg>);
impl PaintChan {
pub fn new() -> (Receiver<Msg>, PaintChan) {
let (chan, port) = channel();
(port, PaintChan(chan))
}
pub fn send(&self, msg: Msg) {
- let &PaintChan(ref chan) = self;
- assert!(chan.send_opt(msg).is_ok(), "PaintChan.send: paint port closed")
+ assert!(self.send_opt(msg).is_ok(), "PaintChan.send: paint port closed")
}
pub fn send_opt(&self, msg: Msg) -> Result<(), Msg> {
let &PaintChan(ref chan) = self;
- chan.send_opt(msg)
+ chan.send(msg).map_err(|e| e.0)
}
}
pub struct PaintTask<C> {
id: PipelineId,
port: Receiver<Msg>,
compositor: C,
constellation_chan: ConstellationChan,
@@ -127,29 +126,29 @@ pub struct PaintTask<C> {
}
// If we implement this as a function, we get borrowck errors from borrowing
// the whole PaintTask struct.
macro_rules! native_graphics_context(
($task:expr) => (
$task.native_graphics_context.as_ref().expect("Need a graphics context to do painting")
)
-)
+);
impl<C> PaintTask<C> where C: PaintListener + Send {
pub fn create(id: PipelineId,
port: Receiver<Msg>,
compositor: C,
constellation_chan: ConstellationChan,
font_cache_task: FontCacheTask,
failure_msg: Failure,
time_profiler_chan: TimeProfilerChan,
shutdown_chan: Sender<()>) {
let ConstellationChan(c) = constellation_chan.clone();
- spawn_named_with_send_on_failure("PaintTask", task_state::PAINT, proc() {
+ spawn_named_with_send_on_failure("PaintTask", task_state::PAINT, move |:| {
{
// Ensures that the paint task and graphics context are destroyed before the
// shutdown message.
let mut compositor = compositor;
let native_graphics_context = compositor.get_graphics_metadata().map(
|md| NativePaintingGraphicsContext::from_metadata(&md));
let worker_threads = WorkerThreadProxy::spawn(compositor.get_graphics_metadata(),
font_cache_task,
@@ -191,17 +190,17 @@ impl<C> PaintTask<C> where C: PaintListe
}
fn start(&mut self) {
debug!("PaintTask: beginning painting loop");
let mut exit_response_channel : Option<Sender<()>> = None;
let mut waiting_for_compositor_buffers_to_exit = false;
loop {
- match self.port.recv() {
+ match self.port.recv().unwrap() {
Msg::PaintInit(stacking_context) => {
self.root_stacking_context = Some(stacking_context.clone());
if !self.paint_permission {
debug!("PaintTask: paint ready msg");
let ConstellationChan(ref mut c) = self.constellation_chan;
c.send(ConstellationMsg::PainterReady(self.id));
continue;
@@ -221,17 +220,17 @@ impl<C> PaintTask<C> where C: PaintListe
let mut replies = Vec::new();
self.compositor.set_paint_state(self.id, PaintState::Painting);
for PaintRequest { buffer_requests, scale, layer_id, epoch }
in requests.into_iter() {
if self.epoch == epoch {
self.paint(&mut replies, buffer_requests, scale, layer_id);
} else {
- debug!("painter epoch mismatch: {} != {}", self.epoch, epoch);
+ debug!("painter epoch mismatch: {:?} != {:?}", self.epoch, epoch);
}
}
self.compositor.set_paint_state(self.id, PaintState::Idle);
for reply in replies.iter() {
let &(_, ref buffer_set) = reply;
self.used_buffer_count += (*buffer_set).buffers.len();
@@ -331,17 +330,17 @@ impl<C> PaintTask<C> where C: PaintListe
}
/// Paints one layer and sends the tiles back to the layer.
fn paint(&mut self,
replies: &mut Vec<(LayerId, Box<LayerBufferSet>)>,
mut tiles: Vec<BufferRequest>,
scale: f32,
layer_id: LayerId) {
- profile(TimeProfilerCategory::Painting, None, self.time_profiler_chan.clone(), || {
+ profile(TimeProfilerCategory::Painting, None, self.time_profiler_chan.clone(), |:| {
// Bail out if there is no appropriate stacking context.
let stacking_context = if let Some(ref stacking_context) = self.root_stacking_context {
match display_list::find_stacking_context_with_layer_id(stacking_context,
layer_id) {
Some(stacking_context) => stacking_context,
None => return,
}
} else {
@@ -355,20 +354,20 @@ impl<C> PaintTask<C> where C: PaintListe
for (i, tile) in tiles.into_iter().enumerate() {
let thread_id = i % self.worker_threads.len();
let layer_buffer = self.find_or_create_layer_buffer_for_tile(&tile, scale);
self.worker_threads[thread_id].paint_tile(tile,
layer_buffer,
stacking_context.clone(),
scale);
}
- let new_buffers = Vec::from_fn(tile_count, |i| {
+ let new_buffers = (0..tile_count).map(|&mut :i| {
let thread_id = i % self.worker_threads.len();
self.worker_threads[thread_id].get_painted_tile_buffer()
- });
+ }).collect();
let layer_buffer_set = box LayerBufferSet {
buffers: new_buffers,
};
replies.push((layer_id, layer_buffer_set));
})
}
@@ -420,53 +419,53 @@ impl WorkerThreadProxy {
font_cache_task: FontCacheTask,
time_profiler_chan: TimeProfilerChan)
-> Vec<WorkerThreadProxy> {
let thread_count = if opts::get().gpu_painting {
1
} else {
opts::get().layout_threads
};
- Vec::from_fn(thread_count, |_| {
+ (0..thread_count).map(|&:_| {
let (from_worker_sender, from_worker_receiver) = channel();
let (to_worker_sender, to_worker_receiver) = channel();
let native_graphics_metadata = native_graphics_metadata.clone();
let font_cache_task = font_cache_task.clone();
let time_profiler_chan = time_profiler_chan.clone();
- TaskBuilder::new().spawn(proc() {
+ Builder::new().spawn(move || {
let mut worker_thread = WorkerThread::new(from_worker_sender,
to_worker_receiver,
native_graphics_metadata,
font_cache_task,
time_profiler_chan);
worker_thread.main();
});
WorkerThreadProxy {
receiver: from_worker_receiver,
sender: to_worker_sender,
}
- })
+ }).collect()
}
fn paint_tile(&mut self,
tile: BufferRequest,
layer_buffer: Option<Box<LayerBuffer>>,
stacking_context: Arc<StackingContext>,
scale: f32) {
- self.sender.send(MsgToWorkerThread::PaintTile(tile, layer_buffer, stacking_context, scale))
+ self.sender.send(MsgToWorkerThread::PaintTile(tile, layer_buffer, stacking_context, scale)).unwrap()
}
fn get_painted_tile_buffer(&mut self) -> Box<LayerBuffer> {
- match self.receiver.recv() {
+ match self.receiver.recv().unwrap() {
MsgFromWorkerThread::PaintedTile(layer_buffer) => layer_buffer,
}
}
fn exit(&mut self) {
- self.sender.send(MsgToWorkerThread::Exit)
+ self.sender.send(MsgToWorkerThread::Exit).unwrap()
}
}
struct WorkerThread {
sender: Sender<MsgFromWorkerThread>,
receiver: Receiver<MsgToWorkerThread>,
native_graphics_context: Option<NativePaintingGraphicsContext>,
font_context: Box<FontContext>,
@@ -488,25 +487,25 @@ impl WorkerThread {
}),
font_context: box FontContext::new(font_cache_task.clone()),
time_profiler_sender: time_profiler_sender,
}
}
fn main(&mut self) {
loop {
- match self.receiver.recv() {
+ match self.receiver.recv().unwrap() {
MsgToWorkerThread::Exit => break,
MsgToWorkerThread::PaintTile(tile, layer_buffer, stacking_context, scale) => {
let draw_target = self.optimize_and_paint_tile(&tile, stacking_context, scale);
let buffer = self.create_layer_buffer_for_painted_tile(&tile,
layer_buffer,
draw_target,
scale);
- self.sender.send(MsgFromWorkerThread::PaintedTile(buffer))
+ self.sender.send(MsgFromWorkerThread::PaintedTile(buffer)).unwrap()
}
}
}
}
fn optimize_and_paint_tile(&mut self,
tile: &BufferRequest,
stacking_context: Arc<StackingContext>,
@@ -577,17 +576,17 @@ impl WorkerThread {
-> Box<LayerBuffer> {
// Extract the texture from the draw target and place it into its slot in the buffer. If
// using CPU painting, upload it first.
//
// FIXME(pcwalton): We should supply the texture and native surface *to* the draw target in
// GPU painting mode, so that it doesn't have to recreate it.
if !opts::get().gpu_painting {
let mut buffer = layer_buffer.unwrap();
- draw_target.snapshot().get_data_surface().with_data(|data| {
+ draw_target.snapshot().get_data_surface().with_data(|&mut:data| {
buffer.native_surface.upload(native_graphics_context!(self), data);
debug!("painting worker thread uploading to native surface {}",
buffer.native_surface.get_id());
});
return buffer
}
// GPU painting path:
--- a/servo/components/gfx/platform/freetype/font.rs
+++ b/servo/components/gfx/platform/freetype/font.rs
@@ -3,16 +3,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
extern crate freetype;
use font::{FontHandleMethods, FontMetrics, FontTableMethods};
use font::{FontTableTag, FractionalPixel};
use servo_util::geometry::Au;
use servo_util::geometry;
+use servo_util::str::c_str_to_string;
use platform::font_context::FontContextHandle;
use text::glyph::GlyphId;
use text::util::{float_to_fixed, fixed_to_float};
use style::computed_values::font_weight;
use platform::font_template::FontTemplateData;
use freetype::freetype::{FT_Get_Char_Index, FT_Get_Postscript_Name};
use freetype::freetype::{FT_Load_Glyph, FT_Set_Char_Size};
@@ -20,35 +21,34 @@ use freetype::freetype::{FT_Get_Kerning,
use freetype::freetype::{FT_New_Memory_Face, FT_Done_Face};
use freetype::freetype::{FTErrorMethods, FT_F26Dot6, FT_Face, FT_FaceRec};
use freetype::freetype::{FT_GlyphSlot, FT_Library, FT_Long, FT_ULong};
use freetype::freetype::{FT_KERNING_DEFAULT, FT_STYLE_FLAG_ITALIC, FT_STYLE_FLAG_BOLD};
use freetype::freetype::{FT_SizeRec, FT_UInt, FT_Size_Metrics, struct_FT_Vector_};
use freetype::freetype::{ft_sfnt_os2};
use freetype::tt_os2::TT_OS2;
+use libc::c_char;
use std::mem;
use std::num::Float;
use std::ptr;
-use std::string::String;
-
use std::sync::Arc;
fn float_to_fixed_ft(f: f64) -> i32 {
float_to_fixed(6, f)
}
fn fixed_to_float_ft(f: i32) -> f64 {
fixed_to_float(6, f)
}
pub struct FontTable;
impl FontTableMethods for FontTable {
- fn with_buffer(&self, _blk: |*const u8, uint|) {
+ fn with_buffer<F>(&self, _blk: F) where F: FnOnce(*const u8, uint) {
panic!()
}
}
pub struct FontHandle {
// The font binary. This must stay valid for the lifetime of the font,
// if the font is created using FT_Memory_Face.
pub font_data: Arc<FontTemplateData>,
@@ -116,20 +116,24 @@ impl FontHandleMethods for FontHandle {
}
}
}
}
fn get_template(&self) -> Arc<FontTemplateData> {
self.font_data.clone()
}
fn family_name(&self) -> String {
- unsafe { String::from_raw_buf(&*(*self.face).family_name as *const i8 as *const u8) }
+ unsafe {
+ c_str_to_string((*self.face).family_name as *const c_char)
+ }
}
fn face_name(&self) -> String {
- unsafe { String::from_raw_buf(&*FT_Get_Postscript_Name(self.face) as *const i8 as *const u8) }
+ unsafe {
+ c_str_to_string(FT_Get_Postscript_Name(self.face) as *const c_char)
+ }
}
fn is_italic(&self) -> bool {
unsafe { (*self.face).style_flags & FT_STYLE_FLAG_ITALIC != 0 }
}
fn boldness(&self) -> font_weight::T {
let default_weight = font_weight::T::Weight400;
if unsafe { (*self.face).style_flags & FT_STYLE_FLAG_BOLD == 0 } {
default_weight
@@ -248,17 +252,17 @@ impl FontHandleMethods for FontHandle {
em_size: em_size,
ascent: ascent,
descent: -descent, // linux font's seem to use the opposite sign from mac
max_advance: max_advance,
average_advance: average_advance,
line_gap: height,
};
- debug!("Font metrics (@{} pt): {}", geometry::to_pt(em_size), metrics);
+ debug!("Font metrics (@{} pt): {:?}", geometry::to_pt(em_size), metrics);
return metrics;
}
fn get_table_for_tag(&self, _: FontTableTag) -> Option<FontTable> {
None
}
}
--- a/servo/components/gfx/platform/freetype/font_context.rs
+++ b/servo/components/gfx/platform/freetype/font_context.rs
@@ -32,22 +32,22 @@ extern fn ft_free(_mem: FT_Memory, block
extern fn ft_realloc(_mem: FT_Memory, _cur_size: c_long, new_size: c_long, block: *mut c_void) -> *mut c_void {
unsafe {
let ptr = libc::realloc(block, new_size as size_t);
ptr as *mut c_void
}
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct FreeTypeLibraryHandle {
pub ctx: FT_Library,
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct FontContextHandle {
pub ctx: Rc<FreeTypeLibraryHandle>,
}
impl Drop for FreeTypeLibraryHandle {
fn drop(&mut self) {
assert!(!self.ctx.is_null());
unsafe { FT_Done_FreeType(self.ctx) };
--- a/servo/components/gfx/platform/freetype/font_list.rs
+++ b/servo/components/gfx/platform/freetype/font_list.rs
@@ -15,76 +15,80 @@ use fontconfig::fontconfig::{
FcNameParse, FcPatternGetString,
FcPatternDestroy, FcFontSetDestroy,
FcMatchPattern,
FcPatternCreate, FcPatternAddString,
FcFontSetList, FcObjectSetCreate, FcObjectSetDestroy,
FcObjectSetAdd, FcPatternGetInteger
};
+use servo_util::str::c_str_to_string;
+
use libc;
-use libc::c_int;
+use libc::{c_int, c_char};
use std::borrow::ToOwned;
+use std::ffi::CString;
use std::ptr;
-use std::string::String;
static FC_FAMILY: &'static [u8] = b"family\0";
static FC_FILE: &'static [u8] = b"file\0";
static FC_INDEX: &'static [u8] = b"index\0";
-pub fn get_available_families(callback: |String|) {
+pub fn get_available_families<F>(mut callback: F) where F: FnMut(String) {
unsafe {
let config = FcConfigGetCurrent();
let fontSet = FcConfigGetFonts(config, FcSetSystem);
for i in range(0, (*fontSet).nfont as int) {
let font = (*fontSet).fonts.offset(i);
let mut family: *mut FcChar8 = ptr::null_mut();
let mut v: c_int = 0;
- while FcPatternGetString(*font, FC_FAMILY.as_ptr() as *mut i8, v, &mut family) == FcResultMatch {
- let family_name = String::from_raw_buf(family as *const i8 as *const u8);
+ while FcPatternGetString(*font, FC_FAMILY.as_ptr() as *mut c_char, v, &mut family) == FcResultMatch {
+ let family_name = c_str_to_string(family as *const c_char);
callback(family_name);
v += 1;
}
}
}
}
-pub fn get_variations_for_family(family_name: &str, callback: |String|) {
+pub fn get_variations_for_family<F>(family_name: &str, mut callback: F)
+ where F: FnMut(String)
+{
debug!("getting variations for {}", family_name);
unsafe {
let config = FcConfigGetCurrent();
let mut font_set = FcConfigGetFonts(config, FcSetSystem);
let font_set_array_ptr = &mut font_set;
let pattern = FcPatternCreate();
assert!(!pattern.is_null());
- let mut family_name_c = family_name.to_c_str();
- let family_name = family_name_c.as_mut_ptr();
- let ok = FcPatternAddString(pattern, FC_FAMILY.as_ptr() as *mut i8, family_name as *mut FcChar8);
+ let family_name_c = CString::from_slice(family_name.as_bytes());
+ let family_name = family_name_c.as_ptr();
+ let ok = FcPatternAddString(pattern, FC_FAMILY.as_ptr() as *mut c_char, family_name as *mut FcChar8);
assert!(ok != 0);
let object_set = FcObjectSetCreate();
assert!(!object_set.is_null());
- FcObjectSetAdd(object_set, FC_FILE.as_ptr() as *mut i8);
- FcObjectSetAdd(object_set, FC_INDEX.as_ptr() as *mut i8);
+ FcObjectSetAdd(object_set, FC_FILE.as_ptr() as *mut c_char);
+ FcObjectSetAdd(object_set, FC_INDEX.as_ptr() as *mut c_char);
let matches = FcFontSetList(config, font_set_array_ptr, 1, pattern, object_set);
debug!("found {} variations", (*matches).nfont);
for i in range(0, (*matches).nfont as int) {
let font = (*matches).fonts.offset(i);
let mut file: *mut FcChar8 = ptr::null_mut();
- let file = if FcPatternGetString(*font, FC_FILE.as_ptr() as *mut i8, 0, &mut file) == FcResultMatch {
- String::from_raw_buf(file as *const i8 as *const u8)
+ let file = if FcPatternGetString(*font, FC_FILE.as_ptr() as *mut c_char, 0, &mut file) == FcResultMatch {
+ c_str_to_string(file as *const c_char)
} else {
panic!();
};
let mut index: libc::c_int = 0;
- let index = if FcPatternGetInteger(*font, FC_INDEX.as_ptr() as *mut i8, 0, &mut index) == FcResultMatch {
+ let index = if FcPatternGetInteger(*font, FC_INDEX.as_ptr() as *mut c_char, 0, &mut index) == FcResultMatch {
index
} else {
panic!();
};
debug!("variation file: {}", file);
debug!("variation index: {}", index);
@@ -93,32 +97,32 @@ pub fn get_variations_for_family(family_
FcFontSetDestroy(matches);
FcPatternDestroy(pattern);
FcObjectSetDestroy(object_set);
}
}
pub fn get_system_default_family(generic_name: &str) -> Option<String> {
- let mut generic_name_c = generic_name.to_c_str();
- let generic_name_ptr = generic_name_c.as_mut_ptr();
+ let generic_name_c = CString::from_slice(generic_name.as_bytes());
+ let generic_name_ptr = generic_name_c.as_ptr();
unsafe {
let pattern = FcNameParse(generic_name_ptr as *mut FcChar8);
FcConfigSubstitute(ptr::null_mut(), pattern, FcMatchPattern);
FcDefaultSubstitute(pattern);
let mut result = 0;
let family_match = FcFontMatch(ptr::null_mut(), pattern, &mut result);
let family_name = if result == FcResultMatch {
let mut match_string: *mut FcChar8 = ptr::null_mut();
- FcPatternGetString(family_match, FC_FAMILY.as_ptr() as *mut i8, 0, &mut match_string);
- let result = String::from_raw_buf(match_string as *const i8 as *const u8);
+ FcPatternGetString(family_match, FC_FAMILY.as_ptr() as *mut c_char, 0, &mut match_string);
+ let result = c_str_to_string(match_string as *const c_char);
FcPatternDestroy(family_match);
Some(result)
} else {
None
};
FcPatternDestroy(pattern);
family_name
--- a/servo/components/gfx/platform/macos/font.rs
+++ b/servo/components/gfx/platform/macos/font.rs
@@ -42,17 +42,17 @@ impl Drop for FontTable {
impl FontTable {
pub fn wrap(data: CFData) -> FontTable {
FontTable { data: data }
}
}
impl FontTableMethods for FontTable {
- fn with_buffer(&self, blk: |*const u8, uint|) {
+ fn with_buffer<F>(&self, blk: F) where F: FnOnce(*const u8, uint) {
blk(self.data.bytes().as_ptr(), self.data.len() as uint);
}
}
pub struct FontHandle {
pub font_data: Arc<FontTemplateData>,
pub ctfont: CTFont,
}
@@ -107,18 +107,18 @@ impl FontHandleMethods for FontHandle {
if normalized < 5.0 { return font_weight::T::Weight500; }
if normalized < 6.0 { return font_weight::T::Weight600; }
if normalized < 7.0 { return font_weight::T::Weight700; }
if normalized < 8.0 { return font_weight::T::Weight800; }
return font_weight::T::Weight900;
}
fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
- let characters: [UniChar, ..1] = [codepoint as UniChar];
- let mut glyphs: [CGGlyph, ..1] = [0 as CGGlyph];
+ let characters: [UniChar; 1] = [codepoint as UniChar];
+ let mut glyphs: [CGGlyph; 1] = [0 as CGGlyph];
let count: CFIndex = 1;
let result = self.ctfont.get_glyphs_for_characters(&characters[0],
&mut glyphs[0],
count);
if !result {
// No glyph for this character
@@ -174,17 +174,17 @@ impl FontHandleMethods for FontHandle {
x_height: Au::from_pt(self.ctfont.x_height() as f64),
em_size: em_size,
ascent: Au::from_pt(ascent * scale),
descent: Au::from_pt(descent * scale),
max_advance: max_advance_width,
average_advance: average_advance,
line_gap: Au::from_frac_px(line_gap),
};
- debug!("Font metrics (@{} pt): {}", self.ctfont.pt_size() as f64, metrics);
+ debug!("Font metrics (@{} pt): {:?}", self.ctfont.pt_size() as f64, metrics);
return metrics;
}
fn get_table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
let result: Option<CFData> = self.ctfont.get_font_table(tag);
result.and_then(|data| {
Some(FontTable::wrap(data))
})
--- a/servo/components/gfx/platform/macos/font_context.rs
+++ b/servo/components/gfx/platform/macos/font_context.rs
@@ -1,13 +1,13 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct FontContextHandle {
ctx: ()
}
impl FontContextHandle {
// this is a placeholder until NSFontManager or whatever is bound in here.
pub fn new() -> FontContextHandle {
FontContextHandle { ctx: () }
--- a/servo/components/gfx/platform/macos/font_list.rs
+++ b/servo/components/gfx/platform/macos/font_list.rs
@@ -5,27 +5,27 @@
use core_foundation::base::TCFType;
use core_foundation::string::{CFString, CFStringRef};
use core_text::font_descriptor::{CTFontDescriptor, CTFontDescriptorRef};
use core_text;
use std::borrow::ToOwned;
use std::mem;
-pub fn get_available_families(callback: |String|) {
+pub fn get_available_families<F>(mut callback: F) where F: FnMut(String) {
let family_names = core_text::font_collection::get_family_names();
for strref in family_names.iter() {
let family_name_ref: CFStringRef = unsafe { mem::transmute(strref) };
let family_name_cf: CFString = unsafe { TCFType::wrap_under_get_rule(family_name_ref) };
let family_name = family_name_cf.to_string();
callback(family_name);
}
}
-pub fn get_variations_for_family(family_name: &str, callback: |String|) {
+pub fn get_variations_for_family<F>(family_name: &str, mut callback: F) where F: FnMut(String) {
debug!("Looking for faces of family: {}", family_name);
let family_collection =
core_text::font_collection::create_for_family(family_name.as_slice());
match family_collection {
Some(family_collection) => {
let family_descriptors = family_collection.get_descriptors();
for descref in family_descriptors.iter() {
--- a/servo/components/gfx/platform/macos/font_template.rs
+++ b/servo/components/gfx/platform/macos/font_template.rs
@@ -13,16 +13,19 @@ use std::borrow::ToOwned;
/// The identifier is a PostScript font name. The
/// CTFont object is cached here for use by the
/// paint functions that create CGFont references.
pub struct FontTemplateData {
pub ctfont: Option<CTFont>,
pub identifier: String,
}
+unsafe impl Send for FontTemplateData {}
+unsafe impl Sync for FontTemplateData {}
+
impl FontTemplateData {
pub fn new(identifier: &str, font_data: Option<Vec<u8>>) -> FontTemplateData {
let ctfont = match font_data {
Some(bytes) => {
let fontprov = CGDataProvider::from_buffer(bytes.as_slice());
let cgfont_result = CGFont::from_data_provider(fontprov);
match cgfont_result {
Ok(cgfont) => Some(core_text::font::new_from_CGFont(&cgfont, 0.0)),
--- a/servo/components/gfx/text/glyph.rs
+++ b/servo/components/gfx/text/glyph.rs
@@ -4,31 +4,32 @@
use servo_util::vec::*;
use servo_util::range;
use servo_util::range::{Range, RangeIndex, EachIndex};
use servo_util::geometry::Au;
use std::cmp::{Ordering, PartialOrd};
use std::iter::repeat;
-use std::num::NumCast;
+use std::num::{ToPrimitive, NumCast};
use std::mem;
+use std::ops::{Add, Sub, Mul, Neg, Div, Rem, BitAnd, BitOr, BitXor, Shl, Shr, Not};
use std::u16;
use std::vec::Vec;
use geom::point::Point2D;
/// GlyphEntry is a port of Gecko's CompressedGlyph scheme for storing glyph data compactly.
///
/// In the common case (reasonable glyph advances, no offsets from the font em-box, and one glyph
/// per character), we pack glyph advance, glyph id, and some flags into a single u32.
///
/// In the uncommon case (multiple glyphs per unicode character, large glyph index/advance, or
/// glyph offsets), we pack the glyph count into GlyphEntry, and store the other glyph information
/// in DetailedGlyphStore.
-#[deriving(Clone, Show, Copy)]
+#[derive(Clone, Show, Copy)]
struct GlyphEntry {
value: u32,
}
impl GlyphEntry {
fn new(value: u32) -> GlyphEntry {
GlyphEntry {
value: value,
@@ -83,17 +84,17 @@ impl GlyphEntry {
GlyphEntry::new((glyph_count as u32) << GLYPH_COUNT_SHIFT as uint)
}
}
/// The id of a particular glyph within a font
pub type GlyphId = u32;
// TODO: unify with bit flags?
-#[deriving(PartialEq, Copy)]
+#[derive(PartialEq, Copy)]
pub enum BreakType {
None,
Normal,
Hyphen,
}
static BREAK_TYPE_NONE: u8 = 0x0;
static BREAK_TYPE_NORMAL: u8 = 0x1;
@@ -247,17 +248,17 @@ impl GlyphEntry {
#[inline(always)]
fn adapt_character_flags_of_entry(&self, other: GlyphEntry) -> GlyphEntry {
GlyphEntry { value: self.value | other.value }
}
}
// Stores data for a detailed glyph, in the case that several glyphs
// correspond to one character, or the glyph's data couldn't be packed.
-#[deriving(Clone, Show, Copy)]
+#[derive(Clone, Show, Copy)]
struct DetailedGlyph {
id: GlyphId,
// glyph's advance, in the text's direction (RTL or RTL)
advance: Au,
// glyph's offset from the font's em-box (from top-left)
offset: Point2D<Au>,
}
@@ -266,17 +267,17 @@ impl DetailedGlyph {
DetailedGlyph {
id: id,
advance: advance,
offset: offset,
}
}
}
-#[deriving(PartialEq, Clone, Eq, Show, Copy)]
+#[derive(PartialEq, Clone, Eq, Show, Copy)]
struct DetailedGlyphRecord {
// source string offset/GlyphEntry offset in the TextRun
entry_offset: CharIndex,
// offset into the detailed glyphs buffer
detail_offset: int,
}
impl PartialOrd for DetailedGlyphRecord {
@@ -315,17 +316,17 @@ impl<'a> DetailedGlyphStore {
}
fn add_detailed_glyphs_for_entry(&mut self, entry_offset: CharIndex, glyphs: &[DetailedGlyph]) {
let entry = DetailedGlyphRecord {
entry_offset: entry_offset,
detail_offset: self.detail_buffer.len() as int,
};
- debug!("Adding entry[off={}] for detailed glyphs: {}", entry_offset, glyphs);
+ debug!("Adding entry[off={:?}] for detailed glyphs: {:?}", entry_offset, glyphs);
/* TODO: don't actually assert this until asserts are compiled
in/out based on severity, debug/release, etc. This assertion
would wreck the complexity of the lookup.
See Rust Issue #3647, #2228, #3627 for related information.
do self.detail_lookup.borrow |arr| {
@@ -335,17 +336,17 @@ impl<'a> DetailedGlyphStore {
self.detail_lookup.push(entry);
self.detail_buffer.push_all(glyphs);
self.lookup_is_sorted = false;
}
fn get_detailed_glyphs_for_entry(&'a self, entry_offset: CharIndex, count: u16)
-> &'a [DetailedGlyph] {
- debug!("Requesting detailed glyphs[n={}] for entry[off={}]", count, entry_offset);
+ debug!("Requesting detailed glyphs[n={}] for entry[off={:?}]", count, entry_offset);
// FIXME: Is this right? --pcwalton
// TODO: should fix this somewhere else
if count == 0 {
return self.detail_buffer.slice(0, 0);
}
assert!((count as uint) <= self.detail_buffer.len());
@@ -407,17 +408,17 @@ impl<'a> DetailedGlyphStore {
mem::swap(&mut self.detail_lookup, &mut sorted_records);
self.lookup_is_sorted = true;
}
}
// This struct is used by GlyphStore clients to provide new glyph data.
// It should be allocated on the stack and passed by reference to GlyphStore.
-#[deriving(Copy)]
+#[derive(Copy)]
pub struct GlyphData {
id: GlyphId,
advance: Au,
offset: Point2D<Au>,
is_missing: bool,
cluster_start: bool,
ligature_start: bool,
}
@@ -440,17 +441,17 @@ impl GlyphData {
}
}
}
// This enum is a proxy that's provided to GlyphStore clients when iterating
// through glyphs (either for a particular TextRun offset, or all glyphs).
// Rather than eagerly assembling and copying glyph data, it only retrieves
// values as they are needed from the GlyphStore, using provided offsets.
-#[deriving(Copy)]
+#[derive(Copy)]
pub enum GlyphInfo<'a> {
Simple(&'a GlyphStore, CharIndex),
Detail(&'a GlyphStore, CharIndex, u16),
}
impl<'a> GlyphInfo<'a> {
pub fn id(self) -> GlyphId {
match self {
@@ -509,17 +510,17 @@ pub struct GlyphStore {
/// A store of the detailed glyph data. Detailed glyphs contained in the
/// `entry_buffer` point to locations in this data structure.
detail_store: DetailedGlyphStore,
is_whitespace: bool,
}
int_range_index! {
- #[deriving(Encodable)]
+ #[derive(RustcEncodable)]
#[doc = "An index that refers to a character in a text run. This could \
point to the middle of a glyph."]
struct CharIndex(int)
}
impl<'a> GlyphStore {
// Initializes the glyph store, but doesn't actually shape anything.
// Use the set_glyph, set_glyphs() methods to store glyph data.
@@ -575,40 +576,40 @@ impl<'a> GlyphStore {
assert!(data_for_glyphs.len() > 0);
let glyph_count = data_for_glyphs.len() as int;
let first_glyph_data = data_for_glyphs[0];
let entry = match first_glyph_data.is_missing {
true => GlyphEntry::missing(glyph_count),
false => {
- let glyphs_vec = Vec::from_fn(glyph_count as uint, |i| {
+ let glyphs_vec: Vec<DetailedGlyph> = (0..glyph_count as uint).map(|&:i| {
DetailedGlyph::new(data_for_glyphs[i].id,
data_for_glyphs[i].advance,
data_for_glyphs[i].offset)
- });
+ }).collect();
self.detail_store.add_detailed_glyphs_for_entry(i, glyphs_vec.as_slice());
GlyphEntry::complex(first_glyph_data.cluster_start,
first_glyph_data.ligature_start,
glyph_count)
}
}.adapt_character_flags_of_entry(self.entry_buffer[i.to_uint()]);
- debug!("Adding multiple glyphs[idx={}, count={}]: {}", i, glyph_count, entry);
+ debug!("Adding multiple glyphs[idx={:?}, count={}]: {:?}", i, glyph_count, entry);
self.entry_buffer[i.to_uint()] = entry;
}
// used when a character index has no associated glyph---for example, a ligature continuation.
pub fn add_nonglyph_for_char_index(&mut self, i: CharIndex, cluster_start: bool, ligature_start: bool) {
assert!(i < self.char_len());
let entry = GlyphEntry::complex(cluster_start, ligature_start, 0);
- debug!("adding spacer for chracter without associated glyph[idx={}]", i);
+ debug!("adding spacer for chracter without associated glyph[idx={:?}]", i);
self.entry_buffer[i.to_uint()] = entry;
}
pub fn iter_glyphs_for_char_index(&'a self, i: CharIndex) -> GlyphIterator<'a> {
self.iter_glyphs_for_char_range(&Range::new(i, CharIndex(1)))
}
@@ -720,32 +721,34 @@ impl<'a> GlyphIterator<'a> {
fn next_complex_glyph(&mut self, entry: &GlyphEntry, i: CharIndex)
-> Option<(CharIndex, GlyphInfo<'a>)> {
let glyphs = self.store.detail_store.get_detailed_glyphs_for_entry(i, entry.glyph_count());
self.glyph_range = Some(range::each_index(CharIndex(0), CharIndex(glyphs.len() as int)));
self.next()
}
}
-impl<'a> Iterator<(CharIndex, GlyphInfo<'a>)> for GlyphIterator<'a> {
+impl<'a> Iterator for GlyphIterator<'a> {
+ type Item = (CharIndex, GlyphInfo<'a>);
+
// I tried to start with something simpler and apply FlatMap, but the
// inability to store free variables in the FlatMap struct was problematic.
//
// This function consists of the fast path and is designed to be inlined into its caller. The
// slow paths, which should not be inlined, are `next_glyph_range()` and
// `next_complex_glyph()`.
#[inline(always)]
fn next(&mut self) -> Option<(CharIndex, GlyphInfo<'a>)> {
// Would use 'match' here but it borrows contents in a way that
// interferes with mutation.
if self.glyph_range.is_some() {
self.next_glyph_range()
} else {
// No glyph range. Look at next character.
- self.char_range.next().and_then(|i| {
+ self.char_range.next().and_then(|:i| {
self.char_index = i;
assert!(i < self.store.char_len());
let entry = self.store.entry_buffer[i.to_uint()];
if entry.is_simple() {
Some((self.char_index, GlyphInfo::Simple(self.store, i)))
} else {
// Fall back to the slow path.
self.next_complex_glyph(&entry, i)
--- a/servo/components/gfx/text/text_run.rs
+++ b/servo/components/gfx/text/text_run.rs
@@ -4,42 +4,42 @@
use font::{Font, FontHandleMethods, FontMetrics, IS_WHITESPACE_SHAPING_FLAG, RunMetrics};
use font::{ShapingOptions};
use platform::font_template::FontTemplateData;
use servo_util::geometry::Au;
use servo_util::range::Range;
use servo_util::vec::{Comparator, FullBinarySearchMethods};
use std::cmp::Ordering;
-use std::slice::Items;
+use std::slice::Iter;
use std::sync::Arc;
use text::glyph::{CharIndex, GlyphStore};
/// A single "paragraph" of text in one font size and style.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct TextRun {
pub text: Arc<String>,
pub font_template: Arc<FontTemplateData>,
pub actual_pt_size: Au,
pub font_metrics: FontMetrics,
/// The glyph runs that make up this text run.
pub glyphs: Arc<Vec<GlyphRun>>,
}
/// A single series of glyphs within a text run.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct GlyphRun {
/// The glyphs.
pub glyph_store: Arc<GlyphStore>,
/// The range of characters in the containing run.
pub range: Range<CharIndex>,
}
pub struct NaturalWordSliceIterator<'a> {
- glyph_iter: Items<'a, GlyphRun>,
+ glyph_iter: Iter<'a, GlyphRun>,
range: Range<CharIndex>,
}
struct CharIndexComparator;
impl Comparator<CharIndex,GlyphRun> for CharIndexComparator {
fn compare(&self, key: &CharIndex, value: &GlyphRun) -> Ordering {
if *key < value.range.begin() {
@@ -68,17 +68,19 @@ impl<'a> TextRunSlice<'a> {
#[inline]
pub fn text_run_range(&self) -> Range<CharIndex> {
let mut range = self.range;
range.shift_by(self.offset);
range
}
}
-impl<'a> Iterator<TextRunSlice<'a>> for NaturalWordSliceIterator<'a> {
+impl<'a> Iterator for NaturalWordSliceIterator<'a> {
+ type Item = TextRunSlice<'a>;
+
// inline(always) due to the inefficient rt failures messing up inline heuristics, I think.
#[inline(always)]
fn next(&mut self) -> Option<TextRunSlice<'a>> {
let slice_glyphs = self.glyph_iter.next();
if slice_glyphs.is_none() {
return None;
}
let slice_glyphs = slice_glyphs.unwrap();
@@ -96,21 +98,23 @@ impl<'a> Iterator<TextRunSlice<'a>> for
} else {
None
}
}
}
pub struct CharacterSliceIterator<'a> {
glyph_run: Option<&'a GlyphRun>,
- glyph_run_iter: Items<'a, GlyphRun>,
+ glyph_run_iter: Iter<'a, GlyphRun>,
range: Range<CharIndex>,
}
-impl<'a> Iterator<TextRunSlice<'a>> for CharacterSliceIterator<'a> {
+impl<'a> Iterator for CharacterSliceIterator<'a> {
+ type Item = TextRunSlice<'a>;
+
// inline(always) due to the inefficient rt failures messing up inline heuristics, I think.
#[inline(always)]
fn next(&mut self) -> Option<TextRunSlice<'a>> {
let glyph_run = match self.glyph_run {
None => return None,
Some(glyph_run) => glyph_run,
};
@@ -135,17 +139,19 @@ impl<'a> Iterator<TextRunSlice<'a>> for
}
pub struct LineIterator<'a> {
range: Range<CharIndex>,
clump: Option<Range<CharIndex>>,
slices: NaturalWordSliceIterator<'a>,
}
-impl<'a> Iterator<Range<CharIndex>> for LineIterator<'a> {
+impl<'a> Iterator for LineIterator<'a> {
+ type Item = Range<CharIndex>;
+
fn next(&mut self) -> Option<Range<CharIndex>> {
// Loop until we hit whitespace and are in a clump.
loop {
match self.slices.next() {
Some(slice) => {
match (slice.glyphs.is_whitespace(), self.clump) {
(false, Some(ref mut c)) => {
c.extend_by(slice.range.length());
@@ -306,19 +312,19 @@ impl<'a> TextRun {
pub fn metrics_for_slice(&self, glyphs: &GlyphStore, slice_range: &Range<CharIndex>) -> RunMetrics {
RunMetrics::new(glyphs.advance_for_char_range(slice_range),
self.font_metrics.ascent,
self.font_metrics.descent)
}
pub fn min_width_for_range(&self, range: &Range<CharIndex>) -> Au {
- debug!("iterating outer range {}", range);
+ debug!("iterating outer range {:?}", range);
self.natural_word_slices_in_range(range).fold(Au(0), |max_piece_width, slice| {
- debug!("iterated on {}[{}]", slice.offset, slice.range);
+ debug!("iterated on {:?}[{:?}]", slice.offset, slice.range);
Au::max(max_piece_width, self.advance_for_range(&slice.range))
})
}
/// Returns the first glyph run containing the given character index.
pub fn first_glyph_run_containing(&'a self, index: CharIndex) -> Option<&'a GlyphRun> {
self.index_of_first_glyph_run_containing(index).map(|index| &self.glyphs[index])
}
--- a/servo/components/gfx/text/util.rs
+++ b/servo/components/gfx/text/util.rs
@@ -1,15 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use text::glyph::CharIndex;
-#[deriving(PartialEq, Eq, Copy)]
+#[derive(PartialEq, Eq, Copy)]
pub enum CompressionMode {
CompressNone,
CompressWhitespace,
CompressWhitespaceNewline,
DiscardNewline
}
// ported from Gecko's nsTextFrameUtils::TransformText.
--- a/servo/components/layout/Cargo.toml
+++ b/servo/components/layout/Cargo.toml
@@ -2,16 +2,19 @@
name = "layout"
version = "0.0.1"
authors = ["The Servo Project Developers"]
[lib]
name = "layout"
path = "lib.rs"
+[dependencies.canvas]
+path = "../canvas"
+
[dependencies.gfx]
path = "../gfx"
[dependencies.script]
path = "../script"
[dependencies.layout_traits]
path = "../layout_traits"
@@ -32,19 +35,17 @@ path = "../net"
path = "../util"
[dependencies.cssparser]
git = "https://github.com/servo/rust-cssparser"
[dependencies.geom]
git = "https://github.com/servo/rust-geom"
-[dependencies.url]
-git = "https://github.com/servo/rust-url"
-
[dependencies.string_cache]
git = "https://github.com/servo/string-cache"
[dependencies.string_cache_macros]
git = "https://github.com/servo/string-cache"
[dependencies]
encoding = "0.2"
+url = "*"
\ No newline at end of file
--- a/servo/components/layout/block.rs
+++ b/servo/components/layout/block.rs
@@ -59,17 +59,17 @@ use std::cmp::{max, min};
use std::fmt;
use style::ComputedValues;
use style::computed_values::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
use style::computed_values::{LengthOrPercentage, box_sizing, display, float};
use style::computed_values::{overflow, position};
use std::sync::Arc;
/// Information specific to floated blocks.
-#[deriving(Clone, Encodable)]
+#[derive(Clone, Encodable)]
pub struct FloatedBlockInfo {
/// The amount of inline size that is available for the float.
pub containing_inline_size: Au,
/// The float ceiling, relative to `BaseFlow::position::cur_b` (i.e. the top part of the border
/// box).
pub float_ceiling: Au,
@@ -87,17 +87,17 @@ impl FloatedBlockInfo {
float_ceiling: Au(0),
index: None,
float_kind: float_kind,
}
}
}
/// The solutions for the block-size-and-margins constraint equation.
-#[deriving(Copy)]
+#[derive(Copy)]
struct BSizeConstraintSolution {
block_start: Au,
_block_end: Au,
block_size: Au,
margin_block_start: Au,
margin_block_end: Au
}
@@ -361,17 +361,18 @@ impl CandidateBSizeIterator {
};
fn adjust(size: Au, delta: Au) -> Au {
max(size - delta, Au(0))
}
}
}
-impl Iterator<MaybeAuto> for CandidateBSizeIterator {
+impl Iterator for CandidateBSizeIterator {
+ type Item = MaybeAuto;
fn next(&mut self) -> Option<MaybeAuto> {
self.status = match self.status {
CandidateBSizeIteratorStatus::Initial => CandidateBSizeIteratorStatus::Trying,
CandidateBSizeIteratorStatus::Trying => {
match self.max_block_size {
Some(max_block_size) if self.candidate_value > max_block_size => {
CandidateBSizeIteratorStatus::TryingMax
}
@@ -482,23 +483,23 @@ pub enum BlockType {
Replaced,
NonReplaced,
AbsoluteReplaced,
AbsoluteNonReplaced,
FloatReplaced,
FloatNonReplaced,
}
-#[deriving(Clone, PartialEq)]
+#[derive(Clone, PartialEq)]
pub enum MarginsMayCollapseFlag {
MarginsMayCollapse,
MarginsMayNotCollapse,
}
-#[deriving(PartialEq)]
+#[derive(PartialEq)]
enum FormattingContextType {
None,
Block,
Other,
}
// Propagates the `layers_needed_for_descendants` flag appropriately from a child. This is called
// as part of block-size assignment.
@@ -520,17 +521,17 @@ fn propagate_layer_flag_from_child(layer
let kid_base = flow::mut_base(kid);
if kid_base.flags.contains(LAYERS_NEEDED_FOR_DESCENDANTS) {
*layers_needed_for_descendants = true
}
}
}
// A block formatting context.
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
pub struct BlockFlow {
/// Data common to all flows.
pub base: BaseFlow,
/// The associated fragment.
pub fragment: Fragment,
/// Static y offset of an absolute flow from its CB.
@@ -556,18 +557,18 @@ pub struct BlockFlow {
bitflags! {
flags BlockFlowFlags: u8 {
#[doc="If this is set, then this block flow is the root flow."]
const IS_ROOT = 0x01,
}
}
-impl<'a,E,S> Encodable<S,E> for BlockFlowFlags where S: Encoder<E> {
- fn encode(&self, e: &mut S) -> Result<(),E> {
+impl Encodable for BlockFlowFlags {
+ fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
self.bits().encode(e)
}
}
impl BlockFlow {
pub fn from_node(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> BlockFlow {
let writing_mode = node.style().writing_mode;
BlockFlow {
@@ -1900,26 +1901,26 @@ impl Flow for BlockFlow {
CoordinateSystem::Parent)
.translate(stacking_context_position));
}
}
impl fmt::Show for BlockFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
- "{} - {:x}: frag={} ({})",
+ "{:?} - {:x}: frag={:?} ({:?})",
self.class(),
self.base.debug_id(),
self.fragment,
self.base)
}
}
/// The inputs for the inline-sizes-and-margins constraint equation.
-#[deriving(Show, Copy)]
+#[derive(Show, Copy)]
pub struct ISizeConstraintInput {
pub computed_inline_size: MaybeAuto,
pub inline_start_margin: MaybeAuto,
pub inline_end_margin: MaybeAuto,
pub inline_start: MaybeAuto,
pub inline_end: MaybeAuto,
pub available_inline_size: Au,
pub static_i_offset: Au,
@@ -1942,17 +1943,17 @@ impl ISizeConstraintInput {
inline_end: inline_end,
available_inline_size: available_inline_size,
static_i_offset: static_i_offset,
}
}
}
/// The solutions for the inline-size-and-margins constraint equation.
-#[deriving(Copy, Show)]
+#[derive(Copy, Show)]
pub struct ISizeConstraintSolution {
pub inline_start: Au,
pub inline_end: Au,
pub inline_size: Au,
pub margin_inline_start: Au,
pub margin_inline_end: Au
}
@@ -2555,17 +2556,17 @@ impl ISizeAndMarginsComputer for FloatNo
input.inline_start_margin,
input.inline_end_margin,
input.available_inline_size);
let margin_inline_start = inline_start_margin.specified_or_zero();
let margin_inline_end = inline_end_margin.specified_or_zero();
let available_inline_size_float = available_inline_size - margin_inline_start - margin_inline_end;
let shrink_to_fit = block.get_shrink_to_fit_inline_size(available_inline_size_float);
let inline_size = computed_inline_size.specified_or_default(shrink_to_fit);
- debug!("assign_inline_sizes_float -- inline_size: {}", inline_size);
+ debug!("assign_inline_sizes_float -- inline_size: {:?}", inline_size);
ISizeConstraintSolution::new(inline_size, margin_inline_start, margin_inline_end)
}
}
impl ISizeAndMarginsComputer for FloatReplaced {
/// CSS Section 10.3.5
///
/// If inline-size is computed as 'auto', the used value is the 'shrink-to-fit' inline-size.
@@ -2575,17 +2576,17 @@ impl ISizeAndMarginsComputer for FloatRe
input.inline_start_margin,
input.inline_end_margin);
let margin_inline_start = inline_start_margin.specified_or_zero();
let margin_inline_end = inline_end_margin.specified_or_zero();
let inline_size = match computed_inline_size {
MaybeAuto::Specified(w) => w,
MaybeAuto::Auto => panic!("FloatReplaced: inline_size should have been computed by now")
};
- debug!("assign_inline_sizes_float -- inline_size: {}", inline_size);
+ debug!("assign_inline_sizes_float -- inline_size: {:?}", inline_size);
ISizeConstraintSolution::new(inline_size, margin_inline_start, margin_inline_end)
}
/// Calculate used value of inline-size just like we do for inline replaced elements.
fn initial_computed_inline_size(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
_: &LayoutContext)
--- a/servo/components/layout/construct.rs
+++ b/servo/components/layout/construct.rs
@@ -56,17 +56,17 @@ use std::mem;
use std::sync::atomic::Ordering;
use style::computed_values::{caption_side, display, empty_cells, float, list_style_position};
use style::computed_values::{position};
use style::{mod, ComputedValues};
use std::sync::Arc;
use url::Url;
/// The results of flow construction for a DOM node.
-#[deriving(Clone)]
+#[derive(Clone)]
pub enum ConstructionResult {
/// This node contributes nothing at all (`display: none`). Alternately, this is what newly
/// created nodes have their `ConstructionResult` set to.
None,
/// This node contributed a flow at the proper position in the tree.
/// Nothing more needs to be done for this node. It has bubbled up fixed
/// and absolute descendant flows that have a containing block above it.
@@ -93,28 +93,28 @@ impl ConstructionResult {
&ConstructionResult::Flow(ref flow_ref, _) => flow::base(&**flow_ref).debug_id(),
}
}
}
/// Represents the output of flow construction for a DOM node that has not yet resulted in a
/// complete flow. Construction items bubble up the tree until they find a `Flow` to be attached
/// to.
-#[deriving(Clone)]
+#[derive(Clone)]
pub enum ConstructionItem {
/// Inline fragments and associated {ib} splits that have not yet found flows.
InlineFragments(InlineFragmentsConstructionResult),
/// Potentially ignorable whitespace.
Whitespace(OpaqueNode, Arc<ComputedValues>, RestyleDamage),
/// TableColumn Fragment
TableColumnFragment(Fragment),
}
/// Represents inline fragments and {ib} splits that are bubbling up from an inline.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct InlineFragmentsConstructionResult {
/// Any {ib} splits that we're bubbling up.
pub splits: DList<InlineBlockSplit>,
/// Any fragments that succeed the {ib} splits.
pub fragments: DList<Fragment>,
/// Any absolute descendants that we're bubbling up.
@@ -142,17 +142,17 @@ pub struct InlineFragmentsConstructionRe
/// ],
/// block: ~BlockFlow {
/// B
/// },
/// }),~[
/// C
/// ])
/// ```
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct InlineBlockSplit {
/// The inline fragments that precede the flow.
pub predecessors: DList<Fragment>,
/// The flow that caused this {ib} split.
pub flow: FlowRef,
}
@@ -1145,17 +1145,17 @@ impl<'a> PostorderNodeMutTraversal for F
Some(NodeTypeId::DocumentType) |
Some(NodeTypeId::DocumentFragment) |
Some(NodeTypeId::Document) |
Some(NodeTypeId::ProcessingInstruction) => {
(display::T::none, float::T::none, position::T::static_)
}
};
- debug!("building flow for node: {} {} {}", display, float, node.type_id());
+ debug!("building flow for node: {:?} {:?} {:?}", display, float, node.type_id());
// Switch on display and floatedness.
match (display, float, positioning) {
// `display: none` contributes no flow construction result. Nuke the flow construction
// results of children.
(display::T::none, _, _) => {
for child in node.children() {
drop(child.swap_out_construction_result())
--- a/servo/components/layout/context.rs
+++ b/servo/components/layout/context.rs
@@ -23,17 +23,17 @@ use style::Stylist;
use url::Url;
struct LocalLayoutContext {
font_context: FontContext,
applicable_declarations_cache: ApplicableDeclarationsCache,
style_sharing_candidate_cache: StyleSharingCandidateCache,
}
-thread_local!(static LOCAL_CONTEXT_KEY: Cell<*mut LocalLayoutContext> = Cell::new(ptr::null_mut()))
+thread_local!(static LOCAL_CONTEXT_KEY: Cell<*mut LocalLayoutContext> = Cell::new(ptr::null_mut()));
fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext) -> *mut LocalLayoutContext {
LOCAL_CONTEXT_KEY.with(|ref r| {
if r.get().is_null() {
let context = box LocalLayoutContext {
font_context: FontContext::new(shared_layout_context.font_cache_task.clone()),
applicable_declarations_cache: ApplicableDeclarationsCache::new(),
style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
@@ -75,16 +75,19 @@ pub struct SharedLayoutContext {
/// The dirty rectangle, used during display list building.
pub dirty: Rect<Au>,
/// Starts at zero, and increased by one every time a layout completes.
/// This can be used to easily check for invalid stale data.
pub generation: uint,
}
+pub struct SharedLayoutContextWrapper(pub *const SharedLayoutContext);
+unsafe impl Send for SharedLayoutContextWrapper {}
+
pub struct LayoutContext<'a> {
pub shared: &'a SharedLayoutContext,
cached_local_layout_context: *mut LocalLayoutContext,
}
impl<'a> LayoutContext<'a> {
pub fn new(shared_layout_context: &'a SharedLayoutContext) -> LayoutContext<'a> {
--- a/servo/components/layout/css/matching.rs
+++ b/servo/components/layout/css/matching.rs
@@ -6,23 +6,23 @@
use css::node_style::StyledNode;
use incremental::{mod, RestyleDamage};
use util::{LayoutDataAccess, LayoutDataWrapper};
use wrapper::{LayoutElement, LayoutNode, TLayoutNode};
use script::dom::node::NodeTypeId;
use servo_util::bloom::BloomFilter;
-use servo_util::cache::{Cache, LRUCache, SimpleHashCache};
+use servo_util::cache::{LRUCache, SimpleHashCache};
use servo_util::smallvec::{SmallVec, SmallVec16};
use servo_util::arc_ptr_eq;
use std::borrow::ToOwned;
use std::mem;
-use std::hash::{Hash, sip};
-use std::slice::Items;
+use std::hash::{Hash, Hasher, Writer};
+use std::slice::Iter;
use string_cache::{Atom, Namespace};
use style::{mod, PseudoElement, ComputedValues, DeclarationBlock, Stylist, TElement, TNode};
use style::{CommonStyleAffectingAttributeMode, CommonStyleAffectingAttributes, cascade};
use std::sync::Arc;
pub struct ApplicableDeclarations {
pub normal: SmallVec16<DeclarationBlock>,
pub before: Vec<DeclarationBlock>,
@@ -45,38 +45,39 @@ impl ApplicableDeclarations {
pub fn clear(&mut self) {
self.normal = SmallVec16::new();
self.before = Vec::new();
self.after = Vec::new();
self.normal_shareable = false;
}
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct ApplicableDeclarationsCacheEntry {
pub declarations: Vec<DeclarationBlock>,
}
impl ApplicableDeclarationsCacheEntry {
fn new(declarations: Vec<DeclarationBlock>) -> ApplicableDeclarationsCacheEntry {
ApplicableDeclarationsCacheEntry {
declarations: declarations,
}
}
}
impl PartialEq for ApplicableDeclarationsCacheEntry {
fn eq(&self, other: &ApplicableDeclarationsCacheEntry) -> bool {
let this_as_query = ApplicableDeclarationsCacheQuery::new(self.declarations.as_slice());
- this_as_query.equiv(other)
+ this_as_query.eq(other)
}
}
+impl Eq for ApplicableDeclarationsCacheEntry {}
-impl Hash for ApplicableDeclarationsCacheEntry {
- fn hash(&self, state: &mut sip::SipState) {
+impl<H: Hasher+Writer> Hash<H> for ApplicableDeclarationsCacheEntry {
+ fn hash(&self, state: &mut H) {
let tmp = ApplicableDeclarationsCacheQuery::new(self.declarations.as_slice());
tmp.hash(state);
}
}
struct ApplicableDeclarationsCacheQuery<'a> {
declarations: &'a [DeclarationBlock],
}
@@ -84,33 +85,40 @@ struct ApplicableDeclarationsCacheQuery<
impl<'a> ApplicableDeclarationsCacheQuery<'a> {
fn new(declarations: &'a [DeclarationBlock]) -> ApplicableDeclarationsCacheQuery<'a> {
ApplicableDeclarationsCacheQuery {
declarations: declarations,
}
}
}
-impl<'a> Equiv<ApplicableDeclarationsCacheEntry> for ApplicableDeclarationsCacheQuery<'a> {
- fn equiv(&self, other: &ApplicableDeclarationsCacheEntry) -> bool {
+impl<'a> PartialEq for ApplicableDeclarationsCacheQuery<'a> {
+ fn eq(&self, other: &ApplicableDeclarationsCacheQuery<'a>) -> bool {
if self.declarations.len() != other.declarations.len() {
return false
}
for (this, other) in self.declarations.iter().zip(other.declarations.iter()) {
if !arc_ptr_eq(&this.declarations, &other.declarations) {
return false
}
}
return true
}
}
-
+impl<'a> Eq for ApplicableDeclarationsCacheQuery<'a> {}
-impl<'a> Hash for ApplicableDeclarationsCacheQuery<'a> {
- fn hash(&self, state: &mut sip::SipState) {
+impl<'a> PartialEq<ApplicableDeclarationsCacheEntry> for ApplicableDeclarationsCacheQuery<'a> {
+ fn eq(&self, other: &ApplicableDeclarationsCacheEntry) -> bool {
+ let other_as_query = ApplicableDeclarationsCacheQuery::new(other.declarations.as_slice());
+ self.eq(&other_as_query)
+ }
+}
+
+impl<'a, H: Hasher+Writer> Hash<H> for ApplicableDeclarationsCacheQuery<'a> {
+ fn hash(&self, state: &mut H) {
for declaration in self.declarations.iter() {
let ptr: uint = unsafe {
mem::transmute_copy(declaration)
};
ptr.hash(state);
}
}
}
@@ -124,17 +132,17 @@ pub struct ApplicableDeclarationsCache {
impl ApplicableDeclarationsCache {
pub fn new() -> ApplicableDeclarationsCache {
ApplicableDeclarationsCache {
cache: SimpleHashCache::new(APPLICABLE_DECLARATIONS_CACHE_SIZE),
}
}
fn find(&self, declarations: &[DeclarationBlock]) -> Option<Arc<ComputedValues>> {
- match self.cache.find_equiv(&ApplicableDeclarationsCacheQuery::new(declarations)) {
+ match self.cache.find(&ApplicableDeclarationsCacheQuery::new(declarations)) {
None => None,
Some(ref values) => Some((*values).clone()),
}
}
fn insert(&mut self, declarations: Vec<DeclarationBlock>, style: Arc<ComputedValues>) {
self.cache.insert(ApplicableDeclarationsCacheEntry::new(declarations), style)
}
@@ -163,17 +171,17 @@ fn create_common_style_affecting_attribu
_ => {}
}
}
}
}
flags
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct StyleSharingCandidate {
pub style: Arc<ComputedValues>,
pub parent_style: Arc<ComputedValues>,
pub local_name: Atom,
// FIXME(pcwalton): Should be a list of atoms instead.
pub class: Option<String>,
pub namespace: Namespace,
pub common_style_affecting_attributes: CommonStyleAffectingAttributes,
@@ -316,17 +324,17 @@ static STYLE_SHARING_CANDIDATE_CACHE_SIZ
impl StyleSharingCandidateCache {
pub fn new() -> StyleSharingCandidateCache {
StyleSharingCandidateCache {
cache: LRUCache::new(STYLE_SHARING_CANDIDATE_CACHE_SIZE),
}
}
- pub fn iter<'a>(&'a self) -> Items<'a,(StyleSharingCandidate,())> {
+ pub fn iter<'a>(&'a self) -> Iter<'a,(StyleSharingCandidate,())> {
self.cache.iter()
}
pub fn insert_if_possible(&mut self, node: &LayoutNode) {
match StyleSharingCandidate::new(node) {
None => {}
Some(candidate) => self.cache.insert(candidate, ())
}
@@ -603,18 +611,18 @@ impl<'ln> MatchMethods for LayoutNode<'l
let parent_layout_data = (&*parent_layout_data_ref).as_ref().expect("no parent data!?");
let parent_style = parent_layout_data.shared_data.style.as_ref().expect("parent hasn't been styled yet!");
Some(parent_style)
}
};
let mut layout_data_ref = self.mutate_layout_data();
match &mut *layout_data_ref {
- &None => panic!("no layout data"),
- &Some(ref mut layout_data) => {
+ &mut None => panic!("no layout data"),
+ &mut Some(ref mut layout_data) => {
match self.type_id() {
Some(NodeTypeId::Text) => {
// Text nodes get a copy of the parent style. This ensures
// that during fragment construction any non-inherited
// CSS properties (such as vertical-align) are correctly
// set on the fragment(s).
let cloned_parent_style = parent_style.unwrap().clone();
layout_data.shared_data.style = Some(cloned_parent_style);
--- a/servo/components/layout/display_list_builder.rs
+++ b/servo/components/layout/display_list_builder.rs
@@ -40,25 +40,27 @@ use servo_msg::constellation_msg::Msg as
use servo_msg::constellation_msg::ConstellationChan;
use servo_net::image::holder::ImageHolder;
use servo_util::cursor::Cursor;
use servo_util::geometry::{mod, Au, to_px};
use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize};
use servo_util::opts;
use std::default::Default;
use std::iter::repeat;
-use std::num::FloatMath;
+use std::num::Float;
use style::values::specified::{AngleOrCorner, HorizontalDirection, VerticalDirection};
use style::computed::{Image, LinearGradient, LengthOrPercentage};
use style::computed_values::filter::Filter;
use style::computed_values::{background_attachment, background_repeat, border_style, overflow};
use style::computed_values::{position, visibility};
use style::style_structs::Border;
use style::{ComputedValues, RGBA};
+use std::num::ToPrimitive;
use std::sync::Arc;
+use std::sync::mpsc::channel;
use url::Url;
/// The results of display list building for a single flow.
pub enum DisplayListBuildingResult {
None,
StackingContext(Arc<StackingContext>),
Normal(Box<DisplayList>),
}
@@ -684,17 +686,17 @@ impl FragmentDisplayListBuilding for Fra
// Compute the fragment position relative to the parent stacking context. If the fragment
// itself establishes a stacking context, then the origin of its position will be (0, 0)
// for the purposes of this computation.
let stacking_relative_border_box =
self.stacking_relative_border_box(stacking_relative_flow_origin,
relative_containing_block_size,
CoordinateSystem::Self);
- debug!("Fragment::build_display_list at rel={}, abs={}, dirty={}, flow origin={}: {}",
+ debug!("Fragment::build_display_list at rel={:?}, abs={:?}, dirty={:?}, flow origin={:?}: {:?}",
self.border_box,
stacking_relative_border_box,
layout_context.shared.dirty,
stacking_relative_flow_origin,
self);
if self.style().get_inheritedbox().visibility != visibility::T::visible {
return
@@ -874,18 +876,18 @@ impl FragmentDisplayListBuilding for Fra
let width = canvas_fragment_info.replaced_image_fragment_info
.computed_inline_size.map_or(0, |w| to_px(w) as uint);
let height = canvas_fragment_info.replaced_image_fragment_info
.computed_block_size.map_or(0, |h| to_px(h) as uint);
let (sender, receiver) = channel::<Vec<u8>>();
let canvas_data = match canvas_fragment_info.renderer {
Some(ref renderer) => {
- renderer.lock().send(SendPixelContents(sender));
- receiver.recv()
+ renderer.lock().unwrap().send(SendPixelContents(sender));
+ receiver.recv().unwrap()
},
None => repeat(0xFFu8).take(width * height * 4).collect(),
};
let canvas_display_item = box ImageDisplayItem {
base: BaseDisplayItem::new(stacking_relative_content_box,
DisplayItemMetadata::new(self.node,
&*self.style,
@@ -911,17 +913,17 @@ impl FragmentDisplayListBuilding for Fra
layout_context: &LayoutContext) {
let border_padding = (self.border_padding).to_physical(self.style.writing_mode);
let content_size = self.content_box().size.to_physical(self.style.writing_mode);
let iframe_rect = Rect(Point2D(geometry::to_frac_px(offset.x + border_padding.left) as f32,
geometry::to_frac_px(offset.y + border_padding.top) as f32),
Size2D(geometry::to_frac_px(content_size.width) as f32,
geometry::to_frac_px(content_size.height) as f32));
- debug!("finalizing position and size of iframe for {},{}",
+ debug!("finalizing position and size of iframe for {:?},{:?}",
iframe_fragment.pipeline_id,
iframe_fragment.subpage_id);
let ConstellationChan(ref chan) = layout_context.shared.constellation_chan;
chan.send(ConstellationMsg::FrameRect(iframe_fragment.pipeline_id,
iframe_fragment.subpage_id,
iframe_rect));
}
@@ -1271,17 +1273,17 @@ impl ListItemFlowDisplayListBuilding for
}
// Draw the rest of the block.
self.block_flow.build_display_list_for_block(display_list, layout_context)
}
}
// A helper data structure for gradients.
-#[deriving(Copy)]
+#[derive(Copy)]
struct StopRun {
start_offset: f32,
end_offset: f32,
start_index: uint,
stop_count: uint,
}
fn fmin(a: f32, b: f32) -> f32 {
@@ -1295,17 +1297,17 @@ fn fmin(a: f32, b: f32) -> f32 {
fn position_to_offset(position: LengthOrPercentage, Au(total_length): Au) -> f32 {
match position {
LengthOrPercentage::Length(Au(length)) => fmin(1.0, (length as f32) / (total_length as f32)),
LengthOrPercentage::Percentage(percentage) => percentage as f32,
}
}
/// "Steps" as defined by CSS 2.1 § E.2.
-#[deriving(Clone, PartialEq, Show, Copy)]
+#[derive(Clone, PartialEq, Show, Copy)]
pub enum StackingLevel {
/// The border and backgrounds for the root of this stacking context: steps 1 and 2.
BackgroundAndBorders,
/// Borders and backgrounds for block-level descendants: step 4.
BlockBackgroundsAndBorders,
/// All other content.
Content,
}
--- a/servo/components/layout/floats.rs
+++ b/servo/components/layout/floats.rs
@@ -7,57 +7,57 @@ use servo_util::logical_geometry::Writin
use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize};
use servo_util::persistent_list::PersistentList;
use std::cmp::{max, min};
use std::i32;
use std::fmt;
use style::computed_values::float;
/// The kind of float: left or right.
-#[deriving(Clone, Encodable, Show, Copy)]
+#[derive(Clone, RustcEncodable, Show, Copy)]
pub enum FloatKind {
Left,
Right
}
impl FloatKind {
pub fn from_property(property: float::T) -> FloatKind {
match property {
float::T::none => panic!("can't create a float type from an unfloated property"),
float::T::left => FloatKind::Left,
float::T::right => FloatKind::Right,
}
}
}
/// The kind of clearance: left, right, or both.
-#[deriving(Copy)]
+#[derive(Copy)]
pub enum ClearType {
Left,
Right,
Both,
}
/// Information about a single float.
-#[deriving(Clone, Copy)]
+#[derive(Clone, Copy)]
struct Float {
/// The boundaries of this float.
bounds: LogicalRect<Au>,
/// The kind of float: left or right.
kind: FloatKind,
}
impl fmt::Show for Float {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "bounds={} kind={}", self.bounds, self.kind)
+ write!(f, "bounds={:?} kind={:?}", self.bounds, self.kind)
}
}
/// Information about the floats next to a flow.
-#[deriving(Clone)]
+#[derive(Clone)]
struct FloatList {
/// Information about each of the floats here.
floats: PersistentList<Float>,
/// Cached copy of the maximum block-start offset of the float.
max_block_start: Au,
}
impl FloatList {
@@ -72,17 +72,17 @@ impl FloatList {
/// not to be any floats.
fn is_present(&self) -> bool {
self.floats.len() > 0
}
}
impl fmt::Show for FloatList {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "max_block_start={} floats={}", self.max_block_start, self.floats.len())
+ write!(f, "max_block_start={:?} floats={}", self.max_block_start, self.floats.len())
}
}
/// All the information necessary to place a float.
pub struct PlacementInfo {
/// The dimensions of the float.
pub size: LogicalSize<Au>,
/// The minimum block-start of the float, as determined by earlier elements.
@@ -91,46 +91,46 @@ pub struct PlacementInfo {
pub max_inline_size: Au,
/// The kind of float.
pub kind: FloatKind
}
impl fmt::Show for PlacementInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
- "size={} ceiling={} max_inline_size={} kind={}",
+ "size={:?} ceiling={:?} max_inline_size={:?} kind={:?}",
self.size,
self.ceiling,
self.max_inline_size,
self.kind)
}
}
fn range_intersect(block_start_1: Au, block_end_1: Au, block_start_2: Au, block_end_2: Au) -> (Au, Au) {
(max(block_start_1, block_start_2), min(block_end_1, block_end_2))
}
/// Encapsulates information about floats. This is optimized to avoid allocation if there are
/// no floats, and to avoid copying when translating the list of floats downward.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct Floats {
/// The list of floats.
list: FloatList,
/// The offset of the flow relative to the first float.
offset: LogicalSize<Au>,
/// The writing mode of these floats.
pub writing_mode: WritingMode,
}
impl fmt::Show for Floats {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if !self.list.is_present() {
write!(f, "[empty]")
} else {
- write!(f, "offset={} floats={}", self.offset, self.list)
+ write!(f, "offset={:?} floats={:?}", self.offset, self.list)
}
}
}
impl Floats {
/// Creates a new `Floats` object.
pub fn new(writing_mode: WritingMode) -> Floats {
Floats {
@@ -161,56 +161,56 @@ impl Floats {
/// with inline-size small enough that it doesn't collide with any floats. max_x is the
/// inline-size beyond which floats have no effect. (Generally this is the containing block
/// inline-size.)
pub fn available_rect(&self, block_start: Au, block_size: Au, max_x: Au)
-> Option<LogicalRect<Au>> {
let list = &self.list;
let block_start = block_start - self.offset.block;
- debug!("available_rect: trying to find space at {}", block_start);
+ debug!("available_rect: trying to find space at {:?}", block_start);
// Relevant dimensions for the inline-end-most inline-start float
let mut max_inline_start = Au(0) - self.offset.inline;
let mut l_block_start = None;
let mut l_block_end = None;
// Relevant dimensions for the inline-start-most inline-end float
let mut min_inline_end = max_x - self.offset.inline;
let mut r_block_start = None;
let mut r_block_end = None;
// Find the float collisions for the given range in the block direction.
for float in list.floats.iter() {
debug!("available_rect: Checking for collision against float");
let float_pos = float.bounds.start;
let float_size = float.bounds.size;
- debug!("float_pos: {}, float_size: {}", float_pos, float_size);
+ debug!("float_pos: {:?}, float_size: {:?}", float_pos, float_size);
match float.kind {
FloatKind::Left if float_pos.i + float_size.inline > max_inline_start &&
float_pos.b + float_size.block > block_start &&
float_pos.b < block_start + block_size => {
max_inline_start = float_pos.i + float_size.inline;
l_block_start = Some(float_pos.b);
l_block_end = Some(float_pos.b + float_size.block);
debug!("available_rect: collision with inline_start float: new \
- max_inline_start is {}",
+ max_inline_start is {:?}",
max_inline_start);
}
FloatKind::Right if float_pos.i < min_inline_end &&
float_pos.b + float_size.block > block_start &&
float_pos.b < block_start + block_size => {
min_inline_end = float_pos.i;
r_block_start = Some(float_pos.b);
r_block_end = Some(float_pos.b + float_size.block);
debug!("available_rect: collision with inline_end float: new min_inline_end \
- is {}",
+ is {:?}",
min_inline_end);
}
FloatKind::Left | FloatKind::Right => {}
}
}
// Extend the vertical range of the rectangle to the closest floats.
// If there are floats on both sides, take the intersection of the
@@ -257,17 +257,17 @@ impl Floats {
new_info = PlacementInfo {
size: info.size,
ceiling: max(info.ceiling, self.list.max_block_start + self.offset.block),
max_inline_size: info.max_inline_size,
kind: info.kind
}
}
- debug!("add_float: added float with info {}", new_info);
+ debug!("add_float: added float with info {:?}", new_info);
let new_float = Float {
bounds: LogicalRect::from_point_size(
self.writing_mode,
self.place_between_floats(&new_info).start - self.offset,
info.size,
),
kind: info.kind
@@ -298,17 +298,17 @@ impl Floats {
}
max_block_size.map(|h| h + self.offset.block)
}
/// Given placement information, finds the closest place a fragment can be positioned without
/// colliding with any floats.
pub fn place_between_floats(&self, info: &PlacementInfo) -> LogicalRect<Au> {
- debug!("place_between_floats: Placing object with {}", info.size);
+ debug!("place_between_floats: Placing object with {:?}", info.size);
// If no floats, use this fast path.
if !self.list.is_present() {
match info.kind {
FloatKind::Left => {
return LogicalRect::new(
self.writing_mode,
Au(0),
@@ -328,17 +328,17 @@ impl Floats {
}
// Can't go any higher than previous floats or previous elements in the document.
let mut float_b = info.ceiling;
loop {
let maybe_location = self.available_rect(float_b,
info.size.block,
info.max_inline_size);
- debug!("place_float: Got available rect: {} for y-pos: {}", maybe_location, float_b);
+ debug!("place_float: Got available rect: {:?} for y-pos: {:?}", maybe_location, float_b);
match maybe_location {
// If there are no floats blocking us, return the current location
// TODO(eatkinson): integrate with overflow
None => {
return match info.kind {
FloatKind::Left => {
LogicalRect::new(
self.writing_mode,
--- a/servo/components/layout/flow.rs
+++ b/servo/components/layout/flow.rs
@@ -50,44 +50,45 @@ use geom::{Point2D, Rect, Size2D};
use gfx::display_list::ClippingRegion;
use serialize::{Encoder, Encodable};
use servo_msg::compositor_msg::LayerId;
use servo_util::geometry::{Au, ZERO_RECT};
use servo_util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
use std::mem;
use std::fmt;
use std::iter::Zip;
+use std::num::FromPrimitive;
use std::raw;
use std::sync::atomic::{AtomicUint, Ordering};
-use std::slice::MutItems;
+use std::slice::IterMut;
use style::computed_values::{clear, empty_cells, float, position, text_align};
use style::ComputedValues;
use std::sync::Arc;
/// Virtual methods that make up a float context.
///
/// Note that virtual methods have a cost; we should not overuse them in Servo. Consider adding
/// methods to `ImmutableFlowUtils` or `MutableFlowUtils` before adding more methods here.
-pub trait Flow: fmt::Show + ToString + Sync {
+pub trait Flow: fmt::Show + Sync {
// RTTI
//
// TODO(pcwalton): Use Rust's RTTI, once that works.
/// Returns the class of flow that this is.
fn class(&self) -> FlowClass;
/// If this is a block flow, returns the underlying object, borrowed immutably. Fails
/// otherwise.
fn as_immutable_block<'a>(&'a self) -> &'a BlockFlow {
panic!("called as_immutable_block() on a non-block flow")
}
/// If this is a block flow, returns the underlying object. Fails otherwise.
fn as_block<'a>(&'a mut self) -> &'a mut BlockFlow {
- debug!("called as_block() on a flow of type {}", self.class());
+ debug!("called as_block() on a flow of type {:?}", self.class());
panic!("called as_block() on a non-block flow")
}
/// If this is an inline flow, returns the underlying object, borrowed immutably. Fails
/// otherwise.
fn as_immutable_inline<'a>(&'a self) -> &'a InlineFlow {
panic!("called as_immutable_inline() on a non-inline flow")
}
@@ -199,20 +200,20 @@ pub trait Flow: fmt::Show + ToString + S
fn place_float_if_applicable<'a>(&mut self, _: &'a LayoutContext<'a>) {}
/// Assigns block-sizes in-order; or, if this is a float, places the float. The default
/// implementation simply assigns block-sizes if this flow is impacted by floats. Returns true
/// if this child was impacted by floats or false otherwise.
fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self,
layout_context: &'a LayoutContext<'a>)
-> bool {
- let impacted = base(&*self).flags.impacted_by_floats();
+ let impacted = base(self).flags.impacted_by_floats();
if impacted {
self.assign_block_size(layout_context);
- mut_base(&mut *self).restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
+ mut_base(self).restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
}
impacted
}
/// Phase 4 of reflow: computes absolute positions.
fn compute_absolute_position(&mut self) {
// The default implementation is a no-op.
}
@@ -290,45 +291,46 @@ pub trait Flow: fmt::Show + ToString + S
/// implications because this can be called on parents concurrently from descendants!
fn generated_containing_block_rect(&self) -> LogicalRect<Au> {
panic!("generated_containing_block_rect not yet implemented for this flow")
}
/// Returns a layer ID for the given fragment.
fn layer_id(&self, fragment_id: uint) -> LayerId {
unsafe {
- let pointer: uint = mem::transmute(self);
+ let obj = mem::transmute::<&&Self, &raw::TraitObject>(&self);
+ let pointer: uint = mem::transmute(obj.data);
LayerId(pointer, fragment_id)
}
}
/// Attempts to perform incremental fixup of this flow by replacing its fragment's style with
/// the new style. This can only succeed if the flow has exactly one fragment.
fn repair_style(&mut self, new_style: &Arc<ComputedValues>);
}
// Base access
#[inline(always)]
-pub fn base<'a>(this: &'a Flow) -> &'a BaseFlow {
+pub fn base<'a, T: ?Sized + Flow>(this: &'a T) -> &'a BaseFlow {
unsafe {
- let obj = mem::transmute::<&'a Flow, raw::TraitObject>(this);
+ let obj = mem::transmute::<&&'a T, &'a raw::TraitObject>(&this);
mem::transmute::<*mut (), &'a BaseFlow>(obj.data)
}
}
/// Iterates over the children of this immutable flow.
pub fn imm_child_iter<'a>(flow: &'a Flow) -> FlowListIterator<'a> {
base(flow).children.iter()
}
#[inline(always)]
-pub fn mut_base<'a>(this: &'a mut Flow) -> &'a mut BaseFlow {
+pub fn mut_base<'a, T: ?Sized + Flow>(this: &'a mut T) -> &'a mut BaseFlow {
unsafe {
- let obj = mem::transmute::<&'a mut Flow, raw::TraitObject>(this);
+ let obj = mem::transmute::<&&'a mut T, &'a raw::TraitObject>(&this);
mem::transmute::<*mut (), &'a mut BaseFlow>(obj.data)
}
}
/// Iterates over the children of this flow.
pub fn child_iter<'a>(flow: &'a mut Flow) -> MutFlowListIterator<'a> {
mut_base(flow).children.iter_mut()
}
@@ -418,17 +420,17 @@ pub trait MutableFlowUtils {
pub trait MutableOwnedFlowUtils {
/// Set absolute descendants for this flow.
///
/// Set this flow as the Containing Block for all the absolute descendants.
fn set_absolute_descendants(&mut self, abs_descendants: AbsDescendants);
}
-#[deriving(Encodable, PartialEq, Show)]
+#[derive(RustcEncodable, PartialEq, Show)]
pub enum FlowClass {
Block,
Inline,
ListItem,
TableWrapper,
Table,
TableColGroup,
TableRowGroup,
@@ -460,17 +462,16 @@ pub trait PostorderFlowTraversal {
/// child nodes are visited.
fn should_process(&self, _flow: &mut Flow) -> bool {
true
}
}
bitflags! {
#[doc = "Flags used in flows."]
- #[deriving(Copy)]
flags FlowFlags: u16 {
// floated descendants flags
#[doc = "Whether this flow has descendants that float left in the same block formatting"]
#[doc = "context."]
const HAS_LEFT_FLOATED_DESCENDANTS = 0b0000_0000_0000_0001,
#[doc = "Whether this flow has descendants that float right in the same block formatting"]
#[doc = "context."]
const HAS_RIGHT_FLOATED_DESCENDANTS = 0b0000_0000_0000_0010,
@@ -535,17 +536,17 @@ impl FlowFlags {
#[inline]
pub fn text_align(self) -> text_align::T {
FromPrimitive::from_u16((self & TEXT_ALIGN).bits() >> TEXT_ALIGN_SHIFT).unwrap()
}
#[inline]
pub fn set_text_align(&mut self, value: text_align::T) {
*self = (*self & !TEXT_ALIGN) |
- FlowFlags::from_bits(value as u16 << TEXT_ALIGN_SHIFT).unwrap();
+ FlowFlags::from_bits((value as u16) << TEXT_ALIGN_SHIFT).unwrap();
}
#[inline]
pub fn set_text_align_override(&mut self, parent: FlowFlags) {
self.insert(parent & TEXT_ALIGN);
}
#[inline]
@@ -587,17 +588,17 @@ impl FlowFlags {
pub fn clears_floats(&self) -> bool {
self.contains(CLEARS_LEFT) || self.contains(CLEARS_RIGHT)
}
}
/// The Descendants of a flow.
///
/// Also, details about their position wrt this flow.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct Descendants {
/// Links to every descendant. This must be private because it is unsafe to leak `FlowRef`s to
/// layout.
descendant_links: Vec<FlowRef>,
/// Static block-direction offsets of all descendants from the start of this flow box.
pub static_block_offsets: Vec<Au>,
}
@@ -645,30 +646,31 @@ impl Descendants {
};
descendant_iter.zip(self.static_block_offsets.slice_from_mut(0).iter_mut())
}
}
pub type AbsDescendants = Descendants;
pub struct DescendantIter<'a> {
- iter: MutItems<'a, FlowRef>,
+ iter: IterMut<'a, FlowRef>,
}
-impl<'a> Iterator<&'a mut (Flow + 'a)> for DescendantIter<'a> {
+impl<'a> Iterator for DescendantIter<'a> {
+ type Item = &'a mut (Flow + 'a);
fn next(&mut self) -> Option<&'a mut (Flow + 'a)> {
self.iter.next().map(|flow| &mut **flow)
}
}
-pub type DescendantOffsetIter<'a> = Zip<DescendantIter<'a>, MutItems<'a, Au>>;
+pub type DescendantOffsetIter<'a> = Zip<DescendantIter<'a>, IterMut<'a, Au>>;
/// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
/// confused with absolutely-positioned flows).
-#[deriving(Encodable, Copy)]
+#[derive(RustcEncodable, Copy)]
pub struct AbsolutePositionInfo {
/// The size of the containing block for relatively-positioned descendants.
pub relative_containing_block_size: LogicalSize<Au>,
/// The position of the absolute containing block relative to the nearest ancestor stacking
/// context. If the absolute containing block establishes the stacking context for this flow,
/// and this flow is not itself absolutely-positioned, then this is (0, 0).
pub stacking_relative_position_of_absolute_containing_block: Point2D<Au>,
@@ -771,58 +773,61 @@ pub struct BaseFlow {
/// The writing mode for this flow.
pub writing_mode: WritingMode,
/// Various flags for flows, tightly packed to save space.
pub flags: FlowFlags,
}
+unsafe impl Send for BaseFlow {}
+unsafe impl Sync for BaseFlow {}
+
impl fmt::Show for BaseFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
- "@ {}, CC {}, ADC {}",
+ "@ {:?}, CC {}, ADC {}",
self.position,
self.parallel.children_count.load(Ordering::SeqCst),
self.abs_descendants.len())
}
}
-impl<E, S: Encoder<E>> Encodable<S, E> for BaseFlow {
- fn encode(&self, e: &mut S) -> Result<(), E> {
+impl Encodable for BaseFlow {
+ fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
e.emit_struct("base", 0, |e| {
- try!(e.emit_struct_field("id", 0, |e| self.debug_id().encode(e)))
+ try!(e.emit_struct_field("id", 0, |e| self.debug_id().encode(e)));
try!(e.emit_struct_field("stacking_relative_position",
1,
- |e| self.stacking_relative_position.encode(e)))
+ |e| self.stacking_relative_position.encode(e)));
try!(e.emit_struct_field("intrinsic_inline_sizes",
2,
- |e| self.intrinsic_inline_sizes.encode(e)))
- try!(e.emit_struct_field("position", 3, |e| self.position.encode(e)))
+ |e| self.intrinsic_inline_sizes.encode(e)));
+ try!(e.emit_struct_field("position", 3, |e| self.position.encode(e)));
e.emit_struct_field("children", 4, |e| {
e.emit_seq(self.children.len(), |e| {
for (i, c) in self.children.iter().enumerate() {
try!(e.emit_seq_elt(i, |e| {
try!(e.emit_struct("flow", 0, |e| {
- try!(e.emit_struct_field("class", 0, |e| c.class().encode(e)))
+ try!(e.emit_struct_field("class", 0, |e| c.class().encode(e)));
e.emit_struct_field("data", 1, |e| {
match c.class() {
FlowClass::Block => c.as_immutable_block().encode(e),
FlowClass::Inline => c.as_immutable_inline().encode(e),
FlowClass::Table => c.as_immutable_table().encode(e),
FlowClass::TableWrapper => c.as_immutable_table_wrapper().encode(e),
FlowClass::TableRowGroup => c.as_immutable_table_rowgroup().encode(e),
FlowClass::TableRow => c.as_immutable_table_row().encode(e),
FlowClass::TableCell => c.as_immutable_table_cell().encode(e),
_ => { Ok(()) } // TODO: Support captions
}
})
- }))
+ }));
Ok(())
- }))
+ }));
}
Ok(())
})
})
})
}
}
@@ -833,17 +838,17 @@ impl Drop for BaseFlow {
if self.ref_count.load(Ordering::SeqCst) != 0 {
panic!("Flow destroyed before its ref count hit zero—this is unsafe!")
}
}
}
/// Whether a base flow should be forced to be nonfloated. This can affect e.g. `TableFlow`, which
/// is never floated because the table wrapper flow is the floated one.
-#[deriving(Clone, PartialEq)]
+#[derive(Clone, PartialEq)]
pub enum ForceNonfloatedFlag {
/// The flow should be floated if the node has a `float` property.
FloatIfNecessary,
/// The flow should be forced to be nonfloated.
ForceNonfloated,
}
impl BaseFlow {
@@ -946,17 +951,17 @@ impl BaseFlow {
for item in all_items.iter() {
let paint_bounds = item.base().clip.clone().intersect_rect(&item.base().bounds);
if !paint_bounds.might_be_nonempty() {
continue;
}
if bounds.union(&paint_bounds.bounding_rect()) != bounds {
- error!("DisplayList item {} outside of Flow overflow ({})", item, paint_bounds);
+ error!("DisplayList item {:?} outside of Flow overflow ({:?})", item, paint_bounds);
}
}
}
}
impl<'a> ImmutableFlowUtils for &'a (Flow + 'a) {
/// Returns true if this flow is a block flow.
fn is_block_like(self) -> bool {
@@ -1120,17 +1125,18 @@ impl<'a> ImmutableFlowUtils for &'a (Flo
/// Dumps the flow tree for debugging, with a prefix to indicate that we're at the given level.
fn dump_with_level(self, level: uint) {
let mut indent = String::new();
for _ in range(0, level) {
indent.push_str("| ")
}
- println!("{}+ {}", indent, self.to_string());
+ // TODO: ICE, already fixed in rustc.
+ //println!("{}+ {:?}", indent, self);
for kid in imm_child_iter(self) {
kid.dump_with_level(level + 1)
}
}
}
impl<'a> MutableFlowUtils for &'a mut (Flow + 'a) {
--- a/servo/components/layout/flow_list.rs
+++ b/servo/components/layout/flow_list.rs
@@ -10,21 +10,21 @@ use std::collections::{dlist, DList};
// This needs to be reworked now that we have dynamically-sized types in Rust.
// Until then, it's just a wrapper around DList.
pub struct FlowList {
flows: DList<FlowRef>,
}
pub struct FlowListIterator<'a> {
- it: dlist::Items<'a, FlowRef>,
+ it: dlist::Iter<'a, FlowRef>,
}
pub struct MutFlowListIterator<'a> {
- it: dlist::MutItems<'a, FlowRef>,
+ it: dlist::IterMut<'a, FlowRef>,
}
impl FlowList {
/// Provide a reference to the front element, or None if the list is empty
#[inline]
pub fn front<'a>(&'a self) -> Option<&'a Flow> {
self.flows.front().map(|head| &**head)
}
@@ -100,29 +100,31 @@ impl FlowList {
/// O(1)
#[inline]
pub fn len(&self) -> uint {
self.flows.len()
}
}
-impl<'a> Iterator<&'a (Flow + 'a)> for FlowListIterator<'a> {
+impl<'a> Iterator for FlowListIterator<'a> {
+ type Item = &'a (Flow + 'a);
#[inline]
fn next(&mut self) -> Option<&'a (Flow + 'a)> {
self.it.next().map(|x| &**x)
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.it.size_hint()
}
}
-impl<'a> Iterator<&'a mut (Flow + 'a)> for MutFlowListIterator<'a> {
+impl<'a> Iterator for MutFlowListIterator<'a> {
+ type Item = &'a mut (Flow + 'a);
#[inline]
fn next(&mut self) -> Option<&'a mut (Flow + 'a)> {
self.it.next().map(|x| &mut **x)
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.it.size_hint()
--- a/servo/components/layout/flow_ref.rs
+++ b/servo/components/layout/flow_ref.rs
@@ -5,48 +5,53 @@
/// Reference-counted pointers to flows.
///
/// Eventually, with dynamically sized types in Rust, much of this code will be superfluous.
use flow::Flow;
use flow;
use std::mem;
+use std::ops::{Deref, DerefMut};
use std::ptr;
use std::raw;
use std::sync::atomic::Ordering;
#[unsafe_no_drop_flag]
pub struct FlowRef {
object: raw::TraitObject,
}
+unsafe impl Send for FlowRef {}
+unsafe impl Sync for FlowRef {}
+
impl FlowRef {
pub fn new(mut flow: Box<Flow>) -> FlowRef {
unsafe {
let result = {
let flow_ref: &mut Flow = &mut *flow;
let object = mem::transmute::<&mut Flow, raw::TraitObject>(flow_ref);
FlowRef { object: object }
};
mem::forget(flow);
result
}
}
}
-impl<'a> Deref<Flow + 'a> for FlowRef {
+impl<'a> Deref for FlowRef {
+ type Target = Flow + 'a;
fn deref(&self) -> &(Flow + 'a) {
unsafe {
mem::transmute_copy::<raw::TraitObject, &(Flow + 'a)>(&self.object)
}
}
}
-impl<'a> DerefMut<Flow + 'a> for FlowRef {
+impl<'a> DerefMut for FlowRef {
fn deref_mut<'a>(&mut self) -> &mut (Flow + 'a) {
unsafe {
mem::transmute_copy::<raw::TraitObject, &mut (Flow + 'a)>(&self.object)
}
}
}
impl Drop for FlowRef {
--- a/servo/components/layout/fragment.rs
+++ b/servo/components/layout/fragment.rs
@@ -34,18 +34,20 @@ use servo_net::image::holder::ImageHolde
use servo_net::local_image_cache::LocalImageCache;
use servo_util::geometry::{mod, Au, ZERO_POINT};
use servo_util::logical_geometry::{LogicalRect, LogicalSize, LogicalMargin};
use servo_util::range::*;
use servo_util::smallvec::SmallVec;
use servo_util::str::is_whitespace;
use std::cmp::{max, min};
use std::fmt;
+use std::num::ToPrimitive;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
+use std::sync::mpsc::Sender;
use string_cache::Atom;
use style::{ComputedValues, TElement, TNode, cascade_anonymous};
use style::computed_values::{LengthOrPercentage, LengthOrPercentageOrAuto};
use style::computed_values::{LengthOrPercentageOrNone, clear, mix_blend_mode, overflow_wrap};
use style::computed_values::{position, text_align, text_decoration, vertical_align, white_space};
use style::computed_values::{word_break};
use url::Url;
@@ -70,17 +72,17 @@ use url::Url;
/// Different types of fragments may also contain custom data; for example, text fragments contain
/// text.
///
/// Do not add fields to this structure unless they're really really mega necessary! Fragments get
/// moved around a lot and thus their size impacts performance of layout quite a bit.
///
/// FIXME(#2260, pcwalton): This can be slimmed down some by (at least) moving `inline_context`
/// to be on `InlineFlow` only.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct Fragment {
/// An opaque reference to the DOM node that this `Fragment` originates from.
pub node: OpaqueNode,
/// The CSS style of this fragment.
pub style: Arc<ComputedValues>,
/// The position of this fragment relative to its owning flow. The size includes padding and
@@ -106,30 +108,33 @@ pub struct Fragment {
/// A debug ID that is consistent for the life of
/// this fragment (via transform etc).
pub debug_id: u16,
/// How damaged this fragment is since last reflow.
pub restyle_damage: RestyleDamage,
}
-impl<E, S: Encoder<E>> Encodable<S, E> for Fragment {
- fn encode(&self, e: &mut S) -> Result<(), E> {
+unsafe impl Send for Fragment {}
+unsafe impl Sync for Fragment {}
+
+impl Encodable for Fragment {
+ fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
e.emit_struct("fragment", 0, |e| {
- try!(e.emit_struct_field("id", 0, |e| self.debug_id().encode(e)))
- try!(e.emit_struct_field("border_box", 1, |e| self.border_box.encode(e)))
+ try!(e.emit_struct_field("id", 0, |e| self.debug_id().encode(e)));
+ try!(e.emit_struct_field("border_box", 1, |e| self.border_box.encode(e)));
e.emit_struct_field("margin", 2, |e| self.margin.encode(e))
})
}
}
/// Info specific to the kind of fragment.
///
/// Keep this enum small. As in, no more than one word. Or pcwalton will yell at you.
-#[deriving(Clone)]
+#[derive(Clone)]
pub enum SpecificFragmentInfo {
Generic,
Iframe(Box<IframeFragmentInfo>),
Image(Box<ImageFragmentInfo>),
Canvas(Box<CanvasFragmentInfo>),
/// A hypothetical box (see CSS 2.1 § 10.3.7) for an absolutely-positioned block that was
/// declared with `display: inline;`.
@@ -186,47 +191,47 @@ impl SpecificFragmentInfo {
}
}
/// A hypothetical box (see CSS 2.1 § 10.3.7) for an absolutely-positioned block that was declared
/// with `display: inline;`.
///
/// FIXME(pcwalton): Stop leaking this `FlowRef` to layout; that is not memory safe because layout
/// can clone it.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct InlineAbsoluteHypotheticalFragmentInfo {
pub flow_ref: FlowRef,
}
impl InlineAbsoluteHypotheticalFragmentInfo {
pub fn new(flow_ref: FlowRef) -> InlineAbsoluteHypotheticalFragmentInfo {
InlineAbsoluteHypotheticalFragmentInfo {
flow_ref: flow_ref,
}
}
}
/// A fragment that represents an inline-block element.
///
/// FIXME(pcwalton): Stop leaking this `FlowRef` to layout; that is not memory safe because layout
/// can clone it.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct InlineBlockFragmentInfo {
pub flow_ref: FlowRef,
}
impl InlineBlockFragmentInfo {
pub fn new(flow_ref: FlowRef) -> InlineBlockFragmentInfo {
InlineBlockFragmentInfo {
flow_ref: flow_ref,
}
}
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct CanvasFragmentInfo {
pub replaced_image_fragment_info: ReplacedImageFragmentInfo,
pub renderer: Option<Arc<Mutex<Sender<CanvasMsg>>>>,
}
impl CanvasFragmentInfo {
pub fn new(node: &ThreadSafeLayoutNode) -> CanvasFragmentInfo {
CanvasFragmentInfo {
@@ -245,17 +250,17 @@ impl CanvasFragmentInfo {
/// Returns the original block-size of the canvas.
pub fn canvas_block_size(&self) -> Au {
self.replaced_image_fragment_info.dom_block_size.unwrap_or(Au(0))
}
}
/// A fragment that represents a replaced content image and its accompanying borders, shadows, etc.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct ImageFragmentInfo {
/// The image held within this fragment.
pub replaced_image_fragment_info: ReplacedImageFragmentInfo,
pub image: ImageHolder<UntrustedNodeAddress>,
}
impl ImageFragmentInfo {
/// Creates a new image fragment from the given URL and local image cache.
@@ -304,17 +309,17 @@ impl ImageFragmentInfo {
let tile_count = (delta_pixels + image_size - 1) / image_size;
let offset = Au::from_px(image_size * tile_count);
let new_position = virtual_position - offset;
*size = *position - new_position + *size;
*position = new_position;
}
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct ReplacedImageFragmentInfo {
pub for_node: UntrustedNodeAddress,
pub computed_inline_size: Option<Au>,
pub computed_block_size: Option<Au>,
pub dom_inline_size: Option<Au>,
pub dom_block_size: Option<Au>,
pub writing_mode_is_vertical: bool,
}
@@ -474,17 +479,17 @@ impl ReplacedImageFragmentInfo {
self.computed_block_size = Some(block_size);
block_size + noncontent_block_size
}
}
/// A fragment that represents an inline frame (iframe). This stores the pipeline ID so that the size
/// of this iframe can be communicated via the constellation to the iframe's own layout task.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct IframeFragmentInfo {
/// The pipeline ID of this iframe.
pub pipeline_id: PipelineId,
/// The subpage ID of this iframe.
pub subpage_id: SubpageId,
}
impl IframeFragmentInfo {
@@ -497,17 +502,17 @@ impl IframeFragmentInfo {
}
}
}
/// A scanned text fragment represents a single run of text with a distinct style. A `TextFragment`
/// may be split into two or more fragments across line breaks. Several `TextFragment`s may
/// correspond to a single DOM text node. Split text fragments are implemented by referring to
/// subsets of a single `TextRun` object.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct ScannedTextFragmentInfo {
/// The text run that this represents.
pub run: Arc<Box<TextRun>>,
/// The range within the above text run that this represents.
pub range: Range<CharIndex>,
/// The positions of newlines within this scanned text fragment.
@@ -538,17 +543,17 @@ impl ScannedTextFragmentInfo {
original_new_line_pos: None,
content_size: content_size,
}
}
}
/// Describes how to split a fragment. This is used during line breaking as part of the return
/// value of `find_split_info_for_inline_size()`.
-#[deriving(Show, Clone)]
+#[derive(Show, Clone)]
pub struct SplitInfo {
// TODO(bjz): this should only need to be a single character index, but both values are
// currently needed for splitting in the `inline::try_append_*` functions.
pub range: Range<CharIndex>,
pub inline_size: Au,
}
impl SplitInfo {
@@ -567,17 +572,17 @@ pub struct SplitResult {
/// The part of the fragment that goes on the second line.
pub inline_end: Option<SplitInfo>,
/// The text run which is being split.
pub text_run: Arc<Box<TextRun>>,
}
/// Data for an unscanned text fragment. Unscanned text fragments are the results of flow
/// construction that have not yet had their inline-size determined.
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct UnscannedTextFragmentInfo {
/// The text inside the fragment.
///
/// FIXME(pcwalton): Is there something more clever we can do here that avoids the double
/// indirection while not penalizing all fragments?
pub text: Box<String>,
}
@@ -595,17 +600,17 @@ impl UnscannedTextFragmentInfo {
pub fn from_text(text: String) -> UnscannedTextFragmentInfo {
UnscannedTextFragmentInfo {
text: box text,
}
}
}
/// A fragment that represents a table column.
-#[deriving(Copy, Clone)]
+#[derive(Copy, Clone)]
pub struct TableColumnFragmentInfo {
/// the number of columns a <col> element should span
pub span: int,
}
impl TableColumnFragmentInfo {
/// Create the information specific to an table column fragment.
pub fn new(node: &ThreadSafeLayoutNode) -> TableColumnFragmentInfo {
@@ -738,28 +743,28 @@ impl Fragment {
self.border_padding = LogicalMargin::zero(self.style.writing_mode);
self.margin = LogicalMargin::zero(self.style.writing_mode);
}
/// Saves the new_line_pos vector into a `SpecificFragmentInfo::ScannedText`. This will fail
/// if called on any other type of fragment.
pub fn save_new_line_pos(&mut self) {
match &mut self.specific {
- &SpecificFragmentInfo::ScannedText(ref mut info) => {
+ &mut SpecificFragmentInfo::ScannedText(ref mut info) => {
if !info.new_line_pos.is_empty() {
info.original_new_line_pos = Some(info.new_line_pos.clone());
}
}
_ => {}
}
}
pub fn restore_new_line_pos(&mut self) {
match &mut self.specific {
- &SpecificFragmentInfo::ScannedText(ref mut info) => {
+ &mut SpecificFragmentInfo::ScannedText(ref mut info) => {
match info.original_new_line_pos.take() {
None => {}
Some(new_line_pos) => info.new_line_pos = new_line_pos,
}
return
}
_ => {}
}
@@ -1273,17 +1278,17 @@ impl Fragment {
panic!("Unscanned text fragments should have been scanned by now!")
}
SpecificFragmentInfo::InlineBlock(_) |
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {
panic!("Inline blocks or inline absolute hypothetical fragments do not get split")
}
SpecificFragmentInfo::ScannedText(ref text_fragment_info) => {
let mut new_line_pos = text_fragment_info.new_line_pos.clone();
- let cur_new_line_pos = new_line_pos.remove(0).unwrap();
+ let cur_new_line_pos = new_line_pos.remove(0);
let inline_start_range = Range::new(text_fragment_info.range.begin(),
cur_new_line_pos);
let inline_end_range = Range::new(
text_fragment_info.range.begin() + cur_new_line_pos + CharIndex(1),
text_fragment_info.range.length() - (cur_new_line_pos + CharIndex(1)));
// Left fragment is for inline-start text of first founded new-line character.
@@ -1350,38 +1355,38 @@ impl Fragment {
/// A helper method that uses the breaking strategy described by `slice_iterator` (at present,
/// either natural word breaking or character breaking) to split this fragment.
fn calculate_split_position_using_breaking_strategy<'a,I>(&self,
mut slice_iterator: I,
max_inline_size: Au,
flags: SplitOptions)
-> Option<SplitResult>
- where I: Iterator<TextRunSlice<'a>> {
+ where I: Iterator<Item=TextRunSlice<'a>> {
let text_fragment_info =
if let SpecificFragmentInfo::ScannedText(ref text_fragment_info) = self.specific {
text_fragment_info
} else {
return None
};
let mut pieces_processed_count: uint = 0;
let mut remaining_inline_size = max_inline_size;
let mut inline_start_range = Range::new(text_fragment_info.range.begin(), CharIndex(0));
let mut inline_end_range = None;
- debug!("calculate_split_position: splitting text fragment (strlen={}, range={}, \
- max_inline_size={})",
+ debug!("calculate_split_position: splitting text fragment (strlen={}, range={:?}, \
+ max_inline_size={:?})",
text_fragment_info.run.text.len(),
text_fragment_info.range,
max_inline_size);
for slice in slice_iterator {
- debug!("calculate_split_position: considering slice (offset={}, slice range={}, \
- remaining_inline_size={})",
+ debug!("calculate_split_position: considering slice (offset={:?}, slice range={:?}, \
+ remaining_inline_size={:?})",
slice.offset,
slice.range,
remaining_inline_size);
let metrics = text_fragment_info.run.metrics_for_slice(slice.glyphs, &slice.range);
let advance = metrics.advance_width;
// Have we found the split point?
@@ -1403,17 +1408,17 @@ impl Fragment {
// The advance is more than the remaining inline-size, so split here.
let slice_begin = slice.text_run_range().begin();
if slice_begin < text_fragment_info.range.end() {
// There still some things left over at the end of the line, so create the
// inline-end chunk.
let mut inline_end = slice.text_run_range();
inline_end.extend_to(text_fragment_info.range.end());
inline_end_range = Some(inline_end);
- debug!("calculate_split_position: splitting remainder with inline-end range={}",
+ debug!("calculate_split_position: splitting remainder with inline-end range={:?}",
inline_end);
}
pieces_processed_count += 1;
break
}
// If we failed to find a suitable split point, we're on the verge of overflowing the line.
@@ -1811,19 +1816,19 @@ impl Fragment {
// box too.
overflow
}
}
impl fmt::Show for Fragment {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "({} {} ", self.debug_id(), self.specific.get_type()));
- try!(write!(f, "bp {}", self.border_padding));
+ try!(write!(f, "bp {:?}", self.border_padding));
try!(write!(f, " "));
- try!(write!(f, "m {}", self.margin));
+ try!(write!(f, "m {:?}", self.margin));
write!(f, ")")
}
}
bitflags! {
flags QuantitiesIncludedInIntrinsicInlineSizes: u8 {
const INTRINSIC_INLINE_SIZE_INCLUDES_MARGINS = 0x01,
const INTRINSIC_INLINE_SIZE_INCLUDES_PADDING = 0x02,
@@ -1851,16 +1856,16 @@ pub trait FragmentBorderBoxIterator {
/// Returns true if this fragment must be processed in-order. If this returns false,
/// we skip the operation for this fragment, but continue processing siblings.
fn should_process(&mut self, fragment: &Fragment) -> bool;
}
/// The coordinate system used in `stacking_relative_border_box()`. See the documentation of that
/// method for details.
-#[deriving(Clone, PartialEq, Show)]
+#[derive(Clone, PartialEq, Show)]
pub enum CoordinateSystem {
/// The border box returned is relative to the fragment's parent stacking context.
Parent,
/// The border box returned is relative to the fragment's own stacking context, if applicable.
Self,
}
--- a/servo/components/layout/incremental.rs
+++ b/servo/components/layout/incremental.rs
@@ -7,17 +7,16 @@ use flow::{IS_ABSOLUTELY_POSITIONED};
use std::fmt;
use std::sync::Arc;
use style::computed_values::float;
use style::ComputedValues;
bitflags! {
#[doc = "Individual layout actions that may be necessary after restyling."]
- #[deriving(Copy)]
flags RestyleDamage: u8 {
#[doc = "Repaint the node itself."]
#[doc = "Currently unused; need to decide how this propagates."]
const REPAINT = 0x01,
#[doc = "Recompute intrinsic inline_sizes (minimum and preferred)."]
#[doc = "Propagates down the flow tree because the computation is"]
#[doc = "bottom-up."]
@@ -120,17 +119,17 @@ impl fmt::Show for RestyleDamage {
// breakage on modifications.
macro_rules! add_if_not_equal(
($old:ident, $new:ident, $damage:ident,
[ $($effect:ident),* ], [ $($style_struct_getter:ident.$name:ident),* ]) => ({
if $( ($old.$style_struct_getter().$name != $new.$style_struct_getter().$name) )||* {
$damage.insert($($effect)|*);
}
})
-)
+);
pub fn compute_damage(old: &Option<Arc<ComputedValues>>, new: &ComputedValues) -> RestyleDamage {
let old: &ComputedValues =
match old.as_ref() {
None => return RestyleDamage::all(),
Some(cv) => &**cv,
};
--- a/servo/components/layout/inline.rs
+++ b/servo/components/layout/inline.rs
@@ -26,16 +26,18 @@ use gfx::font_context::FontContext;
use gfx::text::glyph::CharIndex;
use servo_util::arc_ptr_eq;
use servo_util::geometry::{Au, ZERO_RECT};
use servo_util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
use servo_util::range::{Range, RangeIndex};
use std::cmp::max;
use std::fmt;
use std::mem;
+use std::num::ToPrimitive;
+use std::ops::{Add, Sub, Mul, Div, Rem, Neg, Shl, Shr, Not, BitOr, BitAnd, BitXor};
use std::u16;
use style::computed_values::{text_align, vertical_align, white_space};
use style::ComputedValues;
use std::sync::Arc;
// From gfxFontConstants.h in Firefox
static FONT_SUBSCRIPT_OFFSET_RATIO: f64 = 0.20;
static FONT_SUPERSCRIPT_OFFSET_RATIO: f64 = 0.34;
@@ -60,17 +62,17 @@ static FONT_SUPERSCRIPT_OFFSET_RATIO: f6
/// serve as the starting point, but the current design doesn't make it
/// hard to try out that alternative.
///
/// Line fragments also contain some metadata used during line breaking. The
/// green zone is the area that the line can expand to before it collides
/// with a float or a horizontal wall of the containing block. The block-start
/// inline-start corner of the green zone is the same as that of the line, but
/// the green zone can be taller and wider than the line itself.
-#[deriving(Encodable, Show, Copy)]
+#[derive(RustcEncodable, Show, Copy)]
pub struct Line {
/// A range of line indices that describe line breaks.
///
/// For example, consider the following HTML and rendered element with
/// linebreaks:
///
/// ~~~html
/// <span>I <span>like truffles, <img></span> yes I do.</span>
@@ -145,17 +147,17 @@ pub struct Line {
/// === line
/// ::: green zone
/// FFF float
/// ~~~
pub green_zone: LogicalSize<Au>,
}
int_range_index! {
- #[deriving(Encodable)]
+ #[derive(RustcEncodable)]
#[doc = "The index of a fragment in a flattened vector of DOM elements."]
struct FragmentIndex(int)
}
bitflags! {
flags InlineReflowFlags: u8 {
#[doc="The `white-space: nowrap` property from CSS 2.1 § 16.6 is in effect."]
const NO_WRAP_INLINE_REFLOW_FLAG = 0x01
@@ -251,17 +253,17 @@ impl LineBreaker {
flow.lines = mem::replace(&mut self.lines, Vec::new());
}
/// Reflows the given fragments, which have been plucked out of the inline flow.
fn reflow_fragments<'a,I>(&mut self,
mut old_fragment_iter: I,
flow: &'a InlineFlow,
layout_context: &LayoutContext)
- where I: Iterator<Fragment> {
+ where I: Iterator<Item=Fragment> {
loop {
// Acquire the next fragment to lay out from the work list or fragment list, as
// appropriate.
let fragment = match self.next_unbroken_fragment(&mut old_fragment_iter) {
None => break,
Some(fragment) => fragment,
};
@@ -300,54 +302,54 @@ impl LineBreaker {
self.flush_current_line()
}
}
/// Acquires a new fragment to lay out from the work list or fragment list as appropriate.
/// Note that you probably don't want to call this method directly in order to be
/// incremental-reflow-safe; try `next_unbroken_fragment` instead.
fn next_fragment<I>(&mut self, old_fragment_iter: &mut I) -> Option<Fragment>
- where I: Iterator<Fragment> {
+ where I: Iterator<Item=Fragment> {
if self.work_list.is_empty() {
return match old_fragment_iter.next() {
None => None,
Some(fragment) => {
- debug!("LineBreaker: working with fragment from flow: {}", fragment);
+ debug!("LineBreaker: working with fragment from flow: {:?}", fragment);
Some(fragment)
}
}
}
- debug!("LineBreaker: working with fragment from work list: {}", self.work_list.front());
+ debug!("LineBreaker: working with fragment from work list: {:?}", self.work_list.front());
self.work_list.pop_front()
}
/// Acquires a new fragment to lay out from the work list or fragment list, merging it with any
/// subsequent fragments as appropriate. In effect, what this method does is to return the next
/// fragment to lay out, undoing line break operations that any previous reflows may have
/// performed. You probably want to be using this method instead of `next_fragment`.
fn next_unbroken_fragment<I>(&mut self, old_fragment_iter: &mut I) -> Option<Fragment>
- where I: Iterator<Fragment> {
+ where I: Iterator<Item=Fragment> {
let mut result = match self.next_fragment(old_fragment_iter) {
None => return None,
Some(fragment) => fragment,
};
loop {
// FIXME(pcwalton): Yuck! I hate this `new_line_pos` stuff. Can we avoid having to do
// this?
result.restore_new_line_pos();
let candidate = match self.next_fragment(old_fragment_iter) {
None => return Some(result),
Some(fragment) => fragment,
};
let need_to_merge = match (&mut result.specific, &candidate.specific) {
- (&SpecificFragmentInfo::ScannedText(ref mut result_info),
+ (&mut SpecificFragmentInfo::ScannedText(ref mut result_info),
&SpecificFragmentInfo::ScannedText(ref candidate_info))
if arc_ptr_eq(&result_info.run, &candidate_info.run) &&
result_info.range.end() + CharIndex(1) == candidate_info.range.begin() => {
// We found a previously-broken fragment. Merge it up.
result_info.range.extend_by(candidate_info.range.length() + CharIndex(1));
true
}
_ => false,
@@ -357,17 +359,17 @@ impl LineBreaker {
self.work_list.push_front(candidate);
return Some(result)
}
}
}
/// Commits a line to the list.
fn flush_current_line(&mut self) {
- debug!("LineBreaker: flushing line {}: {}", self.lines.len(), self.pending_line);
+ debug!("LineBreaker: flushing line {}: {:?}", self.lines.len(), self.pending_line);
self.lines.push(self.pending_line);
self.cur_b = self.pending_line.bounds.start.b + self.pending_line.bounds.size.block;
self.reset_line();
}
// FIXME(eatkinson): this assumes that the tallest fragment in the line determines the line
// block-size. This might not be the case with some weird text fonts.
fn new_block_size_for_line(&self, new_fragment: &Fragment, layout_context: &LayoutContext)
@@ -383,17 +385,17 @@ impl LineBreaker {
/// Computes the position of a line that has only the provided fragment. Returns the bounding
/// rect of the line's green zone (whose origin coincides with the line's origin) and the
/// actual inline-size of the first fragment after splitting.
fn initial_line_placement(&self,
flow: &InlineFlow,
first_fragment: &Fragment,
ceiling: Au)
-> (LogicalRect<Au>, Au) {
- debug!("LineBreaker: trying to place first fragment of line {}; fragment size: {}, \
+ debug!("LineBreaker: trying to place first fragment of line {}; fragment size: {:?}, \
splittable: {}",
self.lines.len(),
first_fragment.border_box.size,
first_fragment.can_split());
// Initially, pretend a splittable fragment has zero inline-size. We will move it later if
// it has nonzero inline-size and that causes problems.
let placement_inline_size = if first_fragment.can_split() {
@@ -491,17 +493,17 @@ impl LineBreaker {
debug!("LineBreaker: Found a new-line character, so splitting the line.");
let (inline_start, inline_end, run) =
in_fragment.find_split_info_by_new_line()
.expect("LineBreaker: this split case makes no sense!");
let writing_mode = self.floats.writing_mode;
- let split_fragment = |split: SplitInfo| {
+ let split_fragment = |&:split: SplitInfo| {
let info = box ScannedTextFragmentInfo::new(run.clone(),
split.range,
(*in_fragment.newline_positions()
.unwrap()).clone(),
in_fragment.border_box.size);
let size = LogicalSize::new(writing_mode,
split.inline_size,
in_fragment.border_box.size.block);
@@ -536,17 +538,17 @@ impl LineBreaker {
-> bool {
// Determine initial placement for the fragment if we need to.
if self.pending_line_is_empty() {
let (line_bounds, _) = self.initial_line_placement(flow, &fragment, self.cur_b);
self.pending_line.bounds.start = line_bounds.start;
self.pending_line.green_zone = line_bounds.size;
}
- debug!("LineBreaker: trying to append to line {} (fragment size: {}, green zone: {}): {}",
+ debug!("LineBreaker: trying to append to line {} (fragment size: {:?}, green zone: {:?}): {:?}",
self.lines.len(),
fragment.border_box.size,
self.pending_line.green_zone,
fragment);
// NB: At this point, if `green_zone.inline < self.pending_line.bounds.size.inline` or
// `green_zone.block < self.pending_line.bounds.size.block`, then we committed a line that
// overlaps with floats.
@@ -581,23 +583,23 @@ impl LineBreaker {
// Split it up!
let available_inline_size = green_zone.inline - self.pending_line.bounds.size.inline -
indentation;
let (inline_start_fragment, inline_end_fragment) =
match fragment.calculate_split_position(available_inline_size,
self.pending_line_is_empty()) {
None => {
- debug!("LineBreaker: fragment was unsplittable; deferring to next line: {}",
+ debug!("LineBreaker: fragment was unsplittable; deferring to next line: {:?}",
fragment);
self.work_list.push_front(fragment);
return false
}
Some(split_result) => {
- let split_fragment = |split: SplitInfo| {
+ let split_fragment = |&:split: SplitInfo| {
let info = box ScannedTextFragmentInfo::new(split_result.text_run.clone(),
split.range,
Vec::new(),
fragment.border_box.size);
let size = LogicalSize::new(self.floats.writing_mode,
split.inline_size,
fragment.border_box.size.block);
fragment.transform(size, info)
@@ -652,25 +654,25 @@ impl LineBreaker {
/// Returns true if the pending line is empty and false otherwise.
fn pending_line_is_empty(&self) -> bool {
self.pending_line.range.length() == FragmentIndex(0)
}
}
/// Represents a list of inline fragments, including element ranges.
-#[deriving(Encodable, Clone)]
+#[derive(RustcEncodable, Clone)]
pub struct InlineFragments {
/// The fragments themselves.
pub fragments: Vec<Fragment>,
}
impl fmt::Show for InlineFragments {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}", self.fragments)
+ write!(f, "{:?}", self.fragments)
}
}
impl InlineFragments {
/// Creates an empty set of inline fragments.
pub fn new() -> InlineFragments {
InlineFragments {
@@ -706,17 +708,17 @@ impl InlineFragments {
/// A convenience function to return a mutable reference to the fragment at a given index.
pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut Fragment {
&mut self.fragments[index]
}
}
/// Flows for inline layout.
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
pub struct InlineFlow {
/// Data common to all flows.
pub base: BaseFlow,
/// A vector of all inline fragments. Several fragments may correspond to one node/element.
pub fragments: InlineFragments,
/// A vector of ranges into fragments that represents line positions. These ranges are disjoint
@@ -961,33 +963,33 @@ impl Flow for InlineFlow {
let writing_mode = self.base.writing_mode;
for kid in self.base.child_iter() {
flow::mut_base(kid).floats = Floats::new(writing_mode);
}
let mut computation = IntrinsicISizesContribution::new();
for fragment in self.fragments.fragments.iter_mut() {
- debug!("Flow: measuring {}", *fragment);
+ debug!("Flow: measuring {:?}", *fragment);
computation.union_inline(&fragment.compute_intrinsic_inline_sizes().finish())
}
self.base.intrinsic_inline_sizes = computation.finish()
}
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments.
/// When called on this context, the context has had its inline-size set by the parent context.
fn assign_inline_sizes(&mut self, _: &LayoutContext) {
let _scope = layout_debug_scope!("inline::assign_inline_sizes {:x}", self.base.debug_id());
// Initialize content fragment inline-sizes if they haven't been initialized already.
//
// TODO: Combine this with `LineBreaker`'s walk in the fragment list, or put this into
// `Fragment`.
- debug!("InlineFlow::assign_inline_sizes: floats in: {}", self.base.floats);
+ debug!("InlineFlow::assign_inline_sizes: floats in: {:?}", self.base.floats);
self.base.position.size.inline = self.base.block_container_inline_size;
{
let inline_size = self.base.position.size.inline;
let this = &mut *self;
for fragment in this.fragments.fragments.iter_mut() {
fragment.compute_border_and_padding(inline_size);
@@ -1017,17 +1019,17 @@ impl Flow for InlineFlow {
//
// TODO(pcwalton, #226): Get the CSS `line-height` property from the style of the
// containing block to determine the minimum line block size.
//
// TODO(pcwalton, #226): Get the CSS `line-height` property from each non-replaced inline
// element to determine its block-size for computing the line's own block-size.
//
// TODO(pcwalton): Cache the line scanner?
- debug!("assign_block_size_inline: floats in: {}", self.base.floats);
+ debug!("assign_block_size_inline: floats in: {:?}", self.base.floats);
// Assign the block-size for the inline fragments.
let containing_block_block_size =
self.base.block_container_explicit_block_size.unwrap_or(Au(0));
for fragment in self.fragments.fragments.iter_mut() {
fragment.assign_replaced_block_size_if_necessary(
containing_block_block_size);
}
@@ -1249,21 +1251,21 @@ impl Flow for InlineFlow {
CoordinateSystem::Parent)
.translate(stacking_context_position))
}
}
}
impl fmt::Show for InlineFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{} - {:x} - {}", self.class(), self.base.debug_id(), self.fragments)
+ write!(f, "{:?} - {:x} - {:?}", self.class(), self.base.debug_id(), self.fragments)
}
}
-#[deriving(Clone)]
+#[derive(Clone)]
pub struct InlineFragmentContext {
pub styles: Vec<Arc<ComputedValues>>,
}
impl InlineFragmentContext {
pub fn new() -> InlineFragmentContext {
InlineFragmentContext {
styles: vec!()
--- a/servo/components/layout/layout_debug.rs
+++ b/servo/components/layout/layout_debug.rs
@@ -9,36 +9,36 @@
use flow_ref::FlowRef;
use flow;
use serialize::json;
use std::borrow::ToOwned;
use std::cell::RefCell;
use std::io::File;
-use std::sync::atomic::{AtomicUint, Ordering, INIT_ATOMIC_UINT};
+use std::sync::atomic::{AtomicUint, Ordering, ATOMIC_UINT_INIT};
-thread_local!(static STATE_KEY: RefCell<Option<State>> = RefCell::new(None))
+thread_local!(static STATE_KEY: RefCell<Option<State>> = RefCell::new(None));
-static mut DEBUG_ID_COUNTER: AtomicUint = INIT_ATOMIC_UINT;
+static mut DEBUG_ID_COUNTER: AtomicUint = ATOMIC_UINT_INIT;
pub struct Scope;
#[macro_export]
macro_rules! layout_debug_scope(
($($arg:tt)*) => (
if cfg!(not(ndebug)) {
layout_debug::Scope::new(format!($($arg)*))
} else {
layout_debug::Scope
}
)
-)
+);
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
struct ScopeData {
name: String,
pre: String,
post: String,
children: Vec<Box<ScopeData>>,
}
impl ScopeData {
@@ -58,40 +58,40 @@ struct State {
}
/// A layout debugging scope. The entire state of the flow tree
/// will be output at the beginning and end of this scope.
impl Scope {
pub fn new(name: String) -> Scope {
STATE_KEY.with(|ref r| {
match &mut *r.borrow_mut() {
- &Some(ref mut state) => {
+ &mut Some(ref mut state) => {
let flow_trace = json::encode(&flow::base(&*state.flow_root));
let data = box ScopeData::new(name.clone(), flow_trace);
state.scope_stack.push(data);
}
- &None => {}
+ &mut None => {}
}
});
Scope
}
}
#[cfg(not(ndebug))]
impl Drop for Scope {
fn drop(&mut self) {
STATE_KEY.with(|ref r| {
match &mut *r.borrow_mut() {
- &Some(ref mut state) => {
+ &mut Some(ref mut state) => {
let mut current_scope = state.scope_stack.pop().unwrap();
current_scope.post = json::encode(&flow::base(&*state.flow_root));
let previous_scope = state.scope_stack.last_mut().unwrap();
previous_scope.children.push(current_scope);
}
- &None => {}
+ &mut None => {}
}
});
}
}
/// Generate a unique ID. This is used for items such as Fragment
/// which are often reallocated but represent essentially the
/// same data.
--- a/servo/components/layout/layout_task.rs
+++ b/servo/components/layout/layout_task.rs
@@ -2,17 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! The layout task. Performs layout on the DOM, builds display lists and sends them to be
//! painted.
use css::node_style::StyledNode;
use construct::ConstructionResult;
-use context::SharedLayoutContext;
+use context::{SharedLayoutContext, SharedLayoutContextWrapper};
use flow::{mod, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use flow_ref::FlowRef;
use fragment::{Fragment, FragmentBorderBoxIterator};
use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT};
use layout_debug;
use parallel::{mod, UnsafeFlow};
use sequential;
use util::{LayoutDataAccess, LayoutDataWrapper, OpaqueNodeMethods, ToGfxColor};
@@ -56,17 +56,18 @@ use servo_util::opts;
use servo_util::smallvec::{SmallVec, SmallVec1, VecLike};
use servo_util::task::spawn_named_with_send_on_failure;
use servo_util::task_state;
use servo_util::time::{TimeProfilerCategory, ProfilerMetadata, TimeProfilerChan};
use servo_util::time::{TimerMetadataFrameType, TimerMetadataReflowType, profile};
use servo_util::workqueue::WorkQueue;
use std::borrow::ToOwned;
use std::cell::Cell;
-use std::comm::{channel, Sender, Receiver, Select};
+use std::ops::{Deref, DerefMut};
+use std::sync::mpsc::{channel, Sender, Receiver, Select};
use std::mem;
use std::ptr;
use style::computed_values::{filter, mix_blend_mode};
use style::{StylesheetOrigin, Stylesheet, Stylist, TNode, iter_font_face_rules};
use style::{MediaType, Device};
use std::sync::{Arc, Mutex, MutexGuard};
use url::Url;
@@ -84,17 +85,17 @@ pub struct LayoutTaskData {
pub screen_size: Size2D<Au>,
/// The root stacking context.
pub stacking_context: Option<Arc<StackingContext>>,
pub stylist: Box<Stylist>,
/// The workers that we use for parallel operation.
- pub parallel_traversal: Option<WorkQueue<*const SharedLayoutContext, UnsafeFlow>>,
+ pub parallel_traversal: Option<WorkQueue<SharedLayoutContextWrapper, UnsafeFlow>>,
/// The dirty rect. Used during display list construction.
pub dirty: Rect<Au>,
/// Starts at zero, and increased by one every time a layout completes.
/// This can be used to easily check for invalid stale data.
pub generation: uint,
@@ -148,29 +149,27 @@ pub struct LayoutTask {
}
struct LayoutImageResponder {
id: PipelineId,
script_chan: ScriptControlChan,
}
impl ImageResponder<UntrustedNodeAddress> for LayoutImageResponder {
- fn respond(&self) -> proc(ImageResponseMsg, UntrustedNodeAddress):Send {
+ fn respond(&self) -> Box<Fn(ImageResponseMsg, UntrustedNodeAddress)+Send> {
let id = self.id.clone();
let script_chan = self.script_chan.clone();
- let f: proc(ImageResponseMsg, UntrustedNodeAddress):Send =
- proc(_, node_address) {
- let ScriptControlChan(chan) = script_chan;
- debug!("Dirtying {:x}", node_address.0 as uint);
- let mut nodes = SmallVec1::new();
- nodes.vec_push(node_address);
- drop(chan.send_opt(ConstellationControlMsg::SendEvent(
- id.clone(), CompositorEvent::ReflowEvent(nodes))))
- };
- f
+ box move |&:_, node_address| {
+ let ScriptControlChan(ref chan) = script_chan;
+ debug!("Dirtying {:x}", node_address.0 as uint);
+ let mut nodes = SmallVec1::new();
+ nodes.vec_push(node_address);
+ drop(chan.send(ConstellationControlMsg::SendEvent(
+ id, CompositorEvent::ReflowEvent(nodes))))
+ }
}
}
impl LayoutTaskFactory for LayoutTask {
/// Spawns a new layout task.
fn create(_phantom: Option<&mut LayoutTask>,
id: PipelineId,
chan: OpaqueScriptLayoutChannel,
@@ -180,17 +179,17 @@ impl LayoutTaskFactory for LayoutTask {
script_chan: ScriptControlChan,
paint_chan: PaintChan,
resource_task: ResourceTask,
img_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
time_profiler_chan: TimeProfilerChan,
shutdown_chan: Sender<()>) {
let ConstellationChan(con_chan) = constellation_chan.clone();
- spawn_named_with_send_on_failure("LayoutTask", task_state::LAYOUT, proc() {
+ spawn_named_with_send_on_failure("LayoutTask", task_state::LAYOUT, move || {
{ // Ensures layout task is destroyed before we send shutdown message
let sender = chan.sender();
let layout =
LayoutTask::new(
id,
chan.receiver(),
LayoutChan(sender),
pipeline_port,
@@ -214,26 +213,27 @@ impl LayoutTaskFactory for LayoutTask {
enum RWGuard<'a> {
/// If the lock was previously held, from when the task started.
Held(MutexGuard<'a, LayoutTaskData>),
/// If the lock was just used, and has been returned since there has been
/// a reflow already.
Used(MutexGuard<'a, LayoutTaskData>),
}
-impl<'a> Deref<LayoutTaskData> for RWGuard<'a> {
+impl<'a> Deref for RWGuard<'a> {
+ type Target = LayoutTaskData;
fn deref(&self) -> &LayoutTaskData {
match *self {
RWGuard::Held(ref x) => &**x,
RWGuard::Used(ref x) => &**x,
}
}
}
-impl<'a> DerefMut<LayoutTaskData> for RWGuard<'a> {
+impl<'a> DerefMut for RWGuard<'a> {
fn deref_mut(&mut self) -> &mut LayoutTaskData {
match *self {
RWGuard::Held(ref mut x) => &mut **x,
RWGuard::Used(ref mut x) => &mut **x,
}
}
}
@@ -252,17 +252,17 @@ impl LayoutTask {
time_profiler_chan: TimeProfilerChan)
-> LayoutTask {
let local_image_cache =
Arc::new(Mutex::new(LocalImageCache::new(image_cache_task.clone())));
let screen_size = Size2D(Au(0), Au(0));
let device = Device::new(MediaType::Screen, opts::get().initial_window_size.as_f32() * ScaleFactor(1.0));
let parallel_traversal = if opts::get().layout_threads != 1 {
Some(WorkQueue::new("LayoutWorker", task_state::LAYOUT,
- opts::get().layout_threads, ptr::null()))
+ opts::get().layout_threads, SharedLayoutContextWrapper(ptr::null())))
} else {
None
};
LayoutTask {
id: id,
port: port,
pipeline_port: pipeline_port,
@@ -287,17 +287,17 @@ impl LayoutTask {
content_box_response: Rect::zero(),
content_boxes_response: Vec::new(),
})),
}
}
/// Starts listening on the port.
fn start(self) {
- let mut possibly_locked_rw_data = Some(self.rw_data.lock());
+ let mut possibly_locked_rw_data = Some((*self.rw_data).lock().unwrap());
while self.handle_request(&mut possibly_locked_rw_data) {
// Loop indefinitely.
}
}
// Create a layout context for use in building display lists, hit testing, &c.
fn build_shared_layout_context(&self,
rw_data: &LayoutTaskData,
@@ -342,40 +342,40 @@ impl LayoutTask {
PortToRead::Pipeline
} else {
panic!("invalid select result");
}
};
match port_to_read {
PortToRead::Pipeline => {
- match self.pipeline_port.recv() {
+ match self.pipeline_port.recv().unwrap() {
LayoutControlMsg::ExitNowMsg(exit_type) => {
self.handle_script_request(Msg::ExitNow(exit_type), possibly_locked_rw_data)
}
}
},
PortToRead::Script => {
- let msg = self.port.recv();
+ let msg = self.port.recv().unwrap();
self.handle_script_request(msg, possibly_locked_rw_data)
}
}
}
/// If no reflow has happened yet, this will just return the lock in
/// `possibly_locked_rw_data`. Otherwise, it will acquire the `rw_data` lock.
///
/// If you do not wish RPCs to remain blocked, just drop the `RWGuard`
/// returned from this function. If you _do_ wish for them to remain blocked,
/// use `return_rw_data`.
fn lock_rw_data<'a>(&'a self,
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>)
-> RWGuard<'a> {
match possibly_locked_rw_data.take() {
- None => RWGuard::Used(self.rw_data.lock()),
+ None => RWGuard::Used((*self.rw_data).lock().unwrap()),
Some(x) => RWGuard::Held(x),
}
}
/// If no reflow has ever been triggered, this will keep the lock, locked
/// (and saved in `possibly_locked_rw_data`). If it has been, the lock will
/// be unlocked.
fn return_rw_data<'a>(possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>,
@@ -429,17 +429,17 @@ impl LayoutTask {
/// Enters a quiescent state in which no new messages except for `layout_interface::Msg::ReapLayoutData` will be
/// processed until an `ExitNowMsg` is received. A pong is immediately sent on the given
/// response channel.
fn prepare_to_exit<'a>(&'a self,
response_chan: Sender<()>,
possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) {
response_chan.send(());
loop {
- match self.port.recv() {
+ match self.port.recv().unwrap() {
Msg::ReapLayoutData(dead_layout_data) => {
unsafe {
LayoutTask::handle_reap_layout_data(dead_layout_data)
}
}
Msg::ExitNow(exit_type) => {
debug!("layout task is exiting...");
self.exit_now(possibly_locked_rw_data, exit_type);
@@ -465,17 +465,17 @@ impl LayoutTask {
match (&mut *rw_data).parallel_traversal {
None => {}
Some(ref mut traversal) => traversal.shutdown(),
}
LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data);
}
self.paint_chan.send(PaintMsg::Exit(Some(response_chan), exit_type));
- response_port.recv()
+ response_port.recv().unwrap()
}
fn handle_load_stylesheet<'a>(&'a self,
url: Url,
possibly_locked_rw_data:
&mut Option<MutexGuard<'a, LayoutTaskData>>) {
// TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding
let environment_encoding = UTF_8 as EncodingRef;
@@ -494,17 +494,17 @@ impl LayoutTask {
fn handle_add_stylesheet<'a>(&'a self,
sheet: Stylesheet,
possibly_locked_rw_data:
&mut Option<MutexGuard<'a, LayoutTaskData>>) {
// Find all font-face rules and notify the font cache of them.
// GWTODO: Need to handle unloading web fonts (when we handle unloading stylesheets!)
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
- iter_font_face_rules(&sheet, &rw_data.stylist.device, |family, src| {
+ iter_font_face_rules(&sheet, &rw_data.stylist.device, &|&:family, src| {
self.font_cache_task.add_web_font(family.to_owned(), (*src).clone());
});
rw_data.stylist.add_stylesheet(sheet);
LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data);
}
/// Sets quirks mode for the document, causing the quirks mode stylesheet to be loaded.
fn handle_set_quirks_mode<'a>(&'a self,
@@ -729,17 +729,17 @@ impl LayoutTask {
if log_enabled!(log::DEBUG) {
node.dump();
}
let mut rw_data = self.lock_rw_data(possibly_locked_rw_data);
{
// Reset the image cache.
- let mut local_image_cache = rw_data.local_image_cache.lock();
+ let mut local_image_cache = rw_data.local_image_cache.lock().unwrap();
local_image_cache.next_round(self.make_on_image_available_cb());
}
// TODO: Calculate the "actual viewport":
// http://www.w3.org/TR/css-device-adapt/#actual-viewport
let viewport_size = data.window_size.initial_viewport;
let old_screen_size = rw_data.screen_size;
@@ -941,33 +941,33 @@ impl LayoutTask {
struct LayoutRPCImpl(Arc<Mutex<LayoutTaskData>>);
impl LayoutRPC for LayoutRPCImpl {
// The neat thing here is that in order to answer the following two queries we only
// need to compare nodes for equality. Thus we can safely work only with `OpaqueNode`.
fn content_box(&self) -> ContentBoxResponse {
let &LayoutRPCImpl(ref rw_data) = self;
- let rw_data = rw_data.lock();
+ let rw_data = rw_data.lock().unwrap();
ContentBoxResponse(rw_data.content_box_response)
}
/// Requests the dimensions of all the content boxes, as in the `getClientRects()` call.
fn content_boxes(&self) -> ContentBoxesResponse {
let &LayoutRPCImpl(ref rw_data) = self;
- let rw_data = rw_data.lock();
+ let rw_data = rw_data.lock().unwrap();
ContentBoxesResponse(rw_data.content_boxes_response.clone())
}
/// Requests the node containing the point of interest.
fn hit_test(&self, _: TrustedNodeAddress, point: Point2D<f32>) -> Result<HitTestResponse, ()> {
let point = Point2D(Au::from_frac_px(point.x as f64), Au::from_frac_px(point.y as f64));
let resp = {
let &LayoutRPCImpl(ref rw_data) = self;
- let rw_data = rw_data.lock();
+ let rw_data = rw_data.lock().unwrap();
match rw_data.stacking_context {
None => panic!("no root stacking context!"),
Some(ref stacking_context) => {
let mut result = Vec::new();
stacking_context.hit_test(point, &mut result, true);
if !result.is_empty() {
Some(HitTestResponse(result[0].node.to_untrusted_node_address()))
} else {
@@ -984,17 +984,17 @@ impl LayoutRPC for LayoutRPCImpl {
}
fn mouse_over(&self, _: TrustedNodeAddress, point: Point2D<f32>)
-> Result<MouseOverResponse, ()> {
let mut mouse_over_list: Vec<DisplayItemMetadata> = vec!();
let point = Point2D(Au::from_frac_px(point.x as f64), Au::from_frac_px(point.y as f64));
{
let &LayoutRPCImpl(ref rw_data) = self;
- let rw_data = rw_data.lock();
+ let rw_data = rw_data.lock().unwrap();
match rw_data.stacking_context {
None => panic!("no root stacking context!"),
Some(ref stacking_context) => {
stacking_context.hit_test(point, &mut mouse_over_list, false);
}
}
// Compute the new cursor.
--- a/servo/components/layout/lib.rs
+++ b/servo/components/layout/lib.rs
@@ -1,40 +1,43 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#![feature(globs, macro_rules, phase, thread_local, unsafe_destructor)]
+#![feature(thread_local, unsafe_destructor, box_syntax, plugin, int_uint)]
#![deny(unused_imports)]
#![deny(unused_variables)]
#![allow(unrooted_must_root)]
#![allow(missing_copy_implementations)]
+#![allow(unstable)]
-#[phase(plugin, link)]
+#[macro_use]
extern crate log;
extern crate cssparser;
extern crate canvas;
extern crate geom;
extern crate gfx;
extern crate layout_traits;
extern crate script;
extern crate script_traits;
+extern crate "serialize" as rustc_serialize;
extern crate serialize;
extern crate png;
extern crate style;
-#[phase(plugin)]
+#[macro_use]
+#[no_link] #[plugin]
extern crate "plugins" as servo_plugins;
extern crate "net" as servo_net;
extern crate "msg" as servo_msg;
-#[phase(plugin, link)]
+#[macro_use]
extern crate "util" as servo_util;
-#[phase(plugin)]
+#[no_link] #[macro_use] #[plugin]
extern crate string_cache_macros;
extern crate string_cache;
extern crate collections;
extern crate encoding;
extern crate libc;
extern crate url;
--- a/servo/components/layout/list_item.rs
+++ b/servo/components/layout/list_item.rs
@@ -19,17 +19,17 @@ use geom::{Point2D, Rect};
use gfx::display_list::DisplayList;
use servo_util::geometry::Au;
use servo_util::opts;
use style::ComputedValues;
use style::computed_values::list_style_type;
use std::sync::Arc;
/// A block with the CSS `display` property equal to `list-item`.
-#[deriving(Show)]
+#[derive(Show)]
pub struct ListItemFlow {
/// Data common to all block flows.
pub block_flow: BlockFlow,
/// The marker, if outside. (Markers that are inside are instead just fragments on the interior
/// `InlineFlow`.)
pub marker: Option<Fragment>,
}
--- a/servo/components/layout/model.rs
+++ b/servo/components/layout/model.rs
@@ -13,17 +13,17 @@ use geom::SideOffsets2D;
use style::computed_values::{LengthOrPercentageOrAuto, LengthOrPercentage};
use style::ComputedValues;
use servo_util::geometry::Au;
use servo_util::logical_geometry::LogicalMargin;
use std::cmp::{max, min};
use std::fmt;
/// A collapsible margin. See CSS 2.1 § 8.3.1.
-#[deriving(Copy)]
+#[derive(Copy)]
pub struct AdjoiningMargins {
/// The value of the greatest positive margin.
pub most_positive: Au,
/// The actual value (not the absolute value) of the negative margin with the largest absolute
/// value. Since this is not the absolute value, this is always zero or negative.
pub most_negative: Au,
}
@@ -56,17 +56,17 @@ impl AdjoiningMargins {
}
pub fn collapse(&self) -> Au {
self.most_positive + self.most_negative
}
}
/// Represents the block-start and block-end margins of a flow with collapsible margins. See CSS 2.1 § 8.3.1.
-#[deriving(Copy)]
+#[derive(Copy)]
pub enum CollapsibleMargins {
/// Margins may not collapse with this flow.
None(Au, Au),
/// Both the block-start and block-end margins (specified here in that order) may collapse, but the
/// margins do not collapse through this flow.
Collapse(AdjoiningMargins, AdjoiningMargins),
@@ -234,34 +234,34 @@ impl MarginCollapseInfo {
(MarginCollapseState::AccumulatingMarginIn, CollapsibleMargins::CollapseThrough(block_end)) => {
self.margin_in.union(block_end);
Au(0)
}
}
}
}
-#[deriving(Copy)]
+#[derive(Copy)]
pub enum MarginCollapseState {
AccumulatingCollapsibleTopMargin,
AccumulatingMarginIn,
}
/// Intrinsic inline-sizes, which consist of minimum and preferred.
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
pub struct IntrinsicISizes {
/// The *minimum inline-size* of the content.
pub minimum_inline_size: Au,
/// The *preferred inline-size* of the content.
pub preferred_inline_size: Au,
}
impl fmt::Show for IntrinsicISizes {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "min={}, pref={}", self.minimum_inline_size, self.preferred_inline_size)
+ write!(f, "min={:?}, pref={:?}", self.minimum_inline_size, self.preferred_inline_size)
}
}
impl IntrinsicISizes {
pub fn new() -> IntrinsicISizes {
IntrinsicISizes {
minimum_inline_size: Au(0),
preferred_inline_size: Au(0),
@@ -320,17 +320,17 @@ impl IntrinsicISizesContribution {
self.content_intrinsic_sizes.minimum_inline_size =
max(self.content_intrinsic_sizes.minimum_inline_size, sizes.minimum_inline_size);
self.content_intrinsic_sizes.preferred_inline_size =
max(self.content_intrinsic_sizes.preferred_inline_size, sizes.preferred_inline_size)
}
}
/// Useful helper data type when computing values for blocks and positioned elements.
-#[deriving(Copy, PartialEq, Show)]
+#[derive(Copy, PartialEq, Show)]
pub enum MaybeAuto {
Auto,
Specified(Au),
}
impl MaybeAuto {
#[inline]
pub fn from_style(length: computed::LengthOrPercentageOrAuto, containing_length: Au)
@@ -353,17 +353,17 @@ impl MaybeAuto {
}
#[inline]
pub fn specified_or_zero(&self) -> Au {
self.specified_or_default(Au::new(0))
}
#[inline]
- pub fn map(&self, mapper: |Au| -> Au) -> MaybeAuto {
+ pub fn map<F>(&self, mapper: F) -> MaybeAuto where F: FnOnce(Au) -> Au {
match *self {
MaybeAuto::Auto => MaybeAuto::Auto,
MaybeAuto::Specified(value) => MaybeAuto::Specified(mapper(value)),
}
}
}
pub fn specified_or_none(length: computed::LengthOrPercentageOrNone, containing_length: Au) -> Option<Au> {
--- a/servo/components/layout/parallel.rs
+++ b/servo/components/layout/parallel.rs
@@ -1,17 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Implements parallel traversals over the DOM and flow trees.
//!
//! This code is highly unsafe. Keep this file small and easy to audit.
-use context::{LayoutContext, SharedLayoutContext};
+use context::{LayoutContext, SharedLayoutContextWrapper, SharedLayoutContext};
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
use flow;
use flow_ref::FlowRef;
use traversal::{RecalcStyleForNode, ConstructFlows};
use traversal::{BubbleISizes, AssignISizes, AssignBSizesAndStoreOverflow};
use traversal::{ComputeAbsolutePositions, BuildDisplayList};
use util::{LayoutDataAccess, LayoutDataWrapper};
use wrapper::{layout_node_to_unsafe_layout_node, layout_node_from_unsafe_layout_node, LayoutNode};
@@ -76,27 +76,27 @@ impl DomParallelInfo {
}
}
}
/// A parallel top-down DOM traversal.
pub trait ParallelPreorderDomTraversal : PreorderDomTraversal {
fn run_parallel(&self,
node: UnsafeLayoutNode,
- proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>);
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeLayoutNode>);
#[inline(always)]
fn run_parallel_helper(&self,
unsafe_node: UnsafeLayoutNode,
- proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>,
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeLayoutNode>,
top_down_func: extern "Rust" fn(UnsafeFlow,
- &mut WorkerProxy<*const SharedLayoutContext,
+ &mut WorkerProxy<SharedLayoutContextWrapper,
UnsafeLayoutNode>),
bottom_up_func: extern "Rust" fn(UnsafeFlow,
- &mut WorkerProxy<*const SharedLayoutContext,
+ &mut WorkerProxy<SharedLayoutContextWrapper,
UnsafeFlow>)) {
// Get a real layout node.
let node: LayoutNode = unsafe {
layout_node_from_unsafe_layout_node(&unsafe_node)
};
// Perform the appropriate traversal.
self.process(node);
@@ -136,27 +136,27 @@ trait ParallelPostorderDomTraversal : Po
/// Thus, if we start with all the leaves of a tree, we end up traversing
/// the whole tree bottom-up because each parent will be processed exactly
/// once (by the last child that finishes processing).
///
/// The only communication between siblings is that they both
/// fetch-and-subtract the parent's children count.
fn run_parallel(&self,
mut unsafe_node: UnsafeLayoutNode,
- proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>) {
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeLayoutNode>) {
loop {
// Get a real layout node.
let node: LayoutNode = unsafe {
layout_node_from_unsafe_layout_node(&unsafe_node)
};
// Perform the appropriate traversal.
self.process(node);
- let shared_layout_context = unsafe { &**proxy.user_data() };
+ let shared_layout_context = unsafe { &*(proxy.user_data().0) };
let layout_context = LayoutContext::new(shared_layout_context);
let parent =
match node.layout_parent_node(layout_context.shared) {
None => break,
Some(parent) => parent,
};
@@ -211,17 +211,17 @@ trait ParallelPostorderFlowTraversal : P
/// Thus, if we start with all the leaves of a tree, we end up traversing
/// the whole tree bottom-up because each parent will be processed exactly
/// once (by the last child that finishes processing).
///
/// The only communication between siblings is that they both
/// fetch-and-subtract the parent's children count.
fn run_parallel(&self,
mut unsafe_flow: UnsafeFlow,
- _: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
+ _: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeFlow>) {
loop {
unsafe {
// Get a real flow.
let flow: &mut FlowRef = mem::transmute(&unsafe_flow);
// Perform the appropriate traversal.
if self.should_process(&mut **flow) {
self.process(&mut **flow);
@@ -256,27 +256,27 @@ trait ParallelPostorderFlowTraversal : P
}
}
}
/// A parallel top-down flow traversal.
trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
fn run_parallel(&self,
unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>);
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeFlow>);
#[inline(always)]
fn run_parallel_helper(&self,
unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>,
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeFlow>,
top_down_func: extern "Rust" fn(UnsafeFlow,
- &mut WorkerProxy<*const SharedLayoutContext,
+ &mut WorkerProxy<SharedLayoutContextWrapper,
UnsafeFlow>),
bottom_up_func: extern "Rust" fn(UnsafeFlow,
- &mut WorkerProxy<*const SharedLayoutContext,
+ &mut WorkerProxy<SharedLayoutContextWrapper,
UnsafeFlow>)) {
let mut had_children = false;
unsafe {
// Get a real flow.
let flow: &mut FlowRef = mem::transmute(&unsafe_flow);
if self.should_process(&mut **flow) {
// Perform the appropriate traversal.
@@ -301,166 +301,166 @@ trait ParallelPreorderFlowTraversal : Pr
}
}
impl<'a> ParallelPostorderFlowTraversal for BubbleISizes<'a> {}
impl<'a> ParallelPreorderFlowTraversal for AssignISizes<'a> {
fn run_parallel(&self,
unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeFlow>) {
self.run_parallel_helper(unsafe_flow,
proxy,
assign_inline_sizes,
assign_block_sizes_and_store_overflow)
}
}
impl<'a> ParallelPostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {}
impl<'a> ParallelPreorderFlowTraversal for ComputeAbsolutePositions<'a> {
fn run_parallel(&self,
unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeFlow>) {
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper, UnsafeFlow>) {
self.run_parallel_helper(unsafe_flow,
proxy,
compute_absolute_positions,
build_display_list)
}
}
impl<'a> ParallelPostorderFlowTraversal for BuildDisplayList<'a> {}
impl<'a> ParallelPostorderDomTraversal for ConstructFlows<'a> {}
impl <'a> ParallelPreorderDomTraversal for RecalcStyleForNode<'a> {
fn run_parallel(&self,
unsafe_node: UnsafeLayoutNode,
- proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper, UnsafeLayoutNode>) {
self.run_parallel_helper(unsafe_node,
proxy,
recalc_style,
construct_flows)
}
}
fn recalc_style(unsafe_node: UnsafeLayoutNode,
- proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
- let shared_layout_context = unsafe { &**proxy.user_data() };
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper, UnsafeLayoutNode>) {
+ let shared_layout_context = unsafe { &*(proxy.user_data().0) };
let layout_context = LayoutContext::new(shared_layout_context);
let recalc_style_for_node_traversal = RecalcStyleForNode {
layout_context: &layout_context,
};
recalc_style_for_node_traversal.run_parallel(unsafe_node, proxy)
}
fn construct_flows(unsafe_node: UnsafeLayoutNode,
- proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeLayoutNode>) {
- let shared_layout_context = unsafe { &**proxy.user_data() };
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper, UnsafeLayoutNode>) {
+ let shared_layout_context = unsafe { &*(proxy.user_data().0) };
let layout_context = LayoutContext::new(shared_layout_context);
let construct_flows_traversal = ConstructFlows {
layout_context: &layout_context,
};
construct_flows_traversal.run_parallel(unsafe_node, proxy)
}
fn assign_inline_sizes(unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
- let shared_layout_context = unsafe { &**proxy.user_data() };
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeFlow>) {
+ let shared_layout_context = unsafe { &*(proxy.user_data().0) };
let layout_context = LayoutContext::new(shared_layout_context);
let assign_inline_sizes_traversal = AssignISizes {
layout_context: &layout_context,
};
assign_inline_sizes_traversal.run_parallel(unsafe_flow, proxy)
}
fn assign_block_sizes_and_store_overflow(unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
- let shared_layout_context = unsafe { &**proxy.user_data() };
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeFlow>) {
+ let shared_layout_context = unsafe { &*(proxy.user_data().0) };
let layout_context = LayoutContext::new(shared_layout_context);
let assign_block_sizes_traversal = AssignBSizesAndStoreOverflow {
layout_context: &layout_context,
};
assign_block_sizes_traversal.run_parallel(unsafe_flow, proxy)
}
fn compute_absolute_positions(unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeFlow>) {
- let shared_layout_context = unsafe { &**proxy.user_data() };
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper, UnsafeFlow>) {
+ let shared_layout_context = unsafe { &*(proxy.user_data().0) };
let layout_context = LayoutContext::new(shared_layout_context);
let compute_absolute_positions_traversal = ComputeAbsolutePositions {
layout_context: &layout_context,
};
compute_absolute_positions_traversal.run_parallel(unsafe_flow, proxy);
}
fn build_display_list(unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*const SharedLayoutContext, UnsafeFlow>) {
- let shared_layout_context = unsafe { &**proxy.user_data() };
+ proxy: &mut WorkerProxy<SharedLayoutContextWrapper, UnsafeFlow>) {
+ let shared_layout_context = unsafe { &*(proxy.user_data().0) };
let layout_context = LayoutContext::new(shared_layout_context);
let build_display_list_traversal = BuildDisplayList {
layout_context: &layout_context,
};
build_display_list_traversal.run_parallel(unsafe_flow, proxy);
}
pub fn traverse_dom_preorder(root: LayoutNode,
shared_layout_context: &SharedLayoutContext,
- queue: &mut WorkQueue<*const SharedLayoutContext, UnsafeLayoutNode>) {
- queue.data = shared_layout_context as *const _;
+ queue: &mut WorkQueue<SharedLayoutContextWrapper, UnsafeLayoutNode>) {
+ queue.data = SharedLayoutContextWrapper(shared_layout_context as *const _);
queue.push(WorkUnit {
fun: recalc_style,
data: layout_node_to_unsafe_layout_node(&root),
});
queue.run();
- queue.data = ptr::null();
+ queue.data = SharedLayoutContextWrapper(ptr::null());
}
pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
profiler_metadata: ProfilerMetadata,
time_profiler_chan: TimeProfilerChan,
shared_layout_context: &SharedLayoutContext,
- queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
+ queue: &mut WorkQueue<SharedLayoutContextWrapper,UnsafeFlow>) {
if opts::get().bubble_inline_sizes_separately {
let layout_context = LayoutContext::new(shared_layout_context);
let bubble_inline_sizes = BubbleISizes { layout_context: &layout_context };
root.traverse_postorder(&bubble_inline_sizes);
}
- queue.data = shared_layout_context as *const _;
+ queue.data = SharedLayoutContextWrapper(shared_layout_context as *const _);
profile(TimeProfilerCategory::LayoutParallelWarmup, profiler_metadata,
time_profiler_chan, || {
queue.push(WorkUnit {
fun: assign_inline_sizes,
data: mut_owned_flow_to_unsafe_flow(root),
})
});
queue.run();
- queue.data = ptr::null()
+ queue.data = SharedLayoutContextWrapper(ptr::null())
}
pub fn build_display_list_for_subtree(root: &mut FlowRef,
profiler_metadata: ProfilerMetadata,
time_profiler_chan: TimeProfilerChan,
shared_layout_context: &SharedLayoutContext,
- queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
- queue.data = shared_layout_context as *const _;
+ queue: &mut WorkQueue<SharedLayoutContextWrapper,UnsafeFlow>) {
+ queue.data = SharedLayoutContextWrapper(shared_layout_context as *const _);
profile(TimeProfilerCategory::LayoutParallelWarmup, profiler_metadata,
time_profiler_chan, || {
queue.push(WorkUnit {
fun: compute_absolute_positions,
data: mut_owned_flow_to_unsafe_flow(root),
})
});
queue.run();
- queue.data = ptr::null()
+ queue.data = SharedLayoutContextWrapper(ptr::null())
}
--- a/servo/components/layout/table.rs
+++ b/servo/components/layout/table.rs
@@ -27,17 +27,17 @@ use std::cmp::max;
use std::fmt;
use style::{ComputedValues, CSSFloat};
use style::computed_values::{LengthOrPercentageOrAuto, table_layout};
use std::sync::Arc;
/// A table flow corresponded to the table's internal table fragment under a table wrapper flow.
/// The properties `position`, `float`, and `margin-*` are used on the table wrapper fragment,
/// not table fragment per CSS 2.1 § 10.5.
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
pub struct TableFlow {
pub block_flow: BlockFlow,
/// Information about the intrinsic inline-sizes of each column, computed bottom-up during
/// intrinsic inline-size bubbling.
pub column_intrinsic_inline_sizes: Vec<ColumnIntrinsicInlineSize>,
/// Information about the actual inline-sizes of each column, computed top-down during actual
@@ -394,17 +394,17 @@ impl Flow for TableFlow {
stacking_context_position: &Point2D<Au>) {
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
}
}
impl fmt::Show for TableFlow {
/// Outputs a debugging string describing this table flow.
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "TableFlow: {}", self.block_flow)
+ write!(f, "TableFlow: {:?}", self.block_flow)
}
}
/// Table, TableRowGroup, TableRow, TableCell types.
/// Their inline-sizes are calculated in the same way and do not have margins.
pub struct InternalTable;
impl ISizeAndMarginsComputer for InternalTable {
@@ -436,17 +436,17 @@ impl ISizeAndMarginsComputer for Interna
/// specific width constraint. For instance, one cell might say that it wants to be 100 pixels wide
/// in the inline direction and another cell might say that it wants to take up 20% of the inline-
/// size of the table. Now because we bubble up these constraints during the bubble-inline-sizes
/// phase of layout, we don't know yet how wide the table is ultimately going to be in the inline
/// direction. As we need to pick the maximum width of all cells for a column (in this case, the
/// maximum of 100 pixels and 20% of the table), the preceding constraint means that we must
/// potentially store both a specified width *and* a specified percentage, so that the inline-size
/// assignment phase of layout will know which one to pick.
-#[deriving(Clone, Encodable, Show, Copy)]
+#[derive(Clone, RustcEncodable, Show, Copy)]
pub struct ColumnIntrinsicInlineSize {
/// The preferred intrinsic inline size.
pub preferred: Au,
/// The largest specified size of this column as a length.
pub minimum_length: Au,
/// The largest specified size of this column as a percentage (`width` property).
pub percentage: CSSFloat,
/// Whether the column inline size is *constrained* per INTRINSIC § 4.1.
@@ -480,13 +480,13 @@ impl ColumnIntrinsicInlineSize {
}
}
}
/// The actual inline size for each column.
///
/// TODO(pcwalton): There will probably be some `border-collapse`-related info in here too
/// eventually.
-#[deriving(Encodable, Copy)]
+#[derive(RustcEncodable, Copy)]
pub struct ColumnComputedInlineSize {
/// The computed size of this inline column.
pub size: Au,
}
--- a/servo/components/layout/table_caption.rs
+++ b/servo/components/layout/table_caption.rs
@@ -90,11 +90,11 @@ impl Flow for TableCaptionFlow {
iterator: &mut FragmentBorderBoxIterator,
stacking_context_position: &Point2D<Au>) {
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
}
}
impl fmt::Show for TableCaptionFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "TableCaptionFlow: {}", self.block_flow)
+ write!(f, "TableCaptionFlow: {:?}", self.block_flow)
}
}
--- a/servo/components/layout/table_cell.rs
+++ b/servo/components/layout/table_cell.rs
@@ -17,17 +17,17 @@ use wrapper::ThreadSafeLayoutNode;
use geom::{Point2D, Rect};
use servo_util::geometry::Au;
use std::fmt;
use style::{UnsignedIntegerAttribute, ComputedValues};
use std::sync::Arc;
/// A table formatting context.
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
pub struct TableCellFlow {
/// Data common to all block flows.
pub block_flow: BlockFlow,
/// The column span of this cell.
pub column_span: u32,
/// Whether this cell is visible. If false, the value of `empty-cells` means that we must not
/// display this cell.
pub visible: bool,
@@ -171,11 +171,11 @@ impl Flow for TableCellFlow {
iterator: &mut FragmentBorderBoxIterator,
stacking_context_position: &Point2D<Au>) {
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
}
}
impl fmt::Show for TableCellFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "TableCellFlow: {}", self.block_flow)
+ write!(f, "TableCellFlow: {:?}", self.block_flow)
}
}
--- a/servo/components/layout/table_colgroup.rs
+++ b/servo/components/layout/table_colgroup.rs
@@ -104,13 +104,13 @@ impl Flow for TableColGroupFlow {
fn iterate_through_fragment_border_boxes(&self,
_: &mut FragmentBorderBoxIterator,
_: &Point2D<Au>) {}
}
impl fmt::Show for TableColGroupFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.fragment {
- Some(ref rb) => write!(f, "TableColGroupFlow: {}", rb),
+ Some(ref rb) => write!(f, "TableColGroupFlow: {:?}", rb),
None => write!(f, "TableColGroupFlow"),
}
}
}
--- a/servo/components/layout/table_row.rs
+++ b/servo/components/layout/table_row.rs
@@ -22,29 +22,29 @@ use geom::{Point2D, Rect};
use servo_util::geometry::Au;
use std::cmp::max;
use std::fmt;
use style::ComputedValues;
use style::computed_values::LengthOrPercentageOrAuto;
use std::sync::Arc;
/// A single row of a table.
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
pub struct TableRowFlow {
pub block_flow: BlockFlow,
/// Information about the intrinsic inline-sizes of each cell.
pub cell_intrinsic_inline_sizes: Vec<CellIntrinsicInlineSize>,
/// Information about the computed inline-sizes of each column.
pub column_computed_inline_sizes: Vec<ColumnComputedInlineSize>,
}
/// Information about the column inline size and span for each cell.
-#[deriving(Encodable, Copy)]
+#[derive(RustcEncodable, Copy)]
pub struct CellIntrinsicInlineSize {
/// Inline sizes that this cell contributes to the column.
pub column_size: ColumnIntrinsicInlineSize,
/// The column span of this cell.
pub column_span: u32,
}
impl TableRowFlow {
@@ -324,11 +324,11 @@ impl Flow for TableRowFlow {
iterator: &mut FragmentBorderBoxIterator,
stacking_context_position: &Point2D<Au>) {
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
}
}
impl fmt::Show for TableRowFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "TableRowFlow: {}", self.block_flow.fragment)
+ write!(f, "TableRowFlow: {:?}", self.block_flow.fragment)
}
}
--- a/servo/components/layout/table_rowgroup.rs
+++ b/servo/components/layout/table_rowgroup.rs
@@ -17,17 +17,17 @@ use wrapper::ThreadSafeLayoutNode;
use geom::{Point2D, Rect};
use servo_util::geometry::Au;
use std::fmt;
use style::ComputedValues;
use std::sync::Arc;
/// A table formatting context.
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
pub struct TableRowGroupFlow {
/// Fields common to all block flows.
pub block_flow: BlockFlow,
/// Information about the intrinsic inline-sizes of each column.
pub column_intrinsic_inline_sizes: Vec<ColumnIntrinsicInlineSize>,
/// Information about the actual inline sizes of each column.
@@ -159,11 +159,11 @@ impl Flow for TableRowGroupFlow {
iterator: &mut FragmentBorderBoxIterator,
stacking_context_position: &Point2D<Au>) {
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
}
}
impl fmt::Show for TableRowGroupFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "TableRowGroupFlow: {}", self.block_flow.fragment)
+ write!(f, "TableRowGroupFlow: {:?}", self.block_flow.fragment)
}
}
--- a/servo/components/layout/table_wrapper.rs
+++ b/servo/components/layout/table_wrapper.rs
@@ -22,28 +22,29 @@ use flow::{IMPACTED_BY_LEFT_FLOATS, IMPA
use fragment::{Fragment, FragmentBorderBoxIterator};
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize};
use wrapper::ThreadSafeLayoutNode;
use geom::{Point2D, Rect};
use servo_util::geometry::Au;
use std::cmp::{max, min};
use std::fmt;
+use std::ops::Add;
use style::{ComputedValues, CSSFloat};
use style::computed_values::{table_layout, LengthOrPercentageOrAuto};
use std::sync::Arc;
-#[deriving(Copy, Encodable, Show)]
+#[derive(Copy, RustcEncodable, Show)]
pub enum TableLayout {
Fixed,
Auto
}
/// A table wrapper flow based on a block formatting context.
-#[deriving(Encodable)]
+#[derive(RustcEncodable)]
pub struct TableWrapperFlow {
pub block_flow: BlockFlow,
/// Intrinsic column inline sizes according to INTRINSIC § 4.1
pub column_intrinsic_inline_sizes: Vec<ColumnIntrinsicInlineSize>,
/// Table-layout property
pub table_layout: TableLayout,
@@ -139,21 +140,21 @@ impl TableWrapperFlow {
// to correspond with CSS 2.1 § 17.5.2.2 under "Column and caption widths
// influence the final table width as follows: ..."
_ => available_inline_size,
};
// Compute all the guesses for the column sizes, and sum them.
let mut total_guess = AutoLayoutCandidateGuess::new();
let guesses: Vec<AutoLayoutCandidateGuess> =
- self.column_intrinsic_inline_sizes.iter().map(|column_intrinsic_inline_size| {
+ self.column_intrinsic_inline_sizes.iter().map(|&mut:column_intrinsic_inline_size| {
let guess = AutoLayoutCandidateGuess::from_column_intrinsic_inline_size(
column_intrinsic_inline_size,
available_inline_size);
- total_guess = total_guess + guess;
+ total_guess = &total_guess + &guess;
guess
}).collect();
// Assign inline sizes.
let selection = SelectedAutoLayoutCandidateGuess::select(&total_guess,
available_inline_size);
let mut total_used_inline_size = Au(0);
for (intermediate_column_inline_size, guess) in
@@ -378,19 +379,19 @@ impl Flow for TableWrapperFlow {
stacking_context_position: &Point2D<Au>) {
self.block_flow.iterate_through_fragment_border_boxes(iterator, stacking_context_position)
}
}
impl fmt::Show for TableWrapperFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.block_flow.base.flags.is_float() {
- write!(f, "TableWrapperFlow(Float): {}", self.block_flow.fragment)
+ write!(f, "TableWrapperFlow(Float): {:?}", self.block_flow.fragment)
} else {
- write!(f, "TableWrapperFlow: {}", self.block_flow.fragment)
+ write!(f, "TableWrapperFlow: {:?}", self.block_flow.fragment)
}
}
}
/// The layout "guesses" defined in INTRINSIC § 4.3.
struct AutoLayoutCandidateGuess {
/// The column inline-size assignment where each column is assigned its intrinsic minimum
/// inline-size.
@@ -477,32 +478,33 @@ impl AutoLayoutCandidateGuess {
}
SelectedAutoLayoutCandidateGuess::UsePreferredGuessAndDistributeExcessInlineSize => {
self.preferred_guess
}
}
}
}
-impl Add<AutoLayoutCandidateGuess,AutoLayoutCandidateGuess> for AutoLayoutCandidateGuess {
+impl<'a> Add for &'a AutoLayoutCandidateGuess {
+ type Output = AutoLayoutCandidateGuess;
#[inline]
- fn add(&self, other: &AutoLayoutCandidateGuess) -> AutoLayoutCandidateGuess {
+ fn add(self, other: &AutoLayoutCandidateGuess) -> AutoLayoutCandidateGuess {
AutoLayoutCandidateGuess {
minimum_guess: self.minimum_guess + other.minimum_guess,
minimum_percentage_guess:
self.minimum_percentage_guess + other.minimum_percentage_guess,
minimum_specified_guess: self.minimum_specified_guess + other.minimum_specified_guess,
preferred_guess: self.preferred_guess + other.preferred_guess,
}
}
}
/// The `CSSFloat` member specifies the weight of the smaller of the two guesses, on a scale from
/// 0.0 to 1.0.
-#[deriving(Copy, PartialEq, Show)]
+#[derive(Copy, PartialEq, Show)]
enum SelectedAutoLayoutCandidateGuess {
UseMinimumGuess,
InterpolateBetweenMinimumGuessAndMinimumPercentageGuess(CSSFloat),
InterpolateBetweenMinimumPercentageGuessAndMinimumSpecifiedGuess(CSSFloat),
InterpolateBetweenMinimumSpecifiedGuessAndPreferredGuess(CSSFloat),
UsePreferredGuessAndDistributeExcessInlineSize,
}
--- a/servo/components/layout/text.rs
+++ b/servo/components/layout/text.rs
@@ -190,23 +190,23 @@ impl TextRunScanner {
// Make new fragments with the run and adjusted text indices.
debug!("TextRunScanner: pushing {} fragment(s)", self.clump.len());
for (logical_offset, old_fragment) in
mem::replace(&mut self.clump, DList::new()).into_iter().enumerate() {
let range = *new_ranges.get(logical_offset);
if range.is_empty() {
debug!("Elided an `SpecificFragmentInfo::UnscannedText` because it was zero-length after \
- compression; {}",
+ compression; {:?}",
old_fragment);
continue
}
let text_size = old_fragment.border_box.size;
- let &NewLinePositions(ref mut new_line_positions) =
+ let &mut NewLinePositions(ref mut new_line_positions) =
new_line_positions.get_mut(logical_offset);
let new_text_fragment_info =
box ScannedTextFragmentInfo::new(run.clone(),
range,
mem::replace(new_line_positions, Vec::new()),
text_size);
let new_metrics = new_text_fragment_info.run.metrics_for_range(&range);
let bounding_box_size = bounding_box_for_run_metrics(&new_metrics,
--- a/servo/components/layout/traversal.rs
+++ b/servo/components/layout/traversal.rs
@@ -43,17 +43,17 @@ type Generation = uint;
/// rejected.
///
/// When done styling a node, all selectors previously inserted into the filter
/// are removed.
///
/// Since a work-stealing queue is used for styling, sometimes, the bloom filter
/// will no longer be the for the parent of the node we're currently on. When
/// this happens, the task local bloom filter will be thrown away and rebuilt.
-thread_local!(static STYLE_BLOOM: RefCell<Option<(Box<BloomFilter>, UnsafeLayoutNode, Generation)>> = RefCell::new(None))
+thread_local!(static STYLE_BLOOM: RefCell<Option<(Box<BloomFilter>, UnsafeLayoutNode, Generation)>> = RefCell::new(None));
/// Returns the task local bloom filter.
///
/// If one does not exist, a new one will be made for you. If it is out of date,
/// it will be thrown out and a new one will be made for you.
fn take_task_local_bloom_filter(parent_node: Option<LayoutNode>, layout_context: &LayoutContext)
-> Box<BloomFilter> {
STYLE_BLOOM.with(|style_bloom| {
@@ -69,17 +69,17 @@ fn take_task_local_bloom_filter(parent_n
insert_ancestors_into_bloom_filter(&mut bloom_filter, parent, layout_context);
bloom_filter
}
// Found cached bloom filter.
(Some(parent), Some((mut bloom_filter, old_node, old_generation))) => {
// Hey, the cached parent is our parent! We can reuse the bloom filter.
if old_node == layout_node_to_unsafe_layout_node(&parent) &&
old_generation == layout_context.shared.generation {
- debug!("[{}] Parent matches (={}). Reusing bloom filter.", tid(), old_node.val0());
+ debug!("[{}] Parent matches (={}). Reusing bloom filter.", tid(), old_node.0);
bloom_filter.clone()
} else {
// Oh no. the cached parent is stale. I guess we need a new one. Reuse the existing
// allocation to avoid malloc churn.
*bloom_filter = BloomFilter::new();
insert_ancestors_into_bloom_filter(&mut bloom_filter, parent, layout_context);
bloom_filter
}
@@ -115,17 +115,17 @@ fn insert_ancestors_into_bloom_filter(bf
Some(p) => p,
};
}
debug!("[{}] Inserted {} ancestors.", tid(), ancestors);