diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2014-12-18 18:59:42 -0800 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2015-01-04 17:41:59 -0800 |
commit | 5ea2c6dcfdfc24ce3730f736fcd045a13bcdc5b6 (patch) | |
tree | bd04f1fa5d53a938e91817c8d099456f93b01950 | |
parent | ba8cf6b0e6145265f9472d4855f078d8b5943fe7 (diff) | |
download | servo-5ea2c6dcfdfc24ce3730f736fcd045a13bcdc5b6.tar.gz servo-5ea2c6dcfdfc24ce3730f736fcd045a13bcdc5b6.zip |
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.
30 files changed, 357 insertions, 179 deletions
diff --git a/components/compositing/compositor_layer.rs b/components/compositing/compositor_layer.rs index 4c13d7fb8a0..3658172847e 100644 --- a/components/compositing/compositor_layer.rs +++ b/components/compositing/compositor_layer.rs @@ -283,8 +283,7 @@ impl CompositorLayer for Layer<CompositorData> { self.clamp_scroll_offset_and_scroll_layer(scroll_offset + delta) } - fn clamp_scroll_offset_and_scroll_layer(&self, - new_offset: TypedPoint2D<LayerPixel, f32>) + fn clamp_scroll_offset_and_scroll_layer(&self, new_offset: TypedPoint2D<LayerPixel, f32>) -> ScrollEventResult { let layer_size = self.bounds.borrow().size; let content_size = calculate_content_size_for_layer(self); @@ -339,17 +338,14 @@ impl CompositorLayer for Layer<CompositorData> { let _ = chan.send_opt(ConstellationControlMsg::SendEvent(pipeline.id.clone(), message)); } - fn scroll_layer_and_all_child_layers(&self, - new_offset: TypedPoint2D<LayerPixel, f32>) + fn scroll_layer_and_all_child_layers(&self, new_offset: TypedPoint2D<LayerPixel, f32>) -> bool { let mut result = false; // Only scroll this layer if it's not fixed-positioned. if self.extra_data.borrow().scroll_policy != FixedPosition { let new_offset = new_offset.to_untyped(); - *self.transform.borrow_mut() = identity().translate(new_offset.x, - new_offset.y, - 0.0); + *self.transform.borrow_mut() = identity().translate(new_offset.x, new_offset.y, 0.0); *self.content_offset.borrow_mut() = Point2D::from_untyped(&new_offset); result = true } diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index af32ffad76b..ecd7b170246 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -34,7 +34,7 @@ use servo_msg::compositor_msg::LayerId; use servo_net::image::base::Image; use servo_util::cursor::Cursor; use servo_util::dlist as servo_dlist; -use servo_util::geometry::{mod, Au, MAX_RECT, ZERO_POINT, ZERO_RECT}; +use servo_util::geometry::{mod, Au, MAX_RECT, ZERO_RECT}; use servo_util::range::Range; use servo_util::smallvec::{SmallVec, SmallVec8}; use std::fmt; @@ -160,9 +160,8 @@ pub struct StackingContext { pub layer: Option<Arc<PaintLayer>>, /// The position and size of this stacking context. pub bounds: Rect<Au>, - /// The clipping rect for this stacking context, in the coordinate system of the *parent* - /// stacking context. - pub clip_rect: Rect<Au>, + /// The overflow rect for this stacking context in its coordinate system. + pub overflow: Rect<Au>, /// The `z-index` for this stacking context. pub z_index: i32, /// The opacity of this stacking context. @@ -171,12 +170,10 @@ pub struct StackingContext { impl StackingContext { /// Creates a new stacking context. - /// - /// TODO(pcwalton): Stacking contexts should not always be clipped to their bounds, to handle - /// overflow properly. #[inline] pub fn new(display_list: Box<DisplayList>, - bounds: Rect<Au>, + bounds: &Rect<Au>, + overflow: &Rect<Au>, z_index: i32, opacity: AzFloat, layer: Option<Arc<PaintLayer>>) @@ -184,8 +181,8 @@ impl StackingContext { StackingContext { display_list: display_list, layer: layer, - bounds: bounds, - clip_rect: Rect(ZERO_POINT, bounds.size), + bounds: *bounds, + overflow: *overflow, z_index: z_index, opacity: opacity, } @@ -196,7 +193,7 @@ impl StackingContext { paint_context: &mut PaintContext, tile_bounds: &Rect<AzFloat>, transform: &Matrix2D<AzFloat>, - clip_rect: Option<Rect<Au>>) { + clip_rect: Option<&Rect<Au>>) { let temporary_draw_target = paint_context.get_or_create_temporary_draw_target(self.opacity); { @@ -205,7 +202,7 @@ impl StackingContext { font_ctx: &mut *paint_context.font_ctx, page_rect: paint_context.page_rect, screen_rect: paint_context.screen_rect, - clip_rect: clip_rect, + clip_rect: clip_rect.map(|clip_rect| *clip_rect), transient_clip: None, }; @@ -252,7 +249,7 @@ impl StackingContext { positioned_kid.optimize_and_draw_into_context(&mut paint_subcontext, &new_tile_rect, &new_transform, - Some(positioned_kid.clip_rect)) + Some(&positioned_kid.overflow)) } } @@ -295,7 +292,7 @@ impl StackingContext { positioned_kid.optimize_and_draw_into_context(&mut paint_subcontext, &new_tile_rect, &new_transform, - Some(positioned_kid.clip_rect)) + Some(&positioned_kid.overflow)) } } @@ -329,11 +326,18 @@ impl StackingContext { } }; - let child_stacking_context_bounds = child_stacking_context.bounds.to_azure_rect(); - let tile_subrect = tile_bounds.intersection(&child_stacking_context_bounds) + // Translate the child's overflow region into our coordinate system. + let child_stacking_context_overflow = + child_stacking_context.overflow.translate(&child_stacking_context.bounds.origin) + .to_azure_rect(); + + // Intersect that with the current tile boundaries to find the tile boundaries that the + // child covers. + let tile_subrect = tile_bounds.intersection(&child_stacking_context_overflow) .unwrap_or(ZERO_AZURE_RECT); - let offset = tile_subrect.origin - child_stacking_context_bounds.origin; - Rect(offset, tile_subrect.size) + + // Translate the resulting rect into the child's coordinate system. + tile_subrect.translate(&-child_stacking_context.bounds.to_azure_rect().origin) } /// Places all nodes containing the point of interest into `result`, topmost first. If diff --git a/components/gfx/display_list/optimizer.rs b/components/gfx/display_list/optimizer.rs index c0dac718c51..1b7998f86c9 100644 --- a/components/gfx/display_list/optimizer.rs +++ b/components/gfx/display_list/optimizer.rs @@ -59,7 +59,8 @@ impl DisplayListOptimizer { mut stacking_contexts: I) where I: Iterator<&'a Arc<StackingContext>> { for stacking_context in stacking_contexts { - if self.visible_rect.intersects(&stacking_context.bounds) { + let overflow = stacking_context.overflow.translate(&stacking_context.bounds.origin); + if self.visible_rect.intersects(&overflow) { result_list.push_back((*stacking_context).clone()) } } diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs index 1210c34627b..5fdacfa838d 100644 --- a/components/gfx/paint_task.rs +++ b/components/gfx/paint_task.rs @@ -148,20 +148,21 @@ fn initialize_layers<C>(compositor: &mut C, stacking_context: &StackingContext, page_position: &Point2D<Au>) { let page_position = stacking_context.bounds.origin + *page_position; - match stacking_context.layer { - None => {} - Some(ref paint_layer) => { - metadata.push(LayerMetadata { - id: paint_layer.id, - position: - Rect(Point2D(page_position.x.to_nearest_px() as uint, - page_position.y.to_nearest_px() as uint), - Size2D(stacking_context.bounds.size.width.to_nearest_px() as uint, - stacking_context.bounds.size.height.to_nearest_px() as uint)), - background_color: paint_layer.background_color, - scroll_policy: paint_layer.scroll_policy, - }) - } + if let Some(ref paint_layer) = stacking_context.layer { + // Layers start at the top left of their overflow rect, as far as the info we give to + // the compositor is concerned. + let overflow_relative_page_position = page_position + stacking_context.overflow.origin; + let layer_position = + Rect(Point2D(overflow_relative_page_position.x.to_nearest_px() as i32, + overflow_relative_page_position.y.to_nearest_px() as i32), + Size2D(stacking_context.overflow.size.width.to_nearest_px() as i32, + stacking_context.overflow.size.height.to_nearest_px() as i32)); + metadata.push(LayerMetadata { + id: paint_layer.id, + position: layer_position, + background_color: paint_layer.background_color, + scroll_policy: paint_layer.scroll_policy, + }) } for kid in stacking_context.display_list.children.iter() { @@ -384,15 +385,14 @@ impl<C> PaintTask<C> where C: PaintListener + Send { layer_id: LayerId) { profile(TimeProfilerCategory::Painting, None, self.time_profiler_chan.clone(), || { // Bail out if there is no appropriate stacking context. - let stacking_context = match self.root_stacking_context { - Some(ref stacking_context) => { - match display_list::find_stacking_context_with_layer_id(stacking_context, - layer_id) { - Some(stacking_context) => stacking_context, - None => return, - } + let stacking_context = if let Some(ref stacking_context) = self.root_stacking_context { + match display_list::find_stacking_context_with_layer_id(stacking_context, + layer_id) { + Some(stacking_context) => stacking_context, + None => return, } - None => return, + } else { + return }; // Divide up the layer into tiles and distribute them to workers via a simple round- @@ -547,8 +547,13 @@ impl WorkerThread { transient_clip: None, }; + // Apply a translation to start at the boundaries of the stacking context, since the + // layer's origin starts at its overflow rect's origin. + let tile_bounds = tile.page_rect.translate( + &Point2D(stacking_context.overflow.origin.x.to_subpx() as AzFloat, + stacking_context.overflow.origin.y.to_subpx() as AzFloat)); + // Apply the translation to paint the tile we want. - let tile_bounds = tile.page_rect; let matrix: Matrix2D<AzFloat> = Matrix2D::identity(); let matrix = matrix.scale(scale as AzFloat, scale as AzFloat); let matrix = matrix.translate(-tile_bounds.origin.x as AzFloat, @@ -561,7 +566,7 @@ impl WorkerThread { profile(TimeProfilerCategory::PaintingPerTile, None, self.time_profiler_sender.clone(), || { stacking_context.optimize_and_draw_into_context(&mut paint_context, - &tile.page_rect, + &tile_bounds, &matrix, None); paint_context.draw_target.flush(); diff --git a/components/layout/block.rs b/components/layout/block.rs index 02b58ce463e..eec1f945d1c 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -41,7 +41,7 @@ use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER}; use flow::{IS_ABSOLUTELY_POSITIONED}; use flow::{CLEARS_LEFT, CLEARS_RIGHT}; use flow; -use fragment::{Fragment, FragmentBoundsIterator, SpecificFragmentInfo}; +use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo}; use incremental::{REFLOW, REFLOW_OUT_OF_FLOW}; use layout_debug; use model::{IntrinsicISizes, MarginCollapseInfo}; @@ -49,7 +49,7 @@ use model::{MaybeAuto, CollapsibleMargins, specified, specified_or_none}; use table::ColumnComputedInlineSize; use wrapper::ThreadSafeLayoutNode; -use geom::Size2D; +use geom::{Rect, Size2D}; use gfx::display_list::{ClippingRegion, DisplayList}; use serialize::{Encoder, Encodable}; use servo_msg::compositor_msg::LayerId; @@ -1797,13 +1797,6 @@ impl Flow for BlockFlow { self.flags.insert(IS_ROOT) } - /// Return true if store overflow is delayed for this flow. - /// - /// Currently happens only for absolutely positioned flows. - fn is_store_overflow_delayed(&mut self) -> bool { - self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) - } - fn is_root(&self) -> bool { self.flags.contains(IS_ROOT) } @@ -1864,12 +1857,13 @@ impl Flow for BlockFlow { self.fragment.repair_style(new_style) } - fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) { + fn compute_overflow(&self) -> Rect<Au> { + self.fragment.compute_overflow() + } + + fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { if iterator.should_process(&self.fragment) { - let fragment_origin = - self.base.stacking_relative_position_of_child_fragment(&self.fragment); - iterator.process(&self.fragment, - self.fragment.stacking_relative_bounds(&fragment_origin)); + iterator.process(&self.fragment, self.fragment.compute_overflow()); } } } @@ -2455,11 +2449,14 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced { MaybeAuto::Specified(fragment.content_inline_size()) } - fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext) -> Au { + 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) { + fn set_flow_x_coord_if_necessary(&self, + block: &mut BlockFlow, + solution: ISizeConstraintSolution) { // Set the x-coordinate of the absolute flow wrt to its containing block. block.base.position.start.i = solution.inline_start; } diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index a9ca6d5f547..2696bcc3dc5 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -1103,7 +1103,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow { background_border_level); self.base.display_list_building_result = if self.fragment.establishes_stacking_context() { - DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list, None)) + DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list, + None)) } else { DisplayListBuildingResult::Normal(display_list) } @@ -1120,7 +1121,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow { !self.base.flags.contains(NEEDS_LAYER) { // We didn't need a layer. self.base.display_list_building_result = - DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list, None)); + DisplayListBuildingResult::StackingContext(self.create_stacking_context( + display_list, + None)); return } @@ -1137,7 +1140,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow { Some(Arc::new(PaintLayer::new(self.layer_id(0), transparent, scroll_policy)))); - self.base.display_list_building_result = DisplayListBuildingResult::StackingContext(stacking_context) + self.base.display_list_building_result = + DisplayListBuildingResult::StackingContext(stacking_context) } fn build_display_list_for_floating_block(&mut self, @@ -1149,7 +1153,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow { display_list.form_float_pseudo_stacking_context(); self.base.display_list_building_result = if self.fragment.establishes_stacking_context() { - DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list, None)) + DisplayListBuildingResult::StackingContext(self.create_stacking_context(display_list, + None)) } else { DisplayListBuildingResult::Normal(display_list) } @@ -1165,7 +1170,9 @@ impl BlockFlowDisplayListBuilding for BlockFlow { } else if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) { self.build_display_list_for_absolutely_positioned_block(display_list, layout_context) } else { - self.build_display_list_for_static_block(display_list, layout_context, BackgroundAndBorderLevel::Block) + self.build_display_list_for_static_block(display_list, + layout_context, + BackgroundAndBorderLevel::Block) } } @@ -1173,11 +1180,16 @@ impl BlockFlowDisplayListBuilding for BlockFlow { display_list: Box<DisplayList>, layer: Option<Arc<PaintLayer>>) -> Arc<StackingContext> { - let bounds = Rect(self.base.stacking_relative_position, - self.base.overflow.size.to_physical(self.base.writing_mode)); + let size = self.base.position.size.to_physical(self.base.writing_mode); + let bounds = Rect(self.base.stacking_relative_position, size); let z_index = self.fragment.style().get_box().z_index.number_or_zero(); let opacity = self.fragment.style().get_effects().opacity as f32; - Arc::new(StackingContext::new(display_list, bounds, z_index, opacity, layer)) + Arc::new(StackingContext::new(display_list, + &bounds, + &self.base.overflow, + z_index, + opacity, + layer)) } } diff --git a/components/layout/flow.rs b/components/layout/flow.rs index a36fca0df0a..f20d5a0c128 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -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; } diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index b50f484f8d9..c66087364ed 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -23,7 +23,7 @@ use util::OpaqueNodeMethods; use wrapper::{TLayoutNode, ThreadSafeLayoutNode}; use geom::{Point2D, Rect, Size2D}; -use gfx::display_list::OpaqueNode; +use gfx::display_list::{BOX_SHADOW_INFLATION_FACTOR, OpaqueNode}; use gfx::text::glyph::CharIndex; use gfx::text::text_run::{TextRun, TextRunSlice}; use script_traits::UntrustedNodeAddress; @@ -531,8 +531,9 @@ impl Fragment { // Foo // </div> // - // Anonymous table fragments, SpecificFragmentInfo::TableRow and SpecificFragmentInfo::TableCell, are generated around - // `Foo`, but they shouldn't inherit the border. + // Anonymous table fragments, SpecificFragmentInfo::TableRow and + // SpecificFragmentInfo::TableCell, are generated around `Foo`, but they shouldn't inherit + // the border. let node_style = cascade_anonymous(&**node.style()); let writing_mode = node_style.writing_mode; @@ -647,7 +648,10 @@ impl Fragment { fn quantities_included_in_intrinsic_inline_size(&self) -> QuantitiesIncludedInIntrinsicInlineSizes { match self.specific { - SpecificFragmentInfo::Generic | SpecificFragmentInfo::Iframe(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::InlineBlock(_) => { + SpecificFragmentInfo::Generic | + SpecificFragmentInfo::Iframe(_) | + SpecificFragmentInfo::Image(_) | + SpecificFragmentInfo::InlineBlock(_) => { QuantitiesIncludedInIntrinsicInlineSizes::all() } SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell => { @@ -836,9 +840,7 @@ impl Fragment { } // Return offset from original position because of `position: relative`. - pub fn relative_position(&self, - containing_block_size: &LogicalSize<Au>) - -> LogicalSize<Au> { + pub fn relative_position(&self, containing_block_size: &LogicalSize<Au>) -> LogicalSize<Au> { fn from_style(style: &ComputedValues, container_size: &LogicalSize<Au>) -> LogicalSize<Au> { let offsets = style.logical_position(); @@ -1567,6 +1569,41 @@ impl Fragment { } } } + + /// Computes the overflow rect of this fragment relative to the start of the flow. + pub fn compute_overflow(&self) -> Rect<Au> { + // FIXME(pcwalton, #2795): Get the real container size. + let container_size = Size2D::zero(); + let mut border_box = self.border_box.to_physical(self.style.writing_mode, container_size); + + // Relative position can cause us to draw outside our border box. + // + // FIXME(pcwalton): I'm not a fan of the way this makes us crawl though so many styles all + // the time. Can't we handle relative positioning by just adjusting `border_box`? + let relative_position = + self.relative_position(&LogicalSize::zero(self.style.writing_mode)); + border_box = + border_box.translate_by_size(&relative_position.to_physical(self.style.writing_mode)); + let mut overflow = border_box; + + // Box shadows cause us to draw outside our border box. + for box_shadow in self.style().get_effects().box_shadow.iter() { + let offset = Point2D(box_shadow.offset_x, box_shadow.offset_y); + let inflation = box_shadow.spread_radius + + box_shadow.blur_radius * BOX_SHADOW_INFLATION_FACTOR; + overflow = overflow.union(&border_box.translate(&offset).inflate(inflation, inflation)) + } + + // Outlines cause us to draw outside our border box. + let outline_width = self.style.get_outline().outline_width; + if outline_width != Au(0) { + overflow = overflow.union(&border_box.inflate(outline_width, outline_width)) + } + + // FIXME(pcwalton): Sometimes excessively fancy glyphs can make us draw outside our border + // box too. + overflow + } } impl fmt::Show for Fragment { @@ -1600,10 +1637,10 @@ bitflags! { } } -/// A top-down fragment bounds iteration handler. -pub trait FragmentBoundsIterator { +/// A top-down fragment overflow region iteration handler. +pub trait FragmentOverflowIterator { /// The operation to perform. - fn process(&mut self, fragment: &Fragment, bounds: Rect<Au>); + fn process(&mut self, fragment: &Fragment, overflow: Rect<Au>); /// Returns true if this fragment must be processed in-order. If this returns false, /// we skip the operation for this fragment, but continue processing siblings. diff --git a/components/layout/inline.rs b/components/layout/inline.rs index 2230fb3e823..f8a19708d1e 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -12,7 +12,7 @@ use flow::{BaseFlow, FlowClass, Flow, MutableFlowUtils, ForceNonfloatedFlag}; use flow::{IS_ABSOLUTELY_POSITIONED}; use flow; use fragment::{Fragment, SpecificFragmentInfo}; -use fragment::{FragmentBoundsIterator, ScannedTextFragmentInfo}; +use fragment::{FragmentOverflowIterator, ScannedTextFragmentInfo}; use fragment::SplitInfo; use incremental::{REFLOW, REFLOW_OUT_OF_FLOW}; use layout_debug; @@ -20,12 +20,12 @@ use model::IntrinsicISizesContribution; use text; use collections::{RingBuf}; -use geom::Size2D; +use geom::{Rect, Size2D}; use gfx::display_list::DisplayList; use gfx::font::FontMetrics; use gfx::font_context::FontContext; use gfx::text::glyph::CharIndex; -use servo_util::geometry::Au; +use servo_util::geometry::{Au, ZERO_RECT}; use servo_util::logical_geometry::{LogicalRect, LogicalSize, WritingMode}; use servo_util::opts; use servo_util::range::{Range, RangeIndex}; @@ -1271,7 +1271,15 @@ impl Flow for InlineFlow { fn repair_style(&mut self, _: &Arc<ComputedValues>) {} - fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) { + fn compute_overflow(&self) -> Rect<Au> { + let mut overflow = ZERO_RECT; + for fragment in self.fragments.fragments.iter() { + overflow = overflow.union(&fragment.compute_overflow()) + } + overflow + } + + fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { for fragment in self.fragments.fragments.iter() { if iterator.should_process(fragment) { let fragment_origin = diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 090b51cee70..22e00904c75 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -10,7 +10,7 @@ use construct::ConstructionResult; use context::SharedLayoutContext; use flow::{mod, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils}; use flow_ref::FlowRef; -use fragment::{Fragment, FragmentBoundsIterator}; +use fragment::{Fragment, FragmentOverflowIterator}; use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT}; use layout_debug; use parallel::{mod, UnsafeFlow}; @@ -604,7 +604,7 @@ impl LayoutTask { // FIXME(pcwalton): This has not been updated to handle the stacking context relative // stuff. So the position is wrong in most cases. let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); - let mut iterator = UnioningFragmentBoundsIterator::new(requested_node); + let mut iterator = UnioningFragmentOverflowIterator::new(requested_node); sequential::iterate_through_flow_tree_fragment_bounds(layout_root, &mut iterator); rw_data.content_box_response = iterator.rect; } @@ -616,7 +616,7 @@ impl LayoutTask { // FIXME(pcwalton): This has not been updated to handle the stacking context relative // stuff. So the position is wrong in most cases. let requested_node: OpaqueNode = OpaqueNodeMethods::from_script_node(requested_node); - let mut iterator = CollectingFragmentBoundsIterator::new(requested_node); + let mut iterator = CollectingFragmentOverflowIterator::new(requested_node); sequential::iterate_through_flow_tree_fragment_bounds(layout_root, &mut iterator); rw_data.content_boxes_response = iterator.rects; } @@ -689,11 +689,12 @@ impl LayoutTask { flow::mut_base(layout_root.deref_mut()).display_list_building_result .add_to(&mut *display_list); let paint_layer = Arc::new(PaintLayer::new(layout_root.layer_id(0), - color, - Scrollable)); + color, + Scrollable)); let origin = Rect(Point2D(Au(0), Au(0)), root_size); let stacking_context = Arc::new(StackingContext::new(display_list, - origin, + &origin, + &origin, 0, 1.0, Some(paint_layer))); @@ -1016,21 +1017,21 @@ impl LayoutRPC for LayoutRPCImpl { } } -struct UnioningFragmentBoundsIterator { +struct UnioningFragmentOverflowIterator { node_address: OpaqueNode, rect: Rect<Au>, } -impl UnioningFragmentBoundsIterator { - fn new(node_address: OpaqueNode) -> UnioningFragmentBoundsIterator { - UnioningFragmentBoundsIterator { +impl UnioningFragmentOverflowIterator { + fn new(node_address: OpaqueNode) -> UnioningFragmentOverflowIterator { + UnioningFragmentOverflowIterator { node_address: node_address, rect: Rect::zero(), } } } -impl FragmentBoundsIterator for UnioningFragmentBoundsIterator { +impl FragmentOverflowIterator for UnioningFragmentOverflowIterator { fn process(&mut self, _: &Fragment, bounds: Rect<Au>) { if self.rect.is_empty() { self.rect = bounds; @@ -1044,21 +1045,21 @@ impl FragmentBoundsIterator for UnioningFragmentBoundsIterator { } } -struct CollectingFragmentBoundsIterator { +struct CollectingFragmentOverflowIterator { node_address: OpaqueNode, rects: Vec<Rect<Au>>, } -impl CollectingFragmentBoundsIterator { - fn new(node_address: OpaqueNode) -> CollectingFragmentBoundsIterator { - CollectingFragmentBoundsIterator { +impl CollectingFragmentOverflowIterator { + fn new(node_address: OpaqueNode) -> CollectingFragmentOverflowIterator { + CollectingFragmentOverflowIterator { node_address: node_address, rects: Vec::new(), } } } -impl FragmentBoundsIterator for CollectingFragmentBoundsIterator { +impl FragmentOverflowIterator for CollectingFragmentOverflowIterator { fn process(&mut self, _: &Fragment, bounds: Rect<Au>) { self.rects.push(bounds); } diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs index 3b31d1fdc44..0d0c71d526c 100644 --- a/components/layout/list_item.rs +++ b/components/layout/list_item.rs @@ -12,9 +12,10 @@ use construct::FlowConstructor; use context::LayoutContext; use display_list_builder::ListItemFlowDisplayListBuilding; use flow::{Flow, FlowClass}; -use fragment::{Fragment, FragmentBoundsIterator}; +use fragment::{Fragment, FragmentOverflowIterator}; use wrapper::ThreadSafeLayoutNode; +use geom::Rect; use gfx::display_list::DisplayList; use servo_util::geometry::Au; use servo_util::opts; @@ -111,8 +112,12 @@ impl Flow for ListItemFlow { self.block_flow.repair_style(new_style) } - fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) { - self.block_flow.iterate_through_fragment_bounds(iterator); + fn compute_overflow(&self) -> Rect<Au> { + self.block_flow.compute_overflow() + } + + fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { + self.block_flow.iterate_through_fragment_overflow(iterator); } } diff --git a/components/layout/sequential.rs b/components/layout/sequential.rs index 4636fa9c3eb..01ba0c098ed 100644 --- a/components/layout/sequential.rs +++ b/components/layout/sequential.rs @@ -8,7 +8,7 @@ use context::{LayoutContext, SharedLayoutContext}; use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal}; use flow; use flow_ref::FlowRef; -use fragment::FragmentBoundsIterator; +use fragment::FragmentOverflowIterator; use servo_util::opts; use traversal::{BubbleISizes, RecalcStyleForNode, ConstructFlows}; use traversal::{AssignBSizesAndStoreOverflow, AssignISizes}; @@ -95,9 +95,9 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef, } pub fn iterate_through_flow_tree_fragment_bounds(root: &mut FlowRef, - iterator: &mut FragmentBoundsIterator) { - fn doit(flow: &mut Flow, iterator: &mut FragmentBoundsIterator) { - flow.iterate_through_fragment_bounds(iterator); + iterator: &mut FragmentOverflowIterator) { + fn doit(flow: &mut Flow, iterator: &mut FragmentOverflowIterator) { + flow.iterate_through_fragment_overflow(iterator); for kid in flow::mut_base(flow).child_iter() { doit(kid, iterator); diff --git a/components/layout/table.rs b/components/layout/table.rs index 8f46ef868ff..81c9f40d43d 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -13,13 +13,14 @@ use context::LayoutContext; use floats::FloatKind; use flow::{mod, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS}; use flow::ImmutableFlowUtils; -use fragment::{Fragment, FragmentBoundsIterator}; +use fragment::{Fragment, FragmentOverflowIterator}; use layout_debug; use model::{IntrinsicISizes, IntrinsicISizesContribution}; use table_row::CellIntrinsicInlineSize; use table_wrapper::TableLayout; use wrapper::ThreadSafeLayoutNode; +use geom::Rect; use servo_util::geometry::Au; use servo_util::logical_geometry::LogicalRect; use std::cmp::max; @@ -384,8 +385,12 @@ impl Flow for TableFlow { self.block_flow.repair_style(new_style) } - fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) { - self.block_flow.iterate_through_fragment_bounds(iterator); + fn compute_overflow(&self) -> Rect<Au> { + self.block_flow.compute_overflow() + } + + fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { + self.block_flow.iterate_through_fragment_overflow(iterator); } } diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs index 65493e2c24a..4864e49096a 100644 --- a/components/layout/table_caption.rs +++ b/components/layout/table_caption.rs @@ -10,9 +10,10 @@ use block::BlockFlow; use construct::FlowConstructor; use context::LayoutContext; use flow::{FlowClass, Flow}; -use fragment::FragmentBoundsIterator; +use fragment::FragmentOverflowIterator; use wrapper::ThreadSafeLayoutNode; +use geom::Rect; use servo_util::geometry::Au; use std::fmt; use style::ComputedValues; @@ -81,8 +82,12 @@ impl Flow for TableCaptionFlow { self.block_flow.repair_style(new_style) } - fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) { - self.block_flow.iterate_through_fragment_bounds(iterator); + fn compute_overflow(&self) -> Rect<Au> { + self.block_flow.compute_overflow() + } + + fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { + self.block_flow.iterate_through_fragment_overflow(iterator); } } diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index 3d1f1fd54e3..583c328f315 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -9,12 +9,13 @@ use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag}; use context::LayoutContext; use flow::{Flow, FlowClass}; -use fragment::{Fragment, FragmentBoundsIterator}; +use fragment::{Fragment, FragmentOverflowIterator}; use model::{MaybeAuto}; use layout_debug; use table::InternalTable; use wrapper::ThreadSafeLayoutNode; +use geom::Rect; use servo_util::geometry::Au; use std::fmt; use style::{UnsignedIntegerAttribute, ComputedValues}; @@ -162,8 +163,12 @@ impl Flow for TableCellFlow { self.block_flow.repair_style(new_style) } - fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) { - self.block_flow.iterate_through_fragment_bounds(iterator); + fn compute_overflow(&self) -> Rect<Au> { + self.block_flow.compute_overflow() + } + + fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { + self.block_flow.iterate_through_fragment_overflow(iterator); } } diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index 5ce9f559268..4eb1cae8022 100644 --- a/components/layout/table_colgroup.rs +++ b/components/layout/table_colgroup.rs @@ -9,11 +9,12 @@ use context::LayoutContext; use css::node_style::StyledNode; use flow::{BaseFlow, FlowClass, Flow, ForceNonfloatedFlag}; -use fragment::{Fragment, FragmentBoundsIterator, SpecificFragmentInfo}; +use fragment::{Fragment, FragmentOverflowIterator, SpecificFragmentInfo}; use layout_debug; use wrapper::ThreadSafeLayoutNode; -use servo_util::geometry::Au; +use geom::Rect; +use servo_util::geometry::{Au, ZERO_RECT}; use std::cmp::max; use std::fmt; use style::computed_values::LengthOrPercentageOrAuto; @@ -96,7 +97,11 @@ impl Flow for TableColGroupFlow { fn repair_style(&mut self, _: &Arc<ComputedValues>) {} - fn iterate_through_fragment_bounds(&self, _: &mut FragmentBoundsIterator) { + fn compute_overflow(&self) -> Rect<Au> { + ZERO_RECT + } + + fn iterate_through_fragment_overflow(&self, _: &mut FragmentOverflowIterator) { } } diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index d4979de8800..d27d7d1ffb4 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -12,12 +12,13 @@ use construct::FlowConstructor; use context::LayoutContext; use flow::{FlowClass, Flow, ImmutableFlowUtils}; use flow; -use fragment::{Fragment, FragmentBoundsIterator}; +use fragment::{Fragment, FragmentOverflowIterator}; use layout_debug; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable}; use model::MaybeAuto; use wrapper::ThreadSafeLayoutNode; +use geom::Rect; use servo_util::geometry::Au; use std::cmp::max; use std::fmt; @@ -315,8 +316,12 @@ impl Flow for TableRowFlow { self.block_flow.repair_style(new_style) } - fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) { - self.block_flow.iterate_through_fragment_bounds(iterator); + fn compute_overflow(&self) -> Rect<Au> { + self.block_flow.compute_overflow() + } + + fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { + self.block_flow.iterate_through_fragment_overflow(iterator); } } diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index e004890c53d..5d3673c1612 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -10,11 +10,12 @@ use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag}; use construct::FlowConstructor; use context::LayoutContext; use flow::{FlowClass, Flow}; -use fragment::{Fragment, FragmentBoundsIterator}; +use fragment::{Fragment, FragmentOverflowIterator}; use layout_debug; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable}; use wrapper::ThreadSafeLayoutNode; +use geom::Rect; use servo_util::geometry::Au; use std::fmt; use style::ComputedValues; @@ -150,8 +151,12 @@ impl Flow for TableRowGroupFlow { self.block_flow.repair_style(new_style) } - fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) { - self.block_flow.iterate_through_fragment_bounds(iterator); + fn compute_overflow(&self) -> Rect<Au> { + self.block_flow.compute_overflow() + } + + fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { + self.block_flow.iterate_through_fragment_overflow(iterator); } } diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index e3d6433a36f..fa8497c46d7 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -19,10 +19,11 @@ use context::LayoutContext; use floats::FloatKind; use flow::{FlowClass, Flow, ImmutableFlowUtils}; use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS}; -use fragment::{Fragment, FragmentBoundsIterator}; +use fragment::{Fragment, FragmentOverflowIterator}; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize}; use wrapper::ThreadSafeLayoutNode; +use geom::Rect; use servo_util::geometry::Au; use std::cmp::{max, min}; use std::fmt; @@ -358,8 +359,12 @@ impl Flow for TableWrapperFlow { self.block_flow.repair_style(new_style) } - fn iterate_through_fragment_bounds(&self, iterator: &mut FragmentBoundsIterator) { - self.block_flow.iterate_through_fragment_bounds(iterator); + fn compute_overflow(&self) -> Rect<Au> { + self.block_flow.compute_overflow() + } + + fn iterate_through_fragment_overflow(&self, iterator: &mut FragmentOverflowIterator) { + self.block_flow.iterate_through_fragment_overflow(iterator); } } diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index 4b824160902..df56254c066 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -332,12 +332,7 @@ impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> { } flow.assign_block_size(self.layout_context); - - // Skip store-overflow for absolutely positioned flows. That will be - // done in a separate traversal. - if !flow.is_store_overflow_delayed() { - flow.store_overflow(self.layout_context); - } + flow.store_overflow(self.layout_context); } #[inline] diff --git a/components/msg/compositor_msg.rs b/components/msg/compositor_msg.rs index 284e40b53af..9d280cef673 100644 --- a/components/msg/compositor_msg.rs +++ b/components/msg/compositor_msg.rs @@ -75,7 +75,7 @@ pub struct LayerMetadata { /// An opaque ID. This is usually the address of the flow and index of the box within it. pub id: LayerId, /// The position and size of the layer in pixels. - pub position: Rect<uint>, + pub position: Rect<i32>, /// The background color of the layer. pub background_color: Color, /// The scrolling policy of this layer. diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index e3662c1a3c4..b92f7ea77ce 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -248,7 +248,7 @@ source = "git+https://github.com/alexcrichton/gcc-rs#903e8f8a2e3766ad3d514404d45 [[package]] name = "geom" version = "0.1.0" -source = "git+https://github.com/servo/rust-geom#da6b4a36a5549cf78bf702f0b9387b5c8cf61498" +source = "git+https://github.com/servo/rust-geom#0f77c6ad116748b7e6bedbf2414d4ceea17debc2" [[package]] name = "gfx" diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 3ebeef17673..e203988b28b 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -244,7 +244,7 @@ source = "git+https://github.com/alexcrichton/gcc-rs#903e8f8a2e3766ad3d514404d45 [[package]] name = "geom" version = "0.1.0" -source = "git+https://github.com/servo/rust-geom#da6b4a36a5549cf78bf702f0b9387b5c8cf61498" +source = "git+https://github.com/servo/rust-geom#0f77c6ad116748b7e6bedbf2414d4ceea17debc2" [[package]] name = "gfx" diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 19641c7399c..6be4f9e4535 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -227,7 +227,7 @@ source = "git+https://github.com/alexcrichton/gcc-rs#903e8f8a2e3766ad3d514404d45 [[package]] name = "geom" version = "0.1.0" -source = "git+https://github.com/servo/rust-geom#da6b4a36a5549cf78bf702f0b9387b5c8cf61498" +source = "git+https://github.com/servo/rust-geom#0f77c6ad116748b7e6bedbf2414d4ceea17debc2" [[package]] name = "gfx" diff --git a/tests/ref/basic.list b/tests/ref/basic.list index 29ad0825f00..67e6300969f 100644 --- a/tests/ref/basic.list +++ b/tests/ref/basic.list @@ -222,3 +222,5 @@ fragment=top != ../html/acid2.html acid2_ref.html != inset_blackborder.html blackborder_ref.html != outset_blackborder.html blackborder_ref.html == border_radius_clip_a.html border_radius_clip_ref.html +== stacking_context_overflow_a.html stacking_context_overflow_ref.html +== stacking_context_overflow_relative_outline_a.html stacking_context_overflow_relative_outline_ref.html diff --git a/tests/ref/position_fixed_tile_edge_3.html b/tests/ref/position_fixed_tile_edge_3.html index dcf2341c170..60e20fb22b0 100644 --- a/tests/ref/position_fixed_tile_edge_3.html +++ b/tests/ref/position_fixed_tile_edge_3.html @@ -1,7 +1,7 @@ <html> <body> <div style="position: absolute; top: 0px; left: 0px;"> - <div style="position: absolute; background: green; margin-left: 512px; width: 20px; height: 20px;"></div> + <div style="position: absolute; background: green; top: 0; margin-left: 512px; width: 20px; height: 20px;"></div> <!-- This position:fixed sibling should force its sibling to be layerized. --> <div style="position: fixed;"></div> diff --git a/tests/ref/stacking_context_overflow_a.html b/tests/ref/stacking_context_overflow_a.html new file mode 100644 index 00000000000..ea87a5dba55 --- /dev/null +++ b/tests/ref/stacking_context_overflow_a.html @@ -0,0 +1,22 @@ +<html> +<head> +<!-- Tests that stacking contexts display overflow. --> +<style> +body { + margin: 0; +} +section { + position: absolute; + z-index: 1; + width: 72px; + height: 72px; + border: solid black 2px; + font: 24px Arial; +} +</style> +</head> +<body> +<section>CSS IS AWESOME</section> +</body> +</html> + diff --git a/tests/ref/stacking_context_overflow_ref.html b/tests/ref/stacking_context_overflow_ref.html new file mode 100644 index 00000000000..49991c449ab --- /dev/null +++ b/tests/ref/stacking_context_overflow_ref.html @@ -0,0 +1,21 @@ +<html> +<head> +<!-- Tests that stacking contexts display overflow. --> +<style> +body { + margin: 0; +} +section { + width: 72px; + height: 72px; + border: solid black 2px; + font: 24px Arial; +} +</style> +</head> +<body> +<section>CSS IS AWESOME</section> +</body> +</html> + + diff --git a/tests/ref/stacking_context_overflow_relative_outline_a.html b/tests/ref/stacking_context_overflow_relative_outline_a.html new file mode 100644 index 00000000000..64b965063fc --- /dev/null +++ b/tests/ref/stacking_context_overflow_relative_outline_a.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> +<style> +section { + position: absolute; + top: 100px; + left: 100px; + width: 10px; + height: 10px; +} +h1 { + position: relative; + top: -50px; + left: -50px; + width: 200px; + height: 200px; + margin: 0; + outline: solid 10px green; +} +</style> +<body> +<section><h1></h1></section> +</body> +</html> + diff --git a/tests/ref/stacking_context_overflow_relative_outline_ref.html b/tests/ref/stacking_context_overflow_relative_outline_ref.html new file mode 100644 index 00000000000..6117d76ff8f --- /dev/null +++ b/tests/ref/stacking_context_overflow_relative_outline_ref.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<style> +section { + position: absolute; + top: 40px; + left: 40px; + width: 200px; + height: 200px; + border: solid 10px green; +} +</style> +<body> +<section></section> +</body> +</html> + + |