bug 41262 - new table border collapsing code. sr=attinasi, r=alexsavulov.

git-svn-id: svn://10.0.0.236/trunk@114937 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
karnaze%netscape.com
2002-02-19 15:48:28 +00:00
parent f915ef807f
commit 430941b018
67 changed files with 10162 additions and 1484 deletions

View File

@@ -68,11 +68,6 @@ struct nsTableCellReflowState : public nsHTMLReflowState
const nsSize& aAvailableSpace,
nsReflowReason aReason);
nsTableCellReflowState(nsIPresContext* aPresContext,
const nsHTMLReflowState& aParentReflowState,
nsIFrame* aFrame,
const nsSize& aAvailableSpace);
void FixUp(const nsSize& aAvailSpace);
};
@@ -83,16 +78,43 @@ nsTableCellReflowState::nsTableCellReflowState(nsIPresContext* aPresCon
nsReflowReason aReason)
:nsHTMLReflowState(aPresContext, aParentRS, aFrame, aAvailSpace, aReason)
{
FixUp(aAvailSpace);
}
nsTableCellReflowState::nsTableCellReflowState(nsIPresContext* aPresContext,
const nsHTMLReflowState& aParentRS,
nsIFrame* aFrame,
const nsSize& aAvailSpace)
:nsHTMLReflowState(aPresContext, aParentRS, aFrame, aAvailSpace)
void nsTableCellReflowState::FixUp(const nsSize& aAvailSpace)
{
FixUp(aAvailSpace);
// fix the mComputed values during a pass 2 reflow since the cell can be a percentage base
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.width) {
if (NS_UNCONSTRAINEDSIZE != mComputedWidth) {
mComputedWidth = aAvailSpace.width - mComputedBorderPadding.left - mComputedBorderPadding.right;
mComputedWidth = PR_MAX(0, mComputedWidth);
}
if (NS_UNCONSTRAINEDSIZE != mComputedHeight) {
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.height) {
mComputedHeight = aAvailSpace.height - mComputedBorderPadding.top - mComputedBorderPadding.bottom;
mComputedHeight = PR_MAX(0, mComputedHeight);
}
}
}
}
void
nsTableRowFrame::InitChildReflowState(nsIPresContext& aPresContext,
const nsSize& aAvailSize,
PRBool aBorderCollapse,
float aPixelsToTwips,
nsTableCellReflowState& aReflowState)
{
nsMargin collapseBorder;
nsMargin* pCollapseBorder = nsnull;
if (aBorderCollapse) {
// we only reflow cells, so don't need to check frame type
nsBCTableCellFrame* bcCellFrame = (nsBCTableCellFrame*)aReflowState.frame;
if (bcCellFrame) {
pCollapseBorder = bcCellFrame->GetBorderWidth(aPixelsToTwips, collapseBorder);
}
}
aReflowState.Init(&aPresContext, -1, -1, pCollapseBorder);
aReflowState.FixUp(aAvailSize);
}
void
@@ -132,23 +154,6 @@ nsTableRowFrame::SetPctHeight(float aPctValue,
}
}
void nsTableCellReflowState::FixUp(const nsSize& aAvailSpace)
{
// fix the mComputed values during a pass 2 reflow since the cell can be a percentage base
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.width) {
if (NS_UNCONSTRAINEDSIZE != mComputedWidth) {
mComputedWidth = aAvailSpace.width - mComputedBorderPadding.left - mComputedBorderPadding.right;
mComputedWidth = PR_MAX(0, mComputedWidth);
}
if (NS_UNCONSTRAINEDSIZE != mComputedHeight) {
if (NS_UNCONSTRAINEDSIZE != aAvailSpace.height) {
mComputedHeight = aAvailSpace.height - mComputedBorderPadding.top - mComputedBorderPadding.bottom;
mComputedHeight = PR_MAX(0, mComputedHeight);
}
}
}
}
// 'old' is old cached cell's desired size
// 'new' is new cell's size including style constraints
static PRBool
@@ -217,7 +222,7 @@ nsTableRowFrame::SetInitialChildList(nsIPresContext* aPresContext,
kidFrame->GetNextSibling(&kidFrame)) {
nsCOMPtr<nsIAtom> frameType;
kidFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
if (((nsTableCellFrame*)kidFrame)->GetRowSpan() > 1) {
mState |= NS_FRAME_OUTSIDE_CHILDREN;
}
@@ -241,7 +246,7 @@ nsTableRowFrame::AppendFrames(nsIPresContext* aPresContext,
for (nsIFrame* childFrame = aFrameList; childFrame; childFrame->GetNextSibling(&childFrame)) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
// Add the cell to the cell map
tableFrame->AppendCell(*aPresContext, (nsTableCellFrame&)*childFrame, GetRowIndex());
// XXX this could be optimized with some effort
@@ -272,12 +277,13 @@ nsTableRowFrame::InsertFrames(nsIPresContext* aPresContext,
nsTableFrame::GetTableFrame(this, tableFrame);
// gather the new frames (only those which are cells) into an array
nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(aPresContext, this, aPrevFrame, nsLayoutAtoms::tableCellFrame);
nsIAtom* cellFrameType = (tableFrame->IsBorderCollapse()) ? nsLayoutAtoms::bcTableCellFrame : nsLayoutAtoms::tableCellFrame;
nsTableCellFrame* prevCellFrame = (nsTableCellFrame *)nsTableFrame::GetFrameAtOrBefore(aPresContext, this, aPrevFrame, cellFrameType);
nsVoidArray cellChildren;
for (nsIFrame* childFrame = aFrameList; childFrame; childFrame->GetNextSibling(&childFrame)) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
cellChildren.AppendElement(childFrame);
// XXX this could be optimized with some effort
tableFrame->SetNeedStrategyInit(PR_TRUE);
@@ -315,7 +321,7 @@ nsTableRowFrame::RemoveFrame(nsIPresContext* aPresContext,
if (tableFrame) {
nsCOMPtr<nsIAtom> frameType;
aOldFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)aOldFrame;
PRInt32 colIndex;
cellFrame->GetColIndex(colIndex);
@@ -372,7 +378,7 @@ nsTableRowFrame::GetFirstCell()
while (childFrame) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
return (nsTableCellFrame*)childFrame;
}
childFrame->GetNextSibling(&childFrame);
@@ -398,7 +404,7 @@ nsTableRowFrame::DidResize(nsIPresContext* aPresContext,
while (childFrame) {
nsCOMPtr<nsIAtom> frameType;
childFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)childFrame;
nscoord cellHeight = mRect.height + GetHeightOfRowsSpannedBelowFirst(*cellFrame, *tableFrame);
@@ -534,7 +540,7 @@ nsTableRowFrame::CalcHeight(const nsHTMLReflowState& aReflowState)
for (nsIFrame* kidFrame = mFrames.FirstChild(); kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
nsCOMPtr<nsIAtom> frameType;
kidFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nscoord availWidth = ((nsTableCellFrame *)kidFrame)->GetPriorAvailWidth();
nsSize desSize = ((nsTableCellFrame *)kidFrame)->GetDesiredSize();
if ((NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight) && !mPrevInFlow) {
@@ -888,28 +894,29 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
aStatus = NS_FRAME_COMPLETE;
if (!mFrames.FirstChild()) return NS_OK;
nsTableFrame* tableFrame = &aTableFrame;
if (!tableFrame) return NS_ERROR_NULL_POINTER;
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
PRBool borderCollapse = (((nsTableFrame*)aTableFrame.GetFirstInFlow())->IsBorderCollapse());
nsIFrame* tablePrevInFlow;
tableFrame->GetPrevInFlow(&tablePrevInFlow);
aTableFrame.GetPrevInFlow(&tablePrevInFlow);
PRBool isPaginated;
aPresContext->IsPaginated(&isPaginated);
nsresult rv = NS_OK;
nscoord cellSpacingX = tableFrame->GetCellSpacingX();
nscoord cellSpacingX = aTableFrame.GetCellSpacingX();
PRInt32 cellColSpan = 1; // must be defined here so it's set properly for non-cell kids
nsTableIteration dir = (aReflowState.availableWidth == NS_UNCONSTRAINEDSIZE)
? eTableLTR : eTableDIR;
nsTableIterator iter(aPresContext, *this, dir);
// remember the col index of the previous cell to handle rowspans into this row
PRInt32 firstPrevColIndex = (iter.IsLeftToRight()) ? -1 : tableFrame->GetColCount();
PRInt32 firstPrevColIndex = (iter.IsLeftToRight()) ? -1 : aTableFrame.GetColCount();
PRInt32 prevColIndex = firstPrevColIndex;
nscoord x = 0; // running total of children x offset
nsTableFrame* tableFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
PRBool isAutoLayout = tableFrame->IsAutoLayout();
nsTableFrame* tableFirstInFlow = (nsTableFrame*)aTableFrame.GetFirstInFlow();
PRBool isAutoLayout = aTableFrame.IsAutoLayout();
PRBool needToNotifyTable = PR_TRUE;
nscoord paginatedHeight = 0;
// If the incremental reflow command is a StyleChanged reflow and
@@ -945,7 +952,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
doReflowChild = PR_FALSE;
}
if (aReflowState.mFlags.mSpecialHeightReflow) {
if (!isPaginated && (nsLayoutAtoms::tableCellFrame == frameType.get() &&
if (!isPaginated && (IS_TABLE_CELL(frameType.get()) &&
!((nsTableCellFrame*)kidFrame)->NeedSpecialReflow())) {
kidFrame = iter.Next();
continue;
@@ -954,22 +961,22 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// Reflow the child frame
if (doReflowChild) {
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
if (IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)kidFrame;
PRInt32 cellColIndex;
cellFrame->GetColIndex(cellColIndex);
cellColSpan = tableFrame->GetEffectiveColSpan(*cellFrame);
cellColSpan = aTableFrame.GetEffectiveColSpan(*cellFrame);
x += cellSpacingX;
// If the adjacent cell is in a prior row (because of a rowspan) add in the space
if ((iter.IsLeftToRight() && (prevColIndex != (cellColIndex - 1))) ||
(!iter.IsLeftToRight() && (prevColIndex != cellColIndex + cellColSpan))) {
x += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, *tableFrame,
x += GetSpaceBetween(prevColIndex, cellColIndex, cellColSpan, aTableFrame,
cellSpacingX, iter.IsLeftToRight());
}
// Calculate the available width for the table cell using the known column widths
nscoord availColWidth, availCellWidth;
CalcAvailWidth(*tableFrame, GetComputedWidth(aReflowState, *tableFrame),
CalcAvailWidth(aTableFrame, GetComputedWidth(aReflowState, aTableFrame),
*cellFrame, cellSpacingX, availColWidth, availCellWidth);
if (0 == availColWidth) availColWidth = NS_UNCONSTRAINEDSIZE;
if (0 == availCellWidth) availCellWidth = NS_UNCONSTRAINEDSIZE;
@@ -1032,6 +1039,8 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// Reflow the child
nsTableCellReflowState kidReflowState(aPresContext, aReflowState,
kidFrame, kidAvailSize, reason);
InitChildReflowState(*aPresContext, kidAvailSize, borderCollapse, p2t, kidReflowState);
nsReflowStatus status;
rv = ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState,
x, 0, 0, status);
@@ -1052,7 +1061,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// allow the table to determine if/how the table needs to be rebalanced
if (cellToWatch && needToNotifyTable) {
needToNotifyTable = !tableFrame->CellChangedWidth(*cellFrame, oldMaxWidth, oldMaxElemWidth);
needToNotifyTable = !aTableFrame.CellChangedWidth(*cellFrame, oldMaxWidth, oldMaxElemWidth);
}
// If any of the cells are not complete, then we're not complete
@@ -1081,10 +1090,10 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
// height may have changed, adjust descent to absorb any excess difference
nscoord ascent = cellFrame->GetDesiredAscent();
nscoord descent = desiredSize.height - ascent;
UpdateHeight(desiredSize.height, ascent, descent, tableFrame, cellFrame);
UpdateHeight(desiredSize.height, ascent, descent, &aTableFrame, cellFrame);
}
else {
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan((nsTableCellFrame&)*kidFrame);
PRInt32 rowSpan = aTableFrame.GetEffectiveRowSpan((nsTableCellFrame&)*kidFrame);
if ((1 == rowSpan) && (desiredSize.height > paginatedHeight)) {
paginatedHeight = desiredSize.height;
SetContentHeight(paginatedHeight);
@@ -1102,13 +1111,14 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
else {// it's an unknown frame type, give it a generic reflow and ignore the results
nsTableCellReflowState kidReflowState(aPresContext, aReflowState,
kidFrame, nsSize(0,0), eReflowReason_Resize);
InitChildReflowState(*aPresContext, nsSize(0,0), PR_FALSE, p2t, kidReflowState);
nsHTMLReflowMetrics desiredSize(nsnull);
nsReflowStatus status;
ReflowChild(kidFrame, aPresContext, desiredSize, kidReflowState, 0, 0, 0, status);
kidFrame->DidReflow(aPresContext, nsnull, NS_FRAME_REFLOW_FINISHED);
}
}
else if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
else if (IS_TABLE_CELL(frameType.get())) {
// we need to account for the cell's width even if it isn't reflowed
nsRect rect;
kidFrame->GetRect(rect);
@@ -1244,7 +1254,10 @@ nsTableRowFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
// update its maximum width.
nsHTMLReflowMetrics cellMet(&kidMaxElementSize, isAutoLayout ?
NS_REFLOW_CALC_MAX_WIDTH : 0);
nsTableCellReflowState kidRS(aPresContext, aReflowState, aNextFrame, cellAvailSize);
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
nsTableCellReflowState kidRS(aPresContext, aReflowState, aNextFrame, cellAvailSize,
aReflowState.reason);
InitChildReflowState(*aPresContext, cellAvailSize, aTableFrame.IsBorderCollapse(), p2t, kidRS);
// Remember the current desired size, we'll need it later
nscoord oldCellMinWidth = cellFrame->GetPass1MaxElementWidth();
@@ -1492,13 +1505,20 @@ nsTableRowFrame::ReflowCellFrame(nsIPresContext* aPresContext,
nscoord aAvailableHeight,
nsReflowStatus& aStatus)
{
nsTableFrame* tableFrame = nsnull;
nsTableFrame::GetTableFrame(this, tableFrame); if (!tableFrame) ABORT1(0);
// Reflow the cell frame with the specified height. Use the existing width
nsSize cellSize;
aCellFrame->GetSize(cellSize);
nsSize availSize(cellSize.width, aAvailableHeight);
PRBool borderCollapse = ((nsTableFrame*)tableFrame->GetFirstInFlow())->IsBorderCollapse();
GET_PIXELS_TO_TWIPS(aPresContext, p2t);
nsTableCellReflowState cellReflowState(aPresContext, aReflowState, aCellFrame, availSize,
eReflowReason_Resize);
InitChildReflowState(*aPresContext, availSize, borderCollapse, p2t, cellReflowState);
nsHTMLReflowMetrics desiredSize(nsnull);
ReflowChild(aCellFrame, aPresContext, desiredSize, cellReflowState,
@@ -1534,7 +1554,7 @@ nsTableRowFrame::InsertCellFrame(nsTableCellFrame* aFrame,
for (nsIFrame* child = mFrames.FirstChild(); child; child->GetNextSibling(&child)) {
nsCOMPtr<nsIAtom> frameType;
child->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::tableCellFrame != frameType.get()) {
if (!IS_TABLE_CELL(frameType.get())) {
nsTableCellFrame* cellFrame = (nsTableCellFrame*)child;
PRInt32 colIndex;
cellFrame->GetColIndex(colIndex);