beginnings of collapsing borders now implemented. Doesn't work for spanning cells yet,

and doesn't measure borders where the width changes along a shared edge yet.
This commit is contained in:
buster%netscape.com 1998-12-21 06:38:18 +00:00
parent c869f97f4c
commit d1779f0342
12 changed files with 914 additions and 94 deletions

View File

@ -48,6 +48,54 @@ static const PRBool gsDebug = PR_FALSE;
static const PRBool gsDebugNT = PR_FALSE;
#endif
void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
{
NS_PRECONDITION(0<=aColIndex, "bad col index arg");
mColIndex = aColIndex;
nsTableFrame* tableFrame=nsnull; // I should be checking my own style context, but border-collapse isn't inheriting correctly
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
const nsStyleTable* tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, ((const nsStyleStruct *&)tableStyle));
if (NS_STYLE_BORDER_COLLAPSE==tableStyle->mBorderCollapse)
{
PRInt32 rowspan = GetRowSpan();
PRInt32 i;
for (i=0; i<rowspan; i++)
{
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_LEFT].AppendElement(borderToAdd);
borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_RIGHT].AppendElement(borderToAdd);
}
PRInt32 colspan = GetColSpan();
for (i=0; i<colspan; i++)
{
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_TOP].AppendElement(borderToAdd);
borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_BOTTOM].AppendElement(borderToAdd);
}
}
}
}
void nsTableCellFrame::SetBorderEdgeLength(PRUint8 aSide, PRInt32 aIndex, nscoord aLength)
{
if ((NS_SIDE_LEFT==aSide) || (NS_SIDE_RIGHT==aSide))
{
PRInt32 rowIndex = aIndex-GetRowIndex();
nsBorderEdge *border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(rowIndex));
border->mLength = aLength;
}
else {
NS_ASSERTION(PR_FALSE, "bad arg aSide passed to SetBorderEdgeLength");
}
}
NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
@ -65,6 +113,8 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
NS_ASSERTION(nsnull!=myColor, "bad style color");
NS_ASSERTION(nsnull!=mySpacing, "bad style spacing");
const nsStyleTable* cellTableStyle;
GetStyleData(eStyleStruct_Table, ((const nsStyleStruct *&)cellTableStyle));
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
@ -74,15 +124,29 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
PRBool renderBorder = PR_TRUE;
if (PR_TRUE==GetContentEmpty())
{
const nsStyleTable* cellTableStyle;
GetStyleData(eStyleStruct_Table, ((const nsStyleStruct *&)cellTableStyle));
if (NS_STYLE_TABLE_EMPTY_CELLS_HIDE==cellTableStyle->mEmptyCells)
renderBorder=PR_FALSE;
}
if (PR_TRUE==renderBorder)
{
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *mySpacing, 0);
PRIntn skipSides = GetSkipSides();
nsTableFrame* tableFrame=nsnull; // I should be checking my own style context, but border-collapse isn't inheriting correctly
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
const nsStyleTable* tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, ((const nsStyleStruct *&)tableStyle));
if (NS_STYLE_BORDER_SEPARATE==tableStyle->mBorderCollapse)
{
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *mySpacing, skipSides);
}
else
{
nsCSSRendering::PaintBorderEdges(aPresContext, aRenderingContext, this,
aDirtyRect, rect, &mBorderEdges, skipSides);
}
}
}
}
}
@ -110,6 +174,54 @@ nsTableCellFrame::GetSkipSides() const
return skip;
}
void nsTableCellFrame::SetBorderEdge(PRUint8 aSide,
PRInt32 aRowIndex,
PRInt32 aColIndex,
nsBorderEdge *aBorder)
{
nsBorderEdge *border = nsnull;
switch (aSide)
{
case NS_SIDE_TOP:
{
PRInt32 colIndex = aColIndex-GetColIndex();
border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(colIndex));
mBorderEdges.mMaxBorderWidth.top = PR_MAX(aBorder->mWidth, mBorderEdges.mMaxBorderWidth.top);
break;
}
case NS_SIDE_BOTTOM:
{
PRInt32 colIndex = aColIndex-GetColIndex();
border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(colIndex));
mBorderEdges.mMaxBorderWidth.bottom = PR_MAX(aBorder->mWidth, mBorderEdges.mMaxBorderWidth.bottom);
break;
}
case NS_SIDE_LEFT:
{
PRInt32 rowIndex = aRowIndex-GetRowIndex();
border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(rowIndex));
mBorderEdges.mMaxBorderWidth.left = PR_MAX(aBorder->mWidth, mBorderEdges.mMaxBorderWidth.left);
break;
}
case NS_SIDE_RIGHT:
{
PRInt32 rowIndex = aRowIndex-GetRowIndex();
border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(rowIndex));
mBorderEdges.mMaxBorderWidth.right = PR_MAX(aBorder->mWidth, mBorderEdges.mMaxBorderWidth.right);
break;
}
}
if (nsnull!=border) {
*border=*aBorder;
}
else {
NS_ASSERTION(PR_FALSE, "bad border edge state");
}
}
/**
*
* Align the cell's child frame within the cell

View File

@ -21,6 +21,7 @@
#include "nscore.h"
#include "nsHTMLContainerFrame.h"
#include "nsTableRowFrame.h" // need to actually include this here to inline GetRowIndex
#include "nsIStyleContext.h"
struct nsStyleSpacing;
class nsTableFrame;
@ -40,6 +41,16 @@ public:
void InitCellFrame(PRInt32 aColIndex);
void SetBorderEdge(PRUint8 aSide,
PRInt32 aRowIndex,
PRInt32 aColIndex,
nsBorderEdge *border);
void SetBorderEdgeLength(PRUint8 aSide,
PRInt32 aIndex,
nscoord aLength);
/** instantiate a new instance of nsTableCellFrame.
* @param aResult the new object is returned in this out-param
*
@ -193,15 +204,11 @@ protected:
//XXX: mIsContentEmpty should get yanked in favor of using free a bit on the frame base class
// the FrameState slot (mState; GetFrameState/SetFrameState)
nsBorderEdges mBorderEdges; // one list of border segments for each side of the table frame
// used only for the collapsing border model
};
inline void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
{
NS_PRECONDITION(0<=aColIndex, "bad col index arg");
mColIndex = aColIndex;
}
inline PRInt32 nsTableCellFrame::GetRowIndex()
{
nsTableRowFrame * row;

View File

@ -1177,18 +1177,15 @@ void nsTableFrame::AppendLayoutData(nsVoidArray* aList, nsTableCellFrame* aTable
}
}
/* compute all the collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void nsTableFrame::ComputeCollapsingBorders(PRInt32 aStartRowIndex,
PRInt32 aEndRowIndex)
void nsTableFrame::SetBorderEdgeLength(PRUint8 aSide, PRInt32 aIndex, nscoord aLength)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
PRInt32 colCount = mCellMap->GetColCount();
PRInt32 rowCount = mCellMap->GetRowCount();
if (aStartRowIndex>=rowCount)
{
NS_ASSERTION(PR_FALSE, "aStartRowIndex>=rowCount in ComputeCollapsingBorders");
return; // we don't have the requested row yet
}
nsBorderEdge *border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(aIndex));
border->mLength = aLength;
}
// For every row between aStartRowIndex and aEndRowIndex (or the end of the table),
// walk across every edge and compute the border at that edge.
@ -1197,20 +1194,26 @@ void nsTableFrame::ComputeCollapsingBorders(PRInt32 aStartRowIndex,
// Distribute half the computed border to the appropriate adjacent objects
// (always a cell frame or the table frame.) In the case of odd width,
// the object on the right/bottom gets the extra portion
/* compute the horizontal collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void nsTableFrame::ComputeHorizontalCollapsingBorders(PRInt32 aStartRowIndex,
PRInt32 aEndRowIndex)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
PRInt32 colCount = mCellMap->GetColCount();
PRInt32 rowCount = mCellMap->GetRowCount();
if (aStartRowIndex>=rowCount)
{
NS_ASSERTION(PR_FALSE, "aStartRowIndex>=rowCount in ComputeHorizontalCollapsingBorders");
return; // we don't have the requested row yet
}
PRInt32 rowIndex = aStartRowIndex;
for ( ; rowIndex<rowCount && rowIndex <=aEndRowIndex; rowIndex++)
{
PRInt32 colIndex=0;
for ( ; colIndex<colCount; colIndex++)
{
// compute vertical edges
if (0==colIndex)
{ // table is left neighbor
ComputeLeftBorderForEdgeAt(rowIndex, colIndex);
}
ComputeRightBorderForEdgeAt(rowIndex, colIndex);
// compute horizontal edges
if (0==rowIndex)
{ // table is top neighbor
ComputeTopBorderForEdgeAt(rowIndex, colIndex);
@ -1220,6 +1223,34 @@ void nsTableFrame::ComputeCollapsingBorders(PRInt32 aStartRowIndex,
}
}
/* compute the vertical collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void nsTableFrame::ComputeVerticalCollapsingBorders(PRInt32 aStartRowIndex,
PRInt32 aEndRowIndex)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
PRInt32 colCount = mCellMap->GetColCount();
PRInt32 rowCount = mCellMap->GetRowCount();
if (aStartRowIndex>=rowCount)
{
NS_ASSERTION(PR_FALSE, "aStartRowIndex>=rowCount in ComputeVerticalCollapsingBorders");
return; // we don't have the requested row yet
}
PRInt32 rowIndex = aStartRowIndex;
for ( ; rowIndex<rowCount && rowIndex <=aEndRowIndex; rowIndex++)
{
PRInt32 colIndex=0;
for ( ; colIndex<colCount; colIndex++)
{
if (0==colIndex)
{ // table is left neighbor
ComputeLeftBorderForEdgeAt(rowIndex, colIndex);
}
ComputeRightBorderForEdgeAt(rowIndex, colIndex);
}
}
}
void nsTableFrame::ComputeLeftBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
@ -1252,10 +1283,12 @@ void nsTableFrame::ComputeLeftBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColInd
// 4. rowgroup
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(aRowIndex, aColIndex);
// XXX: some decision needs to be made about row-spanning cell
nsRect rowRect(0,0,0,0);
if (nsnull!=cellFrame)
{
nsIFrame *rowFrame;
cellFrame->GetContentParent(rowFrame);
rowFrame->GetRect(rowRect);
nsIFrame *rowGroupFrame;
rowFrame->GetContentParent(rowGroupFrame);
rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
@ -1271,7 +1304,14 @@ void nsTableFrame::ComputeLeftBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColInd
// now give half the computed border to the table segment, and half to the cell
// XXX give half to the cell
border->mWidth = (border->mWidth)/2;
border->mLength = rowRect.height;
mBorderEdges.mMaxBorderWidth.left = PR_MAX(border->mWidth, mBorderEdges.mMaxBorderWidth.left);
printf("table computed left border width=%d length=%d, color=%d style=%d maxWidth=%d \n",
border->mWidth, border->mLength, border->mColor, border->mStyle, mBorderEdges.mMaxBorderWidth.left);
if (nsnull!=cellFrame)
{
cellFrame->SetBorderEdge(NS_SIDE_LEFT, aRowIndex, aColIndex, border); // set the left edge of the cell frame
}
}
void nsTableFrame::ComputeRightBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex)
@ -1286,7 +1326,7 @@ void nsTableFrame::ComputeRightBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIn
numSegments++;
}
// "border" is the border segment we are going to set
nsBorderEdge *border = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(aRowIndex));
nsBorderEdge border;
// collect all the incident frames and compute the dominant border
nsVoidArray styles;
@ -1339,10 +1379,12 @@ void nsTableFrame::ComputeRightBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIn
// 4. rowgroup
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(aRowIndex, aColIndex);
// XXX: some decision needs to be made about row-spanning cell
nsRect rowRect(0,0,0,0);
if (nsnull!=cellFrame)
{
nsIFrame *rowFrame;
cellFrame->GetContentParent(rowFrame);
rowFrame->GetRect(rowRect);
nsIFrame *rowGroupFrame;
rowFrame->GetContentParent(rowGroupFrame);
rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
@ -1360,29 +1402,196 @@ void nsTableFrame::ComputeRightBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIn
rightNeighborFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
}
ComputeCollapsedBorderSegment(NS_SIDE_RIGHT, &styles, *border, PRBool(nsnull!=rightNeighborFrame));
// now give half the computed border to the table segment, and half to the cell
ComputeCollapsedBorderSegment(NS_SIDE_RIGHT, &styles, border, PRBool(nsnull!=rightNeighborFrame));
// now give half the computed border to each of the two neighbors
// (the 2 cells, or the cell and the table)
// XXX give half to the cell
border->mWidth = (border->mWidth)/2; //XXX: rounding
border.mWidth = (border.mWidth)/2; //XXX: rounding
border.mLength = rowRect.height;
if (nsnull==rightNeighborFrame)
{
nsBorderEdge * tableBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(aRowIndex));
*tableBorder = border;
mBorderEdges.mMaxBorderWidth.right = PR_MAX(border.mWidth, mBorderEdges.mMaxBorderWidth.right);
}
else
rightNeighborFrame->SetBorderEdge(NS_SIDE_LEFT, aRowIndex, aColIndex, &border);
if (nsnull!=cellFrame)
{
cellFrame->SetBorderEdge(NS_SIDE_RIGHT, aRowIndex, aColIndex, &border);
}
printf("table computed right border width=%d length=%d, color=%d style=%d maxWidth=%d \n",
border.mWidth, border.mLength, border.mColor, border.mStyle, mBorderEdges.mMaxBorderWidth.right);
}
void nsTableFrame::ComputeTopBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
PRInt32 numSegments = mBorderEdges.mEdges[NS_SIDE_TOP].Count();
while (numSegments<=aColIndex)
{
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_TOP].AppendElement(borderToAdd);
numSegments++;
}
// "border" is the border segment we are going to set
nsBorderEdge *border = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_TOP].ElementAt(aColIndex));
// collect all the incident frames and compute the dominant border
nsVoidArray styles;
// styles are added to the array in the order least dominant -> most dominant
// 1. table
const nsStyleSpacing *spacing;
GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 2. colgroup
nsTableColFrame *colFrame = mCellMap->GetColumnFrame(aColIndex);
nsIFrame *colGroupFrame;
colFrame->GetContentParent(colGroupFrame);
colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 3. col
colFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 4. rowgroup
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(aRowIndex, aColIndex);
// XXX: some decision needs to be made about row-spanning cell
if (nsnull!=cellFrame)
{
nsIFrame *rowFrame;
cellFrame->GetContentParent(rowFrame);
nsIFrame *rowGroupFrame;
rowFrame->GetContentParent(rowGroupFrame);
rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 5. row
rowFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 6. cell (need to do something smart for rowspanner with row frame)
cellFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
}
ComputeCollapsedBorderSegment(NS_SIDE_TOP, &styles, *border, PR_FALSE);
// now give half the computed border to the table segment, and half to the cell
border->mWidth = (border->mWidth)/2;
border->mLength = GetColumnWidth(aColIndex);
mBorderEdges.mMaxBorderWidth.top = PR_MAX(border->mWidth, mBorderEdges.mMaxBorderWidth.top);
if (nsnull!=cellFrame)
{
cellFrame->SetBorderEdge(NS_SIDE_TOP, aRowIndex, aColIndex, border); // set the top edge of the cell frame
}
printf("table computed top border width=%d length=%d, color=%d style=%d maxWidth=%d \n",
border->mWidth, border->mLength, border->mColor, border->mStyle, mBorderEdges.mMaxBorderWidth.top);
}
void nsTableFrame::ComputeBottomBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
PRInt32 rowCount = mCellMap->GetRowCount();
if ((rowCount-1)==aRowIndex)
{
}
else
{
}
PRInt32 numSegments = mBorderEdges.mEdges[NS_SIDE_BOTTOM].Count();
while (numSegments<=aColIndex)
{
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_BOTTOM].AppendElement(borderToAdd);
numSegments++;
}
// "border" is the border segment we are going to set
nsBorderEdge border;
// collect all the incident frames and compute the dominant border
nsVoidArray styles;
// styles are added to the array in the order least dominant -> most dominant
// 1. table, only if this cell is in the bottom-most row and no colspanning cell is
// beneath it. Otherwise, we remember what cell is the bottom neighbor
nsTableCellFrame *bottomNeighborFrame=nsnull;
if ((rowCount-1)!=aRowIndex)
{
PRInt32 rowIndex = aRowIndex+1;
for ( ; rowIndex<rowCount; rowIndex++)
{
CellData *cd = mCellMap->GetCellAt(rowIndex, aColIndex);
if (cd != nsnull)
{ // there's really a cell at (rowIndex, aColIndex)
if (nsnull==cd->mCell)
{ // the cell at (rowIndex, aColIndex) is the result of a span
nsTableCellFrame *cell = cd->mRealCell->mCell;
NS_ASSERTION(nsnull!=cell, "bad cell map state, missing real cell");
const PRInt32 realColIndex = cell->GetColIndex ();
if (realColIndex!=aColIndex)
{ // the span is caused by a colspan
bottomNeighborFrame = cd->mRealCell->mCell;
break;
}
}
else
{
bottomNeighborFrame = cd->mCell;
break;
}
}
}
}
const nsStyleSpacing *spacing;
if (nsnull==bottomNeighborFrame)
{ // if bottomNeighborFrame is null, our bottom neighbor is the table
GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
}
// 2. colgroup // XXX: need to deterine if we're on a colgroup boundary
nsTableColFrame *colFrame = mCellMap->GetColumnFrame(aColIndex);
nsIFrame *colGroupFrame;
colFrame->GetContentParent(colGroupFrame);
colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 3. col
colFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 4. rowgroup // XXX: use rowgroup only if we're on a table edge
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(aRowIndex, aColIndex);
// XXX: some decision needs to be made about col-spanning cell
nsRect rowRect(0,0,0,0);
if (nsnull!=cellFrame)
{
nsIFrame *rowFrame;
cellFrame->GetContentParent(rowFrame);
rowFrame->GetRect(rowRect);
nsIFrame *rowGroupFrame;
rowFrame->GetContentParent(rowGroupFrame);
rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 5. row
rowFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 6. cell (need to do something smart for rowspanner with row frame)
cellFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
}
// 7. top edge of bottomNeighborCell, if there is one
if (nsnull!=bottomNeighborFrame)
{
bottomNeighborFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
}
ComputeCollapsedBorderSegment(NS_SIDE_BOTTOM, &styles, border, PRBool(nsnull!=bottomNeighborFrame));
// now give half the computed border to each of the two neighbors
// (the 2 cells, or the cell and the table)
// XXX give half to the cell
border.mWidth = (border.mWidth)/2; //XXX: rounding
border.mLength = GetColumnWidth(aColIndex);
if (nsnull==bottomNeighborFrame)
{
nsBorderEdge * tableBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_BOTTOM].ElementAt(aColIndex));
*tableBorder = border;
mBorderEdges.mMaxBorderWidth.bottom = PR_MAX(border.mWidth, mBorderEdges.mMaxBorderWidth.bottom);
}
else
bottomNeighborFrame->SetBorderEdge(NS_SIDE_TOP, aRowIndex, aColIndex, &border);
if (nsnull!=cellFrame)
{
cellFrame->SetBorderEdge(NS_SIDE_BOTTOM, aRowIndex, aColIndex, &border);
}
printf("table computed bottom border width=%d length=%d, color=%d style=%d maxWidth=%d \n",
border.mWidth, border.mLength, border.mColor, border.mStyle, mBorderEdges.mMaxBorderWidth.bottom);
}
nscoord nsTableFrame::GetWidthForSide(const nsMargin &aBorder, PRUint8 aSide)
@ -1633,7 +1842,7 @@ void nsTableFrame::RecalcLayoutData()
const nsStyleTable *tableStyle=nsnull;
GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
if (NS_STYLE_BORDER_COLLAPSE==tableStyle->mBorderCollapse)
ComputeCollapsingBorders(0, rowCount-1);
ComputeVerticalCollapsingBorders(0, rowCount-1);
//XXX need to determine how much of what follows is really necessary
// it does collapsing margins between table elements
@ -1850,11 +2059,10 @@ NS_METHOD nsTableFrame::Paint(nsIPresContext& aPresContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
// table paint code is concerned primarily with borders and bg color
if (eFramePaintLayer_Underlay == aWhichLayer) {
// table paint code is concerned primarily with borders and bg color
const nsStyleDisplay* disp =
(const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
if (disp->mVisible) {
const nsStyleSpacing* spacing =
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
@ -1874,6 +2082,8 @@ NS_METHOD nsTableFrame::Paint(nsIPresContext& aPresContext,
}
else
{
nsCSSRendering::PaintBorderEdges(aPresContext, aRenderingContext, this,
aDirtyRect, rect, &mBorderEdges, skipSides);
}
}
}
@ -3215,8 +3425,11 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
const nsStyleSpacing* spacing =
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
const nsStyleTable* tableStyle =
(const nsStyleTable*)mStyleContext->GetStyleData(eStyleStruct_Table);
nsMargin borderPadding;
spacing->CalcBorderPaddingFor(this, borderPadding);
spacing->CalcBorderPaddingFor(this, borderPadding); // COLLAPSING BORDERS
// need to figure out the overall table width constraint
// default case, get 100% of available space
@ -3252,6 +3465,10 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
}
mTableLayoutStrategy->BalanceColumnWidths(mStyleContext, aReflowState, maxWidth);
mColumnWidthsSet=PR_TRUE;
if (NS_STYLE_BORDER_COLLAPSE==tableStyle->mBorderCollapse)
{
ComputeHorizontalCollapsingBorders(0, mCellMap->GetRowCount()-1);
}
}
/**
@ -3355,6 +3572,8 @@ nscoord nsTableFrame::ComputeDesiredHeight(nsIPresContext& aPresContext,
if (eStyleUnit_Auto == tablePosition->mHeight.GetUnit())
return result; // auto width tables are sized by the row heights, which we already have
const nsStyleTable* tableStyle;
GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
nscoord tableSpecifiedHeight=-1;
if (eStyleUnit_Coord == tablePosition->mHeight.GetUnit())
tableSpecifiedHeight = tablePosition->mHeight.GetCoordValue();
@ -3422,6 +3641,15 @@ nscoord nsTableFrame::ComputeDesiredHeight(nsIPresContext& aPresContext,
nscoord excessForRow = NSToCoordRound((float)excess*percent);
nsRect newRowRect(rowRect.x, y, rowRect.width, excessForRow+rowRect.height);
rowFrame->SetRect(newRowRect);
if (NS_STYLE_BORDER_COLLAPSE==tableStyle->mBorderCollapse)
{
nsBorderEdge *border = (nsBorderEdge *)
(mBorderEdges.mEdges[NS_SIDE_LEFT].ElementAt(((nsTableRowFrame*)rowFrame)->GetRowIndex()));
border->mLength=newRowRect.height;
border = (nsBorderEdge *)
(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(((nsTableRowFrame*)rowFrame)->GetRowIndex()));
border->mLength=newRowRect.height;
}
// resize cells, too
((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState);
// better if this were part of an overloaded row::SetRect

View File

@ -210,12 +210,21 @@ public:
/** Calculate Layout Information */
void AppendLayoutData(nsVoidArray* aList, nsTableCellFrame* aTableCell);
/* compute all the collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void ComputeCollapsingBorders(PRInt32 aStartRowIndex, PRInt32 aEndRowIndex);
/** compute the left and right collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void ComputeVerticalCollapsingBorders(PRInt32 aStartRowIndex, PRInt32 aEndRowIndex);
/** compute the top and bottom collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void ComputeHorizontalCollapsingBorders(PRInt32 aStartRowIndex, PRInt32 aEndRowIndex);
void ComputeLeftBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex);
void ComputeRightBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex);
void ComputeTopBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex);
void ComputeBottomBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex);
/** at the time we initially compute collapsing borders, we don't yet have the
* column widths. So we set them as a post-process of the column balancing algorithm.
*/
void SetCollapsingBorderHorizontalEdgeLengths();
PRUint8 GetOpposingEdge(PRUint8 aEdge);
@ -223,6 +232,8 @@ public:
PRUint8 CompareBorderStyles(PRUint8 aStyle1, PRUint8 aStyle2);
void SetBorderEdgeLength(PRUint8 aSide, PRInt32 aIndex, nscoord aLength);
void ComputeCollapsedBorderSegment(PRUint8 aSide,
nsVoidArray * aStyles,
nsBorderEdge& aBorder,

View File

@ -181,6 +181,8 @@ nsTableRowFrame::DidResize(nsIPresContext& aPresContext,
nsIFrame *cellFrame = mFirstChild;
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
const nsStyleTable* tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
while (nsnull != cellFrame)
{
const nsStyleDisplay *kidDisplay;
@ -209,6 +211,16 @@ nsTableRowFrame::DidResize(nsIPresContext& aPresContext,
//XXX nsReflowStatus status;
//ReflowChild(cellFrame, aPresContext, desiredSize, kidReflowState, status);
((nsTableCellFrame *)cellFrame)->VerticallyAlignChild();
/* if we're collapsing borders, notify the cell that the border edge length has changed */
if (NS_STYLE_BORDER_COLLAPSE==tableStyle->mBorderCollapse)
{
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_LEFT,
GetRowIndex(),
cellHeight);
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_RIGHT,
GetRowIndex(),
cellHeight);
}
}
}
else

