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
/// 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> {
#[inline]
@ -429,7 +429,7 @@ impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
/// After that, it is up to the normal store-overflow traversal to propagate
/// it further up.
struct AbsoluteStoreOverflowTraversal<'a>{
layout_context: &'a mut LayoutContext,
layout_context: &'a LayoutContext<'a>,
}
impl<'a> PostorderFlowTraversal for AbsoluteStoreOverflowTraversal<'a> {
@ -579,7 +579,7 @@ impl BlockFlow {
}
/// 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();
match block_type {
AbsoluteReplacedType => {
@ -805,8 +805,8 @@ impl BlockFlow {
/// `inline(always)` because this is only ever called by in-order or non-in-order top-level
/// methods
#[inline(always)]
pub fn assign_block_size_block_base(&mut self,
layout_context: &mut LayoutContext,
pub fn assign_block_size_block_base<'a>(&mut self,
layout_context: &'a LayoutContext<'a>,
margins_may_collapse: MarginsMayCollapseFlag) {
// Our current border-box position.
let mut cur_b = Au(0);
@ -949,7 +949,7 @@ impl BlockFlow {
let mut block_size = cur_b - block_start_offset;
if self.is_root() {
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)
}
@ -1053,7 +1053,7 @@ impl BlockFlow {
/// should be calculated using CSS Section 10.6.7
///
/// 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);
for kid in self.base.child_iter() {
flow::mut_base(kid).floats = floats.clone();
@ -1179,7 +1179,7 @@ impl BlockFlow {
/// + y-coordinate of the flow wrt its Containing Block.
/// + block-size, vertical margins, and y-coordinate for the flow's box.
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;
// 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.
///
/// 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;
flags.set_has_left_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)
/// 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",
if self.is_float() {
"float"
@ -1501,7 +1501,7 @@ impl Flow for BlockFlow {
debug!("Setting root position");
self.base.position.start = LogicalPoint::zero(self.base.writing_mode);
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);
// 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
/// 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 {
if self.is_float() {
self.place_float();
@ -1573,7 +1573,7 @@ impl Flow for BlockFlow {
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.
self.fragment.assign_replaced_block_size_if_necessary();
@ -1794,7 +1794,7 @@ pub trait ISizeAndMarginsComputer {
fn compute_inline_size_constraint_inputs(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
ctx: &mut LayoutContext)
ctx: &LayoutContext)
-> ISizeConstraintInput {
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);
@ -1864,7 +1864,7 @@ pub trait ISizeAndMarginsComputer {
fn initial_computed_inline_size(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
ctx: &mut LayoutContext)
ctx: &LayoutContext)
-> MaybeAuto {
MaybeAuto::from_style(block.fragment().style().content_inline_size(),
self.containing_block_inline_size(block, parent_flow_inline_size, ctx))
@ -1873,7 +1873,7 @@ pub trait ISizeAndMarginsComputer {
fn containing_block_inline_size(&self,
_: &mut BlockFlow,
parent_flow_inline_size: Au,
_: &mut LayoutContext)
_: &LayoutContext)
-> Au {
parent_flow_inline_size
}
@ -1883,7 +1883,7 @@ pub trait ISizeAndMarginsComputer {
/// CSS Section 10.4: Minimum and Maximum inline-sizes
fn compute_used_inline_size(&self,
block: &mut BlockFlow,
ctx: &mut LayoutContext,
ctx: &LayoutContext,
parent_flow_inline_size: Au) {
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)
}
fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &mut LayoutContext) -> Au {
block.containing_block_size(ctx.screen_size).inline
fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext) -> Au {
block.containing_block_size(ctx.shared.screen_size).inline
}
fn set_flow_x_coord_if_necessary(&self,
@ -2241,9 +2241,9 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
fn initial_computed_inline_size(&self,
block: &mut BlockFlow,
_: Au,
ctx: &mut LayoutContext)
ctx: &LayoutContext)
-> 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();
fragment.assign_replaced_inline_size_if_necessary(containing_block_inline_size, None);
// For replaced absolute flow, the rest of the constraint solving will
@ -2251,8 +2251,8 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
Specified(fragment.content_inline_size())
}
fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &mut LayoutContext) -> Au {
block.containing_block_size(ctx.screen_size).inline
fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext) -> Au {
block.containing_block_size(ctx.shared.screen_size).inline
}
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,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
_: &mut LayoutContext)
_: &LayoutContext)
-> MaybeAuto {
let fragment = block.fragment();
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,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
_: &mut LayoutContext)
_: &LayoutContext)
-> MaybeAuto {
let fragment = block.fragment();
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 gfx::display_list::OpaqueNode;
use gfx::font_context::FontContext;
use script::dom::element::{HTMLIFrameElementTypeId, HTMLImageElementTypeId};
use script::dom::element::{HTMLObjectElementTypeId};
use script::dom::element::{HTMLTableColElementTypeId, HTMLTableDataCellElementTypeId};
@ -184,47 +183,20 @@ enum WhitespaceStrippingMode {
}
/// An object that knows how to create flows.
pub struct FlowConstructor<'a> {
pub struct FlowConstructor<'a, 'b> {
/// The layout context.
pub layout_context: &'a mut LayoutContext,
/// 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>>,
pub layout_context: &'b LayoutContext<'b>,
}
impl<'a> FlowConstructor<'a> {
impl<'a, 'b> FlowConstructor<'a, 'b> {
/// Creates a new flow constructor.
pub fn new(layout_context: &'a mut LayoutContext, font_context: Option<Box<FontContext>>)
-> FlowConstructor<'a> {
pub fn new<'b>(layout_context: &'b LayoutContext)
-> FlowConstructor<'a, 'b> {
FlowConstructor {
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.
fn build_fragment_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>)
-> SpecificFragmentInfo {
@ -233,7 +205,7 @@ impl<'a> FlowConstructor<'a> {
Some(url) => {
// FIXME(pcwalton): The fact that image fragments store the cache within them makes
// 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 (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_depth_below_baseline = descent;
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);
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.
//
// 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
/// 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 {
@ -1066,8 +1038,8 @@ impl FlowConstructionUtils for FlowRef {
/// properly computed. (This is not, however, a memory safety problem.)
///
/// This must not be public because only the layout constructor can do this.
fn finish(&mut self, context: &mut LayoutContext) {
if !context.opts.bubble_inline_sizes_separately {
fn finish(&mut self, context: &LayoutContext) {
if !context.shared.opts.bubble_inline_sizes_separately {
self.get_mut().bubble_inline_sizes(context)
}
}

View file

@ -10,8 +10,6 @@ use geom::{Rect, Size2D};
use gfx::display_list::OpaqueNode;
use gfx::font_context::FontContext;
use gfx::font_cache_task::FontCacheTask;
#[cfg(not(target_os="android"))]
use green::task::GreenTask;
use script::layout_interface::LayoutChan;
use servo_msg::constellation_msg::ConstellationChan;
use servo_net::local_image_cache::LocalImageCache;
@ -19,42 +17,37 @@ use servo_util::geometry::Au;
use servo_util::opts::Opts;
use sync::{Arc, Mutex};
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 url::Url;
#[cfg(not(target_os="android"))]
#[thread_local]
static mut FONT_CONTEXT: *mut FontContext = 0 as *mut FontContext;
struct LocalLayoutContext {
font_context: FontContext,
applicable_declarations_cache: ApplicableDeclarationsCache,
style_sharing_candidate_cache: StyleSharingCandidateCache,
}
#[cfg(target_os="android")]
local_data_key!(font_context: *mut FontContext)
local_data_key!(local_context_key: *mut LocalLayoutContext)
#[cfg(not(target_os="android"))]
#[thread_local]
static mut APPLICABLE_DECLARATIONS_CACHE: *mut ApplicableDeclarationsCache =
0 as *mut ApplicableDeclarationsCache;
fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext) -> *mut LocalLayoutContext {
let maybe_context = local_context_key.get();
#[cfg(target_os="android")]
local_data_key!(applicable_declarations_cache: *mut ApplicableDeclarationsCache)
let context = match maybe_context {
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"))]
#[thread_local]
static mut STYLE_SHARING_CANDIDATE_CACHE: *mut StyleSharingCandidateCache =
0 as *mut StyleSharingCandidateCache;
*context
}
#[cfg(target_os="android")]
local_data_key!(style_sharing_candidate_cache: *mut StyleSharingCandidateCache)
/// Data shared by all layout workers.
#[allow(raw_pointer_deriving)]
#[deriving(Clone)]
pub struct LayoutContext {
pub struct SharedLayoutContext {
/// The local image cache.
pub image_cache: Arc<Mutex<LocalImageCache>>,
@ -88,126 +81,43 @@ pub struct LayoutContext {
pub dirty: Rect<Au>,
}
#[cfg(not(target_os="android"))]
impl LayoutContext {
pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
// 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!")
pub struct LayoutContext<'a> {
pub shared: &'a SharedLayoutContext,
cached_local_layout_context: *mut LocalLayoutContext,
}
None => {}
impl<'a> LayoutContext<'a> {
pub fn new(shared_layout_context: &'a SharedLayoutContext) -> LayoutContext<'a> {
let local_context = create_or_get_local_context(shared_layout_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 {
if FONT_CONTEXT == ptr::mut_null() {
let context = box FontContext::new(self.font_cache_task.clone());
FONT_CONTEXT = mem::transmute(context)
}
mem::transmute(FONT_CONTEXT)
}
}
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 {
if APPLICABLE_DECLARATIONS_CACHE == ptr::mut_null() {
let cache = box ApplicableDeclarationsCache::new();
APPLICABLE_DECLARATIONS_CACHE = mem::transmute(cache)
}
mem::transmute(APPLICABLE_DECLARATIONS_CACHE)
}
}
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 {
if STYLE_SHARING_CANDIDATE_CACHE == ptr::mut_null() {
let cache = box StyleSharingCandidateCache::new();
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)
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 {
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)
let cached_context = &*self.cached_local_layout_context;
mem::transmute(&cached_context.applicable_declarations_cache)
}
}
#[inline(always)]
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)
let cached_context = &*self.cached_local_layout_context;
mem::transmute(&cached_context.style_sharing_candidate_cache)
}
}
}

View file

@ -11,7 +11,6 @@ use extra::LayoutAuxMethods;
use util::{LayoutDataAccess, LayoutDataWrapper};
use wrapper::{LayoutElement, LayoutNode, PostorderNodeMutTraversal, ThreadSafeLayoutNode};
use gfx::font_context::FontContext;
use servo_util::atom::Atom;
use servo_util::cache::{Cache, LRUCache, SimpleHashCache};
use servo_util::namespace::Null;
@ -283,13 +282,9 @@ pub trait MatchMethods {
/// sequentially.
fn recalc_style_for_subtree(&self,
stylist: &Stylist,
layout_context: &mut LayoutContext,
mut font_context: Box<FontContext>,
layout_context: &LayoutContext,
applicable_declarations: &mut ApplicableDeclarations,
applicable_declarations_cache: &mut ApplicableDeclarationsCache,
style_sharing_candidate_cache: &mut StyleSharingCandidateCache,
parent: Option<LayoutNode>)
-> Box<FontContext>;
parent: Option<LayoutNode>);
fn match_node(&self,
stylist: &Stylist,
@ -462,18 +457,14 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
fn recalc_style_for_subtree(&self,
stylist: &Stylist,
layout_context: &mut LayoutContext,
mut font_context: Box<FontContext>,
layout_context: &LayoutContext,
applicable_declarations: &mut ApplicableDeclarations,
applicable_declarations_cache: &mut ApplicableDeclarationsCache,
style_sharing_candidate_cache: &mut StyleSharingCandidateCache,
parent: Option<LayoutNode>)
-> Box<FontContext> {
self.initialize_layout_data(layout_context.layout_chan.clone());
parent: Option<LayoutNode>) {
self.initialize_layout_data(layout_context.shared.layout_chan.clone());
// First, check to see whether we can share a style with someone.
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.
@ -486,34 +477,30 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
unsafe {
self.cascade_node(parent,
applicable_declarations,
applicable_declarations_cache)
layout_context.applicable_declarations_cache())
}
applicable_declarations.clear();
// Add ourselves to the LRU cache.
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() {
font_context = kid.recalc_style_for_subtree(stylist,
kid.recalc_style_for_subtree(stylist,
layout_context,
font_context,
applicable_declarations,
applicable_declarations_cache,
style_sharing_candidate_cache,
Some(self.clone()))
}
// Construct flows.
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.unwrap_font_context().unwrap()
}
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
/// must decide minimum/preferred inline-sizes based on its children's inline-sizes and the dimensions of
/// 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")
}
/// 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")
}
/// 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")
}
/// Assigns block-sizes in-order; or, if this is a float, places the float. The default
/// implementation simply assigns block-sizes if this flow is impacted by floats. Returns true if
/// this child was impacted by floats or false otherwise.
fn assign_block_size_for_inorder_child_if_necessary(&mut self, layout_context: &mut LayoutContext)
fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self, layout_context: &'a LayoutContext<'a>)
-> bool {
let impacted = base(&*self).flags.impacted_by_floats();
if impacted {
@ -365,7 +365,7 @@ pub trait MutableFlowUtils {
// Mutators
/// 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.
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
/// already been set.
/// 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 mut overflow = my_position;

View file

@ -660,7 +660,7 @@ impl Fragment {
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() {
None => {
// No image data at all? Do nothing.
@ -860,7 +860,7 @@ impl Fragment {
absolute_fragment_bounds,
self);
debug!("Fragment::build_display_list: dirty={}, flow_origin={}",
layout_context.dirty,
layout_context.shared.dirty,
flow_origin);
let mut accumulator = ChildDisplayListAccumulator::new(self.style(),
@ -871,7 +871,7 @@ impl Fragment {
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...");
return accumulator
}
@ -1431,7 +1431,7 @@ impl Fragment {
iframe_fragment.pipeline_id,
iframe_fragment.subpage_id);
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)
}
}

View file

@ -932,7 +932,7 @@ impl InlineFlow {
// FIXME(#2795): Get the real container size
let container_size = Size2D::zero();
if !abs_rect.to_physical(self.base.writing_mode, container_size)
.intersects(&layout_context.dirty) {
.intersects(&layout_context.shared.dirty) {
return
}
@ -1090,7 +1090,7 @@ impl Flow for InlineFlow {
self
}
fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) {
fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let writing_mode = self.base.writing_mode;
for kid in self.base.child_iter() {
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
/// 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.
//
// 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.
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");
// 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
//! rendered.
use css::matching::{ApplicableDeclarations, ApplicableDeclarationsCache, MatchMethods};
use css::matching::{StyleSharingCandidateCache};
use css::matching::{ApplicableDeclarations, MatchMethods};
use css::select::new_stylist;
use css::node_style::StyledNode;
use construct::{FlowConstructionResult, NoConstructionResult};
use context::LayoutContext;
use context::{LayoutContext, SharedLayoutContext};
use flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use flow::{PreorderFlowTraversal, PostorderFlowTraversal};
use flow;
@ -27,7 +26,6 @@ use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::{ClipDisplayItemClass, ContentStackingLevel, DisplayItem};
use gfx::display_list::{DisplayItemIterator, DisplayList, OpaqueNode};
use gfx::font_context::FontContext;
use gfx::render_task::{RenderInitMsg, RenderChan, RenderLayer};
use gfx::{render_task, color};
use layout_traits;
@ -104,7 +102,7 @@ pub struct LayoutTask {
pub stylist: Box<Stylist>,
/// 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.
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
/// and intrinsic inline-sizes and bubbles them up the tree.
pub struct BubbleISizesTraversal<'a> {
pub layout_context: &'a mut LayoutContext,
pub layout_context: &'a LayoutContext<'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`.
pub struct AssignISizesTraversal<'a> {
pub layout_context: &'a mut LayoutContext,
pub layout_context: &'a LayoutContext<'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
/// computes overflow regions. In Gecko this corresponds to `FinishAndStoreOverflow`.
pub struct AssignBSizesAndStoreOverflowTraversal<'a> {
pub layout_context: &'a mut LayoutContext,
pub layout_context: &'a LayoutContext<'a>,
}
impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> {
@ -237,7 +235,7 @@ impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> {
/// The display list construction traversal.
pub struct BuildDisplayListTraversal<'a> {
layout_context: &'a LayoutContext,
layout_context: &'a LayoutContext<'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 screen_size = Size2D(Au(0), Au(0));
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 {
None
};
@ -365,8 +363,8 @@ impl LayoutTask {
}
// Create a layout context for use in building display lists, hit testing, &c.
fn build_layout_context(&self, reflow_root: &LayoutNode, url: &Url) -> LayoutContext {
LayoutContext {
fn build_shared_layout_context(&self, reflow_root: &LayoutNode, url: &Url) -> SharedLayoutContext {
SharedLayoutContext {
image_cache: self.local_image_cache.clone(),
screen_size: self.screen_size.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
/// benchmarked against those two. It is marked `#[inline(never)]` to aid profiling.
#[inline(never)]
fn solve_constraints(&mut self,
fn solve_constraints<'a>(&mut self,
layout_root: &mut Flow,
layout_context: &mut LayoutContext) {
if layout_context.opts.bubble_inline_sizes_separately {
layout_context: &'a LayoutContext<'a>) {
if layout_context.shared.opts.bubble_inline_sizes_separately {
let mut traversal = BubbleISizesTraversal {
layout_context: layout_context,
};
@ -580,10 +578,10 @@ impl LayoutTask {
#[inline(never)]
fn solve_constraints_parallel(&mut self,
layout_root: &mut FlowRef,
layout_context: &mut LayoutContext) {
if layout_context.opts.bubble_inline_sizes_separately {
shared_layout_context: &SharedLayoutContext) {
if shared_layout_context.opts.bubble_inline_sizes_separately {
let mut traversal = BubbleISizesTraversal {
layout_context: layout_context,
layout_context: &LayoutContext::new(shared_layout_context),
};
layout_root.get_mut().traverse_postorder(&mut traversal);
}
@ -595,7 +593,7 @@ impl LayoutTask {
// operation out.
parallel::traverse_flow_tree_preorder(layout_root,
self.time_profiler_chan.clone(),
layout_context,
shared_layout_context,
traversal);
}
}
@ -654,17 +652,7 @@ impl LayoutTask {
self.screen_size = current_screen_size;
// Create a layout context for use throughout the following passes.
let mut layout_ctx = self.build_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 shared_layout_ctx = self.build_shared_layout_context(node, &data.url);
let mut layout_root = profile(time::LayoutStyleRecalcCategory,
self.time_profiler_chan.clone(),
@ -672,19 +660,15 @@ impl LayoutTask {
// Perform CSS selector matching and flow construction.
match self.parallel_traversal {
None => {
let layout_ctx = LayoutContext::new(&shared_layout_ctx);
let mut applicable_declarations = ApplicableDeclarations::new();
let mut applicable_declarations_cache = ApplicableDeclarationsCache::new();
let mut style_sharing_candidate_cache = StyleSharingCandidateCache::new();
drop(node.recalc_style_for_subtree(&*self.stylist,
&mut layout_ctx,
font_context_opt.take_unwrap(),
node.recalc_style_for_subtree(&*self.stylist,
&layout_ctx,
&mut applicable_declarations,
&mut applicable_declarations_cache,
&mut style_sharing_candidate_cache,
None))
None)
}
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 {
None => {
// 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(_) => {
// 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(), || {
// FIXME(#2795): Get the real container size
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);
match self.parallel_traversal {
None => {
let layout_ctx = LayoutContext::new(&shared_layout_ctx);
let mut traversal = BuildDisplayListTraversal {
layout_context: &layout_ctx,
};
@ -738,7 +724,7 @@ impl LayoutTask {
Some(ref mut traversal) => {
parallel::build_display_list_for_subtree(&mut layout_root,
self.time_profiler_chan.clone(),
&mut layout_ctx,
&mut shared_layout_ctx,
traversal);
}
}

View file

@ -8,7 +8,7 @@
use css::matching::{ApplicableDeclarations, CannotShare, MatchMethods, StyleWasShared};
use construct::FlowConstructor;
use context::LayoutContext;
use context::{LayoutContext, SharedLayoutContext};
use extra::LayoutAuxMethods;
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
use flow;
@ -116,7 +116,7 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
/// fetch-and-subtract the parent's children count.
fn run_parallel(&mut self,
mut unsafe_flow: UnsafeFlow,
_: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
_: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
loop {
unsafe {
// Get a real flow.
@ -160,17 +160,17 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
fn run_parallel(&mut self,
unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>);
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>);
#[inline(always)]
fn run_parallel_helper(&mut self,
unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>,
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>,
top_down_func: extern "Rust" fn(UnsafeFlow,
&mut WorkerProxy<*mut LayoutContext,
&mut WorkerProxy<*const SharedLayoutContext,
UnsafeFlow>),
bottom_up_func: extern "Rust" fn(UnsafeFlow,
&mut WorkerProxy<*mut LayoutContext,
&mut WorkerProxy<*const SharedLayoutContext,
UnsafeFlow>)) {
let mut had_children = false;
unsafe {
@ -203,7 +203,7 @@ impl<'a> ParallelPostorderFlowTraversal for BubbleISizesTraversal<'a> {}
impl<'a> ParallelPreorderFlowTraversal for AssignISizesTraversal<'a> {
fn run_parallel(&mut self,
unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
self.run_parallel_helper(unsafe_flow,
proxy,
assign_inline_sizes,
@ -214,8 +214,9 @@ impl<'a> ParallelPreorderFlowTraversal for AssignISizesTraversal<'a> {
impl<'a> ParallelPostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> {}
fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) {
let layout_context = unsafe { &mut **proxy.user_data() };
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>) {
let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
// Get a real layout node.
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
// parser.
node.initialize_layout_data(layout_context.layout_chan.clone());
node.initialize_layout_data(layout_context.shared.layout_chan.clone());
// Get the parent 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
} else {
node.parent_node()
@ -250,7 +251,7 @@ fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
if node.is_element() {
// 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);
}
@ -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.
construct_flows(unsafe_layout_node, proxy)
construct_flows(unsafe_layout_node, &layout_context)
}
fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) {
layout_context: &LayoutContext) {
loop {
let layout_context = unsafe { &mut **proxy.user_data() };
// Get a real layout node.
let node: LayoutNode = unsafe {
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.
{
let mut flow_constructor = FlowConstructor::new(layout_context, None);
let mut flow_constructor = FlowConstructor::new(layout_context);
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.
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
}
@ -376,25 +375,27 @@ fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
}
fn assign_inline_sizes(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
let layout_context = unsafe { &mut **proxy.user_data() };
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
let mut assign_inline_sizes_traversal = AssignISizesTraversal {
layout_context: layout_context,
layout_context: &layout_context,
};
assign_inline_sizes_traversal.run_parallel(unsafe_flow, proxy)
}
fn assign_block_sizes_and_store_overflow(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
let layout_context = unsafe { &mut **proxy.user_data() };
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
let mut assign_block_sizes_traversal = AssignBSizesAndStoreOverflowTraversal {
layout_context: layout_context,
layout_context: &layout_context,
};
assign_block_sizes_traversal.run_parallel(unsafe_flow, proxy)
}
fn compute_absolute_position(unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let mut had_descendants = false;
unsafe {
// Get a real flow.
@ -448,8 +449,9 @@ fn compute_absolute_position(unsafe_flow: UnsafeFlow,
}
fn build_display_list(mut unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
let layout_context = unsafe { &mut **proxy.user_data() };
proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let shared_layout_context = unsafe { &**proxy.user_data() };
let layout_context = LayoutContext::new(shared_layout_context);
loop {
unsafe {
@ -457,7 +459,7 @@ fn build_display_list(mut unsafe_flow: UnsafeFlow,
let flow: &mut FlowRef = mem::transmute(&unsafe_flow);
// 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());
@ -506,9 +508,9 @@ fn build_display_list(mut unsafe_flow: UnsafeFlow,
}
pub fn recalc_style_for_subtree(root_node: &LayoutNode,
layout_context: &mut LayoutContext,
queue: &mut WorkQueue<*mut LayoutContext,UnsafeLayoutNode>) {
queue.data = layout_context as *mut _;
shared_layout_context: &SharedLayoutContext,
queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeLayoutNode>) {
queue.data = shared_layout_context as *const _;
// Enqueue the root node.
queue.push(WorkUnit {
@ -518,14 +520,14 @@ pub fn recalc_style_for_subtree(root_node: &LayoutNode,
queue.run();
queue.data = ptr::mut_null()
queue.data = ptr::null()
}
pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
time_profiler_chan: TimeProfilerChan,
layout_context: &mut LayoutContext,
queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) {
queue.data = layout_context as *mut _;
shared_layout_context: &SharedLayoutContext,
queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
queue.data = shared_layout_context as *const _;
profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || {
queue.push(WorkUnit {
@ -536,14 +538,14 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
queue.run();
queue.data = ptr::mut_null()
queue.data = ptr::null()
}
pub fn build_display_list_for_subtree(root: &mut FlowRef,
time_profiler_chan: TimeProfilerChan,
layout_context: &mut LayoutContext,
queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) {
queue.data = layout_context as *mut _;
shared_layout_context: &SharedLayoutContext,
queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
queue.data = shared_layout_context as *const _;
profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || {
queue.push(WorkUnit {
@ -554,6 +556,6 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef,
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
/// methods
#[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);
}
@ -164,7 +164,7 @@ impl Flow for TableFlow {
/// table layout calculation.
/// The maximum min/pref inline-sizes of each column are set from the rows for the automatic
/// 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 pref_inline_size = Au(0);
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
/// 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");
// 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()));
}
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");
self.assign_block_size_table_base(ctx);
}
@ -309,7 +309,7 @@ impl ISizeAndMarginsComputer for InternalTable {
/// CSS Section 10.4: Minimum and Maximum inline-sizes
fn compute_used_inline_size(&self,
block: &mut BlockFlow,
ctx: &mut LayoutContext,
ctx: &LayoutContext,
parent_flow_inline_size: Au) {
let input = self.compute_inline_size_constraint_inputs(block, parent_flow_inline_size, ctx);
let solution = self.solve_inline_size_constraints(block, &input);

View file

@ -47,16 +47,16 @@ impl Flow for TableCaptionFlow {
&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);
}
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");
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");
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
/// methods
#[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)
}
@ -69,7 +69,7 @@ impl Flow for TableCellFlow {
}
/// 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);
let specified_inline_size = MaybeAuto::from_style(self.block_flow.fragment.style().content_inline_size(),
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
/// 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");
// 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);
}
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");
self.assign_block_size_table_cell_base(ctx);
}

View file

@ -52,7 +52,7 @@ impl Flow for TableColGroupFlow {
self
}
fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) {
fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
for fragment in self.cols.iter() {
// get the specified value from inline-size property
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.
/// 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.
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
/// methods
#[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 /* mut */ cur_y = block_start_offset;
@ -165,7 +165,7 @@ impl Flow for TableRowFlow {
/// responsible for flowing.
/// 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.
fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) {
fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let mut min_inline_size = Au(0);
let mut pref_inline_size = Au(0);
/* 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
/// 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");
// 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()));
}
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");
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
/// methods
#[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 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.
/// Also, this function finds the specified column inline-sizes from the first row.
/// 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 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
/// 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");
// 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()));
}
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");
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
/// methods
#[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);
}
@ -129,7 +129,7 @@ impl Flow for TableWrapperFlow {
min/pref inline_sizes based on child context inline_sizes and dimensions of
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
for kid in self.block_flow.base.child_iter() {
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)
/// 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",
if self.is_float() {
"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);
}
fn assign_block_size(&mut self, ctx: &mut LayoutContext) {
fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
if self.is_float() {
debug!("assign_block_size_float: assigning block_size for floated table_wrapper");
self.block_flow.assign_block_size_float(ctx);
@ -208,7 +208,7 @@ struct TableWrapper;
impl TableWrapper {
fn compute_used_inline_size_table_wrapper(&self,
table_wrapper: &mut TableWrapperFlow,
ctx: &mut LayoutContext,
ctx: &LayoutContext,
parent_flow_inline_size: Au) {
let input = self.compute_inline_size_constraint_inputs_table_wrapper(table_wrapper,
parent_flow_inline_size,
@ -223,7 +223,7 @@ impl TableWrapper {
fn compute_inline_size_constraint_inputs_table_wrapper(&self,
table_wrapper: &mut TableWrapperFlow,
parent_flow_inline_size: Au,
ctx: &mut LayoutContext)
ctx: &LayoutContext)
-> ISizeConstraintInput {
let mut input = self.compute_inline_size_constraint_inputs(&mut table_wrapper.block_flow,
parent_flow_inline_size,