diff options
Diffstat (limited to 'components/layout/layout_task.rs')
-rw-r--r-- | components/layout/layout_task.rs | 170 |
1 files changed, 54 insertions, 116 deletions
diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index d4931848f05..6347509ad90 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -12,12 +12,10 @@ use app_units::Au; use azure::azure::AzColor; use canvas_traits::CanvasMsg; use construct::ConstructionResult; -use context::{SharedLayoutContext, heap_size_of_local_context}; +use context::{SharedLayoutContext, StylistWrapper, heap_size_of_local_context}; use cssparser::ToCss; use data::LayoutDataWrapper; use display_list_builder::ToGfxColor; -use encoding::EncodingRef; -use encoding::all::UTF_8; use euclid::Matrix4; use euclid::point::Point2D; use euclid::rect::Rect; @@ -40,9 +38,8 @@ use layout_traits::LayoutTaskFactory; use log; use msg::compositor_msg::{Epoch, LayerId, ScrollPolicy}; use msg::constellation_msg::Msg as ConstellationMsg; -use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId}; +use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheResult, ImageCacheTask}; -use net_traits::{PendingAsyncLoad, load_bytes_iter}; use opaque_node::OpaqueNodeMethods; use parallel::{self, WorkQueueData}; use profile_traits::mem::{self, Report, ReportKind, ReportsChan}; @@ -56,7 +53,6 @@ use script::layout_interface::Animation; use script::layout_interface::{LayoutChan, LayoutRPC, OffsetParentResponse}; use script::layout_interface::{Msg, NewLayoutTaskInfo, Reflow, ReflowGoal, ReflowQueryType}; use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress}; -use script_traits::StylesheetLoadResponder; use script_traits::{ConstellationControlMsg, LayoutControlMsg, OpaqueScriptLayoutChannel}; use selectors::parser::PseudoElement; use sequential; @@ -72,13 +68,12 @@ use std::sync::mpsc::{channel, Sender, Receiver}; use std::sync::{Arc, Mutex, MutexGuard}; use string_cache::Atom; use style::computed_values::{self, filter, mix_blend_mode}; -use style::media_queries::{Device, MediaQueryList, MediaType}; +use style::media_queries::{Device, MediaType}; use style::properties::longhands::{display, position}; use style::properties::style_structs; -use style::selector_matching::Stylist; -use style::stylesheets::{CSSRule, CSSRuleIteratorExt, Origin, Stylesheet}; +use style::selector_matching::{Stylist, USER_OR_USER_AGENT_STYLESHEETS}; +use style::stylesheets::{CSSRuleIteratorExt, Stylesheet}; use style::values::AuExtensionMethods; -use style::viewport::ViewportRule; use url::Url; use util::geometry::{MAX_RECT, ZERO_POINT}; use util::ipc::OptionalIpcSender; @@ -109,9 +104,6 @@ pub struct LayoutTaskData { /// The channel on which messages can be sent to the constellation. pub constellation_chan: ConstellationChan, - /// The size of the screen. - pub screen_size: Size2D<Au>, - /// The size of the viewport. This may be different from the size of the screen due to viewport /// constraints. pub viewport_size: Size2D<Au>, @@ -326,10 +318,18 @@ fn add_font_face_rules(stylesheet: &Stylesheet, outstanding_web_fonts_counter: &Arc<AtomicUsize>) { for font_face in stylesheet.effective_rules(&device).font_face() { for source in &font_face.sources { - outstanding_web_fonts_counter.fetch_add(1, Ordering::SeqCst); - font_cache_task.add_web_font(font_face.family.clone(), - (*source).clone(), - (*font_cache_sender).clone()); + if opts::get().load_webfonts_synchronously { + let (sender, receiver) = channel(); + font_cache_task.add_web_font(font_face.family.clone(), + (*source).clone(), + sender); + receiver.recv().unwrap(); + } else { + outstanding_web_fonts_counter.fetch_add(1, Ordering::SeqCst); + font_cache_task.add_web_font(font_face.family.clone(), + (*source).clone(), + (*font_cache_sender).clone()); + } } } } @@ -350,7 +350,6 @@ impl LayoutTask { time_profiler_chan: time::ProfilerChan, mem_profiler_chan: mem::ProfilerChan) -> LayoutTask { - let screen_size = Size2D::new(Au(0), Au(0)); let device = Device::new( MediaType::Screen, opts::get().initial_window_size.as_f32() * ScaleFactor::new(1.0)); @@ -377,8 +376,8 @@ impl LayoutTask { let stylist = box Stylist::new(device); let outstanding_web_fonts_counter = Arc::new(AtomicUsize::new(0)); - for user_or_user_agent_stylesheet in stylist.stylesheets() { - add_font_face_rules(user_or_user_agent_stylesheet, + for stylesheet in &*USER_OR_USER_AGENT_STYLESHEETS { + add_font_face_rules(stylesheet, &stylist.device, &font_cache_task, &font_cache_sender, @@ -411,8 +410,7 @@ impl LayoutTask { root_flow: None, image_cache_task: image_cache_task, constellation_chan: constellation_chan, - screen_size: screen_size, - viewport_size: screen_size, + viewport_size: Size2D::new(Au(0), Au(0)), stacking_context: None, stylist: stylist, parallel_traversal: parallel_traversal, @@ -449,18 +447,16 @@ impl LayoutTask { -> SharedLayoutContext { SharedLayoutContext { image_cache_task: rw_data.image_cache_task.clone(), - image_cache_sender: self.image_cache_sender.clone(), + image_cache_sender: Mutex::new(self.image_cache_sender.clone()), viewport_size: rw_data.viewport_size.clone(), screen_size_changed: screen_size_changed, - constellation_chan: rw_data.constellation_chan.clone(), - layout_chan: self.chan.clone(), - font_cache_task: self.font_cache_task.clone(), - canvas_layers_sender: self.canvas_layers_sender.clone(), - stylist: &*rw_data.stylist, + font_cache_task: Mutex::new(self.font_cache_task.clone()), + canvas_layers_sender: Mutex::new(self.canvas_layers_sender.clone()), + stylist: StylistWrapper(&*rw_data.stylist), url: (*url).clone(), visible_rects: rw_data.visible_rects.clone(), generation: rw_data.generation, - new_animations_sender: rw_data.new_animations_sender.clone(), + new_animations_sender: Mutex::new(rw_data.new_animations_sender.clone()), goal: goal, running_animations: rw_data.running_animations.clone(), } @@ -492,8 +488,8 @@ impl LayoutTask { self.handle_request_helper(Msg::GetWebFontLoadState(sender), possibly_locked_rw_data) } - LayoutControlMsg::ExitNow(exit_type) => { - self.handle_request_helper(Msg::ExitNow(exit_type), + LayoutControlMsg::ExitNow => { + self.handle_request_helper(Msg::ExitNow, possibly_locked_rw_data) } } @@ -576,20 +572,10 @@ impl LayoutTask { LayoutTaskData>>) -> bool { match request { - Msg::AddStylesheet(sheet, mq) => { - self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data) - } - Msg::LoadStylesheet(url, mq, pending, link_element) => { - self.handle_load_stylesheet(url, - mq, - pending, - link_element, - possibly_locked_rw_data) + Msg::AddStylesheet(style_info) => { + self.handle_add_stylesheet(style_info, possibly_locked_rw_data) } Msg::SetQuirksMode => self.handle_set_quirks_mode(possibly_locked_rw_data), - Msg::AddMetaViewport(translated_rule) => { - self.handle_add_meta_viewport(translated_rule, possibly_locked_rw_data) - } Msg::GetRPC(response_chan) => { response_chan.send(box LayoutRPCImpl(self.rw_data.clone()) as Box<LayoutRPC + Send>).unwrap(); @@ -631,9 +617,9 @@ impl LayoutTask { self.prepare_to_exit(response_chan, possibly_locked_rw_data); return false }, - Msg::ExitNow(exit_type) => { + Msg::ExitNow => { debug!("layout: ExitNow received"); - self.exit_now(possibly_locked_rw_data, exit_type); + self.exit_now(possibly_locked_rw_data); return false } } @@ -711,9 +697,9 @@ impl LayoutTask { self.handle_reap_layout_data(dead_layout_data) } } - Msg::ExitNow(exit_type) => { + Msg::ExitNow => { debug!("layout task is exiting..."); - self.exit_now(possibly_locked_rw_data, exit_type); + self.exit_now(possibly_locked_rw_data); break } Msg::CollectReports(_) => { @@ -729,10 +715,7 @@ impl LayoutTask { /// Shuts down the layout task now. If there are any DOM nodes left, layout will now (safely) /// crash. fn exit_now<'a>(&'a self, - possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>, - exit_type: PipelineExitType) { - let (response_chan, response_port) = ipc::channel().unwrap(); - + possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) { { let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); if let Some(ref mut traversal) = (&mut *rw_data).parallel_traversal { @@ -741,79 +724,36 @@ impl LayoutTask { LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data); } - self.paint_chan.send(LayoutToPaintMsg::Exit(Some(response_chan), exit_type)).unwrap(); + let (response_chan, response_port) = ipc::channel().unwrap(); + self.paint_chan.send(LayoutToPaintMsg::Exit(response_chan)).unwrap(); response_port.recv().unwrap() } - fn handle_load_stylesheet<'a>(&'a self, - url: Url, - mq: MediaQueryList, - pending: PendingAsyncLoad, - responder: Box<StylesheetLoadResponder + Send>, - 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; - - // TODO we don't really even need to load this if mq does not match - let (metadata, iter) = load_bytes_iter(pending); - let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s); - let final_url = metadata.final_url; - - let sheet = Stylesheet::from_bytes_iter(iter, - final_url, - protocol_encoding_label, - Some(environment_encoding), - Origin::Author); - - //TODO: mark critical subresources as blocking load as well (#5974) - self.script_chan.send(ConstellationControlMsg::StylesheetLoadComplete(self.id, - url, - responder)).unwrap(); - - self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data); - } - fn handle_add_stylesheet<'a>(&'a self, - sheet: Stylesheet, - mq: MediaQueryList, + stylesheet: Arc<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!) + // GWTODO: Need to handle unloading web fonts. - let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); - if mq.evaluate(&rw_data.stylist.device) { - add_font_face_rules(&sheet, + let rw_data = self.lock_rw_data(possibly_locked_rw_data); + if stylesheet.is_effective_for_device(&rw_data.stylist.device) { + add_font_face_rules(&*stylesheet, &rw_data.stylist.device, &self.font_cache_task, &self.font_cache_sender, &rw_data.outstanding_web_fonts); - rw_data.stylist.add_stylesheet(sheet); } LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data); } - fn handle_add_meta_viewport<'a>(&'a self, - translated_rule: ViewportRule, - possibly_locked_rw_data: - &mut Option<MutexGuard<'a, LayoutTaskData>>) - { - let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); - rw_data.stylist.add_stylesheet(Stylesheet { - rules: vec![CSSRule::Viewport(translated_rule)], - origin: Origin::Author - }); - LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data); - } - - /// Sets quirks mode for the document, causing the quirks mode stylesheet to be loaded. + /// Sets quirks mode for the document, causing the quirks mode stylesheet to be used. fn handle_set_quirks_mode<'a>(&'a self, possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) { let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); - rw_data.stylist.add_quirks_mode_stylesheet(); + rw_data.stylist.set_quirks_mode(true); LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data); } @@ -1077,7 +1017,7 @@ impl LayoutTask { flow_ref::deref_mut(layout_root)); let root_size = { let root_flow = flow::base(&**layout_root); - if rw_data.stylist.constrain_viewport().is_some() { + if rw_data.stylist.viewport_constraints().is_some() { root_flow.position.size.to_physical(root_flow.writing_mode) } else { root_flow.overflow.size @@ -1153,18 +1093,20 @@ impl LayoutTask { } let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); + let stylesheets: Vec<&Stylesheet> = data.document_stylesheets.iter().map(|entry| &**entry) + .collect(); + let stylesheets_changed = data.stylesheets_changed; let initial_viewport = data.window_size.initial_viewport; let old_viewport_size = rw_data.viewport_size; let current_screen_size = Size2D::new(Au::from_f32_px(initial_viewport.width.get()), Au::from_f32_px(initial_viewport.height.get())); - rw_data.screen_size = current_screen_size; // Calculate the actual viewport as per DEVICE-ADAPT § 6 let device = Device::new(MediaType::Screen, initial_viewport); - rw_data.stylist.set_device(device); + rw_data.stylist.set_device(device, &stylesheets); - let constraints = rw_data.stylist.constrain_viewport(); + let constraints = rw_data.stylist.viewport_constraints().clone(); rw_data.viewport_size = match constraints { Some(ref constraints) => { debug!("Viewport constraints: {:?}", constraints); @@ -1180,9 +1122,6 @@ impl LayoutTask { let viewport_size_changed = rw_data.viewport_size != old_viewport_size; if viewport_size_changed { if let Some(constraints) = constraints { - let device = Device::new(MediaType::Screen, constraints.size); - rw_data.stylist.set_device(device); - // let the constellation know about the viewport constraints let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan; constellation_chan.send(ConstellationMsg::ViewportConstrained( @@ -1191,7 +1130,7 @@ impl LayoutTask { } // If the entire flow tree is invalid, then it will be reflowed anyhow. - let needs_dirtying = rw_data.stylist.update(); + let needs_dirtying = rw_data.stylist.update(&stylesheets, stylesheets_changed); let needs_reflow = viewport_size_changed && !needs_dirtying; unsafe { if needs_dirtying { @@ -1204,13 +1143,12 @@ impl LayoutTask { } } - let state_changes = document.drain_element_state_changes(); + let modified_elements = document.drain_modified_elements(); if !needs_dirtying { - for &(el, state_change) in state_changes.iter() { - debug_assert!(!state_change.is_empty()); + for &(el, old_state) in modified_elements.iter() { let hint = rw_data.stylist.restyle_hint_for_state_change(&el, el.get_state(), - state_change); + old_state); el.note_restyle_hint(hint); } } @@ -1221,7 +1159,7 @@ impl LayoutTask { &self.url, data.reflow_info.goal); - if node.is_dirty() || node.has_dirty_descendants() || rw_data.stylist.is_dirty() { + if node.is_dirty() || node.has_dirty_descendants() { // Recalculate CSS styles and rebuild flows and fragments. profile(time::ProfilerCategory::LayoutStyleRecalc, self.profiler_metadata(), |