Bug 985303. Part 3: Save a block's 'bottom edge of content' in a frame property if it doesn't match the block's content height, and use it in UpdateOverflow to compute the correct overflow. r=dbaron

--HG--
extra : rebase_source : 11fe6925ee266a2e1feec5a4d5c0e5ed152516f5
This commit is contained in:
Robert O'Callahan 2014-04-03 04:27:23 -04:00
parent e7a73b2eb1
commit b1cf0ff0d7
5 changed files with 160 additions and 12 deletions

View File

@ -241,6 +241,7 @@ NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OverflowOutOfFlowsProperty)
NS_DECLARE_FRAME_PROPERTY_FRAMELIST(PushedFloatProperty)
NS_DECLARE_FRAME_PROPERTY_FRAMELIST(OutsideBulletProperty)
NS_DECLARE_FRAME_PROPERTY(InsideBulletProperty, nullptr)
NS_DECLARE_FRAME_PROPERTY(BottomEdgeOfChildrenProperty, nullptr)
//----------------------------------------------------------------------
@ -1452,6 +1453,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
aMetrics.Height() = std::max(0, aMetrics.Height());
*aBottomEdgeOfChildren = bottomEdgeOfChildren;
FrameProperties properties = Properties();
if (bottomEdgeOfChildren != aMetrics.Height() - borderPadding.bottom) {
properties.Set(BottomEdgeOfChildrenProperty(),
NS_INT32_TO_PTR(bottomEdgeOfChildren));
} else {
properties.Delete(BottomEdgeOfChildrenProperty());
}
#ifdef DEBUG_blocks
if (CRAZY_SIZE(aMetrics.Width()) || CRAZY_SIZE(aMetrics.Height())) {
ListTag(stdout);
@ -1460,6 +1469,22 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
#endif
}
static void
ConsiderBottomEdgeOfChildren(nscoord aBottomEdgeOfChildren,
nsOverflowAreas& aOverflowAreas)
{
// Factor in the bottom edge of the children. Child frames will be added
// to the overflow area as we iterate through the lines, but their margins
// won't, so we need to account for bottom margins here.
// REVIEW: For now, we do this for both visual and scrollable area,
// although when we make scrollable overflow area not be a subset of
// visual, we can change this.
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
nsRect& o = aOverflowAreas.Overflow(otype);
o.height = std::max(o.YMost(), aBottomEdgeOfChildren) - o.y;
}
}
void
nsBlockFrame::ComputeOverflowAreas(const nsRect& aBounds,
const nsStyleDisplay* aDisplay,
@ -1487,17 +1512,9 @@ nsBlockFrame::ComputeOverflowAreas(const nsRect& aBounds,
areas.UnionAllWith(outsideBullet->GetRect());
}
// Factor in the bottom edge of the children. Child frames will be added
// to the overflow area as we iterate through the lines, but their margins
// won't, so we need to account for bottom margins here.
// REVIEW: For now, we do this for both visual and scrollable area,
// although when we make scrollable overflow area not be a subset of
// visual, we can change this.
NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
nsRect& o = areas.Overflow(otype);
o.height = std::max(o.YMost(), aBottomEdgeOfChildren) - o.y;
}
ConsiderBottomEdgeOfChildren(aBottomEdgeOfChildren, areas);
}
#ifdef NOISY_COMBINED_AREA
ListTag(stdout);
printf(": ca=%d,%d,%d,%d\n", area.x, area.y, area.width, area.height);
@ -1509,6 +1526,9 @@ nsBlockFrame::ComputeOverflowAreas(const nsRect& aBounds,
bool
nsBlockFrame::UpdateOverflow()
{
nsRect rect(nsPoint(0, 0), GetSize());
nsOverflowAreas overflowAreas(rect, rect);
// We need to update the overflow areas of lines manually, as they
// get cached and re-used otherwise. Lines aren't exposed as normal
// frame children, so calling UnionChildOverflow alone will end up
@ -1516,7 +1536,8 @@ nsBlockFrame::UpdateOverflow()
for (line_iterator line = begin_lines(), line_end = end_lines();
line != line_end;
++line) {
nsOverflowAreas lineAreas;
nsRect bounds = line->mBounds;
nsOverflowAreas lineAreas(bounds, bounds);
int32_t n = line->GetChildCount();
for (nsIFrame* lineFrame = line->mFirstChild;
@ -1532,13 +1553,26 @@ nsBlockFrame::UpdateOverflow()
}
line->SetOverflowAreas(lineAreas);
overflowAreas.UnionWith(lineAreas);
}
// Line cursor invariants depend on the overflow areas of the lines, so
// we must clear the line cursor since those areas may have changed.
ClearLineCursor();
return nsBlockFrameSuper::UpdateOverflow();
// Union with child frames, skipping the principal and float lists
// since we already handled those using the line boxes.
nsLayoutUtils::UnionChildOverflow(this, overflowAreas,
kPrincipalList | kFloatList);
bool found;
nscoord bottomEdgeOfChildren = NS_PTR_TO_INT32(
Properties().Get(BottomEdgeOfChildrenProperty(), &found));
if (found) {
ConsiderBottomEdgeOfChildren(bottomEdgeOfChildren, overflowAreas);
}
return FinishAndStoreOverflow(overflowAreas, GetSize());
}
void

View File

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<style>
#container {
position: absolute;
width: 200px;
height: 200px;
overflow: scroll;
}
#image {
width: 100px;
height: 100px;
margin: 100px;
background: blue;
display: inline-block;
}
#cursor {
position: absolute;
left: 10px;
top: 0;
width: 10px;
height: 10px;
background: red;
}
</style>
</head>
<body>
<div id='container'>
<div id='image'></div>
<div id='cursor'></div>
</div>
</body>
</html>

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<style>
#container {
position: absolute;
width: 200px;
height: 200px;
overflow: scroll;
}
#image {
width: 100px;
height: 100px;
margin: 100px;
background: blue;
display: inline-block;
}
#cursor {
position: absolute;
left: 0;
top: 0;
width: 10px;
height: 10px;
background: red;
}
</style>
</head>
<body>
<div id='container'>
<div id='image'></div>
<div id='cursor'></div>
</div>
</body>
<script>
var x = image.getBoundingClientRect();
cursor.style.left = '10px';
</script>
</html>

View File

@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<style>
#container {
position: absolute;
width: 200px;
height: 200px;
overflow: scroll;
}
#image {
width: 100px;
height: 100px;
margin: 100px;
background: blue;
display: inline-block;
}
#cursor {
position: absolute;
left: 0;
top: 0;
width: 10px;
height: 10px;
background: red;
}
</style>
</head>
<body>
<div id='container'>
<div style="position:relative">
<div id='image'></div>
<div id='cursor'></div>
</div>
</div>
</body>
<script>
var x = image.getBoundingClientRect();
cursor.style.left = '10px';
</script>
</html>

View File

@ -1804,6 +1804,8 @@ skip-if(Android) == 966510-2.html 966510-2-ref.html # same as above
== 983084-2.html 983084-2-ref.html
== 983084-3.html 983084-1-ref.html
== 983691-1.html 983691-ref.html
== 985303-1a.html 985303-1-ref.html
== 985303-1b.html 985303-1-ref.html
== 987680-1.html 987680-1-ref.html
fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,24) == 991046-1.html 991046-1-ref.html
pref(layout.css.overflow-clip-box.enabled,true) == 992447.html 992447-ref.html