Fix #6799: set stacking_context_position correctly on

fragment_border_iterator
This commit is contained in:
Eloy Coto 2017-05-27 13:27:35 +02:00
parent 2151a1f459
commit 33a46597ed
5 changed files with 67 additions and 18 deletions

View file

@ -31,7 +31,7 @@ use app_units::{Au, MAX_AU};
use context::LayoutContext;
use display_list_builder::{BorderPaintingMode, DisplayListBuildState};
use display_list_builder::BlockFlowDisplayListBuilding;
use euclid::{Point2D, Size2D};
use euclid::{Point2D, Size2D, Rect};
use floats::{ClearType, FloatKind, Floats, PlacementInfo};
use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ForceNonfloatedFlag};
use flow::{BLOCK_POSITION_IS_STATIC, CLEARS_LEFT, CLEARS_RIGHT};
@ -647,6 +647,14 @@ impl BlockFlow {
&mut self.fragment
}
pub fn stacking_relative_position(&self, coor: CoordinateSystem) -> Rect<Au> {
return self.fragment.stacking_relative_border_box(
&self.base.stacking_relative_position,
&self.base.early_absolute_position_info.relative_containing_block_size,
self.base.early_absolute_position_info.relative_containing_block_mode,
coor);
}
/// Return the size of the containing block for the given immediate absolute descendant of this
/// flow.
///

View file

@ -2221,13 +2221,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
if state.clip_stack.is_empty() {
return;
}
let border_box = self.fragment.stacking_relative_border_box(
&self.base.stacking_relative_position,
&self.base.early_absolute_position_info.relative_containing_block_size,
self.base.early_absolute_position_info.relative_containing_block_mode,
CoordinateSystem::Parent);
let border_box = self.stacking_relative_position(CoordinateSystem::Parent);
let transform = match self.fragment.transform_matrix(&border_box) {
Some(transform) => transform,
None => return,

View file

@ -12,7 +12,7 @@ use floats::SpeculatedFloatPlacement;
use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils};
use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
use flow::IS_ABSOLUTELY_POSITIONED;
use fragment::FragmentBorderBoxIterator;
use fragment::{FragmentBorderBoxIterator, CoordinateSystem};
use generated_content::ResolveGeneratedContent;
use incremental::RelayoutMode;
use servo_config::opts;
@ -105,15 +105,22 @@ pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut Flow, iterator
flow.iterate_through_fragment_border_boxes(iterator, level, stacking_context_position);
for kid in flow::mut_base(flow).child_iter_mut() {
let stacking_context_position = if kid.is_block_flow() &&
kid.as_block().fragment.establishes_stacking_context() {
let margin = Point2D::new(kid.as_block().fragment.margin.inline_start, Au(0));
*stacking_context_position + flow::base(kid).stacking_relative_position + margin
} else {
*stacking_context_position
};
// FIXME(#2795): Get the real container size.
let mut stacking_context_position = *stacking_context_position;
if kid.is_block_flow() && kid.as_block().fragment.establishes_stacking_context() {
stacking_context_position = Point2D::new(kid.as_block().fragment.margin.inline_start, Au(0)) +
flow::base(kid).stacking_relative_position +
stacking_context_position;
let relative_position = kid.as_block()
.stacking_relative_position(CoordinateSystem::Own);
if let Some(matrix) = kid.as_block()
.fragment
.transform_matrix(&relative_position) {
let transform_matrix = matrix.transform_point(&Point2D::zero());
stacking_context_position = stacking_context_position +
Point2D::new(Au::from_f32_px(transform_matrix.x),
Au::from_f32_px(transform_matrix.y))
}
}
doit(kid, level + 1, iterator, &stacking_context_position);
}
}

View file

@ -321172,6 +321172,12 @@
{}
]
],
"cssom/GetBoundingRect.html": [
[
"/cssom/GetBoundingRect.html",
{}
]
],
"cssom/MediaList.html": [
[
"/cssom/MediaList.html",
@ -553765,6 +553771,10 @@
"f0d47464da9d30e70733f09af78f3e9f982c4406",
"testharness"
],
"cssom/GetBoundingRect.html": [
"7e5a8b25753ac970c2d192376c9dd93943b3dbb5",
"testharness"
],
"cssom/MediaList.html": [
"21d9e43514fb3a7fbf8933429242dc544224ef24",
"testharness"

View file

@ -0,0 +1,30 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>getBoundingClientRect</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#foo {
margin: 0px 0px 0px 5px;
transform: translate(10px, 200px);
position: fixed;
left: 5px;
background-color: red;
}
</style>
</head>
<body>
<div id="foo">
FOO
</div>
<script>
test(function () {
var foo = document.getElementById("foo").getBoundingClientRect();
assert_equals(foo.left, 20);
});
</script>
</body>
</html>