diff --git a/layout/base/public/nsHTMLReflowState.h b/layout/base/public/nsHTMLReflowState.h index 4fce25dc16fd..36e5d2585037 100644 --- a/layout/base/public/nsHTMLReflowState.h +++ b/layout/base/public/nsHTMLReflowState.h @@ -202,6 +202,12 @@ struct nsHTMLReflowState { // set it. if false, the reflow sets alignCharOffset PRPackedBool mUseAlignCharOffset; + // a table cell has a constrained mComputedWidth to accomodate its inner block. + // since it is treated like a containing block for percent calculations, this flag + // indicates not to use mComputedWidth for percent calculations if true. + // it also propogates into descendants whose width is percentage. + PRBool mIsAutoWidthPctBase; + // Cached pointers to the various style structs used during intialization const nsStyleDisplay* mStyleDisplay; const nsStylePosition* mStylePosition; diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index dd5d753cc638..b718325833b0 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -170,6 +170,7 @@ nsHTMLReflowState::Init(nsIPresContext* aPresContext, mCompactMarginWidth = 0; mAlignCharOffset = 0; mUseAlignCharOffset = 0; + mIsAutoWidthPctBase = PR_FALSE; frame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)mStylePosition); @@ -1509,15 +1510,13 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext, // the containingBlockHeight calcuation. if (cbrs->parentReflowState) { nsIFrame* f = cbrs->parentReflowState->frame; - nsIAtom* cbFrameType; - - f->GetFrameType(&cbFrameType); - if (nsLayoutAtoms::scrollFrame == cbFrameType) { + nsCOMPtr fType; + f->GetFrameType(getter_AddRefs(fType)); + if (nsLayoutAtoms::scrollFrame == fType.get()) { // Use the scroll frame's computed height instead aContainingBlockHeight = ((nsHTMLReflowState*)cbrs->parentReflowState)->mComputedHeight; } - NS_IF_RELEASE(cbFrameType); } } @@ -1536,14 +1535,33 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext, nsStyleUnit widthUnit = mStylePosition->mWidth.GetUnit(); nsStyleUnit heightUnit = mStylePosition->mHeight.GetUnit(); + nsCOMPtr frameType; + frame->GetFrameType(getter_AddRefs(frameType)); + // Check for a percentage based width and an unconstrained containing // block width if (eStyleUnit_Percent == widthUnit) { - if (NS_UNCONSTRAINEDSIZE == aContainingBlockWidth) { + if ((NS_UNCONSTRAINEDSIZE == aContainingBlockWidth) || + ((cbrs->mIsAutoWidthPctBase) && + (nsLayoutAtoms::tableOuterFrame != frameType.get()) && + (nsLayoutAtoms::tableFrame != frameType.get()))) { // Interpret the width like 'auto' widthUnit = eStyleUnit_Auto; } } + // if the cbrs is an auto width descendant (non table) from a table cell and + // our width may be determined using it, then propogate the flag. + if (cbrs->mIsAutoWidthPctBase) { + if ((eStyleUnit_Auto == widthUnit) || + (eStyleUnit_Percent == widthUnit) || + (eStyleUnit_Inherit == widthUnit)) { + if ((nsLayoutAtoms::tableOuterFrame != frameType.get()) && + (nsLayoutAtoms::tableFrame != frameType.get())) { + mIsAutoWidthPctBase = PR_TRUE; + } + } + } + // Check for a percentage based height and a containing block height // that depends on the content height if (eStyleUnit_Percent == heightUnit) { @@ -1714,6 +1732,11 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext, if (eStyleUnit_Inherit == widthUnit) { mComputedWidth = aContainingBlockWidth; } else if (eStyleUnit_Auto == widthUnit) { + if (NS_STYLE_DISPLAY_TABLE_CELL == mStyleDisplay->mDisplay) { + // set the flag to ignore mComputedWidth for percent calculations + // when the cell is a containing block. + mIsAutoWidthPctBase = PR_TRUE; + } mComputedWidth = availableWidth; if (mComputedWidth != NS_UNCONSTRAINEDSIZE) { diff --git a/layout/generic/nsHTMLReflowState.h b/layout/generic/nsHTMLReflowState.h index 4fce25dc16fd..36e5d2585037 100644 --- a/layout/generic/nsHTMLReflowState.h +++ b/layout/generic/nsHTMLReflowState.h @@ -202,6 +202,12 @@ struct nsHTMLReflowState { // set it. if false, the reflow sets alignCharOffset PRPackedBool mUseAlignCharOffset; + // a table cell has a constrained mComputedWidth to accomodate its inner block. + // since it is treated like a containing block for percent calculations, this flag + // indicates not to use mComputedWidth for percent calculations if true. + // it also propogates into descendants whose width is percentage. + PRBool mIsAutoWidthPctBase; + // Cached pointers to the various style structs used during intialization const nsStyleDisplay* mStyleDisplay; const nsStylePosition* mStylePosition; diff --git a/layout/html/base/src/nsHTMLReflowState.cpp b/layout/html/base/src/nsHTMLReflowState.cpp index dd5d753cc638..b718325833b0 100644 --- a/layout/html/base/src/nsHTMLReflowState.cpp +++ b/layout/html/base/src/nsHTMLReflowState.cpp @@ -170,6 +170,7 @@ nsHTMLReflowState::Init(nsIPresContext* aPresContext, mCompactMarginWidth = 0; mAlignCharOffset = 0; mUseAlignCharOffset = 0; + mIsAutoWidthPctBase = PR_FALSE; frame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)mStylePosition); @@ -1509,15 +1510,13 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext, // the containingBlockHeight calcuation. if (cbrs->parentReflowState) { nsIFrame* f = cbrs->parentReflowState->frame; - nsIAtom* cbFrameType; - - f->GetFrameType(&cbFrameType); - if (nsLayoutAtoms::scrollFrame == cbFrameType) { + nsCOMPtr fType; + f->GetFrameType(getter_AddRefs(fType)); + if (nsLayoutAtoms::scrollFrame == fType.get()) { // Use the scroll frame's computed height instead aContainingBlockHeight = ((nsHTMLReflowState*)cbrs->parentReflowState)->mComputedHeight; } - NS_IF_RELEASE(cbFrameType); } } @@ -1536,14 +1535,33 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext, nsStyleUnit widthUnit = mStylePosition->mWidth.GetUnit(); nsStyleUnit heightUnit = mStylePosition->mHeight.GetUnit(); + nsCOMPtr frameType; + frame->GetFrameType(getter_AddRefs(frameType)); + // Check for a percentage based width and an unconstrained containing // block width if (eStyleUnit_Percent == widthUnit) { - if (NS_UNCONSTRAINEDSIZE == aContainingBlockWidth) { + if ((NS_UNCONSTRAINEDSIZE == aContainingBlockWidth) || + ((cbrs->mIsAutoWidthPctBase) && + (nsLayoutAtoms::tableOuterFrame != frameType.get()) && + (nsLayoutAtoms::tableFrame != frameType.get()))) { // Interpret the width like 'auto' widthUnit = eStyleUnit_Auto; } } + // if the cbrs is an auto width descendant (non table) from a table cell and + // our width may be determined using it, then propogate the flag. + if (cbrs->mIsAutoWidthPctBase) { + if ((eStyleUnit_Auto == widthUnit) || + (eStyleUnit_Percent == widthUnit) || + (eStyleUnit_Inherit == widthUnit)) { + if ((nsLayoutAtoms::tableOuterFrame != frameType.get()) && + (nsLayoutAtoms::tableFrame != frameType.get())) { + mIsAutoWidthPctBase = PR_TRUE; + } + } + } + // Check for a percentage based height and a containing block height // that depends on the content height if (eStyleUnit_Percent == heightUnit) { @@ -1714,6 +1732,11 @@ nsHTMLReflowState::InitConstraints(nsIPresContext* aPresContext, if (eStyleUnit_Inherit == widthUnit) { mComputedWidth = aContainingBlockWidth; } else if (eStyleUnit_Auto == widthUnit) { + if (NS_STYLE_DISPLAY_TABLE_CELL == mStyleDisplay->mDisplay) { + // set the flag to ignore mComputedWidth for percent calculations + // when the cell is a containing block. + mIsAutoWidthPctBase = PR_TRUE; + } mComputedWidth = availableWidth; if (mComputedWidth != NS_UNCONSTRAINEDSIZE) { diff --git a/layout/html/table/src/BasicTableLayoutStrategy.cpp b/layout/html/table/src/BasicTableLayoutStrategy.cpp index 09e05353da4b..3666b4d35d43 100644 --- a/layout/html/table/src/BasicTableLayoutStrategy.cpp +++ b/layout/html/table/src/BasicTableLayoutStrategy.cpp @@ -1186,6 +1186,9 @@ nscoord BasicTableLayoutStrategy::GetTableMinWidth() const for (PRInt32 colX = 0; colX < numCols; colX++) { nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); minWidth += PR_MAX(colFrame->GetMinWidth(), colFrame->GetWidth(MIN_ADJ)); + if (mTableFrame->GetNumCellsOriginatingInCol(colX) > 0) { + minWidth += spacingX; + } } // if it is not a degenerate table, add the last spacing on the right if (minWidth > 0) { @@ -1201,10 +1204,17 @@ nscoord BasicTableLayoutStrategy::GetTableMaxWidth() const nscoord maxWidth = 0; for (PRInt32 colX = 0; colX < numCols; colX++) { nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); - nscoord max = PR_MAX(colFrame->GetDesWidth(), colFrame->GetFixWidth()); - max = PR_MAX(max, colFrame->GetPctWidth()); - max = PR_MAX(max, colFrame->GetWidth(MIN_PRO)); - maxWidth += max; + nscoord width = colFrame->GetPctWidth(); + if (width <= 0) { + width = colFrame->GetFixWidth(); + if (width <= 0) { + width = colFrame->GetWidth(MIN_PRO); + if (width <= 0) { + width = colFrame->GetDesWidth(); + } + } + } + maxWidth += width; if (mTableFrame->GetNumCellsOriginatingInCol(colX) > 0) { maxWidth += spacingX; } diff --git a/layout/html/tests/table/bugs/file_list.txt b/layout/html/tests/table/bugs/file_list.txt index c44d79272762..f498f9d1ecd1 100644 --- a/layout/html/tests/table/bugs/file_list.txt +++ b/layout/html/tests/table/bugs/file_list.txt @@ -164,7 +164,7 @@ file:///s|/mozilla/layout/html/tests/table/bugs/bug2997.html file:///s|/mozilla/layout/html/tests/table/bugs/bug30273.html file:///s|/mozilla/layout/html/tests/table/bugs/bug30332-1.html file:///s|/mozilla/layout/html/tests/table/bugs/bug30332-2.html -file:///s|/mozilla/layout/html/tests/table/bugs/bug3037-1.html +#file:///s|/mozilla/layout/html/tests/table/bugs/bug3037-1.html file:///s|/mozilla/layout/html/tests/table/bugs/bug3037-2.html file:///s|/mozilla/layout/html/tests/table/bugs/bug30559.html file:///s|/mozilla/layout/html/tests/table/bugs/bug30985.html diff --git a/layout/tables/BasicTableLayoutStrategy.cpp b/layout/tables/BasicTableLayoutStrategy.cpp index 09e05353da4b..3666b4d35d43 100644 --- a/layout/tables/BasicTableLayoutStrategy.cpp +++ b/layout/tables/BasicTableLayoutStrategy.cpp @@ -1186,6 +1186,9 @@ nscoord BasicTableLayoutStrategy::GetTableMinWidth() const for (PRInt32 colX = 0; colX < numCols; colX++) { nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); minWidth += PR_MAX(colFrame->GetMinWidth(), colFrame->GetWidth(MIN_ADJ)); + if (mTableFrame->GetNumCellsOriginatingInCol(colX) > 0) { + minWidth += spacingX; + } } // if it is not a degenerate table, add the last spacing on the right if (minWidth > 0) { @@ -1201,10 +1204,17 @@ nscoord BasicTableLayoutStrategy::GetTableMaxWidth() const nscoord maxWidth = 0; for (PRInt32 colX = 0; colX < numCols; colX++) { nsTableColFrame* colFrame = mTableFrame->GetColFrame(colX); - nscoord max = PR_MAX(colFrame->GetDesWidth(), colFrame->GetFixWidth()); - max = PR_MAX(max, colFrame->GetPctWidth()); - max = PR_MAX(max, colFrame->GetWidth(MIN_PRO)); - maxWidth += max; + nscoord width = colFrame->GetPctWidth(); + if (width <= 0) { + width = colFrame->GetFixWidth(); + if (width <= 0) { + width = colFrame->GetWidth(MIN_PRO); + if (width <= 0) { + width = colFrame->GetDesWidth(); + } + } + } + maxWidth += width; if (mTableFrame->GetNumCellsOriginatingInCol(colX) > 0) { maxWidth += spacingX; }