Bug 812899 - Make vertical 'auto' margins on absolutely positioned elements always center, even when the margins are negative. r=dbaron

This commit is contained in:
Karl Dubost 2015-07-17 16:12:04 +09:00
parent 0e8fe9d3c7
commit 4e6511a3e2
4 changed files with 101 additions and 41 deletions

View File

@ -45,7 +45,7 @@ using namespace mozilla::layout;
enum eNormalLineHeightControl {
eUninitialized = -1,
eNoExternalLeading = 0, // does not include external leading
eNoExternalLeading = 0, // does not include external leading
eIncludeExternalLeading, // use whatever value font vendor provides
eCompensateLeading // compensate leading if leading provided by font vendor is not enough
};
@ -485,11 +485,11 @@ void nsHTMLReflowState::InitCBReflowState()
}
/* Check whether CalcQuirkContainingBlockHeight would stop on the
* given reflow state, using its block as a height. (essentially
* returns false for any case in which CalcQuirkContainingBlockHeight
* given reflow state, using its block as a height. (essentially
* returns false for any case in which CalcQuirkContainingBlockHeight
* has a "continue" in its main loop.)
*
* XXX Maybe refactor CalcQuirkContainingBlockHeight so it uses
* XXX Maybe refactor CalcQuirkContainingBlockHeight so it uses
* this function as well
*/
static bool
@ -669,9 +669,9 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameT
// the special bsize reflow, since in that case it will already be
// set correctly above if we need it set.
if (!IsBResize() && mCBReflowState &&
(IS_TABLE_CELL(mCBReflowState->frame->GetType()) ||
(IS_TABLE_CELL(mCBReflowState->frame->GetType()) ||
mCBReflowState->mFlags.mHeightDependsOnAncestorCell) &&
!mCBReflowState->mFlags.mSpecialBSizeReflow &&
!mCBReflowState->mFlags.mSpecialBSizeReflow &&
dependsOnCBBSize) {
SetBResize(true);
mFlags.mHeightDependsOnAncestorCell = true;
@ -694,11 +694,11 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameT
if (!rs) {
break;
}
if (rs->frame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_BSIZE)
break; // no need to go further
rs->frame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
// Keep track of whether we've hit the containing block, because
// we need to go at least that far.
if (rs == mCBReflowState) {
@ -716,7 +716,7 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext, nsIAtom* aFrameT
// where we hit the early break statements in
// CalcQuirkContainingBlockHeight. But it doesn't hurt
// us to set the bit in these cases.
}
if (frame->GetStateBits() & NS_FRAME_IS_DIRTY) {
// If we're reflowing everything, then we'll find out if we need
@ -1741,15 +1741,10 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext,
if (marginBStartIsAuto) {
if (marginBEndIsAuto) {
if (availMarginSpace < 0) {
// FIXME: Note that the spec doesn't actually say we should do this!
margin.BEnd(cbwm) = availMarginSpace;
} else {
// Both margin-block-start and -end are 'auto', so they get
// equal values
margin.BStart(cbwm) = availMarginSpace / 2;
margin.BEnd(cbwm) = availMarginSpace - margin.BStart(cbwm);
}
// Both 'margin-top' and 'margin-bottom' are 'auto', so they get
// equal values
margin.BStart(cbwm) = availMarginSpace / 2;
margin.BEnd(cbwm) = availMarginSpace - margin.BStart(cbwm);
} else {
// Just margin-block-start is 'auto'
margin.BStart(cbwm) = availMarginSpace;
@ -1783,19 +1778,19 @@ GetBlockMarginBorderPadding(const nsHTMLReflowState* aReflowState)
// zero auto margins
nsMargin margin = aReflowState->ComputedPhysicalMargin();
if (NS_AUTOMARGIN == margin.top)
if (NS_AUTOMARGIN == margin.top)
margin.top = 0;
if (NS_AUTOMARGIN == margin.bottom)
if (NS_AUTOMARGIN == margin.bottom)
margin.bottom = 0;
result += margin.top + margin.bottom;
result += aReflowState->ComputedPhysicalBorderPadding().top +
result += aReflowState->ComputedPhysicalBorderPadding().top +
aReflowState->ComputedPhysicalBorderPadding().bottom;
return result;
}
/* Get the height based on the viewport of the containing block specified
/* Get the height based on the viewport of the containing block specified
* in aReflowState when the containing block has mComputedHeight == NS_AUTOHEIGHT
* This will walk up the chain of containing blocks looking for a computed height
* until it finds the canvas frame, or it encounters a frame that is not a block,
@ -1811,16 +1806,16 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState* aCBReflowState)
{
const nsHTMLReflowState* firstAncestorRS = nullptr; // a candidate for html frame
const nsHTMLReflowState* secondAncestorRS = nullptr; // a candidate for body frame
// initialize the default to NS_AUTOHEIGHT as this is the containings block
// computed height when this function is called. It is possible that we
// computed height when this function is called. It is possible that we
// don't alter this height especially if we are restricted to one level
nscoord result = NS_AUTOHEIGHT;
nscoord result = NS_AUTOHEIGHT;
const nsHTMLReflowState* rs = aCBReflowState;
for (; rs; rs = rs->parentReflowState) {
nsIAtom* frameType = rs->frame->GetType();
// if the ancestor is auto height then skip it and continue up if it
// if the ancestor is auto height then skip it and continue up if it
// is the first block frame and possibly the body/html
if (nsGkAtoms::blockFrame == frameType ||
#ifdef MOZ_XUL
@ -1849,23 +1844,23 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState* aCBReflowState)
else if (nsGkAtoms::pageContentFrame == frameType) {
nsIFrame* prevInFlow = rs->frame->GetPrevInFlow();
// only use the page content frame for a height basis if it is the first in flow
if (prevInFlow)
if (prevInFlow)
break;
}
else {
break;
}
// if the ancestor is the page content frame then the percent base is
// if the ancestor is the page content frame then the percent base is
// the avail height, otherwise it is the computed height
result = (nsGkAtoms::pageContentFrame == frameType)
? rs->AvailableHeight() : rs->ComputedHeight();
// if unconstrained - don't sutract borders - would result in huge height
if (NS_AUTOHEIGHT == result) return result;
// if we got to the canvas or page content frame, then subtract out
// if we got to the canvas or page content frame, then subtract out
// margin/border/padding for the BODY and HTML elements
if ((nsGkAtoms::canvasFrame == frameType) ||
if ((nsGkAtoms::canvasFrame == frameType) ||
(nsGkAtoms::pageContentFrame == frameType)) {
result -= GetBlockMarginBorderPadding(firstAncestorRS);
@ -1888,7 +1883,7 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState* aCBReflowState)
}
}
#endif
}
// if we got to the html frame (a block child of the canvas) ...
else if (nsGkAtoms::blockFrame == frameType &&
@ -2443,7 +2438,7 @@ nsCSSOffsetState::InitOffsets(WritingMode aWM,
//
// 'margin-left' + 'border-left-width' + 'padding-left' + 'width' +
// 'padding-right' + 'border-right-width' + 'margin-right'
// = width of containing block
// = width of containing block
//
// Note: the width unit is not auto when this is called
void
@ -2559,14 +2554,14 @@ nsHTMLReflowState::CalculateBlockSideMargins(nsIAtom* aFrameType)
SetComputedLogicalMargin(margin.ConvertTo(mWritingMode, cbWM));
}
#define NORMAL_LINE_HEIGHT_FACTOR 1.2f // in term of emHeight
#define NORMAL_LINE_HEIGHT_FACTOR 1.2f // in term of emHeight
// For "normal" we use the font's normal line height (em height + leading).
// If both internal leading and external leading specified by font itself
// are zeros, we should compensate this by creating extra (external) leading
// in eCompensateLeading mode. This is necessary because without this
// compensation, normal line height might looks too tight.
// are zeros, we should compensate this by creating extra (external) leading
// in eCompensateLeading mode. This is necessary because without this
// compensation, normal line height might looks too tight.
// For risk management, we use preference to control the behavior, and
// For risk management, we use preference to control the behavior, and
// eNoExternalLeading is the old behavior.
static nscoord
GetNormalLineHeight(nsFontMetrics* aFontMetrics)
@ -2611,7 +2606,7 @@ ComputeLineHeight(nsStyleContext* aStyleContext,
}
if (lhCoord.GetUnit() == eStyleUnit_Factor)
// For factor units the computed value of the line-height property
// For factor units the computed value of the line-height property
// is found by multiplying the factor by the font's computed size
// (adjusted for min-size prefs and text zoom).
return NSToCoordRound(lhCoord.GetFactorValue() * aFontSizeInflation *
@ -2620,7 +2615,7 @@ ComputeLineHeight(nsStyleContext* aStyleContext,
NS_ASSERTION(lhCoord.GetUnit() == eStyleUnit_Normal ||
lhCoord.GetUnit() == eStyleUnit_Enumerated,
"bad line-height unit");
if (lhCoord.GetUnit() == eStyleUnit_Enumerated) {
NS_ASSERTION(lhCoord.GetIntValue() == NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT,
"bad line-height value");
@ -2875,4 +2870,4 @@ uint8_t
nsHTMLReflowState::GetDisplay() const
{
return mStyleDisplay->GetDisplay(frame);
}
}

View File

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<title> absolutely positioned element should be vertically centered even if the height is bigger than that of the containing block (reference) - bug 812899</title>
<style>
body > div {
font-size: 16px;
position: relative;
border: red solid;
margin-top: 5em;
width: 5em;
height: 5em;
}
body > div > div {
position: absolute;
border: medium solid blue;
margin: -23px auto
height: 150%;
width: 150%;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
}
</style>
<body>
<div>
<div></div>
</div>
</body>
</html>

View File

@ -0,0 +1,32 @@
<!DOCTYPE HTML>
<title> absolutely positioned element should be vertically centered even if the height is bigger than that of the containing block (reference) - bug 812899</title>
<style>
body > div {
font-size: 16px;
position: relative;
border: red solid;
margin-top: 5em;
width: 5em;
height: 5em;
}
body > div > div {
position: absolute;
border: medium solid blue;
margin: auto auto;
height: 150%;
width: 150%;
left: 0px;
right: 0px;
top: 0px;
bottom: 0px;
}
</style>
<body>
<div>
<div></div>
</div>
</body>
</html>

View File

@ -1,5 +1,6 @@
== font-size-wrap.html font-size-wrap-ref.html
== abs-pos-auto-margin-1.html abs-pos-auto-margin-1-ref.html
== abs-pos-auto-margin-centered.html abs-pos-auto-margin-centered-ref.html
fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)&&!layersGPUAccelerated&&!azureSkia,73,1) == auto-offset-inline-block-1.html auto-offset-inline-block-1-ref.html # bug 696670
== fieldset-1.html fieldset-1-ref.html
== table-1.html table-1-ref.html