View File

@ -331,6 +331,9 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC
kidFrame = mFirstChild;
else
kidFrame = aStartFrame;
PRUint8 borderStyle = aReflowState.tableFrame->GetBorderCollapseStyle();
for ( ; nsnull != kidFrame; )
{
nsSize kidAvailSize(aReflowState.availSize);
@ -406,6 +409,43 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC
aReflowState.prevMaxPosBottomMargin = bottomMargin;
}
/* if the table has collapsing borders, we need to reset the length of the shared vertical borders
* for the table and the cells that overlap this row
*/
if ((eReflowReason_Initial != aReflowState.reflowState.reason) && (NS_STYLE_BORDER_COLLAPSE==borderStyle))
{
const nsStyleDisplay *childDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
PRInt32 rowIndex = ((nsTableRowFrame*)kidFrame)->GetRowIndex();
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
nsIFrame *cellFrame=nsnull;
kidFrame->FirstChild(nsnull, cellFrame);
while (nsnull!=cellFrame)
{
const nsStyleDisplay *cellDisplay;
cellFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)cellDisplay));
if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay)
{
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
}
cellFrame->GetNextSibling(cellFrame);
}
}
}
// Remember where we just were in case we end up pushing children
prevKidFrame = kidFrame;

View File

@ -48,6 +48,54 @@ static const PRBool gsDebug = PR_FALSE;
static const PRBool gsDebugNT = PR_FALSE;
#endif
void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
{
NS_PRECONDITION(0<=aColIndex, "bad col index arg");
mColIndex = aColIndex;
nsTableFrame* tableFrame=nsnull; // I should be checking my own style context, but border-collapse isn't inheriting correctly
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
const nsStyleTable* tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, ((const nsStyleStruct *&)tableStyle));
if (NS_STYLE_BORDER_COLLAPSE==tableStyle->mBorderCollapse)
{
PRInt32 rowspan = GetRowSpan();
PRInt32 i;
for (i=0; i<rowspan; i++)
{
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_LEFT].AppendElement(borderToAdd);
borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_RIGHT].AppendElement(borderToAdd);
}
PRInt32 colspan = GetColSpan();
for (i=0; i<colspan; i++)
{
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_TOP].AppendElement(borderToAdd);
borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_BOTTOM].AppendElement(borderToAdd);
}
}
}
}
void nsTableCellFrame::SetBorderEdgeLength(PRUint8 aSide, PRInt32 aIndex, nscoord aLength)
{
if ((NS_SIDE_LEFT==aSide) || (NS_SIDE_RIGHT==aSide))
{
PRInt32 rowIndex = aIndex-GetRowIndex();
nsBorderEdge *border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(rowIndex));
border->mLength = aLength;
}
else {
NS_ASSERTION(PR_FALSE, "bad arg aSide passed to SetBorderEdgeLength");
}
}
NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
@ -65,6 +113,8 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
NS_ASSERTION(nsnull!=myColor, "bad style color");
NS_ASSERTION(nsnull!=mySpacing, "bad style spacing");
const nsStyleTable* cellTableStyle;
GetStyleData(eStyleStruct_Table, ((const nsStyleStruct *&)cellTableStyle));
nsRect rect(0, 0, mRect.width, mRect.height);
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
@ -74,15 +124,29 @@ NS_METHOD nsTableCellFrame::Paint(nsIPresContext& aPresContext,
PRBool renderBorder = PR_TRUE;
if (PR_TRUE==GetContentEmpty())
{
const nsStyleTable* cellTableStyle;
GetStyleData(eStyleStruct_Table, ((const nsStyleStruct *&)cellTableStyle));
if (NS_STYLE_TABLE_EMPTY_CELLS_HIDE==cellTableStyle->mEmptyCells)
renderBorder=PR_FALSE;
}
if (PR_TRUE==renderBorder)
{
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *mySpacing, 0);
PRIntn skipSides = GetSkipSides();
nsTableFrame* tableFrame=nsnull; // I should be checking my own style context, but border-collapse isn't inheriting correctly
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
if ((NS_SUCCEEDED(rv)) && (nsnull!=tableFrame))
{
const nsStyleTable* tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, ((const nsStyleStruct *&)tableStyle));
if (NS_STYLE_BORDER_SEPARATE==tableStyle->mBorderCollapse)
{
nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this,
aDirtyRect, rect, *mySpacing, skipSides);
}
else
{
nsCSSRendering::PaintBorderEdges(aPresContext, aRenderingContext, this,
aDirtyRect, rect, &mBorderEdges, skipSides);
}
}
}
}
}
@ -110,6 +174,54 @@ nsTableCellFrame::GetSkipSides() const
return skip;
}
void nsTableCellFrame::SetBorderEdge(PRUint8 aSide,
PRInt32 aRowIndex,
PRInt32 aColIndex,
nsBorderEdge *aBorder)
{
nsBorderEdge *border = nsnull;
switch (aSide)
{
case NS_SIDE_TOP:
{
PRInt32 colIndex = aColIndex-GetColIndex();
border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(colIndex));
mBorderEdges.mMaxBorderWidth.top = PR_MAX(aBorder->mWidth, mBorderEdges.mMaxBorderWidth.top);
break;
}
case NS_SIDE_BOTTOM:
{
PRInt32 colIndex = aColIndex-GetColIndex();
border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(colIndex));
mBorderEdges.mMaxBorderWidth.bottom = PR_MAX(aBorder->mWidth, mBorderEdges.mMaxBorderWidth.bottom);
break;
}
case NS_SIDE_LEFT:
{
PRInt32 rowIndex = aRowIndex-GetRowIndex();
border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(rowIndex));
mBorderEdges.mMaxBorderWidth.left = PR_MAX(aBorder->mWidth, mBorderEdges.mMaxBorderWidth.left);
break;
}
case NS_SIDE_RIGHT:
{
PRInt32 rowIndex = aRowIndex-GetRowIndex();
border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(rowIndex));
mBorderEdges.mMaxBorderWidth.right = PR_MAX(aBorder->mWidth, mBorderEdges.mMaxBorderWidth.right);
break;
}
}
if (nsnull!=border) {
*border=*aBorder;
}
else {
NS_ASSERTION(PR_FALSE, "bad border edge state");
}
}
/**
*
* Align the cell's child frame within the cell

View File

@ -21,6 +21,7 @@
#include "nscore.h"
#include "nsHTMLContainerFrame.h"
#include "nsTableRowFrame.h" // need to actually include this here to inline GetRowIndex
#include "nsIStyleContext.h"
struct nsStyleSpacing;
class nsTableFrame;
@ -40,6 +41,16 @@ public:
void InitCellFrame(PRInt32 aColIndex);
void SetBorderEdge(PRUint8 aSide,
PRInt32 aRowIndex,
PRInt32 aColIndex,
nsBorderEdge *border);
void SetBorderEdgeLength(PRUint8 aSide,
PRInt32 aIndex,
nscoord aLength);
/** instantiate a new instance of nsTableCellFrame.
* @param aResult the new object is returned in this out-param
*
@ -193,15 +204,11 @@ protected:
//XXX: mIsContentEmpty should get yanked in favor of using free a bit on the frame base class
// the FrameState slot (mState; GetFrameState/SetFrameState)
nsBorderEdges mBorderEdges; // one list of border segments for each side of the table frame
// used only for the collapsing border model
};
inline void nsTableCellFrame::InitCellFrame(PRInt32 aColIndex)
{
NS_PRECONDITION(0<=aColIndex, "bad col index arg");
mColIndex = aColIndex;
}
inline PRInt32 nsTableCellFrame::GetRowIndex()
{
nsTableRowFrame * row;

View File

@ -1177,18 +1177,15 @@ void nsTableFrame::AppendLayoutData(nsVoidArray* aList, nsTableCellFrame* aTable
}
}
/* compute all the collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void nsTableFrame::ComputeCollapsingBorders(PRInt32 aStartRowIndex,
PRInt32 aEndRowIndex)
void nsTableFrame::SetBorderEdgeLength(PRUint8 aSide, PRInt32 aIndex, nscoord aLength)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
PRInt32 colCount = mCellMap->GetColCount();
PRInt32 rowCount = mCellMap->GetRowCount();
if (aStartRowIndex>=rowCount)
{
NS_ASSERTION(PR_FALSE, "aStartRowIndex>=rowCount in ComputeCollapsingBorders");
return; // we don't have the requested row yet
}
nsBorderEdge *border = (nsBorderEdge *)(mBorderEdges.mEdges[aSide].ElementAt(aIndex));
border->mLength = aLength;
}
// For every row between aStartRowIndex and aEndRowIndex (or the end of the table),
// walk across every edge and compute the border at that edge.
@ -1197,20 +1194,26 @@ void nsTableFrame::ComputeCollapsingBorders(PRInt32 aStartRowIndex,
// Distribute half the computed border to the appropriate adjacent objects
// (always a cell frame or the table frame.) In the case of odd width,
// the object on the right/bottom gets the extra portion
/* compute the horizontal collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void nsTableFrame::ComputeHorizontalCollapsingBorders(PRInt32 aStartRowIndex,
PRInt32 aEndRowIndex)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
PRInt32 colCount = mCellMap->GetColCount();
PRInt32 rowCount = mCellMap->GetRowCount();
if (aStartRowIndex>=rowCount)
{
NS_ASSERTION(PR_FALSE, "aStartRowIndex>=rowCount in ComputeHorizontalCollapsingBorders");
return; // we don't have the requested row yet
}
PRInt32 rowIndex = aStartRowIndex;
for ( ; rowIndex<rowCount && rowIndex <=aEndRowIndex; rowIndex++)
{
PRInt32 colIndex=0;
for ( ; colIndex<colCount; colIndex++)
{
// compute vertical edges
if (0==colIndex)
{ // table is left neighbor
ComputeLeftBorderForEdgeAt(rowIndex, colIndex);
}
ComputeRightBorderForEdgeAt(rowIndex, colIndex);
// compute horizontal edges
if (0==rowIndex)
{ // table is top neighbor
ComputeTopBorderForEdgeAt(rowIndex, colIndex);
@ -1220,6 +1223,34 @@ void nsTableFrame::ComputeCollapsingBorders(PRInt32 aStartRowIndex,
}
}
/* compute the vertical collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void nsTableFrame::ComputeVerticalCollapsingBorders(PRInt32 aStartRowIndex,
PRInt32 aEndRowIndex)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
PRInt32 colCount = mCellMap->GetColCount();
PRInt32 rowCount = mCellMap->GetRowCount();
if (aStartRowIndex>=rowCount)
{
NS_ASSERTION(PR_FALSE, "aStartRowIndex>=rowCount in ComputeVerticalCollapsingBorders");
return; // we don't have the requested row yet
}
PRInt32 rowIndex = aStartRowIndex;
for ( ; rowIndex<rowCount && rowIndex <=aEndRowIndex; rowIndex++)
{
PRInt32 colIndex=0;
for ( ; colIndex<colCount; colIndex++)
{
if (0==colIndex)
{ // table is left neighbor
ComputeLeftBorderForEdgeAt(rowIndex, colIndex);
}
ComputeRightBorderForEdgeAt(rowIndex, colIndex);
}
}
}
void nsTableFrame::ComputeLeftBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
@ -1252,10 +1283,12 @@ void nsTableFrame::ComputeLeftBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColInd
// 4. rowgroup
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(aRowIndex, aColIndex);
// XXX: some decision needs to be made about row-spanning cell
nsRect rowRect(0,0,0,0);
if (nsnull!=cellFrame)
{
nsIFrame *rowFrame;
cellFrame->GetContentParent(rowFrame);
rowFrame->GetRect(rowRect);
nsIFrame *rowGroupFrame;
rowFrame->GetContentParent(rowGroupFrame);
rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
@ -1271,7 +1304,14 @@ void nsTableFrame::ComputeLeftBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColInd
// now give half the computed border to the table segment, and half to the cell
// XXX give half to the cell
border->mWidth = (border->mWidth)/2;
border->mLength = rowRect.height;
mBorderEdges.mMaxBorderWidth.left = PR_MAX(border->mWidth, mBorderEdges.mMaxBorderWidth.left);
printf("table computed left border width=%d length=%d, color=%d style=%d maxWidth=%d \n",
border->mWidth, border->mLength, border->mColor, border->mStyle, mBorderEdges.mMaxBorderWidth.left);
if (nsnull!=cellFrame)
{
cellFrame->SetBorderEdge(NS_SIDE_LEFT, aRowIndex, aColIndex, border); // set the left edge of the cell frame
}
}
void nsTableFrame::ComputeRightBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex)
@ -1286,7 +1326,7 @@ void nsTableFrame::ComputeRightBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIn
numSegments++;
}
// "border" is the border segment we are going to set
nsBorderEdge *border = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(aRowIndex));
nsBorderEdge border;
// collect all the incident frames and compute the dominant border
nsVoidArray styles;
@ -1339,10 +1379,12 @@ void nsTableFrame::ComputeRightBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIn
// 4. rowgroup
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(aRowIndex, aColIndex);
// XXX: some decision needs to be made about row-spanning cell
nsRect rowRect(0,0,0,0);
if (nsnull!=cellFrame)
{
nsIFrame *rowFrame;
cellFrame->GetContentParent(rowFrame);
rowFrame->GetRect(rowRect);
nsIFrame *rowGroupFrame;
rowFrame->GetContentParent(rowGroupFrame);
rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
@ -1360,29 +1402,196 @@ void nsTableFrame::ComputeRightBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIn
rightNeighborFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
}
ComputeCollapsedBorderSegment(NS_SIDE_RIGHT, &styles, *border, PRBool(nsnull!=rightNeighborFrame));
// now give half the computed border to the table segment, and half to the cell
ComputeCollapsedBorderSegment(NS_SIDE_RIGHT, &styles, border, PRBool(nsnull!=rightNeighborFrame));
// now give half the computed border to each of the two neighbors
// (the 2 cells, or the cell and the table)
// XXX give half to the cell
border->mWidth = (border->mWidth)/2; //XXX: rounding
border.mWidth = (border.mWidth)/2; //XXX: rounding
border.mLength = rowRect.height;
if (nsnull==rightNeighborFrame)
{
nsBorderEdge * tableBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(aRowIndex));
*tableBorder = border;
mBorderEdges.mMaxBorderWidth.right = PR_MAX(border.mWidth, mBorderEdges.mMaxBorderWidth.right);
}
else
rightNeighborFrame->SetBorderEdge(NS_SIDE_LEFT, aRowIndex, aColIndex, &border);
if (nsnull!=cellFrame)
{
cellFrame->SetBorderEdge(NS_SIDE_RIGHT, aRowIndex, aColIndex, &border);
}
printf("table computed right border width=%d length=%d, color=%d style=%d maxWidth=%d \n",
border.mWidth, border.mLength, border.mColor, border.mStyle, mBorderEdges.mMaxBorderWidth.right);
}
void nsTableFrame::ComputeTopBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
PRInt32 numSegments = mBorderEdges.mEdges[NS_SIDE_TOP].Count();
while (numSegments<=aColIndex)
{
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_TOP].AppendElement(borderToAdd);
numSegments++;
}
// "border" is the border segment we are going to set
nsBorderEdge *border = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_TOP].ElementAt(aColIndex));
// collect all the incident frames and compute the dominant border
nsVoidArray styles;
// styles are added to the array in the order least dominant -> most dominant
// 1. table
const nsStyleSpacing *spacing;
GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 2. colgroup
nsTableColFrame *colFrame = mCellMap->GetColumnFrame(aColIndex);
nsIFrame *colGroupFrame;
colFrame->GetContentParent(colGroupFrame);
colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 3. col
colFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 4. rowgroup
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(aRowIndex, aColIndex);
// XXX: some decision needs to be made about row-spanning cell
if (nsnull!=cellFrame)
{
nsIFrame *rowFrame;
cellFrame->GetContentParent(rowFrame);
nsIFrame *rowGroupFrame;
rowFrame->GetContentParent(rowGroupFrame);
rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 5. row
rowFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 6. cell (need to do something smart for rowspanner with row frame)
cellFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
}
ComputeCollapsedBorderSegment(NS_SIDE_TOP, &styles, *border, PR_FALSE);
// now give half the computed border to the table segment, and half to the cell
border->mWidth = (border->mWidth)/2;
border->mLength = GetColumnWidth(aColIndex);
mBorderEdges.mMaxBorderWidth.top = PR_MAX(border->mWidth, mBorderEdges.mMaxBorderWidth.top);
if (nsnull!=cellFrame)
{
cellFrame->SetBorderEdge(NS_SIDE_TOP, aRowIndex, aColIndex, border); // set the top edge of the cell frame
}
printf("table computed top border width=%d length=%d, color=%d style=%d maxWidth=%d \n",
border->mWidth, border->mLength, border->mColor, border->mStyle, mBorderEdges.mMaxBorderWidth.top);
}
void nsTableFrame::ComputeBottomBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex)
{
// this method just uses mCellMap, because it can't get called unless nCellMap!=nsnull
PRInt32 rowCount = mCellMap->GetRowCount();
if ((rowCount-1)==aRowIndex)
{
}
else
{
}
PRInt32 numSegments = mBorderEdges.mEdges[NS_SIDE_BOTTOM].Count();
while (numSegments<=aColIndex)
{
nsBorderEdge *borderToAdd = new nsBorderEdge();
mBorderEdges.mEdges[NS_SIDE_BOTTOM].AppendElement(borderToAdd);
numSegments++;
}
// "border" is the border segment we are going to set
nsBorderEdge border;
// collect all the incident frames and compute the dominant border
nsVoidArray styles;
// styles are added to the array in the order least dominant -> most dominant
// 1. table, only if this cell is in the bottom-most row and no colspanning cell is
// beneath it. Otherwise, we remember what cell is the bottom neighbor
nsTableCellFrame *bottomNeighborFrame=nsnull;
if ((rowCount-1)!=aRowIndex)
{
PRInt32 rowIndex = aRowIndex+1;
for ( ; rowIndex<rowCount; rowIndex++)
{
CellData *cd = mCellMap->GetCellAt(rowIndex, aColIndex);
if (cd != nsnull)
{ // there's really a cell at (rowIndex, aColIndex)
if (nsnull==cd->mCell)
{ // the cell at (rowIndex, aColIndex) is the result of a span
nsTableCellFrame *cell = cd->mRealCell->mCell;
NS_ASSERTION(nsnull!=cell, "bad cell map state, missing real cell");
const PRInt32 realColIndex = cell->GetColIndex ();
if (realColIndex!=aColIndex)
{ // the span is caused by a colspan
bottomNeighborFrame = cd->mRealCell->mCell;
break;
}
}
else
{
bottomNeighborFrame = cd->mCell;
break;
}
}
}
}
const nsStyleSpacing *spacing;
if (nsnull==bottomNeighborFrame)
{ // if bottomNeighborFrame is null, our bottom neighbor is the table
GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
}
// 2. colgroup // XXX: need to deterine if we're on a colgroup boundary
nsTableColFrame *colFrame = mCellMap->GetColumnFrame(aColIndex);
nsIFrame *colGroupFrame;
colFrame->GetContentParent(colGroupFrame);
colGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 3. col
colFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 4. rowgroup // XXX: use rowgroup only if we're on a table edge
nsTableCellFrame *cellFrame = mCellMap->GetCellFrameAt(aRowIndex, aColIndex);
// XXX: some decision needs to be made about col-spanning cell
nsRect rowRect(0,0,0,0);
if (nsnull!=cellFrame)
{
nsIFrame *rowFrame;
cellFrame->GetContentParent(rowFrame);
rowFrame->GetRect(rowRect);
nsIFrame *rowGroupFrame;
rowFrame->GetContentParent(rowGroupFrame);
rowGroupFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 5. row
rowFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
// 6. cell (need to do something smart for rowspanner with row frame)
cellFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
}
// 7. top edge of bottomNeighborCell, if there is one
if (nsnull!=bottomNeighborFrame)
{
bottomNeighborFrame->GetStyleData(eStyleStruct_Spacing, ((const nsStyleStruct *&)spacing));
styles.AppendElement((void*)spacing);
}
ComputeCollapsedBorderSegment(NS_SIDE_BOTTOM, &styles, border, PRBool(nsnull!=bottomNeighborFrame));
// now give half the computed border to each of the two neighbors
// (the 2 cells, or the cell and the table)
// XXX give half to the cell
border.mWidth = (border.mWidth)/2; //XXX: rounding
border.mLength = GetColumnWidth(aColIndex);
if (nsnull==bottomNeighborFrame)
{
nsBorderEdge * tableBorder = (nsBorderEdge *)(mBorderEdges.mEdges[NS_SIDE_BOTTOM].ElementAt(aColIndex));
*tableBorder = border;
mBorderEdges.mMaxBorderWidth.bottom = PR_MAX(border.mWidth, mBorderEdges.mMaxBorderWidth.bottom);
}
else
bottomNeighborFrame->SetBorderEdge(NS_SIDE_TOP, aRowIndex, aColIndex, &border);
if (nsnull!=cellFrame)
{
cellFrame->SetBorderEdge(NS_SIDE_BOTTOM, aRowIndex, aColIndex, &border);
}
printf("table computed bottom border width=%d length=%d, color=%d style=%d maxWidth=%d \n",
border.mWidth, border.mLength, border.mColor, border.mStyle, mBorderEdges.mMaxBorderWidth.bottom);
}
nscoord nsTableFrame::GetWidthForSide(const nsMargin &aBorder, PRUint8 aSide)
@ -1633,7 +1842,7 @@ void nsTableFrame::RecalcLayoutData()
const nsStyleTable *tableStyle=nsnull;
GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
if (NS_STYLE_BORDER_COLLAPSE==tableStyle->mBorderCollapse)
ComputeCollapsingBorders(0, rowCount-1);
ComputeVerticalCollapsingBorders(0, rowCount-1);
//XXX need to determine how much of what follows is really necessary
// it does collapsing margins between table elements
@ -1850,11 +2059,10 @@ NS_METHOD nsTableFrame::Paint(nsIPresContext& aPresContext,
const nsRect& aDirtyRect,
nsFramePaintLayer aWhichLayer)
{
// table paint code is concerned primarily with borders and bg color
if (eFramePaintLayer_Underlay == aWhichLayer) {
// table paint code is concerned primarily with borders and bg color
const nsStyleDisplay* disp =
(const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display);
if (disp->mVisible) {
const nsStyleSpacing* spacing =
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
@ -1874,6 +2082,8 @@ NS_METHOD nsTableFrame::Paint(nsIPresContext& aPresContext,
}
else
{
nsCSSRendering::PaintBorderEdges(aPresContext, aRenderingContext, this,
aDirtyRect, rect, &mBorderEdges, skipSides);
}
}
}
@ -3215,8 +3425,11 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
const nsStyleSpacing* spacing =
(const nsStyleSpacing*)mStyleContext->GetStyleData(eStyleStruct_Spacing);
const nsStyleTable* tableStyle =
(const nsStyleTable*)mStyleContext->GetStyleData(eStyleStruct_Table);
nsMargin borderPadding;
spacing->CalcBorderPaddingFor(this, borderPadding);
spacing->CalcBorderPaddingFor(this, borderPadding); // COLLAPSING BORDERS
// need to figure out the overall table width constraint
// default case, get 100% of available space
@ -3252,6 +3465,10 @@ void nsTableFrame::BalanceColumnWidths(nsIPresContext& aPresContext,
}
mTableLayoutStrategy->BalanceColumnWidths(mStyleContext, aReflowState, maxWidth);
mColumnWidthsSet=PR_TRUE;
if (NS_STYLE_BORDER_COLLAPSE==tableStyle->mBorderCollapse)
{
ComputeHorizontalCollapsingBorders(0, mCellMap->GetRowCount()-1);
}
}
/**
@ -3355,6 +3572,8 @@ nscoord nsTableFrame::ComputeDesiredHeight(nsIPresContext& aPresContext,
if (eStyleUnit_Auto == tablePosition->mHeight.GetUnit())
return result; // auto width tables are sized by the row heights, which we already have
const nsStyleTable* tableStyle;
GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
nscoord tableSpecifiedHeight=-1;
if (eStyleUnit_Coord == tablePosition->mHeight.GetUnit())
tableSpecifiedHeight = tablePosition->mHeight.GetCoordValue();
@ -3422,6 +3641,15 @@ nscoord nsTableFrame::ComputeDesiredHeight(nsIPresContext& aPresContext,
nscoord excessForRow = NSToCoordRound((float)excess*percent);
nsRect newRowRect(rowRect.x, y, rowRect.width, excessForRow+rowRect.height);
rowFrame->SetRect(newRowRect);
if (NS_STYLE_BORDER_COLLAPSE==tableStyle->mBorderCollapse)
{
nsBorderEdge *border = (nsBorderEdge *)
(mBorderEdges.mEdges[NS_SIDE_LEFT].ElementAt(((nsTableRowFrame*)rowFrame)->GetRowIndex()));
border->mLength=newRowRect.height;
border = (nsBorderEdge *)
(mBorderEdges.mEdges[NS_SIDE_RIGHT].ElementAt(((nsTableRowFrame*)rowFrame)->GetRowIndex()));
border->mLength=newRowRect.height;
}
// resize cells, too
((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState);
// better if this were part of an overloaded row::SetRect

View File

@ -210,12 +210,21 @@ public:
/** Calculate Layout Information */
void AppendLayoutData(nsVoidArray* aList, nsTableCellFrame* aTableCell);
/* compute all the collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void ComputeCollapsingBorders(PRInt32 aStartRowIndex, PRInt32 aEndRowIndex);
/** compute the left and right collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void ComputeVerticalCollapsingBorders(PRInt32 aStartRowIndex, PRInt32 aEndRowIndex);
/** compute the top and bottom collapsed borders between aStartRowIndex and aEndRowIndex, inclusive */
void ComputeHorizontalCollapsingBorders(PRInt32 aStartRowIndex, PRInt32 aEndRowIndex);
void ComputeLeftBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex);
void ComputeRightBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex);
void ComputeTopBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex);
void ComputeBottomBorderForEdgeAt(PRInt32 aRowIndex, PRInt32 aColIndex);
/** at the time we initially compute collapsing borders, we don't yet have the
* column widths. So we set them as a post-process of the column balancing algorithm.
*/
void SetCollapsingBorderHorizontalEdgeLengths();
PRUint8 GetOpposingEdge(PRUint8 aEdge);
@ -223,6 +232,8 @@ public:
PRUint8 CompareBorderStyles(PRUint8 aStyle1, PRUint8 aStyle2);
void SetBorderEdgeLength(PRUint8 aSide, PRInt32 aIndex, nscoord aLength);
void ComputeCollapsedBorderSegment(PRUint8 aSide,
nsVoidArray * aStyles,
nsBorderEdge& aBorder,

View File

@ -181,6 +181,8 @@ nsTableRowFrame::DidResize(nsIPresContext& aPresContext,
nsIFrame *cellFrame = mFirstChild;
nsTableFrame* tableFrame;
nsTableFrame::GetTableFrame(this, tableFrame);
const nsStyleTable* tableStyle;
tableFrame->GetStyleData(eStyleStruct_Table, (const nsStyleStruct *&)tableStyle);
while (nsnull != cellFrame)
{
const nsStyleDisplay *kidDisplay;
@ -209,6 +211,16 @@ nsTableRowFrame::DidResize(nsIPresContext& aPresContext,
//XXX nsReflowStatus status;
//ReflowChild(cellFrame, aPresContext, desiredSize, kidReflowState, status);
((nsTableCellFrame *)cellFrame)->VerticallyAlignChild();
/* if we're collapsing borders, notify the cell that the border edge length has changed */
if (NS_STYLE_BORDER_COLLAPSE==tableStyle->mBorderCollapse)
{
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_LEFT,
GetRowIndex(),
cellHeight);
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_RIGHT,
GetRowIndex(),
cellHeight);
}
}
}
else

