Refactor how LayoutContext structure works (reduce TLS lookups + simplify fns used by seq/parallel code paths).

- LayoutContext is renamed to SharedLayoutContext.
- SharedLayoutContext is immutable.
- LayoutContext is a wrapper around SharedLayoutContext + access to local caches (font, style etc).
- Creating a LayoutContext does a single local_data lookup to fetch the cache information.
- Android shares same implementation of context.rs as other platforms.
- LayoutContext can be used from both green thread (parallel layout) and native thread (sequential layout).
- Removes the need for other types (such as FontContext, StyleSharingCandidateCache etc) to be passed around.
This commit is contained in:
Glenn Watson 2014-08-08 13:53:37 +10:00
parent 4062af69ec
commit 4a0e01b4f0
16 changed files with 215 additions and 358 deletions

View file

@ -402,7 +402,7 @@ fn translate_including_floats(cur_b: &mut Au, delta: Au, floats: &mut Floats) {
/// ///
/// Note that flows with position 'fixed' just form a flat list as they all /// Note that flows with position 'fixed' just form a flat list as they all
/// have the Root flow as their CB. /// have the Root flow as their CB.
struct AbsoluteAssignBSizesTraversal<'a>(&'a mut LayoutContext); struct AbsoluteAssignBSizesTraversal<'a>(&'a LayoutContext<'a>);
impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> { impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
#[inline] #[inline]
@ -429,7 +429,7 @@ impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
/// After that, it is up to the normal store-overflow traversal to propagate /// After that, it is up to the normal store-overflow traversal to propagate
/// it further up. /// it further up.
struct AbsoluteStoreOverflowTraversal<'a>{ struct AbsoluteStoreOverflowTraversal<'a>{
layout_context: &'a mut LayoutContext, layout_context: &'a LayoutContext<'a>,
} }
impl<'a> PostorderFlowTraversal for AbsoluteStoreOverflowTraversal<'a> { impl<'a> PostorderFlowTraversal for AbsoluteStoreOverflowTraversal<'a> {
@ -579,7 +579,7 @@ impl BlockFlow {
} }
/// Compute the used value of inline-size for this Block. /// Compute the used value of inline-size for this Block.
fn compute_used_inline_size(&mut self, ctx: &mut LayoutContext, containing_block_inline_size: Au) { fn compute_used_inline_size(&mut self, ctx: &LayoutContext, containing_block_inline_size: Au) {
let block_type = self.block_type(); let block_type = self.block_type();
match block_type { match block_type {
AbsoluteReplacedType => { AbsoluteReplacedType => {
@ -805,8 +805,8 @@ impl BlockFlow {
/// `inline(always)` because this is only ever called by in-order or non-in-order top-level /// `inline(always)` because this is only ever called by in-order or non-in-order top-level
/// methods /// methods
#[inline(always)] #[inline(always)]
pub fn assign_block_size_block_base(&mut self, pub fn assign_block_size_block_base<'a>(&mut self,
layout_context: &mut LayoutContext, layout_context: &'a LayoutContext<'a>,
margins_may_collapse: MarginsMayCollapseFlag) { margins_may_collapse: MarginsMayCollapseFlag) {
// Our current border-box position. // Our current border-box position.
let mut cur_b = Au(0); let mut cur_b = Au(0);
@ -949,7 +949,7 @@ impl BlockFlow {
let mut block_size = cur_b - block_start_offset; let mut block_size = cur_b - block_start_offset;
if self.is_root() { if self.is_root() {
let screen_size = LogicalSize::from_physical( let screen_size = LogicalSize::from_physical(
self.fragment.style.writing_mode, layout_context.screen_size); self.fragment.style.writing_mode, layout_context.shared.screen_size);
block_size = Au::max(screen_size.block, block_size) block_size = Au::max(screen_size.block, block_size)
} }
@ -1053,7 +1053,7 @@ impl BlockFlow {
/// should be calculated using CSS Section 10.6.7 /// should be calculated using CSS Section 10.6.7
/// ///
/// It does not calculate the block-size of the flow itself. /// It does not calculate the block-size of the flow itself.
pub fn assign_block_size_float(&mut self, ctx: &mut LayoutContext) { pub fn assign_block_size_float<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
let mut floats = Floats::new(self.fragment.style.writing_mode); let mut floats = Floats::new(self.fragment.style.writing_mode);
for kid in self.base.child_iter() { for kid in self.base.child_iter() {
flow::mut_base(kid).floats = floats.clone(); flow::mut_base(kid).floats = floats.clone();
@ -1179,7 +1179,7 @@ impl BlockFlow {
/// + y-coordinate of the flow wrt its Containing Block. /// + y-coordinate of the flow wrt its Containing Block.
/// + block-size, vertical margins, and y-coordinate for the flow's box. /// + block-size, vertical margins, and y-coordinate for the flow's box.
fn calculate_abs_block_size_and_margins(&mut self, ctx: &LayoutContext) { fn calculate_abs_block_size_and_margins(&mut self, ctx: &LayoutContext) {
let containing_block_block_size = self.containing_block_size(ctx.screen_size).block; let containing_block_block_size = self.containing_block_size(ctx.shared.screen_size).block;
let static_b_offset = self.static_b_offset; let static_b_offset = self.static_b_offset;
// This is the stored content block-size value from assign-block-size // This is the stored content block-size value from assign-block-size
@ -1445,7 +1445,7 @@ impl Flow for BlockFlow {
/// any fragments it is responsible for flowing. /// any fragments it is responsible for flowing.
/// ///
/// TODO(pcwalton): Inline blocks. /// TODO(pcwalton): Inline blocks.
fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) { fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let mut flags = self.base.flags; let mut flags = self.base.flags;
flags.set_has_left_floated_descendants(false); flags.set_has_left_floated_descendants(false);
flags.set_has_right_floated_descendants(false); flags.set_has_right_floated_descendants(false);
@ -1489,7 +1489,7 @@ impl Flow for BlockFlow {
/// ///
/// Dual fragments consume some inline-size first, and the remainder is assigned to all child (block) /// Dual fragments consume some inline-size first, and the remainder is assigned to all child (block)
/// contexts. /// contexts.
fn assign_inline_sizes(&mut self, layout_context: &mut LayoutContext) { fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", debug!("assign_inline_sizes({}): assigning inline_size for flow",
if self.is_float() { if self.is_float() {
"float" "float"
@ -1501,7 +1501,7 @@ impl Flow for BlockFlow {
debug!("Setting root position"); debug!("Setting root position");
self.base.position.start = LogicalPoint::zero(self.base.writing_mode); self.base.position.start = LogicalPoint::zero(self.base.writing_mode);
self.base.position.size.inline = LogicalSize::from_physical( self.base.position.size.inline = LogicalSize::from_physical(
self.base.writing_mode, layout_context.screen_size).inline; self.base.writing_mode, layout_context.shared.screen_size).inline;
self.base.floats = Floats::new(self.base.writing_mode); self.base.floats = Floats::new(self.base.writing_mode);
// The root element is never impacted by floats. // The root element is never impacted by floats.
@ -1559,7 +1559,7 @@ impl Flow for BlockFlow {
/// ///
/// This is called on child flows by the parent. Hence, we can assume that `assign_block-size` has /// This is called on child flows by the parent. Hence, we can assume that `assign_block-size` has
/// already been called on the child (because of the bottom-up traversal). /// already been called on the child (because of the bottom-up traversal).
fn assign_block_size_for_inorder_child_if_necessary(&mut self, layout_context: &mut LayoutContext) fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self, layout_context: &'a LayoutContext<'a>)
-> bool { -> bool {
if self.is_float() { if self.is_float() {
self.place_float(); self.place_float();
@ -1573,7 +1573,7 @@ impl Flow for BlockFlow {
impacted impacted
} }
fn assign_block_size(&mut self, ctx: &mut LayoutContext) { fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
// Assign block-size for fragment if it is an image fragment. // Assign block-size for fragment if it is an image fragment.
self.fragment.assign_replaced_block_size_if_necessary(); self.fragment.assign_replaced_block_size_if_necessary();
@ -1794,7 +1794,7 @@ pub trait ISizeAndMarginsComputer {
fn compute_inline_size_constraint_inputs(&self, fn compute_inline_size_constraint_inputs(&self,
block: &mut BlockFlow, block: &mut BlockFlow,
parent_flow_inline_size: Au, parent_flow_inline_size: Au,
ctx: &mut LayoutContext) ctx: &LayoutContext)
-> ISizeConstraintInput { -> ISizeConstraintInput {
let containing_block_inline_size = self.containing_block_inline_size(block, parent_flow_inline_size, ctx); let containing_block_inline_size = self.containing_block_inline_size(block, parent_flow_inline_size, ctx);
let computed_inline_size = self.initial_computed_inline_size(block, parent_flow_inline_size, ctx); let computed_inline_size = self.initial_computed_inline_size(block, parent_flow_inline_size, ctx);
@ -1864,7 +1864,7 @@ pub trait ISizeAndMarginsComputer {
fn initial_computed_inline_size(&self, fn initial_computed_inline_size(&self,
block: &mut BlockFlow, block: &mut BlockFlow,
parent_flow_inline_size: Au, parent_flow_inline_size: Au,
ctx: &mut LayoutContext) ctx: &LayoutContext)
-> MaybeAuto { -> MaybeAuto {
MaybeAuto::from_style(block.fragment().style().content_inline_size(), MaybeAuto::from_style(block.fragment().style().content_inline_size(),
self.containing_block_inline_size(block, parent_flow_inline_size, ctx)) self.containing_block_inline_size(block, parent_flow_inline_size, ctx))
@ -1873,7 +1873,7 @@ pub trait ISizeAndMarginsComputer {
fn containing_block_inline_size(&self, fn containing_block_inline_size(&self,
_: &mut BlockFlow, _: &mut BlockFlow,
parent_flow_inline_size: Au, parent_flow_inline_size: Au,
_: &mut LayoutContext) _: &LayoutContext)
-> Au { -> Au {
parent_flow_inline_size parent_flow_inline_size
} }
@ -1883,7 +1883,7 @@ pub trait ISizeAndMarginsComputer {
/// CSS Section 10.4: Minimum and Maximum inline-sizes /// CSS Section 10.4: Minimum and Maximum inline-sizes
fn compute_used_inline_size(&self, fn compute_used_inline_size(&self,
block: &mut BlockFlow, block: &mut BlockFlow,
ctx: &mut LayoutContext, ctx: &LayoutContext,
parent_flow_inline_size: Au) { parent_flow_inline_size: Au) {
let mut input = self.compute_inline_size_constraint_inputs(block, parent_flow_inline_size, ctx); let mut input = self.compute_inline_size_constraint_inputs(block, parent_flow_inline_size, ctx);
@ -2127,8 +2127,8 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
ISizeConstraintSolution::for_absolute_flow(inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end) ISizeConstraintSolution::for_absolute_flow(inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end)
} }
fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &mut LayoutContext) -> Au { fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext) -> Au {
block.containing_block_size(ctx.screen_size).inline block.containing_block_size(ctx.shared.screen_size).inline
} }
fn set_flow_x_coord_if_necessary(&self, fn set_flow_x_coord_if_necessary(&self,
@ -2241,9 +2241,9 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
fn initial_computed_inline_size(&self, fn initial_computed_inline_size(&self,
block: &mut BlockFlow, block: &mut BlockFlow,
_: Au, _: Au,
ctx: &mut LayoutContext) ctx: &LayoutContext)
-> MaybeAuto { -> MaybeAuto {
let containing_block_inline_size = block.containing_block_size(ctx.screen_size).inline; let containing_block_inline_size = block.containing_block_size(ctx.shared.screen_size).inline;
let fragment = block.fragment(); let fragment = block.fragment();
fragment.assign_replaced_inline_size_if_necessary(containing_block_inline_size, None); fragment.assign_replaced_inline_size_if_necessary(containing_block_inline_size, None);
// For replaced absolute flow, the rest of the constraint solving will // For replaced absolute flow, the rest of the constraint solving will
@ -2251,8 +2251,8 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
Specified(fragment.content_inline_size()) Specified(fragment.content_inline_size())
} }
fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &mut LayoutContext) -> Au { fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext) -> Au {
block.containing_block_size(ctx.screen_size).inline block.containing_block_size(ctx.shared.screen_size).inline
} }
fn set_flow_x_coord_if_necessary(&self, block: &mut BlockFlow, solution: ISizeConstraintSolution) { fn set_flow_x_coord_if_necessary(&self, block: &mut BlockFlow, solution: ISizeConstraintSolution) {
@ -2291,7 +2291,7 @@ impl ISizeAndMarginsComputer for BlockReplaced {
fn initial_computed_inline_size(&self, fn initial_computed_inline_size(&self,
block: &mut BlockFlow, block: &mut BlockFlow,
parent_flow_inline_size: Au, parent_flow_inline_size: Au,
_: &mut LayoutContext) _: &LayoutContext)
-> MaybeAuto { -> MaybeAuto {
let fragment = block.fragment(); let fragment = block.fragment();
fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, None); fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, None);
@ -2347,7 +2347,7 @@ impl ISizeAndMarginsComputer for FloatReplaced {
fn initial_computed_inline_size(&self, fn initial_computed_inline_size(&self,
block: &mut BlockFlow, block: &mut BlockFlow,
parent_flow_inline_size: Au, parent_flow_inline_size: Au,
_: &mut LayoutContext) _: &LayoutContext)
-> MaybeAuto { -> MaybeAuto {
let fragment = block.fragment(); let fragment = block.fragment();
fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, None); fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, None);

View file

@ -47,7 +47,6 @@ use wrapper::{PostorderNodeMutTraversal, TLayoutNode, ThreadSafeLayoutNode};
use wrapper::{Before, BeforeBlock, After, AfterBlock, Normal}; use wrapper::{Before, BeforeBlock, After, AfterBlock, Normal};
use gfx::display_list::OpaqueNode; use gfx::display_list::OpaqueNode;
use gfx::font_context::FontContext;
use script::dom::element::{HTMLIFrameElementTypeId, HTMLImageElementTypeId}; use script::dom::element::{HTMLIFrameElementTypeId, HTMLImageElementTypeId};
use script::dom::element::{HTMLObjectElementTypeId}; use script::dom::element::{HTMLObjectElementTypeId};
use script::dom::element::{HTMLTableColElementTypeId, HTMLTableDataCellElementTypeId}; use script::dom::element::{HTMLTableColElementTypeId, HTMLTableDataCellElementTypeId};
@ -184,47 +183,20 @@ enum WhitespaceStrippingMode {
} }
/// An object that knows how to create flows. /// An object that knows how to create flows.
pub struct FlowConstructor<'a> { pub struct FlowConstructor<'a, 'b> {
/// The layout context. /// The layout context.
pub layout_context: &'a mut LayoutContext, pub layout_context: &'b LayoutContext<'b>,
/// An optional font context. If this is `None`, then we fetch the font context from the
/// layout context.
///
/// FIXME(pcwalton): This is pretty bogus and is basically just a workaround for libgreen
/// having slow TLS.
pub font_context: Option<Box<FontContext>>,
} }
impl<'a> FlowConstructor<'a> { impl<'a, 'b> FlowConstructor<'a, 'b> {
/// Creates a new flow constructor. /// Creates a new flow constructor.
pub fn new(layout_context: &'a mut LayoutContext, font_context: Option<Box<FontContext>>) pub fn new<'b>(layout_context: &'b LayoutContext)
-> FlowConstructor<'a> { -> FlowConstructor<'a, 'b> {
FlowConstructor { FlowConstructor {
layout_context: layout_context, layout_context: layout_context,
font_context: font_context,
} }
} }
fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
match self.font_context {
Some(ref mut font_context) => {
let font_context: &mut FontContext = &mut **font_context;
font_context
}
None => self.layout_context.font_context(),
}
}
/// Destroys this flow constructor and retrieves the font context.
pub fn unwrap_font_context(self) -> Option<Box<FontContext>> {
let FlowConstructor {
font_context,
..
} = self;
font_context
}
/// Builds the `ImageFragmentInfo` for the given image. This is out of line to guide inlining. /// Builds the `ImageFragmentInfo` for the given image. This is out of line to guide inlining.
fn build_fragment_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>) fn build_fragment_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>)
-> SpecificFragmentInfo { -> SpecificFragmentInfo {
@ -233,7 +205,7 @@ impl<'a> FlowConstructor<'a> {
Some(url) => { Some(url) => {
// FIXME(pcwalton): The fact that image fragments store the cache within them makes // FIXME(pcwalton): The fact that image fragments store the cache within them makes
// little sense to me. // little sense to me.
ImageFragment(ImageFragmentInfo::new(node, url, self.layout_context.image_cache.clone())) ImageFragment(ImageFragmentInfo::new(node, url, self.layout_context.shared.image_cache.clone()))
} }
} }
} }
@ -293,11 +265,11 @@ impl<'a> FlowConstructor<'a> {
} }
let mut inline_flow = box InlineFlow::from_fragments((*node).clone(), fragments); let mut inline_flow = box InlineFlow::from_fragments((*node).clone(), fragments);
let (ascent, descent) = inline_flow.compute_minimum_ascent_and_descent(self.font_context(), &**node.style()); let (ascent, descent) = inline_flow.compute_minimum_ascent_and_descent(self.layout_context.font_context(), &**node.style());
inline_flow.minimum_block_size_above_baseline = ascent; inline_flow.minimum_block_size_above_baseline = ascent;
inline_flow.minimum_depth_below_baseline = descent; inline_flow.minimum_depth_below_baseline = descent;
let mut inline_flow = inline_flow as Box<Flow>; let mut inline_flow = inline_flow as Box<Flow>;
TextRunScanner::new().scan_for_runs(self.font_context(), inline_flow); TextRunScanner::new().scan_for_runs(self.layout_context.font_context(), inline_flow);
let mut inline_flow = FlowRef::new(inline_flow); let mut inline_flow = FlowRef::new(inline_flow);
inline_flow.finish(self.layout_context); inline_flow.finish(self.layout_context);
@ -797,7 +769,7 @@ impl<'a> FlowConstructor<'a> {
} }
} }
impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> { impl<'a, 'b> PostorderNodeMutTraversal for FlowConstructor<'a, 'b> {
// Construct Flow based on 'display', 'position', and 'float' values. // Construct Flow based on 'display', 'position', and 'float' values.
// //
// CSS 2.1 Section 9.7 // CSS 2.1 Section 9.7
@ -1039,7 +1011,7 @@ pub trait FlowConstructionUtils {
/// ///
/// All flows must be finished at some point, or they will not have their intrinsic inline-sizes /// All flows must be finished at some point, or they will not have their intrinsic inline-sizes
/// properly computed. (This is not, however, a memory safety problem.) /// properly computed. (This is not, however, a memory safety problem.)
fn finish(&mut self, context: &mut LayoutContext); fn finish(&mut self, context: &LayoutContext);
} }
impl FlowConstructionUtils for FlowRef { impl FlowConstructionUtils for FlowRef {
@ -1066,8 +1038,8 @@ impl FlowConstructionUtils for FlowRef {
/// properly computed. (This is not, however, a memory safety problem.) /// properly computed. (This is not, however, a memory safety problem.)
/// ///
/// This must not be public because only the layout constructor can do this. /// This must not be public because only the layout constructor can do this.
fn finish(&mut self, context: &mut LayoutContext) { fn finish(&mut self, context: &LayoutContext) {
if !context.opts.bubble_inline_sizes_separately { if !context.shared.opts.bubble_inline_sizes_separately {
self.get_mut().bubble_inline_sizes(context) self.get_mut().bubble_inline_sizes(context)
} }
} }

View file

@ -10,8 +10,6 @@ use geom::{Rect, Size2D};
use gfx::display_list::OpaqueNode; use gfx::display_list::OpaqueNode;
use gfx::font_context::FontContext; use gfx::font_context::FontContext;
use gfx::font_cache_task::FontCacheTask; use gfx::font_cache_task::FontCacheTask;
#[cfg(not(target_os="android"))]
use green::task::GreenTask;
use script::layout_interface::LayoutChan; use script::layout_interface::LayoutChan;
use servo_msg::constellation_msg::ConstellationChan; use servo_msg::constellation_msg::ConstellationChan;
use servo_net::local_image_cache::LocalImageCache; use servo_net::local_image_cache::LocalImageCache;
@ -19,42 +17,37 @@ use servo_util::geometry::Au;
use servo_util::opts::Opts; use servo_util::opts::Opts;
use sync::{Arc, Mutex}; use sync::{Arc, Mutex};
use std::mem; use std::mem;
#[cfg(not(target_os="android"))]
use std::ptr;
#[cfg(not(target_os="android"))]
use std::rt::local::Local;
#[cfg(not(target_os="android"))]
use std::rt::task::Task;
use style::Stylist; use style::Stylist;
use url::Url; use url::Url;
#[cfg(not(target_os="android"))] struct LocalLayoutContext {
#[thread_local] font_context: FontContext,
static mut FONT_CONTEXT: *mut FontContext = 0 as *mut FontContext; applicable_declarations_cache: ApplicableDeclarationsCache,
style_sharing_candidate_cache: StyleSharingCandidateCache,
}
#[cfg(target_os="android")] local_data_key!(local_context_key: *mut LocalLayoutContext)
local_data_key!(font_context: *mut FontContext)
#[cfg(not(target_os="android"))] fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext) -> *mut LocalLayoutContext {
#[thread_local] let maybe_context = local_context_key.get();
static mut APPLICABLE_DECLARATIONS_CACHE: *mut ApplicableDeclarationsCache =
0 as *mut ApplicableDeclarationsCache;
#[cfg(target_os="android")] let context = match maybe_context {
local_data_key!(applicable_declarations_cache: *mut ApplicableDeclarationsCache) None => {
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(),
};
local_context_key.replace(Some(unsafe { mem::transmute(context) }));
local_context_key.get().unwrap()
},
Some(context) => context
};
#[cfg(not(target_os="android"))] *context
#[thread_local] }
static mut STYLE_SHARING_CANDIDATE_CACHE: *mut StyleSharingCandidateCache =
0 as *mut StyleSharingCandidateCache;
#[cfg(target_os="android")] pub struct SharedLayoutContext {
local_data_key!(style_sharing_candidate_cache: *mut StyleSharingCandidateCache)
/// Data shared by all layout workers.
#[allow(raw_pointer_deriving)]
#[deriving(Clone)]
pub struct LayoutContext {
/// The local image cache. /// The local image cache.
pub image_cache: Arc<Mutex<LocalImageCache>>, pub image_cache: Arc<Mutex<LocalImageCache>>,
@ -88,126 +81,43 @@ pub struct LayoutContext {
pub dirty: Rect<Au>, pub dirty: Rect<Au>,
} }
#[cfg(not(target_os="android"))] pub struct LayoutContext<'a> {
impl LayoutContext { pub shared: &'a SharedLayoutContext,
pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext { cached_local_layout_context: *mut LocalLayoutContext,
// Sanity check. }
{
let mut task = Local::borrow(None::<Task>);
match task.maybe_take_runtime::<GreenTask>() {
Some(green) => {
task.put_runtime(green);
fail!("can't call this on a green task!")
}
None => {}
}
}
unsafe { impl<'a> LayoutContext<'a> {
if FONT_CONTEXT == ptr::mut_null() { pub fn new(shared_layout_context: &'a SharedLayoutContext) -> LayoutContext<'a> {
let context = box FontContext::new(self.font_cache_task.clone());
FONT_CONTEXT = mem::transmute(context) let local_context = create_or_get_local_context(shared_layout_context);
}
mem::transmute(FONT_CONTEXT) LayoutContext {
shared: shared_layout_context,
cached_local_layout_context: local_context,
} }
} }
#[inline(always)]
pub fn font_context<'a>(&'a self) -> &'a mut FontContext {
unsafe {
let cached_context = &*self.cached_local_layout_context;
mem::transmute(&cached_context.font_context)
}
}
#[inline(always)]
pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache { pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
// Sanity check.
{
let mut task = Local::borrow(None::<Task>);
match task.maybe_take_runtime::<GreenTask>() {
Some(green) => {
task.put_runtime(green);
fail!("can't call this on a green task!")
}
None => {}
}
}
unsafe { unsafe {
if APPLICABLE_DECLARATIONS_CACHE == ptr::mut_null() { let cached_context = &*self.cached_local_layout_context;
let cache = box ApplicableDeclarationsCache::new(); mem::transmute(&cached_context.applicable_declarations_cache)
APPLICABLE_DECLARATIONS_CACHE = mem::transmute(cache)
}
mem::transmute(APPLICABLE_DECLARATIONS_CACHE)
} }
} }
#[inline(always)]
pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache { pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
// Sanity check.
{
let mut task = Local::borrow(None::<Task>);
match task.maybe_take_runtime::<GreenTask>() {
Some(green) => {
task.put_runtime(green);
fail!("can't call this on a green task!")
}
None => {}
}
}
unsafe { unsafe {
if STYLE_SHARING_CANDIDATE_CACHE == ptr::mut_null() { let cached_context = &*self.cached_local_layout_context;
let cache = box StyleSharingCandidateCache::new(); mem::transmute(&cached_context.style_sharing_candidate_cache)
STYLE_SHARING_CANDIDATE_CACHE = mem::transmute(cache)
}
mem::transmute(STYLE_SHARING_CANDIDATE_CACHE)
} }
} }
} }
// On Android, we don't have the __tls_* functions emitted by rustc, so we
// need to use the slower local_data functions.
// Making matters worse, the local_data functions are very particular about
// enforcing the lifetimes associated with objects that they hold onto,
// which causes us some trouble we work around as below.
#[cfg(target_os="android")]
impl LayoutContext {
pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
unsafe {
let opt = font_context.replace(None);
let mut context;
match opt {
Some(c) => context = mem::transmute(c),
None => {
context = mem::transmute(box FontContext::new(self.font_cache_task.clone()))
}
}
font_context.replace(Some(context));
mem::transmute(context)
}
}
pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
unsafe {
let opt = applicable_declarations_cache.replace(None);
let mut cache;
match opt {
Some(c) => cache = mem::transmute(c),
None => {
cache = mem::transmute(box ApplicableDeclarationsCache::new());
}
}
applicable_declarations_cache.replace(Some(cache));
mem::transmute(cache)
}
}
pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
unsafe {
let opt = style_sharing_candidate_cache.replace(None);
let mut cache;
match opt {
Some(c) => cache = mem::transmute(c),
None => {
cache = mem::transmute(box StyleSharingCandidateCache::new());
}
}
style_sharing_candidate_cache.replace(Some(cache));
mem::transmute(cache)
}
}
}

View file

@ -11,7 +11,6 @@ use extra::LayoutAuxMethods;
use util::{LayoutDataAccess, LayoutDataWrapper}; use util::{LayoutDataAccess, LayoutDataWrapper};
use wrapper::{LayoutElement, LayoutNode, PostorderNodeMutTraversal, ThreadSafeLayoutNode}; use wrapper::{LayoutElement, LayoutNode, PostorderNodeMutTraversal, ThreadSafeLayoutNode};
use gfx::font_context::FontContext;
use servo_util::atom::Atom; use servo_util::atom::Atom;
use servo_util::cache::{Cache, LRUCache, SimpleHashCache}; use servo_util::cache::{Cache, LRUCache, SimpleHashCache};
use servo_util::namespace::Null; use servo_util::namespace::Null;
@ -283,13 +282,9 @@ pub trait MatchMethods {
/// sequentially. /// sequentially.
fn recalc_style_for_subtree(&self, fn recalc_style_for_subtree(&self,
stylist: &Stylist, stylist: &Stylist,
layout_context: &mut LayoutContext, layout_context: &LayoutContext,
mut font_context: Box<FontContext>,
applicable_declarations: &mut ApplicableDeclarations, applicable_declarations: &mut ApplicableDeclarations,
applicable_declarations_cache: &mut ApplicableDeclarationsCache, parent: Option<LayoutNode>);
style_sharing_candidate_cache: &mut StyleSharingCandidateCache,
parent: Option<LayoutNode>)
-> Box<FontContext>;
fn match_node(&self, fn match_node(&self,
stylist: &Stylist, stylist: &Stylist,
@ -462,18 +457,14 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
fn recalc_style_for_subtree(&self, fn recalc_style_for_subtree(&self,
stylist: &Stylist, stylist: &Stylist,
layout_context: &mut LayoutContext, layout_context: &LayoutContext,
mut font_context: Box<FontContext>,
applicable_declarations: &mut ApplicableDeclarations, applicable_declarations: &mut ApplicableDeclarations,
applicable_declarations_cache: &mut ApplicableDeclarationsCache, parent: Option<LayoutNode>) {
style_sharing_candidate_cache: &mut StyleSharingCandidateCache, self.initialize_layout_data(layout_context.shared.layout_chan.clone());
parent: Option<LayoutNode>)
-> Box<FontContext> {
self.initialize_layout_data(layout_context.layout_chan.clone());
// First, check to see whether we can share a style with someone. // First, check to see whether we can share a style with someone.
let sharing_result = unsafe { let sharing_result = unsafe {
self.share_style_if_possible(style_sharing_candidate_cache, parent.clone()) self.share_style_if_possible(layout_context.style_sharing_candidate_cache(), parent.clone())
}; };
// Otherwise, match and cascade selectors. // Otherwise, match and cascade selectors.
@ -486,34 +477,30 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
unsafe { unsafe {
self.cascade_node(parent, self.cascade_node(parent,
applicable_declarations, applicable_declarations,
applicable_declarations_cache) layout_context.applicable_declarations_cache())
} }
applicable_declarations.clear(); applicable_declarations.clear();
// Add ourselves to the LRU cache. // Add ourselves to the LRU cache.
if shareable { if shareable {
style_sharing_candidate_cache.insert_if_possible(self) layout_context.style_sharing_candidate_cache().insert_if_possible(self)
} }
} }
StyleWasShared(index) => style_sharing_candidate_cache.touch(index), StyleWasShared(index) => layout_context.style_sharing_candidate_cache().touch(index),
} }
for kid in self.children() { for kid in self.children() {
font_context = kid.recalc_style_for_subtree(stylist, kid.recalc_style_for_subtree(stylist,
layout_context, layout_context,
font_context, applicable_declarations,
applicable_declarations, Some(self.clone()))
applicable_declarations_cache,
style_sharing_candidate_cache,
Some(self.clone()))
} }
// Construct flows. // Construct flows.
let layout_node = ThreadSafeLayoutNode::new(self); let layout_node = ThreadSafeLayoutNode::new(self);
let mut flow_constructor = FlowConstructor::new(layout_context, Some(font_context)); let mut flow_constructor = FlowConstructor::new(layout_context);
flow_constructor.process(&layout_node); flow_constructor.process(&layout_node);
flow_constructor.unwrap_font_context().unwrap()
} }
unsafe fn cascade_node(&self, unsafe fn cascade_node(&self,

View file

@ -149,24 +149,24 @@ pub trait Flow: fmt::Show + ToString + Share {
/// this flow, all child flows have had their minimum and preferred inline-sizes set. This function /// this flow, all child flows have had their minimum and preferred inline-sizes set. This function
/// must decide minimum/preferred inline-sizes based on its children's inline-sizes and the dimensions of /// must decide minimum/preferred inline-sizes based on its children's inline-sizes and the dimensions of
/// any boxes it is responsible for flowing. /// any boxes it is responsible for flowing.
fn bubble_inline_sizes(&mut self, _ctx: &mut LayoutContext) { fn bubble_inline_sizes(&mut self, _ctx: &LayoutContext) {
fail!("bubble_inline_sizes not yet implemented") fail!("bubble_inline_sizes not yet implemented")
} }
/// Pass 2 of reflow: computes inline-size. /// Pass 2 of reflow: computes inline-size.
fn assign_inline_sizes(&mut self, _ctx: &mut LayoutContext) { fn assign_inline_sizes(&mut self, _ctx: &LayoutContext) {
fail!("assign_inline_sizes not yet implemented") fail!("assign_inline_sizes not yet implemented")
} }
/// Pass 3a of reflow: computes block-size. /// Pass 3a of reflow: computes block-size.
fn assign_block_size(&mut self, _ctx: &mut LayoutContext) { fn assign_block_size<'a>(&mut self, _ctx: &'a LayoutContext<'a>) {
fail!("assign_block_size not yet implemented") fail!("assign_block_size not yet implemented")
} }
/// Assigns block-sizes in-order; or, if this is a float, places the float. The default /// 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 /// implementation simply assigns block-sizes if this flow is impacted by floats. Returns true if
/// this child was impacted by floats or false otherwise. /// this child was impacted by floats or false otherwise.
fn assign_block_size_for_inorder_child_if_necessary(&mut self, layout_context: &mut LayoutContext) fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self, layout_context: &'a LayoutContext<'a>)
-> bool { -> bool {
let impacted = base(&*self).flags.impacted_by_floats(); let impacted = base(&*self).flags.impacted_by_floats();
if impacted { if impacted {
@ -365,7 +365,7 @@ pub trait MutableFlowUtils {
// Mutators // Mutators
/// Computes the overflow region for this flow. /// Computes the overflow region for this flow.
fn store_overflow(self, _: &mut LayoutContext); fn store_overflow(self, _: &LayoutContext);
/// Builds the display lists for this flow. /// Builds the display lists for this flow.
fn build_display_list(self, layout_context: &LayoutContext); fn build_display_list(self, layout_context: &LayoutContext);
@ -963,7 +963,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
/// Assumption: This is called in a bottom-up traversal, so kids' overflows have /// Assumption: This is called in a bottom-up traversal, so kids' overflows have
/// already been set. /// already been set.
/// Assumption: Absolute descendants have had their overflow calculated. /// Assumption: Absolute descendants have had their overflow calculated.
fn store_overflow(self, _: &mut LayoutContext) { fn store_overflow(self, _: &LayoutContext) {
let my_position = mut_base(self).position; let my_position = mut_base(self).position;
let mut overflow = my_position; let mut overflow = my_position;

View file

@ -660,7 +660,7 @@ impl Fragment {
Some(ref image_url) => image_url, Some(ref image_url) => image_url,
}; };
let mut holder = ImageHolder::new(image_url.clone(), layout_context.image_cache.clone()); let mut holder = ImageHolder::new(image_url.clone(), layout_context.shared.image_cache.clone());
let image = match holder.get_image() { let image = match holder.get_image() {
None => { None => {
// No image data at all? Do nothing. // No image data at all? Do nothing.
@ -860,7 +860,7 @@ impl Fragment {
absolute_fragment_bounds, absolute_fragment_bounds,
self); self);
debug!("Fragment::build_display_list: dirty={}, flow_origin={}", debug!("Fragment::build_display_list: dirty={}, flow_origin={}",
layout_context.dirty, layout_context.shared.dirty,
flow_origin); flow_origin);
let mut accumulator = ChildDisplayListAccumulator::new(self.style(), let mut accumulator = ChildDisplayListAccumulator::new(self.style(),
@ -871,7 +871,7 @@ impl Fragment {
return accumulator return accumulator
} }
if !absolute_fragment_bounds.intersects(&layout_context.dirty) { if !absolute_fragment_bounds.intersects(&layout_context.shared.dirty) {
debug!("Fragment::build_display_list: Did not intersect..."); debug!("Fragment::build_display_list: Did not intersect...");
return accumulator return accumulator
} }
@ -1431,7 +1431,7 @@ impl Fragment {
iframe_fragment.pipeline_id, iframe_fragment.pipeline_id,
iframe_fragment.subpage_id); iframe_fragment.subpage_id);
let msg = FrameRectMsg(iframe_fragment.pipeline_id, iframe_fragment.subpage_id, rect); let msg = FrameRectMsg(iframe_fragment.pipeline_id, iframe_fragment.subpage_id, rect);
let ConstellationChan(ref chan) = layout_context.constellation_chan; let ConstellationChan(ref chan) = layout_context.shared.constellation_chan;
chan.send(msg) chan.send(msg)
} }
} }

View file

@ -932,7 +932,7 @@ impl InlineFlow {
// FIXME(#2795): Get the real container size // FIXME(#2795): Get the real container size
let container_size = Size2D::zero(); let container_size = Size2D::zero();
if !abs_rect.to_physical(self.base.writing_mode, container_size) if !abs_rect.to_physical(self.base.writing_mode, container_size)
.intersects(&layout_context.dirty) { .intersects(&layout_context.shared.dirty) {
return return
} }
@ -1090,7 +1090,7 @@ impl Flow for InlineFlow {
self self
} }
fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) { fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let writing_mode = self.base.writing_mode; let writing_mode = self.base.writing_mode;
for kid in self.base.child_iter() { for kid in self.base.child_iter() {
flow::mut_base(kid).floats = Floats::new(writing_mode); flow::mut_base(kid).floats = Floats::new(writing_mode);
@ -1115,7 +1115,7 @@ impl Flow for InlineFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When called /// 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. /// on this context, the context has had its inline-size set by the parent context.
fn assign_inline_sizes(&mut self, _: &mut LayoutContext) { fn assign_inline_sizes(&mut self, _: &LayoutContext) {
// Initialize content fragment inline-sizes if they haven't been initialized already. // 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`. // TODO: Combine this with `LineBreaker`'s walk in the fragment list, or put this into `Fragment`.
@ -1144,7 +1144,7 @@ impl Flow for InlineFlow {
} }
/// Calculate and set the block-size of this flow. See CSS 2.1 § 10.6.1. /// Calculate and set the block-size of this flow. See CSS 2.1 § 10.6.1.
fn assign_block_size(&mut self, _: &mut LayoutContext) { fn assign_block_size(&mut self, _: &LayoutContext) {
debug!("assign_block_size_inline: assigning block_size for flow"); debug!("assign_block_size_inline: assigning block_size for flow");
// Divide the fragments into lines. // Divide the fragments into lines.

View file

@ -5,12 +5,11 @@
//! The layout task. Performs layout on the DOM, builds display lists and sends them to be //! The layout task. Performs layout on the DOM, builds display lists and sends them to be
//! rendered. //! rendered.
use css::matching::{ApplicableDeclarations, ApplicableDeclarationsCache, MatchMethods}; use css::matching::{ApplicableDeclarations, MatchMethods};
use css::matching::{StyleSharingCandidateCache};
use css::select::new_stylist; use css::select::new_stylist;
use css::node_style::StyledNode; use css::node_style::StyledNode;
use construct::{FlowConstructionResult, NoConstructionResult}; use construct::{FlowConstructionResult, NoConstructionResult};
use context::LayoutContext; use context::{LayoutContext, SharedLayoutContext};
use flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils}; use flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use flow::{PreorderFlowTraversal, PostorderFlowTraversal}; use flow::{PreorderFlowTraversal, PostorderFlowTraversal};
use flow; use flow;
@ -27,7 +26,6 @@ use geom::rect::Rect;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::display_list::{ClipDisplayItemClass, ContentStackingLevel, DisplayItem}; use gfx::display_list::{ClipDisplayItemClass, ContentStackingLevel, DisplayItem};
use gfx::display_list::{DisplayItemIterator, DisplayList, OpaqueNode}; use gfx::display_list::{DisplayItemIterator, DisplayList, OpaqueNode};
use gfx::font_context::FontContext;
use gfx::render_task::{RenderInitMsg, RenderChan, RenderLayer}; use gfx::render_task::{RenderInitMsg, RenderChan, RenderLayer};
use gfx::{render_task, color}; use gfx::{render_task, color};
use layout_traits; use layout_traits;
@ -104,7 +102,7 @@ pub struct LayoutTask {
pub stylist: Box<Stylist>, pub stylist: Box<Stylist>,
/// The workers that we use for parallel operation. /// The workers that we use for parallel operation.
pub parallel_traversal: Option<WorkQueue<*mut LayoutContext,UnsafeFlow>>, pub parallel_traversal: Option<WorkQueue<*const SharedLayoutContext,UnsafeFlow>>,
/// The channel on which messages can be sent to the time profiler. /// The channel on which messages can be sent to the time profiler.
pub time_profiler_chan: TimeProfilerChan, pub time_profiler_chan: TimeProfilerChan,
@ -178,7 +176,7 @@ impl PreorderFlowTraversal for FlowTreeVerificationTraversal {
/// The bubble-inline-sizes traversal, the first part of layout computation. This computes preferred /// The bubble-inline-sizes traversal, the first part of layout computation. This computes preferred
/// and intrinsic inline-sizes and bubbles them up the tree. /// and intrinsic inline-sizes and bubbles them up the tree.
pub struct BubbleISizesTraversal<'a> { pub struct BubbleISizesTraversal<'a> {
pub layout_context: &'a mut LayoutContext, pub layout_context: &'a LayoutContext<'a>,
} }
impl<'a> PostorderFlowTraversal for BubbleISizesTraversal<'a> { impl<'a> PostorderFlowTraversal for BubbleISizesTraversal<'a> {
@ -199,7 +197,7 @@ impl<'a> PostorderFlowTraversal for BubbleISizesTraversal<'a> {
/// The assign-inline-sizes traversal. In Gecko this corresponds to `Reflow`. /// The assign-inline-sizes traversal. In Gecko this corresponds to `Reflow`.
pub struct AssignISizesTraversal<'a> { pub struct AssignISizesTraversal<'a> {
pub layout_context: &'a mut LayoutContext, pub layout_context: &'a LayoutContext<'a>,
} }
impl<'a> PreorderFlowTraversal for AssignISizesTraversal<'a> { impl<'a> PreorderFlowTraversal for AssignISizesTraversal<'a> {
@ -214,7 +212,7 @@ impl<'a> PreorderFlowTraversal for AssignISizesTraversal<'a> {
/// computation. Determines the final block-sizes for all layout objects, computes positions, and /// computation. Determines the final block-sizes for all layout objects, computes positions, and
/// computes overflow regions. In Gecko this corresponds to `FinishAndStoreOverflow`. /// computes overflow regions. In Gecko this corresponds to `FinishAndStoreOverflow`.
pub struct AssignBSizesAndStoreOverflowTraversal<'a> { pub struct AssignBSizesAndStoreOverflowTraversal<'a> {
pub layout_context: &'a mut LayoutContext, pub layout_context: &'a LayoutContext<'a>,
} }
impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> { impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> {
@ -237,7 +235,7 @@ impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> {
/// The display list construction traversal. /// The display list construction traversal.
pub struct BuildDisplayListTraversal<'a> { pub struct BuildDisplayListTraversal<'a> {
layout_context: &'a LayoutContext, layout_context: &'a LayoutContext<'a>,
} }
impl<'a> BuildDisplayListTraversal<'a> { impl<'a> BuildDisplayListTraversal<'a> {
@ -330,7 +328,7 @@ impl LayoutTask {
let local_image_cache = Arc::new(Mutex::new(LocalImageCache::new(image_cache_task.clone()))); let local_image_cache = Arc::new(Mutex::new(LocalImageCache::new(image_cache_task.clone())));
let screen_size = Size2D(Au(0), Au(0)); let screen_size = Size2D(Au(0), Au(0));
let parallel_traversal = if opts.layout_threads != 1 { let parallel_traversal = if opts.layout_threads != 1 {
Some(WorkQueue::new("LayoutWorker", opts.layout_threads, ptr::mut_null())) Some(WorkQueue::new("LayoutWorker", opts.layout_threads, ptr::null()))
} else { } else {
None None
}; };
@ -365,8 +363,8 @@ impl LayoutTask {
} }
// Create a layout context for use in building display lists, hit testing, &c. // Create a layout context for use in building display lists, hit testing, &c.
fn build_layout_context(&self, reflow_root: &LayoutNode, url: &Url) -> LayoutContext { fn build_shared_layout_context(&self, reflow_root: &LayoutNode, url: &Url) -> SharedLayoutContext {
LayoutContext { SharedLayoutContext {
image_cache: self.local_image_cache.clone(), image_cache: self.local_image_cache.clone(),
screen_size: self.screen_size.clone(), screen_size: self.screen_size.clone(),
constellation_chan: self.constellation_chan.clone(), constellation_chan: self.constellation_chan.clone(),
@ -542,10 +540,10 @@ impl LayoutTask {
/// This corresponds to `Reflow()` in Gecko and `layout()` in WebKit/Blink and should be /// This corresponds to `Reflow()` in Gecko and `layout()` in WebKit/Blink and should be
/// benchmarked against those two. It is marked `#[inline(never)]` to aid profiling. /// benchmarked against those two. It is marked `#[inline(never)]` to aid profiling.
#[inline(never)] #[inline(never)]
fn solve_constraints(&mut self, fn solve_constraints<'a>(&mut self,
layout_root: &mut Flow, layout_root: &mut Flow,
layout_context: &mut LayoutContext) { layout_context: &'a LayoutContext<'a>) {
if layout_context.opts.bubble_inline_sizes_separately { if layout_context.shared.opts.bubble_inline_sizes_separately {
let mut traversal = BubbleISizesTraversal { let mut traversal = BubbleISizesTraversal {
layout_context: layout_context, layout_context: layout_context,
}; };
@ -580,10 +578,10 @@ impl LayoutTask {
#[inline(never)] #[inline(never)]
fn solve_constraints_parallel(&mut self, fn solve_constraints_parallel(&mut self,
layout_root: &mut FlowRef, layout_root: &mut FlowRef,
layout_context: &mut LayoutContext) { shared_layout_context: &SharedLayoutContext) {
if layout_context.opts.bubble_inline_sizes_separately { if shared_layout_context.opts.bubble_inline_sizes_separately {
let mut traversal = BubbleISizesTraversal { let mut traversal = BubbleISizesTraversal {
layout_context: layout_context, layout_context: &LayoutContext::new(shared_layout_context),
}; };
layout_root.get_mut().traverse_postorder(&mut traversal); layout_root.get_mut().traverse_postorder(&mut traversal);
} }
@ -595,7 +593,7 @@ impl LayoutTask {
// operation out. // operation out.
parallel::traverse_flow_tree_preorder(layout_root, parallel::traverse_flow_tree_preorder(layout_root,
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
layout_context, shared_layout_context,
traversal); traversal);
} }
} }
@ -654,17 +652,7 @@ impl LayoutTask {
self.screen_size = current_screen_size; self.screen_size = current_screen_size;
// Create a layout context for use throughout the following passes. // Create a layout context for use throughout the following passes.
let mut layout_ctx = self.build_layout_context(node, &data.url); let mut shared_layout_ctx = self.build_shared_layout_context(node, &data.url);
// Create a font context, if this is sequential.
//
// FIXME(pcwalton): This is a pretty bogus thing to do. Essentially this is a workaround
// for libgreen having slow TLS.
let mut font_context_opt = if self.parallel_traversal.is_none() {
Some(box FontContext::new(layout_ctx.font_cache_task.clone()))
} else {
None
};
let mut layout_root = profile(time::LayoutStyleRecalcCategory, let mut layout_root = profile(time::LayoutStyleRecalcCategory,
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
@ -672,19 +660,15 @@ impl LayoutTask {
// Perform CSS selector matching and flow construction. // Perform CSS selector matching and flow construction.
match self.parallel_traversal { match self.parallel_traversal {
None => { None => {
let layout_ctx = LayoutContext::new(&shared_layout_ctx);
let mut applicable_declarations = ApplicableDeclarations::new(); let mut applicable_declarations = ApplicableDeclarations::new();
let mut applicable_declarations_cache = ApplicableDeclarationsCache::new(); node.recalc_style_for_subtree(&*self.stylist,
let mut style_sharing_candidate_cache = StyleSharingCandidateCache::new(); &layout_ctx,
drop(node.recalc_style_for_subtree(&*self.stylist, &mut applicable_declarations,
&mut layout_ctx, None)
font_context_opt.take_unwrap(),
&mut applicable_declarations,
&mut applicable_declarations_cache,
&mut style_sharing_candidate_cache,
None))
} }
Some(ref mut traversal) => { Some(ref mut traversal) => {
parallel::recalc_style_for_subtree(node, &mut layout_ctx, traversal) parallel::recalc_style_for_subtree(node, &mut shared_layout_ctx, traversal)
} }
} }
@ -710,11 +694,12 @@ impl LayoutTask {
match self.parallel_traversal { match self.parallel_traversal {
None => { None => {
// Sequential mode. // Sequential mode.
self.solve_constraints(layout_root.get_mut(), &mut layout_ctx) let layout_ctx = LayoutContext::new(&shared_layout_ctx);
self.solve_constraints(layout_root.get_mut(), &layout_ctx)
} }
Some(_) => { Some(_) => {
// Parallel mode. // Parallel mode.
self.solve_constraints_parallel(&mut layout_root, &mut layout_ctx) self.solve_constraints_parallel(&mut layout_root, &mut shared_layout_ctx)
} }
} }
}); });
@ -725,11 +710,12 @@ impl LayoutTask {
profile(time::LayoutDispListBuildCategory, self.time_profiler_chan.clone(), || { profile(time::LayoutDispListBuildCategory, self.time_profiler_chan.clone(), || {
// FIXME(#2795): Get the real container size // FIXME(#2795): Get the real container size
let container_size = Size2D::zero(); let container_size = Size2D::zero();
layout_ctx.dirty = flow::base(layout_root.get()).position.to_physical( shared_layout_ctx.dirty = flow::base(layout_root.get()).position.to_physical(
writing_mode, container_size); writing_mode, container_size);
match self.parallel_traversal { match self.parallel_traversal {
None => { None => {
let layout_ctx = LayoutContext::new(&shared_layout_ctx);
let mut traversal = BuildDisplayListTraversal { let mut traversal = BuildDisplayListTraversal {
layout_context: &layout_ctx, layout_context: &layout_ctx,
}; };
@ -738,7 +724,7 @@ impl LayoutTask {
Some(ref mut traversal) => { Some(ref mut traversal) => {
parallel::build_display_list_for_subtree(&mut layout_root, parallel::build_display_list_for_subtree(&mut layout_root,
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
&mut layout_ctx, &mut shared_layout_ctx,
traversal); traversal);
} }
} }

View file

@ -8,7 +8,7 @@
use css::matching::{ApplicableDeclarations, CannotShare, MatchMethods, StyleWasShared}; use css::matching::{ApplicableDeclarations, CannotShare, MatchMethods, StyleWasShared};
use construct::FlowConstructor; use construct::FlowConstructor;
use context::LayoutContext; use context::{LayoutContext, SharedLayoutContext};
use extra::LayoutAuxMethods; use extra::LayoutAuxMethods;
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal}; use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
use flow; use flow;
@ -116,7 +116,7 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
/// fetch-and-subtract the parent's children count. /// fetch-and-subtract the parent's children count.
fn run_parallel(&mut self, fn run_parallel(&mut self,
mut unsafe_flow: UnsafeFlow, mut unsafe_flow: UnsafeFlow,
_: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) { _: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
loop { loop {
unsafe { unsafe {
// Get a real flow. // Get a real flow.
@ -160,17 +160,17 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
trait ParallelPreorderFlowTraversal : PreorderFlowTraversal { trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
fn run_parallel(&mut self, fn run_parallel(&mut self,
unsafe_flow: UnsafeFlow, unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>); proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>);
#[inline(always)] #[inline(always)]
fn run_parallel_helper(&mut self, fn run_parallel_helper(&mut self,
unsafe_flow: UnsafeFlow, unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>, proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>,
top_down_func: extern "Rust" fn(UnsafeFlow, top_down_func: extern "Rust" fn(UnsafeFlow,
&mut WorkerProxy<*mut LayoutContext, &mut WorkerProxy<*const SharedLayoutContext,
UnsafeFlow>), UnsafeFlow>),
bottom_up_func: extern "Rust" fn(UnsafeFlow, bottom_up_func: extern "Rust" fn(UnsafeFlow,
&mut WorkerProxy<*mut LayoutContext, &mut WorkerProxy<*const SharedLayoutContext,
UnsafeFlow>)) { UnsafeFlow>)) {
let mut had_children = false; let mut had_children = false;
unsafe { unsafe {
@ -203,7 +203,7 @@ impl<'a> ParallelPostorderFlowTraversal for BubbleISizesTraversal<'a> {}
impl<'a> ParallelPreorderFlowTraversal for AssignISizesTraversal<'a> { impl<'a> ParallelPreorderFlowTraversal for AssignISizesTraversal<'a> {
fn run_parallel(&mut self, fn run_parallel(&mut self,
unsafe_flow: UnsafeFlow, unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) { proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
self.run_parallel_helper(unsafe_flow, self.run_parallel_helper(unsafe_flow,
proxy, proxy,
assign_inline_sizes, assign_inline_sizes,
@ -214,8 +214,9 @@ impl<'a> ParallelPreorderFlowTraversal for AssignISizesTraversal<'a> {
impl<'a> ParallelPostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> {} impl<'a> ParallelPostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> {}
fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode, fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) { proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>) {
let layout_context = unsafe { &mut **proxy.user_data() }; let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
// Get a real layout node. // Get a real layout node.
let node: LayoutNode = unsafe { let node: LayoutNode = unsafe {
@ -226,11 +227,11 @@ fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
// //
// FIXME(pcwalton): Stop allocating here. Ideally this should just be done by the HTML // FIXME(pcwalton): Stop allocating here. Ideally this should just be done by the HTML
// parser. // parser.
node.initialize_layout_data(layout_context.layout_chan.clone()); node.initialize_layout_data(layout_context.shared.layout_chan.clone());
// Get the parent node. // Get the parent node.
let opaque_node: OpaqueNode = OpaqueNodeMethods::from_layout_node(&node); let opaque_node: OpaqueNode = OpaqueNodeMethods::from_layout_node(&node);
let parent_opt = if opaque_node == layout_context.reflow_root { let parent_opt = if opaque_node == layout_context.shared.reflow_root {
None None
} else { } else {
node.parent_node() node.parent_node()
@ -250,7 +251,7 @@ fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
if node.is_element() { if node.is_element() {
// Perform the CSS selector matching. // Perform the CSS selector matching.
let stylist = unsafe { &*layout_context.stylist }; let stylist = unsafe { &*layout_context.shared.stylist };
node.match_node(stylist, &mut applicable_declarations, &mut shareable); node.match_node(stylist, &mut applicable_declarations, &mut shareable);
} }
@ -302,14 +303,12 @@ fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
} }
// If we got here, we're a leaf. Start construction of flows for this node. // If we got here, we're a leaf. Start construction of flows for this node.
construct_flows(unsafe_layout_node, proxy) construct_flows(unsafe_layout_node, &layout_context)
} }
fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode, fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) { layout_context: &LayoutContext) {
loop { loop {
let layout_context = unsafe { &mut **proxy.user_data() };
// Get a real layout node. // Get a real layout node.
let node: LayoutNode = unsafe { let node: LayoutNode = unsafe {
layout_node_from_unsafe_layout_node(&unsafe_layout_node) layout_node_from_unsafe_layout_node(&unsafe_layout_node)
@ -317,7 +316,7 @@ fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
// Construct flows for this node. // Construct flows for this node.
{ {
let mut flow_constructor = FlowConstructor::new(layout_context, None); let mut flow_constructor = FlowConstructor::new(layout_context);
flow_constructor.process(&ThreadSafeLayoutNode::new(&node)); flow_constructor.process(&ThreadSafeLayoutNode::new(&node));
} }
@ -340,7 +339,7 @@ fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
// If this is the reflow root, we're done. // If this is the reflow root, we're done.
let opaque_node: OpaqueNode = OpaqueNodeMethods::from_layout_node(&node); let opaque_node: OpaqueNode = OpaqueNodeMethods::from_layout_node(&node);
if layout_context.reflow_root == opaque_node { if layout_context.shared.reflow_root == opaque_node {
break break
} }
@ -376,25 +375,27 @@ fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
} }
fn assign_inline_sizes(unsafe_flow: UnsafeFlow, fn assign_inline_sizes(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) { proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let layout_context = unsafe { &mut **proxy.user_data() }; let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
let mut assign_inline_sizes_traversal = AssignISizesTraversal { let mut assign_inline_sizes_traversal = AssignISizesTraversal {
layout_context: layout_context, layout_context: &layout_context,
}; };
assign_inline_sizes_traversal.run_parallel(unsafe_flow, proxy) assign_inline_sizes_traversal.run_parallel(unsafe_flow, proxy)
} }
fn assign_block_sizes_and_store_overflow(unsafe_flow: UnsafeFlow, fn assign_block_sizes_and_store_overflow(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) { proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let layout_context = unsafe { &mut **proxy.user_data() }; let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
let mut assign_block_sizes_traversal = AssignBSizesAndStoreOverflowTraversal { let mut assign_block_sizes_traversal = AssignBSizesAndStoreOverflowTraversal {
layout_context: layout_context, layout_context: &layout_context,
}; };
assign_block_sizes_traversal.run_parallel(unsafe_flow, proxy) assign_block_sizes_traversal.run_parallel(unsafe_flow, proxy)
} }
fn compute_absolute_position(unsafe_flow: UnsafeFlow, fn compute_absolute_position(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) { proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let mut had_descendants = false; let mut had_descendants = false;
unsafe { unsafe {
// Get a real flow. // Get a real flow.
@ -448,8 +449,9 @@ fn compute_absolute_position(unsafe_flow: UnsafeFlow,
} }
fn build_display_list(mut unsafe_flow: UnsafeFlow, fn build_display_list(mut unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) { proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let layout_context = unsafe { &mut **proxy.user_data() }; let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
loop { loop {
unsafe { unsafe {
@ -457,7 +459,7 @@ fn build_display_list(mut unsafe_flow: UnsafeFlow,
let flow: &mut FlowRef = mem::transmute(&unsafe_flow); let flow: &mut FlowRef = mem::transmute(&unsafe_flow);
// Build display lists. // Build display lists.
flow.get_mut().build_display_list(layout_context); flow.get_mut().build_display_list(&layout_context);
{ {
let base = flow::mut_base(flow.get_mut()); let base = flow::mut_base(flow.get_mut());
@ -506,9 +508,9 @@ fn build_display_list(mut unsafe_flow: UnsafeFlow,
} }
pub fn recalc_style_for_subtree(root_node: &LayoutNode, pub fn recalc_style_for_subtree(root_node: &LayoutNode,
layout_context: &mut LayoutContext, shared_layout_context: &SharedLayoutContext,
queue: &mut WorkQueue<*mut LayoutContext,UnsafeLayoutNode>) { queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeLayoutNode>) {
queue.data = layout_context as *mut _; queue.data = shared_layout_context as *const _;
// Enqueue the root node. // Enqueue the root node.
queue.push(WorkUnit { queue.push(WorkUnit {
@ -518,14 +520,14 @@ pub fn recalc_style_for_subtree(root_node: &LayoutNode,
queue.run(); queue.run();
queue.data = ptr::mut_null() queue.data = ptr::null()
} }
pub fn traverse_flow_tree_preorder(root: &mut FlowRef, pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
time_profiler_chan: TimeProfilerChan, time_profiler_chan: TimeProfilerChan,
layout_context: &mut LayoutContext, shared_layout_context: &SharedLayoutContext,
queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) { queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
queue.data = layout_context as *mut _; queue.data = shared_layout_context as *const _;
profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || { profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || {
queue.push(WorkUnit { queue.push(WorkUnit {
@ -536,14 +538,14 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
queue.run(); queue.run();
queue.data = ptr::mut_null() queue.data = ptr::null()
} }
pub fn build_display_list_for_subtree(root: &mut FlowRef, pub fn build_display_list_for_subtree(root: &mut FlowRef,
time_profiler_chan: TimeProfilerChan, time_profiler_chan: TimeProfilerChan,
layout_context: &mut LayoutContext, shared_layout_context: &SharedLayoutContext,
queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) { queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
queue.data = layout_context as *mut _; queue.data = shared_layout_context as *const _;
profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || { profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || {
queue.push(WorkUnit { queue.push(WorkUnit {
@ -554,6 +556,6 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef,
queue.run(); queue.run();
queue.data = ptr::mut_null() queue.data = ptr::null()
} }

View file

@ -125,7 +125,7 @@ impl TableFlow {
/// inline(always) because this is only ever called by in-order or non-in-order top-level /// inline(always) because this is only ever called by in-order or non-in-order top-level
/// methods /// methods
#[inline(always)] #[inline(always)]
fn assign_block_size_table_base(&mut self, layout_context: &mut LayoutContext) { fn assign_block_size_table_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse); self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse);
} }
@ -164,7 +164,7 @@ impl Flow for TableFlow {
/// table layout calculation. /// table layout calculation.
/// The maximum min/pref inline-sizes of each column are set from the rows for the automatic /// The maximum min/pref inline-sizes of each column are set from the rows for the automatic
/// table layout calculation. /// table layout calculation.
fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) { fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let mut min_inline_size = Au(0); let mut min_inline_size = Au(0);
let mut pref_inline_size = Au(0); let mut pref_inline_size = Au(0);
let mut did_first_row = false; let mut did_first_row = false;
@ -235,7 +235,7 @@ impl Flow for TableFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When /// 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. /// called on this context, the context has had its inline-size set by the parent context.
fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) { fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table"); debug!("assign_inline_sizes({}): assigning inline_size for flow", "table");
// The position was set to the containing block by the flow's parent. // The position was set to the containing block by the flow's parent.
@ -282,7 +282,7 @@ impl Flow for TableFlow {
self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, content_inline_size, Some(self.col_inline_sizes.clone())); self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, content_inline_size, Some(self.col_inline_sizes.clone()));
} }
fn assign_block_size(&mut self, ctx: &mut LayoutContext) { fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table"); debug!("assign_block_size: assigning block_size for table");
self.assign_block_size_table_base(ctx); self.assign_block_size_table_base(ctx);
} }
@ -309,7 +309,7 @@ impl ISizeAndMarginsComputer for InternalTable {
/// CSS Section 10.4: Minimum and Maximum inline-sizes /// CSS Section 10.4: Minimum and Maximum inline-sizes
fn compute_used_inline_size(&self, fn compute_used_inline_size(&self,
block: &mut BlockFlow, block: &mut BlockFlow,
ctx: &mut LayoutContext, ctx: &LayoutContext,
parent_flow_inline_size: Au) { parent_flow_inline_size: Au) {
let input = self.compute_inline_size_constraint_inputs(block, parent_flow_inline_size, ctx); let input = self.compute_inline_size_constraint_inputs(block, parent_flow_inline_size, ctx);
let solution = self.solve_inline_size_constraints(block, &input); let solution = self.solve_inline_size_constraints(block, &input);

View file

@ -47,16 +47,16 @@ impl Flow for TableCaptionFlow {
&mut self.block_flow &mut self.block_flow
} }
fn bubble_inline_sizes(&mut self, ctx: &mut LayoutContext) { fn bubble_inline_sizes(&mut self, ctx: &LayoutContext) {
self.block_flow.bubble_inline_sizes(ctx); self.block_flow.bubble_inline_sizes(ctx);
} }
fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) { fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_caption"); debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_caption");
self.block_flow.assign_inline_sizes(ctx); self.block_flow.assign_inline_sizes(ctx);
} }
fn assign_block_size(&mut self, ctx: &mut LayoutContext) { fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table_caption"); debug!("assign_block_size: assigning block_size for table_caption");
self.block_flow.assign_block_size(ctx); self.block_flow.assign_block_size(ctx);
} }

View file

@ -45,7 +45,7 @@ impl TableCellFlow {
/// inline(always) because this is only ever called by in-order or non-in-order top-level /// inline(always) because this is only ever called by in-order or non-in-order top-level
/// methods /// methods
#[inline(always)] #[inline(always)]
fn assign_block_size_table_cell_base(&mut self, layout_context: &mut LayoutContext) { fn assign_block_size_table_cell_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse) self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse)
} }
@ -69,7 +69,7 @@ impl Flow for TableCellFlow {
} }
/// Minimum/preferred inline-sizes set by this function are used in automatic table layout calculation. /// Minimum/preferred inline-sizes set by this function are used in automatic table layout calculation.
fn bubble_inline_sizes(&mut self, ctx: &mut LayoutContext) { fn bubble_inline_sizes(&mut self, ctx: &LayoutContext) {
self.block_flow.bubble_inline_sizes(ctx); self.block_flow.bubble_inline_sizes(ctx);
let specified_inline_size = MaybeAuto::from_style(self.block_flow.fragment.style().content_inline_size(), let specified_inline_size = MaybeAuto::from_style(self.block_flow.fragment.style().content_inline_size(),
Au::new(0)).specified_or_zero(); Au::new(0)).specified_or_zero();
@ -85,7 +85,7 @@ impl Flow for TableCellFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When /// 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 table row. /// called on this context, the context has had its inline-size set by the parent table row.
fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) { fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_cell"); debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_cell");
// The position was set to the column inline-size by the parent flow, table row flow. // The position was set to the column inline-size by the parent flow, table row flow.
@ -104,7 +104,7 @@ impl Flow for TableCellFlow {
None); None);
} }
fn assign_block_size(&mut self, ctx: &mut LayoutContext) { fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table_cell"); debug!("assign_block_size: assigning block_size for table_cell");
self.assign_block_size_table_cell_base(ctx); self.assign_block_size_table_cell_base(ctx);
} }

View file

@ -52,7 +52,7 @@ impl Flow for TableColGroupFlow {
self self
} }
fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) { fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
for fragment in self.cols.iter() { for fragment in self.cols.iter() {
// get the specified value from inline-size property // get the specified value from inline-size property
let inline_size = MaybeAuto::from_style(fragment.style().content_inline_size(), let inline_size = MaybeAuto::from_style(fragment.style().content_inline_size(),
@ -70,11 +70,11 @@ impl Flow for TableColGroupFlow {
/// Table column inline-sizes are assigned in table flow and propagated to table row or rowgroup flow. /// Table column inline-sizes are assigned in table flow and propagated to table row or rowgroup flow.
/// Therefore, table colgroup flow does not need to assign its inline-size. /// Therefore, table colgroup flow does not need to assign its inline-size.
fn assign_inline_sizes(&mut self, _ctx: &mut LayoutContext) { fn assign_inline_sizes(&mut self, _ctx: &LayoutContext) {
} }
/// Table column do not have block-size. /// Table column do not have block-size.
fn assign_block_size(&mut self, _ctx: &mut LayoutContext) { fn assign_block_size(&mut self, _ctx: &LayoutContext) {
} }
} }

View file

@ -75,7 +75,7 @@ impl TableRowFlow {
/// inline(always) because this is only ever called by in-order or non-in-order top-level /// inline(always) because this is only ever called by in-order or non-in-order top-level
/// methods /// methods
#[inline(always)] #[inline(always)]
fn assign_block_size_table_row_base(&mut self, layout_context: &mut LayoutContext) { fn assign_block_size_table_row_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
let (block_start_offset, _, _) = self.initialize_offsets(); let (block_start_offset, _, _) = self.initialize_offsets();
let /* mut */ cur_y = block_start_offset; let /* mut */ cur_y = block_start_offset;
@ -165,7 +165,7 @@ impl Flow for TableRowFlow {
/// responsible for flowing. /// responsible for flowing.
/// Min/pref inline-sizes set by this function are used in automatic table layout calculation. /// Min/pref inline-sizes set by this function are used in automatic table layout calculation.
/// The specified column inline-sizes of children cells are used in fixed table layout calculation. /// The specified column inline-sizes of children cells are used in fixed table layout calculation.
fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) { fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let mut min_inline_size = Au(0); let mut min_inline_size = Au(0);
let mut pref_inline_size = Au(0); let mut pref_inline_size = Au(0);
/* find the specified inline_sizes from child table-cell contexts */ /* find the specified inline_sizes from child table-cell contexts */
@ -194,7 +194,7 @@ impl Flow for TableRowFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When called /// 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. /// on this context, the context has had its inline-size set by the parent context.
fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) { fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_row"); debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_row");
// The position was set to the containing block by the flow's parent. // The position was set to the containing block by the flow's parent.
@ -208,7 +208,7 @@ impl Flow for TableRowFlow {
self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, Au(0), Some(self.col_inline_sizes.clone())); self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, Au(0), Some(self.col_inline_sizes.clone()));
} }
fn assign_block_size(&mut self, ctx: &mut LayoutContext) { fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table_row"); debug!("assign_block_size: assigning block_size for table_row");
self.assign_block_size_table_row_base(ctx); self.assign_block_size_table_row_base(ctx);
} }

View file

@ -74,7 +74,7 @@ impl TableRowGroupFlow {
/// inline(always) because this is only ever called by in-order or non-in-order top-level /// inline(always) because this is only ever called by in-order or non-in-order top-level
/// methods /// methods
#[inline(always)] #[inline(always)]
fn assign_block_size_table_rowgroup_base(&mut self, layout_context: &mut LayoutContext) { fn assign_block_size_table_rowgroup_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
let (block_start_offset, _, _) = self.initialize_offsets(); let (block_start_offset, _, _) = self.initialize_offsets();
let mut cur_y = block_start_offset; let mut cur_y = block_start_offset;
@ -133,7 +133,7 @@ impl Flow for TableRowGroupFlow {
/// Min/pref inline-sizes set by this function are used in automatic table layout calculation. /// Min/pref inline-sizes set by this function are used in automatic table layout calculation.
/// Also, this function finds the specified column inline-sizes from the first row. /// Also, this function finds the specified column inline-sizes from the first row.
/// Those are used in fixed table layout calculation /// Those are used in fixed table layout calculation
fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) { fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let mut min_inline_size = Au(0); let mut min_inline_size = Au(0);
let mut pref_inline_size = Au(0); let mut pref_inline_size = Au(0);
@ -175,7 +175,7 @@ impl Flow for TableRowGroupFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When /// 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. /// called on this context, the context has had its inline-size set by the parent context.
fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) { fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_rowgroup"); debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_rowgroup");
// The position was set to the containing block by the flow's parent. // The position was set to the containing block by the flow's parent.
@ -191,7 +191,7 @@ impl Flow for TableRowGroupFlow {
self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, content_inline_size, Some(self.col_inline_sizes.clone())); self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, content_inline_size, Some(self.col_inline_sizes.clone()));
} }
fn assign_block_size(&mut self, ctx: &mut LayoutContext) { fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table_rowgroup"); debug!("assign_block_size: assigning block_size for table_rowgroup");
self.assign_block_size_table_rowgroup_base(ctx); self.assign_block_size_table_rowgroup_base(ctx);
} }

View file

@ -100,7 +100,7 @@ impl TableWrapperFlow {
/// inline(always) because this is only ever called by in-order or non-in-order top-level /// inline(always) because this is only ever called by in-order or non-in-order top-level
/// methods /// methods
#[inline(always)] #[inline(always)]
fn assign_block_size_table_wrapper_base(&mut self, layout_context: &mut LayoutContext) { fn assign_block_size_table_wrapper_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse); self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse);
} }
@ -129,7 +129,7 @@ impl Flow for TableWrapperFlow {
min/pref inline_sizes based on child context inline_sizes and dimensions of min/pref inline_sizes based on child context inline_sizes and dimensions of
any fragments it is responsible for flowing. */ any fragments it is responsible for flowing. */
fn bubble_inline_sizes(&mut self, ctx: &mut LayoutContext) { fn bubble_inline_sizes(&mut self, ctx: &LayoutContext) {
// get column inline-sizes info from table flow // get column inline-sizes info from table flow
for kid in self.block_flow.base.child_iter() { for kid in self.block_flow.base.child_iter() {
assert!(kid.is_table_caption() || kid.is_table()); assert!(kid.is_table_caption() || kid.is_table());
@ -147,7 +147,7 @@ impl Flow for TableWrapperFlow {
/// ///
/// Dual fragments consume some inline-size first, and the remainder is assigned to all child (block) /// Dual fragments consume some inline-size first, and the remainder is assigned to all child (block)
/// contexts. /// contexts.
fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) { fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", debug!("assign_inline_sizes({}): assigning inline_size for flow",
if self.is_float() { if self.is_float() {
"floated table_wrapper" "floated table_wrapper"
@ -178,7 +178,7 @@ impl Flow for TableWrapperFlow {
self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, content_inline_size, assigned_col_inline_sizes); self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, content_inline_size, assigned_col_inline_sizes);
} }
fn assign_block_size(&mut self, ctx: &mut LayoutContext) { fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
if self.is_float() { if self.is_float() {
debug!("assign_block_size_float: assigning block_size for floated table_wrapper"); debug!("assign_block_size_float: assigning block_size for floated table_wrapper");
self.block_flow.assign_block_size_float(ctx); self.block_flow.assign_block_size_float(ctx);
@ -208,7 +208,7 @@ struct TableWrapper;
impl TableWrapper { impl TableWrapper {
fn compute_used_inline_size_table_wrapper(&self, fn compute_used_inline_size_table_wrapper(&self,
table_wrapper: &mut TableWrapperFlow, table_wrapper: &mut TableWrapperFlow,
ctx: &mut LayoutContext, ctx: &LayoutContext,
parent_flow_inline_size: Au) { parent_flow_inline_size: Au) {
let input = self.compute_inline_size_constraint_inputs_table_wrapper(table_wrapper, let input = self.compute_inline_size_constraint_inputs_table_wrapper(table_wrapper,
parent_flow_inline_size, parent_flow_inline_size,
@ -223,7 +223,7 @@ impl TableWrapper {
fn compute_inline_size_constraint_inputs_table_wrapper(&self, fn compute_inline_size_constraint_inputs_table_wrapper(&self,
table_wrapper: &mut TableWrapperFlow, table_wrapper: &mut TableWrapperFlow,
parent_flow_inline_size: Au, parent_flow_inline_size: Au,
ctx: &mut LayoutContext) ctx: &LayoutContext)
-> ISizeConstraintInput { -> ISizeConstraintInput {
let mut input = self.compute_inline_size_constraint_inputs(&mut table_wrapper.block_flow, let mut input = self.compute_inline_size_constraint_inputs(&mut table_wrapper.block_flow,
parent_flow_inline_size, parent_flow_inline_size,