mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
bug 175455 - Added mTableDerivedComputedWidth to the reflow state to detect computed widths which exist only because of table cells. Limit percent width of descendants whose percentage base has such a computed width. sr=roc, r=bernd
This commit is contained in:
parent
6345aa5b6c
commit
a4389a11ce
@ -246,10 +246,12 @@ struct nsHTMLReflowState {
|
||||
struct ReflowStateFlags {
|
||||
PRUint16 mSpecialHeightReflow:1; // used by tables to communicate special reflow (in process) to handle
|
||||
// percent height frames inside cells which may not have computed heights
|
||||
PRUint16 mTableDerivedComputedWidth:1; // Computed width is due to a table cell's final width, not style
|
||||
// on the frame itself. Restrictions apply.
|
||||
PRUint16 mIsTopOfPage:1; // is the current context at the top of a page?
|
||||
PRUint16 mBlinks:1; // Keep track of text-decoration: blink
|
||||
PRUint16 mVisualBidiFormControl:1; // Keep track of descendants of form controls on Visual Bidi pages
|
||||
PRUint16 mUnused:12; // for future use
|
||||
PRUint16 mUnused:11; // for future use
|
||||
} mFlags;
|
||||
|
||||
#ifdef IBMBIDI
|
||||
|
@ -121,7 +121,6 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
: mReflowDepth(0)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aRenderingContext, "no rendering context");
|
||||
mFlags.mSpecialHeightReflow = mFlags.mUnused = 0;
|
||||
parentReflowState = nsnull;
|
||||
frame = aFrame;
|
||||
reason = aReason;
|
||||
@ -131,7 +130,10 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
rendContext = aRenderingContext;
|
||||
mSpaceManager = nsnull;
|
||||
mLineLayout = nsnull;
|
||||
mFlags.mSpecialHeightReflow = PR_FALSE;
|
||||
mFlags.mTableDerivedComputedWidth = PR_FALSE;
|
||||
mFlags.mIsTopOfPage = PR_FALSE;
|
||||
mFlags.mUnused = 0;
|
||||
mPercentHeightObserver = nsnull;
|
||||
mPercentHeightReflowInitiator = nsnull;
|
||||
Init(aPresContext);
|
||||
@ -152,7 +154,6 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aRenderingContext, "no rendering context");
|
||||
|
||||
mFlags.mSpecialHeightReflow = mFlags.mUnused = 0;
|
||||
reason = eReflowReason_Incremental;
|
||||
path = aReflowPath;
|
||||
parentReflowState = nsnull;
|
||||
@ -162,7 +163,10 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
rendContext = aRenderingContext;
|
||||
mSpaceManager = nsnull;
|
||||
mLineLayout = nsnull;
|
||||
mFlags.mSpecialHeightReflow = PR_FALSE;
|
||||
mFlags.mTableDerivedComputedWidth = PR_FALSE;
|
||||
mFlags.mIsTopOfPage = PR_FALSE;
|
||||
mFlags.mUnused = 0;
|
||||
mPercentHeightObserver = nsnull;
|
||||
mPercentHeightReflowInitiator = nsnull;
|
||||
Init(aPresContext);
|
||||
@ -344,6 +348,9 @@ void nsHTMLReflowState::InitCBReflowState()
|
||||
parentReflowState->frame->GetFrameType(getter_AddRefs(fType));
|
||||
if (IS_TABLE_CELL(fType.get())) {
|
||||
mCBReflowState = parentReflowState;
|
||||
// Set mFlags.mTableDerivedComputedWidth to true for a cell block. Its default
|
||||
// value was set to what the parent reflow state has.
|
||||
mFlags.mTableDerivedComputedWidth = PR_TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1661,6 +1668,35 @@ static eNormalLineHeightControl GetNormalLineHeightCalcControl(void)
|
||||
return sNormalLineHeightControl;
|
||||
}
|
||||
|
||||
// Reset mFlags.mTableDerivedComputedWidth if there is a non percent style width
|
||||
// or if there is a percent style width and the parent has a style width.
|
||||
// This function assumes that aWidthUnit is never Auto or Inherit and that aState's
|
||||
// mFlags.mTableDerivedComputedWidth is set.
|
||||
static void
|
||||
CheckResetTableDerivedComputedWidth(nsHTMLReflowState& aState,
|
||||
nsStyleUnit aWidthUnit)
|
||||
{
|
||||
if (eStyleUnit_Percent == aWidthUnit) {
|
||||
// If the parent isn't a table cell and has a style width reset the flag
|
||||
if (aState.parentReflowState) {
|
||||
nsCOMPtr<nsIAtom> parentType;
|
||||
aState.parentReflowState->frame->GetFrameType(getter_AddRefs(parentType));
|
||||
if (!IS_TABLE_CELL(parentType)) {
|
||||
nsStyleUnit parentUnit = aState.parentReflowState->mStylePosition->mWidth.GetUnit();
|
||||
if ((eStyleUnit_Inherit != parentUnit) &&
|
||||
(eStyleUnit_Auto != parentUnit)) {
|
||||
aState.mFlags.mTableDerivedComputedWidth = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// always reset the flag if there is a fixed width
|
||||
aState.mFlags.mTableDerivedComputedWidth = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// XXX refactor this code to have methods for each set of properties
|
||||
// we are computing: width,height,line-height; margin; offsets
|
||||
|
||||
@ -1835,9 +1871,10 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
|
||||
// A specified value of 'auto' uses the element's intrinsic width
|
||||
mComputedWidth = NS_INTRINSICSIZE;
|
||||
} else {
|
||||
if (mFlags.mTableDerivedComputedWidth)
|
||||
CheckResetTableDerivedComputedWidth(*this, widthUnit);
|
||||
ComputeHorizontalValue(aContainingBlockWidth, widthUnit,
|
||||
mStylePosition->mWidth,
|
||||
mComputedWidth);
|
||||
mStylePosition->mWidth, mComputedWidth);
|
||||
}
|
||||
|
||||
AdjustComputedWidth();
|
||||
@ -1893,9 +1930,10 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
} else {
|
||||
if (mFlags.mTableDerivedComputedWidth)
|
||||
CheckResetTableDerivedComputedWidth(*this, widthUnit);
|
||||
ComputeHorizontalValue(aContainingBlockWidth, widthUnit,
|
||||
mStylePosition->mWidth,
|
||||
mComputedWidth);
|
||||
mStylePosition->mWidth, mComputedWidth);
|
||||
}
|
||||
|
||||
// Take into account minimum and maximum sizes
|
||||
@ -1938,9 +1976,10 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
} else {
|
||||
if (mFlags.mTableDerivedComputedWidth)
|
||||
CheckResetTableDerivedComputedWidth(*this, widthUnit);
|
||||
ComputeHorizontalValue(aContainingBlockWidth, widthUnit,
|
||||
mStylePosition->mWidth,
|
||||
mComputedWidth);
|
||||
mStylePosition->mWidth, mComputedWidth);
|
||||
}
|
||||
|
||||
// Calculate the computed height
|
||||
@ -2089,6 +2128,8 @@ nsHTMLReflowState::ComputeBlockBoxData(nsIPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mFlags.mTableDerivedComputedWidth)
|
||||
CheckResetTableDerivedComputedWidth(*this, aWidthUnit);
|
||||
ComputeHorizontalValue(aContainingBlockWidth, aWidthUnit,
|
||||
mStylePosition->mWidth, mComputedWidth);
|
||||
}
|
||||
@ -2747,6 +2788,16 @@ void nsHTMLReflowState::AdjustComputedWidth(void)
|
||||
// NS_ASSERTION(mComputedWidth>=0, "Negative Width Result - very bad");
|
||||
// if it did go bozo, set to 0
|
||||
if(mComputedWidth<0) mComputedWidth = 0;
|
||||
|
||||
// Tables allow enough width for cells without considering percent based constraints
|
||||
// of content within the cells. Since such content could exceed the available width,
|
||||
// we don't allow that to happen.
|
||||
if (mFlags.mTableDerivedComputedWidth) {
|
||||
nscoord borderPadding = mComputedBorderPadding.left + mComputedBorderPadding.right;
|
||||
if (borderPadding + mComputedWidth > availableWidth) {
|
||||
mComputedWidth = PR_MAX(0, availableWidth - borderPadding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef IBMBIDI
|
||||
|
@ -246,10 +246,12 @@ struct nsHTMLReflowState {
|
||||
struct ReflowStateFlags {
|
||||
PRUint16 mSpecialHeightReflow:1; // used by tables to communicate special reflow (in process) to handle
|
||||
// percent height frames inside cells which may not have computed heights
|
||||
PRUint16 mTableDerivedComputedWidth:1; // Computed width is due to a table cell's final width, not style
|
||||
// on the frame itself. Restrictions apply.
|
||||
PRUint16 mIsTopOfPage:1; // is the current context at the top of a page?
|
||||
PRUint16 mBlinks:1; // Keep track of text-decoration: blink
|
||||
PRUint16 mVisualBidiFormControl:1; // Keep track of descendants of form controls on Visual Bidi pages
|
||||
PRUint16 mUnused:12; // for future use
|
||||
PRUint16 mUnused:11; // for future use
|
||||
} mFlags;
|
||||
|
||||
#ifdef IBMBIDI
|
||||
|
@ -121,7 +121,6 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
: mReflowDepth(0)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aRenderingContext, "no rendering context");
|
||||
mFlags.mSpecialHeightReflow = mFlags.mUnused = 0;
|
||||
parentReflowState = nsnull;
|
||||
frame = aFrame;
|
||||
reason = aReason;
|
||||
@ -131,7 +130,10 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
rendContext = aRenderingContext;
|
||||
mSpaceManager = nsnull;
|
||||
mLineLayout = nsnull;
|
||||
mFlags.mSpecialHeightReflow = PR_FALSE;
|
||||
mFlags.mTableDerivedComputedWidth = PR_FALSE;
|
||||
mFlags.mIsTopOfPage = PR_FALSE;
|
||||
mFlags.mUnused = 0;
|
||||
mPercentHeightObserver = nsnull;
|
||||
mPercentHeightReflowInitiator = nsnull;
|
||||
Init(aPresContext);
|
||||
@ -152,7 +154,6 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aRenderingContext, "no rendering context");
|
||||
|
||||
mFlags.mSpecialHeightReflow = mFlags.mUnused = 0;
|
||||
reason = eReflowReason_Incremental;
|
||||
path = aReflowPath;
|
||||
parentReflowState = nsnull;
|
||||
@ -162,7 +163,10 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
rendContext = aRenderingContext;
|
||||
mSpaceManager = nsnull;
|
||||
mLineLayout = nsnull;
|
||||
mFlags.mSpecialHeightReflow = PR_FALSE;
|
||||
mFlags.mTableDerivedComputedWidth = PR_FALSE;
|
||||
mFlags.mIsTopOfPage = PR_FALSE;
|
||||
mFlags.mUnused = 0;
|
||||
mPercentHeightObserver = nsnull;
|
||||
mPercentHeightReflowInitiator = nsnull;
|
||||
Init(aPresContext);
|
||||
@ -344,6 +348,9 @@ void nsHTMLReflowState::InitCBReflowState()
|
||||
parentReflowState->frame->GetFrameType(getter_AddRefs(fType));
|
||||
if (IS_TABLE_CELL(fType.get())) {
|
||||
mCBReflowState = parentReflowState;
|
||||
// Set mFlags.mTableDerivedComputedWidth to true for a cell block. Its default
|
||||
// value was set to what the parent reflow state has.
|
||||
mFlags.mTableDerivedComputedWidth = PR_TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1661,6 +1668,35 @@ static eNormalLineHeightControl GetNormalLineHeightCalcControl(void)
|
||||
return sNormalLineHeightControl;
|
||||
}
|
||||
|
||||
// Reset mFlags.mTableDerivedComputedWidth if there is a non percent style width
|
||||
// or if there is a percent style width and the parent has a style width.
|
||||
// This function assumes that aWidthUnit is never Auto or Inherit and that aState's
|
||||
// mFlags.mTableDerivedComputedWidth is set.
|
||||
static void
|
||||
CheckResetTableDerivedComputedWidth(nsHTMLReflowState& aState,
|
||||
nsStyleUnit aWidthUnit)
|
||||
{
|
||||
if (eStyleUnit_Percent == aWidthUnit) {
|
||||
// If the parent isn't a table cell and has a style width reset the flag
|
||||
if (aState.parentReflowState) {
|
||||
nsCOMPtr<nsIAtom> parentType;
|
||||
aState.parentReflowState->frame->GetFrameType(getter_AddRefs(parentType));
|
||||
if (!IS_TABLE_CELL(parentType)) {
|
||||
nsStyleUnit parentUnit = aState.parentReflowState->mStylePosition->mWidth.GetUnit();
|
||||
if ((eStyleUnit_Inherit != parentUnit) &&
|
||||
(eStyleUnit_Auto != parentUnit)) {
|
||||
aState.mFlags.mTableDerivedComputedWidth = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// always reset the flag if there is a fixed width
|
||||
aState.mFlags.mTableDerivedComputedWidth = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// XXX refactor this code to have methods for each set of properties
|
||||
// we are computing: width,height,line-height; margin; offsets
|
||||
|
||||
@ -1835,9 +1871,10 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
|
||||
// A specified value of 'auto' uses the element's intrinsic width
|
||||
mComputedWidth = NS_INTRINSICSIZE;
|
||||
} else {
|
||||
if (mFlags.mTableDerivedComputedWidth)
|
||||
CheckResetTableDerivedComputedWidth(*this, widthUnit);
|
||||
ComputeHorizontalValue(aContainingBlockWidth, widthUnit,
|
||||
mStylePosition->mWidth,
|
||||
mComputedWidth);
|
||||
mStylePosition->mWidth, mComputedWidth);
|
||||
}
|
||||
|
||||
AdjustComputedWidth();
|
||||
@ -1893,9 +1930,10 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
} else {
|
||||
if (mFlags.mTableDerivedComputedWidth)
|
||||
CheckResetTableDerivedComputedWidth(*this, widthUnit);
|
||||
ComputeHorizontalValue(aContainingBlockWidth, widthUnit,
|
||||
mStylePosition->mWidth,
|
||||
mComputedWidth);
|
||||
mStylePosition->mWidth, mComputedWidth);
|
||||
}
|
||||
|
||||
// Take into account minimum and maximum sizes
|
||||
@ -1938,9 +1976,10 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
} else {
|
||||
if (mFlags.mTableDerivedComputedWidth)
|
||||
CheckResetTableDerivedComputedWidth(*this, widthUnit);
|
||||
ComputeHorizontalValue(aContainingBlockWidth, widthUnit,
|
||||
mStylePosition->mWidth,
|
||||
mComputedWidth);
|
||||
mStylePosition->mWidth, mComputedWidth);
|
||||
}
|
||||
|
||||
// Calculate the computed height
|
||||
@ -2089,6 +2128,8 @@ nsHTMLReflowState::ComputeBlockBoxData(nsIPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mFlags.mTableDerivedComputedWidth)
|
||||
CheckResetTableDerivedComputedWidth(*this, aWidthUnit);
|
||||
ComputeHorizontalValue(aContainingBlockWidth, aWidthUnit,
|
||||
mStylePosition->mWidth, mComputedWidth);
|
||||
}
|
||||
@ -2747,6 +2788,16 @@ void nsHTMLReflowState::AdjustComputedWidth(void)
|
||||
// NS_ASSERTION(mComputedWidth>=0, "Negative Width Result - very bad");
|
||||
// if it did go bozo, set to 0
|
||||
if(mComputedWidth<0) mComputedWidth = 0;
|
||||
|
||||
// Tables allow enough width for cells without considering percent based constraints
|
||||
// of content within the cells. Since such content could exceed the available width,
|
||||
// we don't allow that to happen.
|
||||
if (mFlags.mTableDerivedComputedWidth) {
|
||||
nscoord borderPadding = mComputedBorderPadding.left + mComputedBorderPadding.right;
|
||||
if (borderPadding + mComputedWidth > availableWidth) {
|
||||
mComputedWidth = PR_MAX(0, availableWidth - borderPadding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef IBMBIDI
|
||||
|
25
layout/html/tests/table/bugs/bug175455-4.html
Normal file
25
layout/html/tests/table/bugs/bug175455-4.html
Normal file
@ -0,0 +1,25 @@
|
||||
<!doctype html public "-//w3c//dtd html 3.2//en">
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>testcase 2</title>
|
||||
<meta name="GENERATOR" content="Arachnophilia 4.0">
|
||||
<meta name="FORMATTER" content="Arachnophilia 4.0">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff" text="#000000" link="#0000ff" vlink="#800080" alink="#ff0000">
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<td width="300">
|
||||
|
||||
<div style="width:30%; border: solid purple">
|
||||
<div style="width:200%; border:solid blue">
|
||||
foo
|
||||
</div>
|
||||
</div>
|
||||
</td></tr></table>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -23,6 +23,7 @@ file:///s|/mozilla/layout/html/tests/table/bugs/bug17138.html
|
||||
file:///s|/mozilla/layout/html/tests/table/bugs/bug1725.html
|
||||
file:///s|/mozilla/layout/html/tests/table/bugs/bug17548.html
|
||||
file:///s|/mozilla/layout/html/tests/table/bugs/bug17168.html
|
||||
file:///s|/mozilla/layout/html/tests/table/bugs/bug175455-4.html
|
||||
file:///s|/mozilla/layout/html/tests/table/bugs/bug17587.html
|
||||
file:///s|/mozilla/layout/html/tests/table/bugs/bug17826.html
|
||||
file:///s|/mozilla/layout/html/tests/table/bugs/bug178855.xml
|
||||
|
19
layout/html/tests/table/interactive/bug175455-1.html
Normal file
19
layout/html/tests/table/interactive/bug175455-1.html
Normal file
@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>bug 175455</title>
|
||||
<style>
|
||||
a.freesubtype {display: block; width: 100%; padding-left: 16px;}
|
||||
a.freesubtype:hover {font-weight: bold;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table border="1">
|
||||
<tr>
|
||||
|
||||
<td>
|
||||
<a class='freesubtype'>Classic</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
33
layout/html/tests/table/interactive/bug175455-2.html
Normal file
33
layout/html/tests/table/interactive/bug175455-2.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 175455 testcase</title>
|
||||
<style type="text/css">
|
||||
/* All of these rules seem to be required to trigger this bug */
|
||||
a.xxx {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding-left: 16px;
|
||||
background-color: silver;
|
||||
}
|
||||
a.xxx:hover {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Bug 175455 testcase</h1>
|
||||
<table>
|
||||
<tr>
|
||||
<td style="background-color: lime">
|
||||
|
||||
<a href="" class='xxx'>Hover on me, then move your mouse off again...</a>
|
||||
</td>
|
||||
<td style="background-color: green">
|
||||
...and watch this cell move!
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
16
layout/html/tests/table/interactive/bug175455-3.html
Normal file
16
layout/html/tests/table/interactive/bug175455-3.html
Normal file
@ -0,0 +1,16 @@
|
||||
<html><head><title>bug 175455</title>
|
||||
|
||||
<style>
|
||||
a.freesubtype {display: block; width: 100%; padding-left: 16px;}
|
||||
a.freesubtype:hover {font-weight: bold;}
|
||||
</style></head>
|
||||
<body>
|
||||
<table border="1">
|
||||
<tbody><tr>
|
||||
<td><i>
|
||||
<a class="freesubtype">Classic</a></i>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</body></html>
|
Loading…
Reference in New Issue
Block a user