View File

@ -331,6 +331,9 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC
kidFrame = mFirstChild;
else
kidFrame = aStartFrame;
PRUint8 borderStyle = aReflowState.tableFrame->GetBorderCollapseStyle();
for ( ; nsnull != kidFrame; )
{
nsSize kidAvailSize(aReflowState.availSize);
@ -406,6 +409,43 @@ NS_METHOD nsTableRowGroupFrame::ReflowMappedChildren(nsIPresContext& aPresC
aReflowState.prevMaxPosBottomMargin = bottomMargin;
}
/* if the table has collapsing borders, we need to reset the length of the shared vertical borders
* for the table and the cells that overlap this row
*/
if ((eReflowReason_Initial != aReflowState.reflowState.reason) && (NS_STYLE_BORDER_COLLAPSE==borderStyle))
{
const nsStyleDisplay *childDisplay;
kidFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)childDisplay));
if (NS_STYLE_DISPLAY_TABLE_ROW == childDisplay->mDisplay)
{
PRInt32 rowIndex = ((nsTableRowFrame*)kidFrame)->GetRowIndex();
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
aReflowState.tableFrame->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
nsIFrame *cellFrame=nsnull;
kidFrame->FirstChild(nsnull, cellFrame);
while (nsnull!=cellFrame)
{
const nsStyleDisplay *cellDisplay;
cellFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)cellDisplay));
if (NS_STYLE_DISPLAY_TABLE_CELL == cellDisplay->mDisplay)
{
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_LEFT,
rowIndex,
kidRect.height);
((nsTableCellFrame *)(cellFrame))->SetBorderEdgeLength(NS_SIDE_RIGHT,
rowIndex,
kidRect.height);
}
cellFrame->GetNextSibling(cellFrame);
}
}
}
// Remember where we just were in case we end up pushing children
prevKidFrame = kidFrame;