aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/layout_task.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/layout_task.rs')
-rw-r--r--components/layout/layout_task.rs170
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(),