mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
layout: Paint stacking contexts' overflow areas properly.
This was making `box-shadow` not show up in many cases, in particular, but the effects were not limited to that.
This commit is contained in:
parent
ba8cf6b0e6
commit
5ea2c6dcfd
30 changed files with 357 additions and 179 deletions
|
@ -32,7 +32,7 @@ use display_list_builder::DisplayListBuildingResult;
|
|||
use floats::Floats;
|
||||
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
|
||||
use flow_ref::FlowRef;
|
||||
use fragment::{Fragment, FragmentBoundsIterator, SpecificFragmentInfo};
|
||||
use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo};
|
||||
use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
||||
use inline::InlineFlow;
|
||||
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
|
||||
|
@ -50,7 +50,7 @@ use geom::{Point2D, Rect, Size2D};
|
|||
use gfx::display_list::ClippingRegion;
|
||||
use serialize::{Encoder, Encodable};
|
||||
use servo_msg::compositor_msg::LayerId;
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::geometry::{Au, ZERO_RECT};
|
||||
use servo_util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
|
||||
use std::mem;
|
||||
use std::fmt;
|
||||
|
@ -220,8 +220,11 @@ pub trait Flow: fmt::Show + ToString + Sync {
|
|||
/// Phase 5 of reflow: builds display lists.
|
||||
fn build_display_list(&mut self, layout_context: &LayoutContext);
|
||||
|
||||
/// Perform an iteration of fragment bounds on this flow.
|
||||
fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator);
|
||||
/// Returns the union of all overflow rects of all of this flow's fragments.
|
||||
fn compute_overflow(&self) -> Rect<Au>;
|
||||
|
||||
/// Iterates through overflow rects of all of this flow's fragments.
|
||||
fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator);
|
||||
|
||||
fn compute_collapsible_block_start_margin(&mut self,
|
||||
_layout_context: &mut LayoutContext,
|
||||
|
@ -718,7 +721,7 @@ pub struct BaseFlow {
|
|||
|
||||
/// The amount of overflow of this flow, relative to the containing block. Must include all the
|
||||
/// pixels of all the display list items for correct invalidation.
|
||||
pub overflow: LogicalRect<Au>,
|
||||
pub overflow: Rect<Au>,
|
||||
|
||||
/// Data used during parallel traversals.
|
||||
///
|
||||
|
@ -894,7 +897,7 @@ impl BaseFlow {
|
|||
children: FlowList::new(),
|
||||
intrinsic_inline_sizes: IntrinsicISizes::new(),
|
||||
position: LogicalRect::zero(writing_mode),
|
||||
overflow: LogicalRect::zero(writing_mode),
|
||||
overflow: ZERO_RECT,
|
||||
parallel: FlowParallelInfo::new(),
|
||||
floats: Floats::new(writing_mode),
|
||||
collapsible_margins: CollapsibleMargins::new(),
|
||||
|
@ -929,10 +932,12 @@ impl BaseFlow {
|
|||
/// Ensures that all display list items generated by this flow are within the flow's overflow
|
||||
/// rect. This should only be used for debugging.
|
||||
pub fn validate_display_list_geometry(&self) {
|
||||
let position_with_overflow = self.position.union(&self.overflow);
|
||||
let bounds = Rect(self.stacking_relative_position,
|
||||
Size2D(position_with_overflow.size.inline,
|
||||
position_with_overflow.size.block));
|
||||
// FIXME(pcwalton, #2795): Get the real container size.
|
||||
let container_size = Size2D::zero();
|
||||
let position_with_overflow = self.position
|
||||
.to_physical(self.writing_mode, container_size)
|
||||
.union(&self.overflow);
|
||||
let bounds = Rect(self.stacking_relative_position, position_with_overflow.size);
|
||||
|
||||
let all_items = match self.display_list_building_result {
|
||||
DisplayListBuildingResult::None => Vec::new(),
|
||||
|
@ -1175,40 +1180,29 @@ impl<'a> MutableFlowUtils for &'a mut Flow + 'a {
|
|||
/// already been set.
|
||||
/// Assumption: Absolute descendants have had their overflow calculated.
|
||||
fn store_overflow(self, _: &LayoutContext) {
|
||||
let my_position = mut_base(self).position;
|
||||
|
||||
// FIXME(pcwalton): We should calculate overflow on a per-fragment basis, because their
|
||||
// styles can affect overflow regions. Consider `box-shadow`, `outline`, etc.--anything
|
||||
// that can draw outside the border box. For now we assume overflow is the border box, but
|
||||
// that is wrong.
|
||||
let mut overflow = my_position;
|
||||
|
||||
// Calculate overflow on a per-fragment basis.
|
||||
let mut overflow = self.compute_overflow();
|
||||
if self.is_block_container() {
|
||||
let writing_mode = base(self).writing_mode;
|
||||
// FIXME(#2795): Get the real container size
|
||||
// FIXME(#2795): Get the real container size.
|
||||
let container_size = Size2D::zero();
|
||||
for kid in child_iter(self) {
|
||||
if kid.is_store_overflow_delayed() {
|
||||
// Absolute flows will be handled by their CB. If we are
|
||||
// their CB, they will show up in `abs_descendants`.
|
||||
continue;
|
||||
if base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
|
||||
continue
|
||||
}
|
||||
let kid_base = base(kid);
|
||||
let mut kid_overflow = kid_base.overflow.convert(
|
||||
kid_base.writing_mode, writing_mode, container_size);
|
||||
kid_overflow = kid_overflow.translate(&my_position.start);
|
||||
overflow = overflow.union(&kid_overflow)
|
||||
let kid_overflow = base(kid).overflow;
|
||||
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
|
||||
container_size);
|
||||
overflow = overflow.union(&kid_overflow.translate(&kid_position.origin))
|
||||
}
|
||||
|
||||
// FIXME(#2004, pcwalton): This is wrong for `position: fixed`.
|
||||
for descendant_link in mut_base(self).abs_descendants.iter() {
|
||||
let kid_base = base(descendant_link);
|
||||
let mut kid_overflow = kid_base.overflow.convert(
|
||||
kid_base.writing_mode, writing_mode, container_size);
|
||||
kid_overflow = kid_overflow.translate(&my_position.start);
|
||||
overflow = overflow.union(&kid_overflow)
|
||||
for kid in mut_base(self).abs_descendants.iter() {
|
||||
let kid_overflow = base(kid).overflow;
|
||||
let kid_position = base(kid).position.to_physical(base(kid).writing_mode,
|
||||
container_size);
|
||||
overflow = overflow.union(&kid_overflow.translate(&kid_position.origin))
|
||||
}
|
||||
}
|
||||
|
||||
mut_base(self).overflow = overflow;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue