bug 97138 - rework of table, row group, row, cell height code. sr=attinasi, r=alexsavulov
git-svn-id: svn://10.0.0.236/trunk@107299 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
57b929e4bf
commit
d30758e3fc
@ -239,7 +239,14 @@ struct nsHTMLReflowState {
|
||||
|
||||
// This value keeps track of how deeply nested a given reflow state
|
||||
// is from the top of the frame tree.
|
||||
PRInt32 mReflowDepth;
|
||||
PRInt16 mReflowDepth;
|
||||
|
||||
struct ReflowStateFlags {
|
||||
//unsigned mUseAlignCharOffset:1; // ditto
|
||||
//unsigned isTopOfPage:1; // ditto
|
||||
PRUint16 mSpecialTableReflow:1; // used by tables to communicate special reflow in process
|
||||
PRUint16 mUnused:15;
|
||||
} mFlags;
|
||||
|
||||
#ifdef IBMBIDI
|
||||
nscoord mRightEdge;
|
||||
|
||||
@ -86,7 +86,7 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
: mReflowDepth(0)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aRenderingContext, "no rendering context");
|
||||
|
||||
mFlags.mSpecialTableReflow = mFlags.mUnused = 0;
|
||||
parentReflowState = nsnull;
|
||||
frame = aFrame;
|
||||
reason = aReason;
|
||||
@ -114,6 +114,7 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aRenderingContext, "no rendering context");
|
||||
|
||||
mFlags.mSpecialTableReflow = mFlags.mUnused = 0;
|
||||
reason = eReflowReason_Incremental;
|
||||
parentReflowState = nsnull;
|
||||
frame = aFrame;
|
||||
@ -138,7 +139,8 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
const nsSize& aAvailableSpace,
|
||||
nsReflowReason aReason)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1),
|
||||
mFlags(aParentReflowState.mFlags)
|
||||
{
|
||||
parentReflowState = &aParentReflowState;
|
||||
frame = aFrame;
|
||||
@ -167,7 +169,8 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aParentReflowState,
|
||||
nsIFrame* aFrame,
|
||||
const nsSize& aAvailableSpace)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1),
|
||||
mFlags(aParentReflowState.mFlags)
|
||||
{
|
||||
parentReflowState = &aParentReflowState;
|
||||
frame = aFrame;
|
||||
@ -195,7 +198,8 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
const nsSize& aAvailableSpace,
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1),
|
||||
mFlags(aParentReflowState.mFlags)
|
||||
{
|
||||
parentReflowState = &aParentReflowState;
|
||||
frame = aFrame;
|
||||
|
||||
@ -239,7 +239,14 @@ struct nsHTMLReflowState {
|
||||
|
||||
// This value keeps track of how deeply nested a given reflow state
|
||||
// is from the top of the frame tree.
|
||||
PRInt32 mReflowDepth;
|
||||
PRInt16 mReflowDepth;
|
||||
|
||||
struct ReflowStateFlags {
|
||||
//unsigned mUseAlignCharOffset:1; // ditto
|
||||
//unsigned isTopOfPage:1; // ditto
|
||||
PRUint16 mSpecialTableReflow:1; // used by tables to communicate special reflow in process
|
||||
PRUint16 mUnused:15;
|
||||
} mFlags;
|
||||
|
||||
#ifdef IBMBIDI
|
||||
nscoord mRightEdge;
|
||||
|
||||
@ -86,7 +86,7 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
: mReflowDepth(0)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aRenderingContext, "no rendering context");
|
||||
|
||||
mFlags.mSpecialTableReflow = mFlags.mUnused = 0;
|
||||
parentReflowState = nsnull;
|
||||
frame = aFrame;
|
||||
reason = aReason;
|
||||
@ -114,6 +114,7 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aRenderingContext, "no rendering context");
|
||||
|
||||
mFlags.mSpecialTableReflow = mFlags.mUnused = 0;
|
||||
reason = eReflowReason_Incremental;
|
||||
parentReflowState = nsnull;
|
||||
frame = aFrame;
|
||||
@ -138,7 +139,8 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
const nsSize& aAvailableSpace,
|
||||
nsReflowReason aReason)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1),
|
||||
mFlags(aParentReflowState.mFlags)
|
||||
{
|
||||
parentReflowState = &aParentReflowState;
|
||||
frame = aFrame;
|
||||
@ -167,7 +169,8 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aParentReflowState,
|
||||
nsIFrame* aFrame,
|
||||
const nsSize& aAvailableSpace)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1),
|
||||
mFlags(aParentReflowState.mFlags)
|
||||
{
|
||||
parentReflowState = &aParentReflowState;
|
||||
frame = aFrame;
|
||||
@ -195,7 +198,8 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
|
||||
const nsSize& aAvailableSpace,
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1)
|
||||
: mReflowDepth(aParentReflowState.mReflowDepth + 1),
|
||||
mFlags(aParentReflowState.mFlags)
|
||||
{
|
||||
parentReflowState = &aParentReflowState;
|
||||
frame = aFrame;
|
||||
|
||||
@ -337,15 +337,19 @@ nsTableCellMap::RemoveRows(nsIPresContext* aPresContext,
|
||||
PRInt32
|
||||
nsTableCellMap::GetNumCellsOriginatingInRow(PRInt32 aRowIndex)
|
||||
{
|
||||
PRInt32 cellCount = 0;
|
||||
CellData* tempCell;
|
||||
do
|
||||
{
|
||||
tempCell = GetCellAt(aRowIndex,cellCount);
|
||||
if (tempCell)
|
||||
cellCount++;
|
||||
}while(tempCell);
|
||||
return cellCount;
|
||||
PRInt32 originCount = 0;
|
||||
|
||||
CellData* cellData;
|
||||
PRInt32 colIndex = 0;
|
||||
|
||||
do {
|
||||
cellData = GetCellAt(aRowIndex, colIndex);
|
||||
if (cellData && cellData->GetCellFrame())
|
||||
originCount++;
|
||||
colIndex++;
|
||||
} while(cellData);
|
||||
|
||||
return originCount;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
|
||||
@ -91,6 +91,22 @@ nsTableCellFrame::~nsTableCellFrame()
|
||||
#endif
|
||||
}
|
||||
|
||||
nsTableCellFrame*
|
||||
nsTableCellFrame::GetNextCell() const
|
||||
{
|
||||
nsIFrame* childFrame;
|
||||
GetNextSibling(&childFrame);
|
||||
while (childFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
childFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
|
||||
return (nsTableCellFrame*)childFrame;
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableCellFrame::Init(nsIPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
@ -694,6 +710,15 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) &&
|
||||
((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) ||
|
||||
(0 == aReflowState.mComputedHeight)) &&
|
||||
!mPrevInFlow &&
|
||||
nsTableFrame::IsPctHeight(mStyleContext)) {
|
||||
nsTableFrame::NotifyAncestorsOfSpecialReflow(aReflowState);
|
||||
SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
// this should probably be cached somewhere
|
||||
nsCompatibility compatMode;
|
||||
aPresContext->GetCompatibilityMode(&compatMode);
|
||||
@ -714,6 +739,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
/* XXX: remove tableFrame when border-collapse inherits */
|
||||
nsTableFrame* tableFrame=nsnull;
|
||||
rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
nsTableFrame* tableFrameFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
|
||||
|
||||
nsMargin borderPadding = aReflowState.mComputedPadding;
|
||||
nsMargin border;
|
||||
GetCellBorder(border, tableFrame);
|
||||
@ -768,6 +795,10 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
kidSize.width=kidSize.height=kidSize.ascent=kidSize.descent=0;
|
||||
SetPriorAvailWidth(aReflowState.availableWidth);
|
||||
nsIFrame* firstKid = mFrames.FirstChild();
|
||||
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
((nsHTMLReflowState&)aReflowState).mComputedHeight = mRect.height - topInset - bottomInset;
|
||||
}
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, firstKid,
|
||||
availSize);
|
||||
|
||||
@ -898,8 +929,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
|
||||
// if the table allocated extra vertical space to row groups, rows, cells in pagination mode
|
||||
// then use that height as the desired height unless the cell needs to split.
|
||||
nsTableFrame* tableFrameFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
|
||||
if ((NS_FRAME_COMPLETE == aStatus) && tableFrameFirstInFlow->IsThirdPassReflow()) {
|
||||
if ((NS_FRAME_COMPLETE == aStatus) && aReflowState.mFlags.mSpecialTableReflow) {
|
||||
cellHeight = PR_MAX(cellHeight, mRect.height);
|
||||
}
|
||||
// next determine the cell's width
|
||||
@ -942,6 +972,10 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
// remember my desired size for this reflow
|
||||
SetDesiredSize(aDesiredSize);
|
||||
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
SetNeedSpecialReflow(PR_FALSE);
|
||||
}
|
||||
|
||||
#if defined DEBUG_TABLE_REFLOW_TIMING
|
||||
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aReflowState, &aDesiredSize, aStatus);
|
||||
#endif
|
||||
|
||||
@ -49,7 +49,8 @@ class nsHTMLValue;
|
||||
/**
|
||||
* Additional frame-state bits
|
||||
*/
|
||||
#define NS_TABLE_CELL_FRAME_CONTENT_EMPTY 0x80000000
|
||||
#define NS_TABLE_CELL_CONTENT_EMPTY 0x80000000
|
||||
#define NS_TABLE_CELL_NEED_SPECIAL_REFLOW 0x40000000
|
||||
|
||||
/**
|
||||
* nsTableCellFrame
|
||||
@ -239,11 +240,16 @@ public:
|
||||
PRBool GetContentEmpty();
|
||||
void SetContentEmpty(PRBool aContentEmpty);
|
||||
|
||||
PRBool NeedSpecialReflow();
|
||||
void SetNeedSpecialReflow(PRBool aContentEmpty);
|
||||
|
||||
// The collapse offset is (0,0) except for cells originating in a row/col which is collapsed
|
||||
void SetCollapseOffsetX(nsIPresContext* aPresContext, nscoord aXOffset);
|
||||
void SetCollapseOffsetY(nsIPresContext* aPresContext, nscoord aYOffset);
|
||||
void GetCollapseOffset(nsIPresContext* aPresContext, nsPoint& aOffset);
|
||||
|
||||
nsTableCellFrame* GetNextCell() const;
|
||||
|
||||
protected:
|
||||
/** implement abstract method on nsHTMLContainerFrame */
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
@ -332,19 +338,33 @@ inline nsSize nsTableCellFrame::GetPass1MaxElementSize() const
|
||||
|
||||
inline PRBool nsTableCellFrame::GetContentEmpty()
|
||||
{
|
||||
return (mState & NS_TABLE_CELL_FRAME_CONTENT_EMPTY) ==
|
||||
NS_TABLE_CELL_FRAME_CONTENT_EMPTY;
|
||||
return (mState & NS_TABLE_CELL_CONTENT_EMPTY) ==
|
||||
NS_TABLE_CELL_CONTENT_EMPTY;
|
||||
}
|
||||
|
||||
inline void nsTableCellFrame::SetContentEmpty(PRBool aContentEmpty)
|
||||
{
|
||||
if (aContentEmpty) {
|
||||
mState |= NS_TABLE_CELL_FRAME_CONTENT_EMPTY;
|
||||
mState |= NS_TABLE_CELL_CONTENT_EMPTY;
|
||||
} else {
|
||||
mState &= ~NS_TABLE_CELL_FRAME_CONTENT_EMPTY;
|
||||
mState &= ~NS_TABLE_CELL_CONTENT_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
inline PRBool nsTableCellFrame::NeedSpecialReflow()
|
||||
{
|
||||
return (mState & NS_TABLE_CELL_NEED_SPECIAL_REFLOW) ==
|
||||
NS_TABLE_CELL_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
|
||||
inline void nsTableCellFrame::SetNeedSpecialReflow(PRBool aValue)
|
||||
{
|
||||
if (aValue) {
|
||||
mState |= NS_TABLE_CELL_NEED_SPECIAL_REFLOW;
|
||||
} else {
|
||||
mState &= ~NS_TABLE_CELL_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -84,6 +84,7 @@ void nsTableColFrame::SetType(nsTableColType aType) {
|
||||
mBits.mType = aType - eColContent;
|
||||
}
|
||||
|
||||
|
||||
// XXX what about other style besides width
|
||||
nsStyleCoord nsTableColFrame::GetStyleWidth() const
|
||||
{
|
||||
|
||||
@ -1580,8 +1580,15 @@ nsTableFrame::GetSkipSides() const
|
||||
PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
PRBool result = PR_TRUE;
|
||||
if ((eReflowReason_Incremental == aReflowState.reason) &&
|
||||
(NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight)) {
|
||||
if (eReflowReason_Resize == aReflowState.reason) {
|
||||
if (aReflowState.mFlags.mSpecialTableReflow &&
|
||||
!NeedSpecialReflow() &&
|
||||
!NeedToInitiateSpecialReflow()) {
|
||||
result = PR_FALSE;
|
||||
}
|
||||
}
|
||||
else if ((eReflowReason_Incremental == aReflowState.reason) &&
|
||||
(NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight)) {
|
||||
// It's an incremental reflow and we're in galley mode. Only
|
||||
// do a full reflow if we need to.
|
||||
#ifndef TABLE_REFLOW_COALESCING_OFF
|
||||
@ -1809,6 +1816,30 @@ ProcessRowInserted(nsIPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTableFrame::NotifyAncestorsOfSpecialReflow(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
const nsHTMLReflowState* rs = aReflowState.parentReflowState;
|
||||
while (rs) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
rs->frame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
|
||||
((nsTableCellFrame*)rs->frame)->SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
else if (nsLayoutAtoms::tableRowFrame == frameType.get()) {
|
||||
((nsTableRowFrame*)rs->frame)->SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
else if (nsLayoutAtoms::tableRowGroupFrame == frameType.get()) {
|
||||
((nsTableRowGroupFrame*)rs->frame)->SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
else if (nsLayoutAtoms::tableFrame == frameType.get()) {
|
||||
((nsTableFrame*)rs->frame)->SetNeedToInitiateSpecialReflow(PR_TRUE);
|
||||
break;
|
||||
}
|
||||
rs = rs->parentReflowState;
|
||||
}
|
||||
}
|
||||
|
||||
/* overview:
|
||||
if mFirstPassValid is false, this is our first time through since content was last changed
|
||||
do pass 1
|
||||
@ -1904,36 +1935,57 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRBool needPass3Reflow = PR_FALSE;
|
||||
PRBool haveDesiredHeight = PR_FALSE;
|
||||
PRBool balanced = PR_FALSE;
|
||||
|
||||
// Reflow the entire table. This phase is necessary during a constrained initial reflow
|
||||
// and other reflows which require either a strategy init or balance. This isn't done
|
||||
// during an unconstrained reflow because another reflow will be processed later.
|
||||
if (NeedsReflow(aReflowState) && (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)) {
|
||||
// see if an extra (3rd) reflow will be necessary in pagination mode when there is a specified table height
|
||||
if (isPaginated && !mPrevInFlow && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) {
|
||||
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
||||
if ((tableSpecifiedHeight > 0) &&
|
||||
(tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE)) {
|
||||
needPass3Reflow = PR_TRUE;
|
||||
if (!mPrevInFlow) {
|
||||
// see if an extra reflow will be necessary when there is a pct height but no height on the parent
|
||||
if ( ((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) ||
|
||||
(0 == aReflowState.mComputedHeight)) && IsPctHeight(mStyleContext)) {
|
||||
NotifyAncestorsOfSpecialReflow(aReflowState);
|
||||
SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
// see if an extra reflow will be necessary in pagination mode when there is a specified table height
|
||||
else if (isPaginated && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) {
|
||||
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
||||
if ((tableSpecifiedHeight > 0) &&
|
||||
(tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE)) {
|
||||
SetNeedToInitiateSpecialReflow(PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we need to reflow the table an extra time, then don't constrain the height of the previous reflow
|
||||
nscoord availHeight = (needPass3Reflow) ? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight;
|
||||
nscoord availHeight = !aReflowState.mFlags.mSpecialTableReflow &&
|
||||
(NeedSpecialReflow() | NeedToInitiateSpecialReflow())
|
||||
? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight;
|
||||
|
||||
ReflowTable(aPresContext, aDesiredSize, aReflowState, availHeight, nextReason, doCollapse, balanced, aStatus);
|
||||
|
||||
if (needPass3Reflow) {
|
||||
if (!aReflowState.mFlags.mSpecialTableReflow && NeedToInitiateSpecialReflow() && !NeedSpecialReflow()) {
|
||||
aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState); // distributes extra vertical space to rows
|
||||
SetThirdPassReflow(PR_TRUE); // set it and leave it set for frames that may split
|
||||
((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialTableReflow = PR_TRUE;
|
||||
ReflowTable(aPresContext, aDesiredSize, aReflowState, aReflowState.availableHeight,
|
||||
nextReason, doCollapse, balanced, aStatus);
|
||||
haveDesiredHeight = PR_TRUE;;
|
||||
}
|
||||
}
|
||||
else if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
aDesiredSize.width = mRect.width;
|
||||
aDesiredSize.height = mRect.height;
|
||||
#if defined DEBUG_TABLE_REFLOW_TIMING
|
||||
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aReflowState, &aDesiredSize, aStatus);
|
||||
#endif
|
||||
SetNeedSpecialReflow(PR_FALSE);
|
||||
SetNeedToInitiateSpecialReflow(PR_FALSE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aDesiredSize.width = GetDesiredWidth();
|
||||
if (!needPass3Reflow) {
|
||||
aDesiredSize.width = GetDesiredWidth();
|
||||
if (!haveDesiredHeight) {
|
||||
aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState);
|
||||
}
|
||||
|
||||
@ -1986,6 +2038,10 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
SetNeedSpecialReflow(PR_FALSE);
|
||||
SetNeedToInitiateSpecialReflow(PR_FALSE);
|
||||
}
|
||||
#if defined DEBUG_TABLE_REFLOW_TIMING
|
||||
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aReflowState, &aDesiredSize, aStatus);
|
||||
#endif
|
||||
@ -3253,81 +3309,6 @@ nsTableFrame::CalcDesiredWidth(const nsHTMLReflowState& aReflowState)
|
||||
return tableWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
get the table height attribute
|
||||
if it is auto, table height = SUM(height of rowgroups)
|
||||
else if (resolved table height attribute > SUM(height of rowgroups))
|
||||
proportionately distribute extra height to each row
|
||||
we assume we are passed in the default table height==the sum of the heights of the table's rowgroups
|
||||
in aDesiredSize.height.
|
||||
*/
|
||||
void
|
||||
nsTableFrame::DistributeSpaceToCells(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame* aRowGroupFrame)
|
||||
{
|
||||
// now that all of the rows have been resized, resize the cells
|
||||
nsTableRowGroupFrame* rowGroupFrame = (nsTableRowGroupFrame*)aRowGroupFrame;
|
||||
nsIFrame * rowFrame = rowGroupFrame->GetFirstFrame();
|
||||
while (rowFrame) {
|
||||
const nsStyleDisplay *rowDisplay;
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
|
||||
((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState);
|
||||
}
|
||||
rowGroupFrame->GetNextFrame(rowFrame, &rowFrame);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTableFrame::DistributeSpaceToRows(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame* aRowGroupFrame,
|
||||
nscoord aSumOfRowHeights,
|
||||
nscoord aExcess,
|
||||
nscoord& aExcessAllocated,
|
||||
nscoord& aRowGroupYPos)
|
||||
{
|
||||
// the rows in rowGroupFrame need to be expanded by rowHeightDelta[i]
|
||||
// and the rowgroup itself needs to be expanded by SUM(row height deltas)
|
||||
nscoord cellSpacingY = GetCellSpacingY();
|
||||
nsTableRowGroupFrame* rowGroupFrame = (nsTableRowGroupFrame*)aRowGroupFrame;
|
||||
nsIFrame* rowFrame = rowGroupFrame->GetFirstFrame();
|
||||
nscoord excessForRowGroup = 0;
|
||||
nscoord y = 0;
|
||||
float p2t;
|
||||
aPresContext->GetPixelsToTwips(&p2t);
|
||||
while (rowFrame) {
|
||||
const nsStyleDisplay *rowDisplay;
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
|
||||
// the row needs to be expanded by the proportion this row contributed to the original height
|
||||
nsRect rowRect;
|
||||
rowFrame->GetRect(rowRect);
|
||||
float percent = ((float)(rowRect.height)) / (float)aSumOfRowHeights;
|
||||
nscoord excessForRow = RoundToPixel(NSToCoordRound((float)aExcess * percent), p2t);
|
||||
excessForRow = PR_MIN(excessForRow, aExcess - aExcessAllocated);
|
||||
|
||||
nsRect newRowRect(rowRect.x, y, rowRect.width, excessForRow + rowRect.height);
|
||||
rowFrame->SetRect(aPresContext, newRowRect);
|
||||
y = newRowRect.YMost() + cellSpacingY;
|
||||
|
||||
aExcessAllocated += excessForRow;
|
||||
excessForRowGroup += excessForRow;
|
||||
}
|
||||
|
||||
rowGroupFrame->GetNextFrame(rowFrame, &rowFrame);
|
||||
}
|
||||
|
||||
nsRect rowGroupRect;
|
||||
aRowGroupFrame->GetRect(rowGroupRect);
|
||||
nsRect newRowGroupRect(rowGroupRect.x, aRowGroupYPos, rowGroupRect.width,
|
||||
excessForRowGroup + rowGroupRect.height);
|
||||
aRowGroupFrame->SetRect(aPresContext, newRowGroupRect);
|
||||
aRowGroupYPos = newRowGroupRect.YMost();
|
||||
|
||||
DistributeSpaceToCells(aPresContext, aReflowState, aRowGroupFrame);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsTableFrame::CalcDesiredHeight(nsIPresContext* aPresContext,
|
||||
@ -3347,65 +3328,239 @@ nsTableFrame::CalcDesiredHeight(nsIPresContext* aPresContext,
|
||||
OrderRowGroups(rowGroups, numRowGroups, nsnull);
|
||||
if (numRowGroups <= 0) return 0;
|
||||
|
||||
nscoord naturalHeight = borderPadding.top + cellSpacingY + borderPadding.bottom;
|
||||
nscoord desiredHeight = borderPadding.top + cellSpacingY + borderPadding.bottom;
|
||||
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
|
||||
nsIFrame* rg = (nsIFrame*)rowGroups.ElementAt(rgX);
|
||||
if (rg) {
|
||||
nsRect rgRect;
|
||||
rg->GetRect(rgRect);
|
||||
naturalHeight += rgRect.height + cellSpacingY;
|
||||
desiredHeight += rgRect.height + cellSpacingY;
|
||||
}
|
||||
}
|
||||
|
||||
nscoord desiredHeight = naturalHeight;
|
||||
|
||||
// see if a specified table height requires dividing additional space to rows
|
||||
if (!mPrevInFlow) {
|
||||
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
||||
if ((tableSpecifiedHeight > 0) &&
|
||||
(tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE) &&
|
||||
(tableSpecifiedHeight > naturalHeight)) {
|
||||
desiredHeight = tableSpecifiedHeight;
|
||||
|
||||
(tableSpecifiedHeight > desiredHeight)) {
|
||||
// proportionately distribute the excess height to unconstrained rows in each
|
||||
// unconstrained row group.We don't need to do this if it's an unconstrained reflow
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) {
|
||||
// proportionately distribute the excess height to each row. Note that we
|
||||
// don't need to do this if it's an unconstrained reflow
|
||||
nscoord excess = tableSpecifiedHeight - naturalHeight;
|
||||
nscoord sumOfRowHeights = 0;
|
||||
nscoord rowGroupYPos = aReflowState.mComputedBorderPadding.top + cellSpacingY;
|
||||
|
||||
nsAutoVoidArray rowGroups;
|
||||
PRUint32 numRowGroups;
|
||||
OrderRowGroups(rowGroups, numRowGroups, nsnull);
|
||||
|
||||
PRUint32 rgX;
|
||||
for (rgX = 0; rgX < numRowGroups; rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame =
|
||||
GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
if (rgFrame) {
|
||||
sumOfRowHeights += rgFrame->GetHeightOfRows(aPresContext);
|
||||
}
|
||||
}
|
||||
nscoord excessAllocated = 0;
|
||||
for (rgX = 0; rgX < numRowGroups; rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame =
|
||||
GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
if (rgFrame) {
|
||||
DistributeSpaceToRows(aPresContext, aReflowState, rgFrame, sumOfRowHeights,
|
||||
excess, excessAllocated, rowGroupYPos);
|
||||
|
||||
// Make sure child views are properly positioned
|
||||
// XXX what happens if childFrame is a scroll frame and this gets skipped?
|
||||
nsTableFrame::RePositionViews(aPresContext, rgFrame);
|
||||
}
|
||||
rowGroupYPos += cellSpacingY;
|
||||
}
|
||||
DistributeHeightToRows(aPresContext, aReflowState, tableSpecifiedHeight - desiredHeight);
|
||||
}
|
||||
desiredHeight = tableSpecifiedHeight;
|
||||
}
|
||||
}
|
||||
return desiredHeight;
|
||||
}
|
||||
|
||||
static
|
||||
void ResizeCells(nsTableFrame& aTableFrame,
|
||||
nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
nsAutoVoidArray rowGroups;
|
||||
PRUint32 numRowGroups;
|
||||
aTableFrame.OrderRowGroups(rowGroups, numRowGroups, nsnull);
|
||||
|
||||
for (PRUint32 rgX = 0; (rgX < numRowGroups); rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame = aTableFrame.GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
rowFrame->DidResize(aPresContext, aReflowState);
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTableFrame::DistributeHeightToRows(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nscoord aAmount)
|
||||
{
|
||||
float p2t;
|
||||
aPresContext->GetPixelsToTwips(&p2t);
|
||||
|
||||
nscoord cellSpacingY = GetCellSpacingY();
|
||||
|
||||
nscoord sumOfRowHeights = 0;
|
||||
nscoord rowGroupYPos = aReflowState.mComputedBorderPadding.top + cellSpacingY;
|
||||
|
||||
nsVoidArray rowGroups;
|
||||
PRUint32 numRowGroups;
|
||||
OrderRowGroups(rowGroups, numRowGroups, nsnull);
|
||||
|
||||
nscoord amountUsed = 0;
|
||||
// distribute space to each pct height row whose row group doesn't have a computed
|
||||
// height, and base the pct on the table height. If the row group had a computed
|
||||
// height, then this was already done in nsTableRowGroupFrame::CalculateRowHeights
|
||||
nscoord pctBasis = aReflowState.mComputedHeight - (GetCellSpacingY() * (GetRowCount() + 1));
|
||||
nscoord yOriginRG = aReflowState.mComputedBorderPadding.top + GetCellSpacingY();
|
||||
nscoord yEndRG = yOriginRG;
|
||||
PRUint32 rgX;
|
||||
for (rgX = 0; (rgX < numRowGroups); rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
nscoord amountUsedByRG = 0;
|
||||
nscoord yOriginRow = 0;
|
||||
nsRect rgRect;
|
||||
rgFrame->GetRect(rgRect);
|
||||
if (rgFrame && !rgFrame->HasStyleHeight()) {
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
nsRect rowRect;
|
||||
rowFrame->GetRect(rowRect);
|
||||
if ((amountUsed < aAmount) && rowFrame->HasPctHeight()) {
|
||||
nscoord pctHeight = nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctBasis), p2t);
|
||||
nscoord amountForRow = PR_MIN(aAmount - amountUsed, pctHeight - rowRect.height);
|
||||
if (amountForRow > 0) {
|
||||
rowRect.height += amountForRow;
|
||||
rowFrame->SetRect(aPresContext, rowRect);
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
amountUsed += amountForRow;
|
||||
amountUsedByRG += amountForRow;
|
||||
//rowFrame->DidResize(aPresContext, aReflowState);
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (amountUsed > 0) {
|
||||
rowFrame->MoveTo(aPresContext, rowRect.x, yOriginRow);
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
}
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
if (amountUsed > 0) {
|
||||
rgRect.y = yOriginRG;
|
||||
rgRect.height += amountUsedByRG;
|
||||
rgFrame->SetRect(aPresContext, rgRect);
|
||||
}
|
||||
}
|
||||
else if (amountUsed > 0) {
|
||||
rgFrame->MoveTo(aPresContext, 0, yOriginRG);
|
||||
// Make sure child views are properly positioned
|
||||
nsTableFrame::RePositionViews(aPresContext, rgFrame);
|
||||
}
|
||||
yOriginRG = yEndRG;
|
||||
}
|
||||
|
||||
if (amountUsed >= aAmount) {
|
||||
ResizeCells(*this, aPresContext, aReflowState);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the first row without a style height where its row group has an unconstrianed height
|
||||
nsTableRowGroupFrame* firstUnStyledRG = nsnull;
|
||||
nsTableRowFrame* firstUnStyledRow = nsnull;
|
||||
for (rgX = 0; (rgX < numRowGroups) && !firstUnStyledRG; rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
if (rgFrame && !rgFrame->HasStyleHeight()) {
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
if (!rowFrame->HasStyleHeight()) {
|
||||
firstUnStyledRG = rgFrame;
|
||||
firstUnStyledRow = rowFrame;
|
||||
break;
|
||||
}
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsTableRowFrame* lastElligibleRow = nsnull;
|
||||
// accumulate the correct divisor. This will be the total of all unstyled rows inside
|
||||
// unstyled row groups, unless there are none, in which case, it will be all rows
|
||||
nscoord divisor = 0;
|
||||
for (rgX = 0; rgX < numRowGroups; rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
if (rgFrame && (!firstUnStyledRG || !rgFrame->HasStyleHeight())) {
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
if (!firstUnStyledRG || !rowFrame->HasStyleHeight()) {
|
||||
nsRect rowRect;
|
||||
rowFrame->GetRect(rowRect);
|
||||
divisor += rowRect.height;
|
||||
lastElligibleRow = rowFrame;
|
||||
}
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (divisor <= 0) {
|
||||
NS_ASSERTION(PR_FALSE, "invlaid divisor");
|
||||
return;
|
||||
}
|
||||
|
||||
// allocate the extra height to the unstyled row groups and rows
|
||||
pctBasis = aAmount - amountUsed;
|
||||
yOriginRG = aReflowState.mComputedBorderPadding.top + cellSpacingY;
|
||||
yEndRG = yOriginRG;
|
||||
for (rgX = 0; rgX < numRowGroups; rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
if (!rgFrame) continue;
|
||||
nscoord amountUsedByRG = 0;
|
||||
nscoord yOriginRow = 0;
|
||||
nsRect rgRect;
|
||||
rgFrame->GetRect(rgRect);
|
||||
// see if there is an eligible row group
|
||||
if (!firstUnStyledRG || !rgFrame->HasStyleHeight()) {
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
nsRect rowRect;
|
||||
rowFrame->GetRect(rowRect);
|
||||
// see if there is an eligible row
|
||||
if (!firstUnStyledRow || !rowFrame->HasStyleHeight()) {
|
||||
// The amount of additional space each row gets is proportional to its height
|
||||
float percent = rowRect.height / ((float)divisor);
|
||||
// give rows their percentage, except for the last row which gets the remainder
|
||||
nscoord amountForRow = (rowFrame == lastElligibleRow)
|
||||
? aAmount - amountUsed : NSToCoordRound(((float)(pctBasis)) * percent);
|
||||
amountForRow = PR_MIN(nsTableFrame::RoundToPixel(amountForRow, p2t), aAmount - amountUsed);
|
||||
// update the row height
|
||||
nsRect newRowRect(rowRect.x, yOriginRow, rowRect.width, rowRect.height + amountForRow);
|
||||
rowFrame->SetRect(aPresContext, newRowRect);
|
||||
yOriginRow += newRowRect.height + cellSpacingY;
|
||||
yEndRG += newRowRect.height + cellSpacingY;
|
||||
|
||||
amountUsed += amountForRow;
|
||||
amountUsedByRG += amountForRow;
|
||||
NS_ASSERTION((amountUsed <= aAmount), "invalid row allocation");
|
||||
//rowFrame->DidResize(aPresContext, aReflowState);
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
else {
|
||||
if (amountUsed > 0) {
|
||||
rowFrame->MoveTo(aPresContext, rowRect.x, yOriginRow);
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
}
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
if (amountUsed > 0) {
|
||||
rgRect.y = yOriginRG;
|
||||
rgRect.height += amountUsedByRG;
|
||||
rgFrame->SetRect(aPresContext, rgRect);
|
||||
}
|
||||
// Make sure child views are properly positioned
|
||||
// XXX what happens if childFrame is a scroll frame and this gets skipped? see also below
|
||||
}
|
||||
else if (amountUsed > 0) {
|
||||
rgFrame->MoveTo(aPresContext, 0, yOriginRG);
|
||||
// Make sure child views are properly positioned
|
||||
nsTableFrame::RePositionViews(aPresContext, rgFrame);
|
||||
}
|
||||
yOriginRG = yEndRG;
|
||||
}
|
||||
|
||||
ResizeCells(*this, aPresContext, aReflowState);
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateCol(nsTableFrame& aTableFrame,
|
||||
nsTableColFrame& aColFrame,
|
||||
@ -3435,6 +3590,17 @@ UpdateCol(nsTableFrame& aTableFrame,
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsTableFrame::IsPctHeight(nsIStyleContext* aStyleContext)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
if (aStyleContext) {
|
||||
nsStylePosition* position = (nsStylePosition*)aStyleContext->GetStyleData(eStyleStruct_Position);
|
||||
result = (eStyleUnit_Percent == position->mHeight.GetUnit());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsTableFrame::CellChangedWidth(const nsTableCellFrame& aCellFrame,
|
||||
nscoord aPrevCellMin,
|
||||
@ -4370,9 +4536,20 @@ NS_IMETHODIMP nsTableFrame::GetTableSize(PRInt32& aRowCount, PRInt32& aColCount)
|
||||
PRInt32 nsTableFrame::GetNumCellsOriginatingInCol(PRInt32 aColIndex) const
|
||||
{
|
||||
nsTableCellMap* cellMap = GetCellMap();
|
||||
return cellMap->GetNumCellsOriginatingInCol(aColIndex);
|
||||
if (cellMap)
|
||||
return cellMap->GetNumCellsOriginatingInCol(aColIndex);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32 nsTableFrame::GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const
|
||||
{
|
||||
nsTableCellMap* cellMap = GetCellMap();
|
||||
if (cellMap)
|
||||
return cellMap->GetNumCellsOriginatingInRow(aRowIndex);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
@ -4477,7 +4654,11 @@ void nsTableFrame::DebugReflow(nsIFrame* aFrame,
|
||||
if (!aMetrics) { // start
|
||||
PrettyUC(aState.availableWidth, width);
|
||||
PrettyUC(aState.availableHeight, height);
|
||||
printf("r=%d a=%s,%s ", aState.reason, width, height);
|
||||
printf("r=%d ", aState.reason);
|
||||
if (aState.mFlags.mSpecialTableReflow) {
|
||||
printf("special ");
|
||||
}
|
||||
printf("a=%s,%s ", width, height);
|
||||
PrettyUC(aState.mComputedWidth, width);
|
||||
PrettyUC(aState.mComputedHeight, height);
|
||||
printf("c=%s,%s ", width, height);
|
||||
|
||||
@ -207,6 +207,8 @@ public:
|
||||
float aPixelToTwips,
|
||||
nsPixelRound aRound= eAlwaysRoundUp);
|
||||
|
||||
static void NotifyAncestorsOfSpecialReflow(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
NS_IMETHOD IsPercentageBase(PRBool& aBase) const;
|
||||
|
||||
static nsresult AppendDirtyReflowCommand(nsIPresShell* aPresShell,
|
||||
@ -258,6 +260,7 @@ public:
|
||||
nsIAtom* aChildType);
|
||||
PRBool IsAutoWidth(PRBool* aIsPctWidth = nsnull);
|
||||
PRBool IsAutoHeight();
|
||||
static PRBool IsPctHeight(nsIStyleContext* aStyleContext);
|
||||
|
||||
/** @return PR_TRUE if aDisplayType represents a rowgroup of any sort
|
||||
* (header, footer, or body)
|
||||
@ -491,14 +494,18 @@ public:
|
||||
PRInt32* aColSpan = nsnull);
|
||||
|
||||
PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
|
||||
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;
|
||||
|
||||
PRBool HasPctCol() const;
|
||||
void SetHasPctCol(PRBool aValue);
|
||||
|
||||
PRBool HasCellSpanningPctCol() const;
|
||||
void SetHasCellSpanningPctCol(PRBool aValue);
|
||||
// is this the 3rd reflow due to a height on a table in pagination mode.
|
||||
PRBool IsThirdPassReflow() const;
|
||||
|
||||
PRBool NeedSpecialReflow() const;
|
||||
void SetNeedSpecialReflow(PRBool aValue);
|
||||
PRBool NeedToInitiateSpecialReflow() const;
|
||||
void SetNeedToInitiateSpecialReflow(PRBool aValue);
|
||||
|
||||
protected:
|
||||
|
||||
@ -527,7 +534,6 @@ protected:
|
||||
void SetDescendantReflowedNotTimeout(PRBool aValue);
|
||||
PRBool RequestedTimeoutReflow() const;
|
||||
void SetRequestedTimeoutReflow(PRBool aValue);
|
||||
void SetThirdPassReflow(PRBool aValue);
|
||||
|
||||
void InterruptNotification(nsIPresContext* aPresContext,
|
||||
PRBool aIsRequest);
|
||||
@ -652,18 +658,12 @@ protected:
|
||||
// reflow state, and for the table attributes and parent
|
||||
nscoord CalcDesiredHeight(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState);
|
||||
// The following two functions are helpers for CalcDesiredHeight
|
||||
|
||||
// The following is a helper for CalcDesiredHeight
|
||||
|
||||
void DistributeSpaceToCells(nsIPresContext* aPresContext,
|
||||
void DistributeHeightToRows(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame* aRowGroupFrame);
|
||||
void DistributeSpaceToRows(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame* aRowGroupFrame,
|
||||
nscoord aSumOfRowHeights,
|
||||
nscoord aExcess,
|
||||
nscoord& aExcessAllocated,
|
||||
nscoord& aRowGroupYPos);
|
||||
nscoord aAmount);
|
||||
|
||||
void PlaceChild(nsIPresContext* aPresContext,
|
||||
nsTableReflowState& aReflowState,
|
||||
@ -830,8 +830,6 @@ public: /* ----- Cell Map public methods ----- */
|
||||
// percentage height cells
|
||||
void ComputePercentBasisForRows(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
nscoord GetPercentBasisForRows();
|
||||
|
||||
nscoord GetMinWidth() const;
|
||||
void SetMinWidth(nscoord aWidth);
|
||||
|
||||
@ -895,8 +893,9 @@ protected:
|
||||
// targeted at us, as an optimization.
|
||||
unsigned mRequestedTimeoutReflow:1;
|
||||
unsigned mRowInserted:1;
|
||||
unsigned mThirdPassReflow:1;
|
||||
int : 21; // unused
|
||||
unsigned mNeedSpecialReflow:1;
|
||||
unsigned mNeedToInitiateSpecialReflow:1;
|
||||
int : 19; // unused
|
||||
} mBits;
|
||||
|
||||
nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
|
||||
@ -941,11 +940,6 @@ inline PRBool nsTableFrame::IsRowGroup(PRInt32 aDisplayType) const
|
||||
(NS_STYLE_DISPLAY_TABLE_ROW_GROUP == aDisplayType));
|
||||
}
|
||||
|
||||
inline nscoord nsTableFrame::GetPercentBasisForRows()
|
||||
{
|
||||
return mPercentBasisForRows;
|
||||
}
|
||||
|
||||
inline void nsTableFrame::SetHadInitialReflow(PRBool aValue)
|
||||
{
|
||||
mBits.mHadInitialReflow = aValue;
|
||||
@ -1006,16 +1000,25 @@ inline void nsTableFrame::SetRequestedTimeoutReflow(PRBool aValue)
|
||||
mBits.mRequestedTimeoutReflow = (unsigned)aValue;
|
||||
}
|
||||
|
||||
inline PRBool nsTableFrame::IsThirdPassReflow() const
|
||||
inline PRBool nsTableFrame::NeedSpecialReflow() const
|
||||
{
|
||||
return (PRBool)mBits.mThirdPassReflow;
|
||||
return (PRBool)mBits.mNeedSpecialReflow;
|
||||
}
|
||||
|
||||
inline void nsTableFrame::SetThirdPassReflow(PRBool aValue)
|
||||
inline void nsTableFrame::SetNeedSpecialReflow(PRBool aValue)
|
||||
{
|
||||
mBits.mThirdPassReflow = (unsigned)aValue;
|
||||
mBits.mNeedSpecialReflow = (unsigned)aValue;
|
||||
}
|
||||
|
||||
inline PRBool nsTableFrame::NeedToInitiateSpecialReflow() const
|
||||
{
|
||||
return (PRBool)mBits.mNeedToInitiateSpecialReflow;
|
||||
}
|
||||
|
||||
inline void nsTableFrame::SetNeedToInitiateSpecialReflow(PRBool aValue)
|
||||
{
|
||||
mBits.mNeedToInitiateSpecialReflow = (unsigned)aValue;
|
||||
}
|
||||
inline PRBool nsTableFrame::IsRowInserted() const
|
||||
{
|
||||
return (PRBool)mBits.mRowInserted;
|
||||
|
||||
@ -94,6 +94,42 @@ nsTableCellReflowState::nsTableCellReflowState(nsIPresContext* aPresCon
|
||||
FixUp(aAvailSpace);
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::SetFixedHeight(nscoord aValue)
|
||||
{
|
||||
if (!HasPctHeight()) {
|
||||
nscoord height = PR_MAX(0, aValue);
|
||||
if (HasFixedHeight()) {
|
||||
if (height > mStyleHeight) {
|
||||
mStyleHeight = height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mStyleHeight = height;
|
||||
if (height > 0) {
|
||||
SetHasFixedHeight(PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::SetPctHeight(float aPctValue)
|
||||
{
|
||||
nscoord height = PR_MAX(0, NSToCoordRound(aPctValue * 100.0f));
|
||||
if (HasPctHeight()) {
|
||||
if (height > mStyleHeight) {
|
||||
mStyleHeight = height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mStyleHeight = height;
|
||||
if (height > 0.0f) {
|
||||
SetHasPctHeight(PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsTableCellReflowState::FixUp(const nsSize& aAvailSpace)
|
||||
{
|
||||
// fix the mComputed values during a pass 2 reflow since the cell can be a percentage base
|
||||
@ -121,15 +157,13 @@ TallestCellGotShorter(nscoord aOld,
|
||||
return ((aNew < aOld) && (aOld == aTallest));
|
||||
}
|
||||
|
||||
/* ----------- nsTableRowpFrame ---------- */
|
||||
/* ----------- nsTableRowFrame ---------- */
|
||||
|
||||
nsTableRowFrame::nsTableRowFrame()
|
||||
: nsHTMLContainerFrame(),
|
||||
mAllBits(0)
|
||||
: nsHTMLContainerFrame()
|
||||
{
|
||||
mBits.mMinRowSpan = 1;
|
||||
mBits.mRowIndex = 0;
|
||||
ResetTallestCell(0);
|
||||
mBits.mRowIndex = mBits.mFirstInserted = 0;
|
||||
ResetHeight(0);
|
||||
#ifdef DEBUG_TABLE_REFLOW_TIMING
|
||||
mTimer = new nsReflowTimer(this);
|
||||
#endif
|
||||
@ -329,6 +363,20 @@ GetHeightOfRowsSpannedBelowFirst(nsTableCellFrame& aTableCellFrame,
|
||||
return height;
|
||||
}
|
||||
|
||||
nsTableCellFrame*
|
||||
nsTableRowFrame::GetFirstCell()
|
||||
{
|
||||
nsIFrame* childFrame = mFrames.FirstChild();
|
||||
while (childFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
childFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
|
||||
return (nsTableCellFrame*)childFrame;
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-reflow hook. This is where the table row does its post-processing
|
||||
@ -390,43 +438,53 @@ nscoord nsTableRowFrame::GetMaxCellAscent() const
|
||||
return mMaxCellAscent;
|
||||
}
|
||||
|
||||
#if 0 // nobody uses this
|
||||
// returns max-descent amongst all cells that have 'vertical-align: baseline'
|
||||
// does *not* include cells with rowspans
|
||||
nscoord nsTableRowFrame::GetMaxCellDescent() const
|
||||
nscoord
|
||||
nsTableRowFrame::GetHeight(nscoord aPctBasis) const
|
||||
{
|
||||
return mMaxCellDescent;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** returns the height of the tallest child in this row (ignoring any cell with rowspans) */
|
||||
nscoord nsTableRowFrame::GetTallestCell() const
|
||||
{
|
||||
return mTallestCell;
|
||||
nscoord height = 0;
|
||||
if ((aPctBasis > 0) && HasPctHeight()) {
|
||||
height = NSToCoordRound(GetPctHeight() * (float)aPctBasis);
|
||||
}
|
||||
else if (HasFixedHeight()) {
|
||||
height = GetFixedHeight();
|
||||
}
|
||||
return PR_MAX(height, GetContentHeight());
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::ResetTallestCell(nscoord aRowStyleHeight)
|
||||
nsTableRowFrame::ResetHeight(nscoord aFixedHeight)
|
||||
{
|
||||
mTallestCell = (NS_UNCONSTRAINEDSIZE == aRowStyleHeight) ? 0 : aRowStyleHeight;
|
||||
SetHasFixedHeight(PR_FALSE);
|
||||
SetHasPctHeight(PR_FALSE);
|
||||
SetFixedHeight(0);
|
||||
SetContentHeight(0);
|
||||
|
||||
if (aFixedHeight > 0) {
|
||||
SetFixedHeight(aFixedHeight);
|
||||
}
|
||||
|
||||
mMaxCellAscent = 0;
|
||||
mMaxCellDescent = 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::SetTallestCell(nscoord aHeight,
|
||||
nscoord aAscent,
|
||||
nscoord aDescent,
|
||||
nsTableFrame* aTableFrame,
|
||||
nsTableCellFrame* aCellFrame)
|
||||
nsTableRowFrame::UpdateHeight(nscoord aHeight,
|
||||
nscoord aAscent,
|
||||
nscoord aDescent,
|
||||
nsTableFrame* aTableFrame,
|
||||
nsTableCellFrame* aCellFrame)
|
||||
{
|
||||
NS_ASSERTION((aTableFrame && aCellFrame) , "invalid call");
|
||||
if (!aTableFrame || !aCellFrame) {
|
||||
NS_ASSERTION(PR_FALSE , "invalid call");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aHeight != NS_UNCONSTRAINEDSIZE) {
|
||||
if (!(aCellFrame->HasVerticalAlignBaseline())) { // only the cell's height matters
|
||||
if (mTallestCell < aHeight) {
|
||||
if (GetHeight() < aHeight) {
|
||||
PRInt32 rowSpan = aTableFrame->GetEffectiveRowSpan(*aCellFrame);
|
||||
if (rowSpan == 1) {
|
||||
mTallestCell = aHeight;
|
||||
SetContentHeight(aHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,21 +502,23 @@ nsTableRowFrame::SetTallestCell(nscoord aHeight,
|
||||
}
|
||||
}
|
||||
// keep the tallest height in sync
|
||||
if (mTallestCell < mMaxCellAscent + mMaxCellDescent) {
|
||||
mTallestCell = mMaxCellAscent + mMaxCellDescent;
|
||||
if (GetHeight() < mMaxCellAscent + mMaxCellDescent) {
|
||||
SetContentHeight(mMaxCellAscent + mMaxCellDescent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::CalcTallestCell()
|
||||
nscoord
|
||||
nsTableRowFrame::CalcHeight(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (NS_FAILED(rv)) return;
|
||||
if (!tableFrame) return 0;
|
||||
|
||||
ResetTallestCell(0);
|
||||
nscoord computedHeight = (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight)
|
||||
? 0 : aReflowState.mComputedHeight;
|
||||
ResetHeight(computedHeight);
|
||||
|
||||
for (nsIFrame* kidFrame = mFrames.FirstChild(); kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
@ -470,9 +530,10 @@ nsTableRowFrame::CalcTallestCell()
|
||||
// height may have changed, adjust descent to absorb any excess difference
|
||||
nscoord ascent = ((nsTableCellFrame *)kidFrame)->GetDesiredAscent();
|
||||
nscoord descent = desSize.height - ascent;
|
||||
SetTallestCell(desSize.height, ascent, descent, tableFrame, (nsTableCellFrame*)kidFrame);
|
||||
UpdateHeight(desSize.height, ascent, descent, tableFrame, (nsTableCellFrame*)kidFrame);
|
||||
}
|
||||
}
|
||||
return GetHeight();
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -648,49 +709,6 @@ nsTableRowFrame::GetFrameForPoint(nsIPresContext* aPresContext,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* GetMinRowSpan is needed for deviant cases where every cell in a row has a rowspan > 1.
|
||||
* It sets mMinRowSpan, which is used in FixMinCellHeight
|
||||
*/
|
||||
void nsTableRowFrame::GetMinRowSpan(nsTableFrame *aTableFrame)
|
||||
{
|
||||
PRInt32 minRowSpan=-1;
|
||||
nsIFrame* frame = mFrames.FirstChild();
|
||||
while (frame)
|
||||
{
|
||||
const nsStyleDisplay *kidDisplay;
|
||||
frame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)kidDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
|
||||
{
|
||||
PRInt32 rowSpan = aTableFrame->GetEffectiveRowSpan((nsTableCellFrame &)*frame);
|
||||
if (-1==minRowSpan)
|
||||
minRowSpan = rowSpan;
|
||||
else if (minRowSpan>rowSpan)
|
||||
minRowSpan = rowSpan;
|
||||
}
|
||||
frame->GetNextSibling(&frame);
|
||||
}
|
||||
mBits.mMinRowSpan = unsigned(minRowSpan);
|
||||
}
|
||||
|
||||
void nsTableRowFrame::FixMinCellHeight(nsTableFrame *aTableFrame)
|
||||
{
|
||||
nsIFrame* frame = mFrames.FirstChild();
|
||||
while (frame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
frame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
|
||||
PRInt32 rowSpan = aTableFrame->GetEffectiveRowSpan((nsTableCellFrame &)*frame);
|
||||
if (PRInt32(mBits.mMinRowSpan) == rowSpan) {
|
||||
nsRect rect;
|
||||
frame->GetRect(rect);
|
||||
if (rect.height > mTallestCell)
|
||||
mTallestCell = rect.height;
|
||||
}
|
||||
}
|
||||
frame->GetNextSibling(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the cell's actual size given its pass2 desired width and height.
|
||||
// Takes into account the specified height (in the style), and any special logic
|
||||
// needed for backwards compatibility.
|
||||
@ -701,37 +719,37 @@ nsTableRowFrame::CalculateCellActualSize(nsIFrame* aCellFrame,
|
||||
nscoord& aDesiredHeight,
|
||||
nscoord aAvailWidth)
|
||||
{
|
||||
nscoord specifiedHeight = 0;
|
||||
const nsStylePosition* position;
|
||||
nscoord specifiedHeight = 0;
|
||||
|
||||
// Get the height specified in the style information
|
||||
const nsStylePosition* position;
|
||||
aCellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position);
|
||||
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (!tableFrame) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan((nsTableCellFrame&)*aCellFrame);
|
||||
|
||||
switch (position->mHeight.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
specifiedHeight = position->mHeight.GetCoordValue();
|
||||
if (1 == rowSpan)
|
||||
SetFixedHeight(specifiedHeight);
|
||||
break;
|
||||
case eStyleUnit_Percent: {
|
||||
nsTableFrame* table = nsnull;
|
||||
nsTableFrame::GetTableFrame(this, table);
|
||||
if (table) {
|
||||
nscoord basis = table->GetPercentBasisForRows();
|
||||
if (basis > 0) {
|
||||
float percent = position->mHeight.GetPercentValue();
|
||||
specifiedHeight = NSToCoordRound(percent * ((float)basis));
|
||||
}
|
||||
}
|
||||
if (1 == rowSpan)
|
||||
SetPctHeight(position->mHeight.GetPercentValue());
|
||||
// pct heights are handled when all of the cells are finished, so don't set specifiedHeight
|
||||
break;
|
||||
}
|
||||
case eStyleUnit_Inherit:
|
||||
// XXX for now, do nothing
|
||||
case eStyleUnit_Auto:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// If the specified height is greater than the desired height, then use the
|
||||
// specified height
|
||||
// If the specified height is greater than the desired height, then use the specified height
|
||||
if (specifiedHeight > aDesiredHeight)
|
||||
aDesiredHeight = specifiedHeight;
|
||||
|
||||
@ -865,6 +883,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
PRInt32 prevColIndex = firstPrevColIndex;
|
||||
nscoord x = 0; // running total of children x offset
|
||||
|
||||
nsTableFrame* tableFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
|
||||
PRBool isAutoLayout = tableFrame->IsAutoLayout();
|
||||
PRBool needToNotifyTable = PR_TRUE;
|
||||
// Reflow each of our existing cell frames
|
||||
@ -874,14 +893,21 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
nsFrameState frameState;
|
||||
kidFrame->GetFrameState(&frameState);
|
||||
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
kidFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
|
||||
// See if we should only reflow the dirty child frames
|
||||
PRBool doReflowChild = PR_TRUE;
|
||||
if (aDirtyOnly && ((frameState & NS_FRAME_IS_DIRTY) == 0)) {
|
||||
doReflowChild = PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
kidFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
if (!isPaginated && (nsLayoutAtoms::tableCellFrame == frameType.get() &&
|
||||
!((nsTableCellFrame*)kidFrame)->NeedSpecialReflow())) {
|
||||
kidFrame = iter.Next();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Reflow the child frame
|
||||
if (doReflowChild) {
|
||||
@ -919,7 +945,9 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
if ((availCellWidth != cellFrame->GetPriorAvailWidth()) ||
|
||||
(cellDesiredSize.width > cellFrame->GetPriorAvailWidth()) ||
|
||||
(eReflowReason_StyleChange == aReflowState.reason) ||
|
||||
isPaginated) {
|
||||
isPaginated ||
|
||||
(aReflowState.mFlags.mSpecialTableReflow && cellFrame->NeedSpecialReflow()) ||
|
||||
HasPctHeight()) {
|
||||
// Reflow the cell to fit the available width, height
|
||||
nsSize kidAvailSize(availColWidth, aReflowState.availableHeight);
|
||||
nsReflowReason reason = eReflowReason_Resize;
|
||||
@ -1002,7 +1030,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
// height may have changed, adjust descent to absorb any excess difference
|
||||
nscoord ascent = cellFrame->GetDesiredAscent();
|
||||
nscoord descent = desiredSize.height - ascent;
|
||||
SetTallestCell(desiredSize.height, ascent, descent, tableFrame, cellFrame);
|
||||
UpdateHeight(desiredSize.height, ascent, descent, tableFrame, cellFrame);
|
||||
|
||||
// Place the child
|
||||
if (NS_UNCONSTRAINEDSIZE != availColWidth) {
|
||||
@ -1037,8 +1065,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
|
||||
// just set our width to what was available. The table will calculate the width and not use our value.
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
CalcTallestCell();
|
||||
aDesiredSize.height = GetTallestCell();
|
||||
aDesiredSize.height = CalcHeight(aReflowState);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -1050,7 +1077,7 @@ NS_METHOD nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresConte
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
CalcTallestCell(); // need to recalculate it based on last reflow sizes
|
||||
CalcHeight(aReflowState); // need to recalculate it based on last reflow sizes
|
||||
|
||||
// determine if this frame is the target or not
|
||||
nsIFrame* target = nsnull;
|
||||
@ -1193,7 +1220,7 @@ nsTableRowFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
|
||||
if (!hasVerticalAlignBaseline) {
|
||||
// only the height matters
|
||||
tallestCellGotShorter =
|
||||
TallestCellGotShorter(oldCellDesSize.height, cellMet.height, mTallestCell);
|
||||
TallestCellGotShorter(oldCellDesSize.height, cellMet.height, GetHeight());
|
||||
}
|
||||
else {
|
||||
// the ascent matters
|
||||
@ -1209,10 +1236,10 @@ nsTableRowFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
if (tallestCellGotShorter) {
|
||||
CalcTallestCell();
|
||||
CalcHeight(aReflowState);
|
||||
}
|
||||
else {
|
||||
SetTallestCell(cellMet.height, cellMet.ascent, cellMet.descent, &aTableFrame, cellFrame);
|
||||
UpdateHeight(cellMet.height, cellMet.ascent, cellMet.descent, &aTableFrame, cellFrame);
|
||||
}
|
||||
|
||||
// if the cell's desired size didn't changed, our height is unchanged
|
||||
@ -1232,7 +1259,7 @@ nsTableRowFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
}
|
||||
aDesiredSize.height = (aDesiredSize.mNothingChanged) ? mRect.height : GetTallestCell();
|
||||
aDesiredSize.height = (aDesiredSize.mNothingChanged) ? mRect.height : GetHeight();
|
||||
if (1 == rowSpan) {
|
||||
cellMet.height = aDesiredSize.height;
|
||||
}
|
||||
@ -1308,25 +1335,19 @@ nsTableRowFrame::Reflow(nsIPresContext* aPresContext,
|
||||
rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (!tableFrame) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) && !mPrevInFlow) {
|
||||
// see if an extra reflow will be necessary when there is a pct height but no height on the parent
|
||||
if ( ((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) ||
|
||||
(0 == aReflowState.mComputedHeight)) &&
|
||||
nsTableFrame::IsPctHeight(mStyleContext)) {
|
||||
nsTableFrame::NotifyAncestorsOfSpecialReflow(aReflowState);
|
||||
SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
switch (aReflowState.reason) {
|
||||
case eReflowReason_Initial:
|
||||
rv = ReflowChildren(aPresContext, aDesiredSize, aReflowState, *tableFrame, aStatus, PR_FALSE);
|
||||
#ifdef WHY
|
||||
if (!tableFrame->IsAutoLayout()) {
|
||||
// this resize reflow is necessary to place the cells correctly in the case of rowspans and colspans.
|
||||
// It is very efficient. It does not actually need to pass a reflow down to the cells.
|
||||
nsSize availSpace(aReflowState.availableWidth, aReflowState.availableHeight);
|
||||
nsHTMLReflowState resizeReflowState(aPresContext,
|
||||
(const nsHTMLReflowState&)(*(aReflowState.parentReflowState)),
|
||||
(nsIFrame *)this,
|
||||
availSpace,
|
||||
eReflowReason_Resize);
|
||||
RowReflowState rowResizeReflowState(resizeReflowState, tableFrame);
|
||||
rv = ReflowChildren(aPresContext, aDesiredSize, rowResizeReflowState, aStatus);
|
||||
}
|
||||
#endif
|
||||
//GetMinRowSpan(tableFrame);
|
||||
//FixMinCellHeight(tableFrame);
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
break;
|
||||
|
||||
@ -1343,6 +1364,10 @@ nsTableRowFrame::Reflow(nsIPresContext* aPresContext,
|
||||
// just set our width to what was available. The table will calculate the width and not use our value.
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
SetNeedSpecialReflow(PR_FALSE);
|
||||
}
|
||||
|
||||
#if defined DEBUG_TABLE_REFLOW_TIMING
|
||||
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aReflowState, &aDesiredSize, aStatus);
|
||||
#endif
|
||||
@ -1463,6 +1488,21 @@ nsTableRowFrame::GetFrameType(nsIAtom** aType) const
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsTableRowFrame*
|
||||
nsTableRowFrame::GetNextRow() const
|
||||
{
|
||||
nsIFrame* childFrame;
|
||||
GetNextSibling(&childFrame);
|
||||
while (childFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
childFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableRowFrame == frameType.get()) {
|
||||
return (nsTableRowFrame*)childFrame;
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/* ----- global methods ----- */
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ class nsTableCellFrame;
|
||||
class nsReflowTimer;
|
||||
#endif
|
||||
|
||||
#define NS_TABLE_MAX_ROW_INDEX (1<<19)
|
||||
#define NS_ROW_NEED_SPECIAL_REFLOW 0x20000000
|
||||
#define NS_ROW_FRAME_PAINT_SKIP_ROW 0x00000001
|
||||
#define NS_ROW_FRAME_PAINT_SKIP_CELLS 0x00000002
|
||||
|
||||
@ -121,6 +121,8 @@ public:
|
||||
nsFramePaintLayer aWhichLayer,
|
||||
nsIFrame** aFrame);
|
||||
|
||||
nsTableCellFrame* GetFirstCell() ;
|
||||
|
||||
/** calls Reflow for all of its child cells.
|
||||
* Cells with rowspan=1 are all set to the same height and stacked horizontally.
|
||||
* <P> Cells are not split unless absolutely necessary.
|
||||
@ -155,19 +157,17 @@ public:
|
||||
PRUint32* aResult) const;
|
||||
#endif
|
||||
|
||||
void SetTallestCell(nscoord aHeight,
|
||||
nscoord aAscent,
|
||||
nscoord aDescent,
|
||||
nsTableFrame* aTableFrame = nsnull,
|
||||
nsTableCellFrame* aCellFrame = nsnull);
|
||||
void UpdateHeight(nscoord aHeight,
|
||||
nscoord aAscent,
|
||||
nscoord aDescent,
|
||||
nsTableFrame* aTableFrame = nsnull,
|
||||
nsTableCellFrame* aCellFrame = nsnull);
|
||||
|
||||
void ResetTallestCell(nscoord aRowStyleHeight);
|
||||
void ResetHeight(nscoord aRowStyleHeight);
|
||||
|
||||
// calculate the tallest child when the previous tallest child gets shorter
|
||||
void CalcTallestCell();
|
||||
|
||||
/** returns the tallest child in this row (ignoring any cell with rowspans) */
|
||||
nscoord GetTallestCell() const;
|
||||
// calculate the height, considering content height of the
|
||||
// cells and the style height of the row and cells, excluding pct heights
|
||||
nscoord CalcHeight(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
// Support for cells with 'vertical-align: baseline'.
|
||||
|
||||
@ -210,14 +210,38 @@ public:
|
||||
|
||||
void RemoveCellFrame(nsTableCellFrame* aFrame);
|
||||
|
||||
nsresult CalculateCellActualSize(nsIFrame* aRowFrame,
|
||||
nscoord& aDesiredWidth,
|
||||
nscoord& aDesiredHeight,
|
||||
nscoord aAvailWidth);
|
||||
nsresult CalculateCellActualSize(nsIFrame* aRowFrame,
|
||||
nscoord& aDesiredWidth,
|
||||
nscoord& aDesiredHeight,
|
||||
nscoord aAvailWidth);
|
||||
|
||||
PRBool IsFirstInserted() const;
|
||||
void SetFirstInserted(PRBool aValue);
|
||||
|
||||
PRBool NeedSpecialReflow() const;
|
||||
void SetNeedSpecialReflow(PRBool aValue);
|
||||
|
||||
PRBool GetContentHeight() const;
|
||||
void SetContentHeight(nscoord aTwipValue);
|
||||
|
||||
PRBool HasStyleHeight() const;
|
||||
|
||||
PRBool HasFixedHeight() const;
|
||||
void SetHasFixedHeight(PRBool aValue);
|
||||
|
||||
PRBool HasPctHeight() const;
|
||||
void SetHasPctHeight(PRBool aValue);
|
||||
|
||||
nscoord GetFixedHeight() const;
|
||||
void SetFixedHeight(nscoord aValue);
|
||||
|
||||
float GetPctHeight() const;
|
||||
void SetPctHeight(float aPctValue);
|
||||
|
||||
nscoord GetHeight(nscoord aBasis = 0) const;
|
||||
|
||||
nsTableRowFrame* GetNextRow() const;
|
||||
|
||||
protected:
|
||||
|
||||
/** protected constructor.
|
||||
@ -262,10 +286,6 @@ protected:
|
||||
|
||||
// row-specific methods
|
||||
|
||||
void GetMinRowSpan(nsTableFrame *aTableFrame);
|
||||
|
||||
void FixMinCellHeight(nsTableFrame *aTableFrame);
|
||||
|
||||
nscoord ComputeCellXOffset(const nsHTMLReflowState& aState,
|
||||
nsIFrame* aKidFrame,
|
||||
const nsMargin& aKidMargin) const;
|
||||
@ -280,19 +300,18 @@ protected:
|
||||
nsReflowStatus& aStatus,
|
||||
PRBool aDirtyOnly = PR_FALSE);
|
||||
|
||||
public:
|
||||
struct RowBits {
|
||||
int mRowIndex:20;
|
||||
unsigned mMinRowSpan:11; // the smallest row span among all my child cells
|
||||
unsigned mFirstInserted; // if true, then it was the top most newly inserted row
|
||||
};
|
||||
|
||||
private:
|
||||
union {
|
||||
PRUint32 mAllBits;
|
||||
RowBits mBits;
|
||||
};
|
||||
nscoord mTallestCell; // not my height, but the height of my tallest child
|
||||
struct RowBits {
|
||||
unsigned mRowIndex:29;
|
||||
unsigned mHasFixedHeight:1; // set if the dominating style height on the row or any cell is pixel based
|
||||
unsigned mHasPctHeight:1; // set if the dominating style height on the row or any cell is pct based
|
||||
unsigned mFirstInserted:1; // if true, then it was the top most newly inserted row
|
||||
} mBits;
|
||||
|
||||
nscoord mContentHeight; // the desired height based on the content of the tallest cell in the row
|
||||
nscoord mStyleHeight; // the height based on a style pct on either the row or any cell if mHasPctHeight
|
||||
// is set, otherwise the height based on a style pixel height on the row or any
|
||||
// cell if mHasFixedHeight is set
|
||||
|
||||
// max-ascent and max-descent amongst all cells that have 'vertical-align: baseline'
|
||||
nscoord mMaxCellAscent; // does include cells with rowspan > 1
|
||||
@ -311,7 +330,6 @@ inline PRInt32 nsTableRowFrame::GetRowIndex() const
|
||||
|
||||
inline void nsTableRowFrame::SetRowIndex (int aRowIndex)
|
||||
{
|
||||
NS_PRECONDITION(aRowIndex < NS_TABLE_MAX_ROW_INDEX, "unexpected row index");
|
||||
mBits.mRowIndex = aRowIndex;
|
||||
}
|
||||
|
||||
@ -325,4 +343,68 @@ inline void nsTableRowFrame::SetFirstInserted(PRBool aValue)
|
||||
mBits.mFirstInserted = aValue;
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowFrame::HasStyleHeight() const
|
||||
{
|
||||
return (PRBool)mBits.mHasFixedHeight || (PRBool)mBits.mHasPctHeight;
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowFrame::HasFixedHeight() const
|
||||
{
|
||||
return (PRBool)mBits.mHasFixedHeight;
|
||||
}
|
||||
|
||||
inline void nsTableRowFrame::SetHasFixedHeight(PRBool aValue)
|
||||
{
|
||||
mBits.mHasFixedHeight = aValue;
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowFrame::HasPctHeight() const
|
||||
{
|
||||
return (PRBool)mBits.mHasPctHeight;
|
||||
}
|
||||
|
||||
inline void nsTableRowFrame::SetHasPctHeight(PRBool aValue)
|
||||
{
|
||||
mBits.mHasPctHeight = aValue;
|
||||
}
|
||||
|
||||
inline nscoord nsTableRowFrame::GetContentHeight() const
|
||||
{
|
||||
return mContentHeight;
|
||||
}
|
||||
|
||||
inline void nsTableRowFrame::SetContentHeight(nscoord aValue)
|
||||
{
|
||||
mContentHeight = aValue;
|
||||
}
|
||||
|
||||
inline nscoord nsTableRowFrame::GetFixedHeight() const
|
||||
{
|
||||
if (mBits.mHasFixedHeight && !mBits.mHasPctHeight)
|
||||
return mStyleHeight;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline float nsTableRowFrame::GetPctHeight() const
|
||||
{
|
||||
if (mBits.mHasPctHeight)
|
||||
return (float)mStyleHeight / 100.0f;
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowFrame::NeedSpecialReflow() const
|
||||
{
|
||||
return (mState & NS_ROW_NEED_SPECIAL_REFLOW) == NS_ROW_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
|
||||
inline void nsTableRowFrame::SetNeedSpecialReflow(PRBool aValue)
|
||||
{
|
||||
if (aValue) {
|
||||
mState |= NS_ROW_NEED_SPECIAL_REFLOW;
|
||||
} else {
|
||||
mState &= ~NS_ROW_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -105,6 +105,13 @@ nsTableRowGroupFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableRowGroupFrame::IsPercentageBase(PRBool& aBase) const
|
||||
{
|
||||
aBase = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsTableRowGroupFrame::GetRowCount()
|
||||
{
|
||||
@ -362,6 +369,9 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
|
||||
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
|
||||
|
||||
PRBool isPaginated;
|
||||
aPresContext->IsPaginated(&isPaginated);
|
||||
|
||||
if (aFirstRowReflowed) {
|
||||
*aFirstRowReflowed = nsnull;
|
||||
}
|
||||
@ -369,8 +379,11 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
PRBool adjustSiblings = PR_TRUE;
|
||||
nsIFrame* kidFrame = (aStartFrame) ? aStartFrame : mFrames.FirstChild();
|
||||
|
||||
for ( ; kidFrame; ) {
|
||||
nsTableFrame* tableFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
|
||||
for ( ; kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
|
||||
// Get the frame state bits
|
||||
nsCOMPtr<nsIAtom> kidType;
|
||||
kidFrame->GetFrameType(getter_AddRefs(kidType));
|
||||
nsFrameState frameState;
|
||||
kidFrame->GetFrameState(&frameState);
|
||||
|
||||
@ -379,6 +392,12 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
if (aDirtyOnly && ((frameState & NS_FRAME_IS_DIRTY) == 0)) {
|
||||
doReflowChild = PR_FALSE;
|
||||
}
|
||||
if (aReflowState.reflowState.mFlags.mSpecialTableReflow) {
|
||||
if (!isPaginated && (nsLayoutAtoms::tableRowFrame == kidType.get() &&
|
||||
!((nsTableRowFrame*)kidFrame)->NeedSpecialReflow())) {
|
||||
doReflowChild = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Reflow the row frame
|
||||
if (doReflowChild) {
|
||||
@ -413,9 +432,7 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
lastReflowedRow = kidFrame;
|
||||
|
||||
if (aFirstRowReflowed && !*aFirstRowReflowed) {
|
||||
nsCOMPtr<nsIAtom> fType;
|
||||
kidFrame->GetFrameType(getter_AddRefs(fType));
|
||||
if (nsLayoutAtoms::tableRowFrame == fType.get()) {
|
||||
if (nsLayoutAtoms::tableRowFrame == kidType.get()) {
|
||||
*aFirstRowReflowed = (nsTableRowFrame*)kidFrame;
|
||||
}
|
||||
}
|
||||
@ -432,8 +449,6 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
kidFrame->GetSize(kidSize);
|
||||
aReflowState.y += kidSize.height + cellSpacingY;
|
||||
}
|
||||
|
||||
kidFrame->GetNextSibling(&kidFrame); // Get the next child
|
||||
}
|
||||
|
||||
// adjust the rows after the ones that were reflowed
|
||||
@ -454,56 +469,82 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowGroupFrame::GetNextRowSibling(nsIFrame** aRowFrame)
|
||||
nsTableRowFrame*
|
||||
nsTableRowGroupFrame::GetFirstRow()
|
||||
{
|
||||
if (!*aRowFrame) return;
|
||||
GetNextFrame(*aRowFrame, aRowFrame);
|
||||
while(*aRowFrame) {
|
||||
const nsStyleDisplay *display;
|
||||
(*aRowFrame)->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == display->mDisplay) {
|
||||
return;
|
||||
nsIFrame* childFrame = GetFirstFrame();
|
||||
while (childFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
childFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableRowFrame == frameType.get()) {
|
||||
return (nsTableRowFrame*)childFrame;
|
||||
}
|
||||
GetNextFrame(*aRowFrame, aRowFrame);
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
struct RowInfo {
|
||||
unsigned height:30;
|
||||
unsigned hasStyleHeight:1;
|
||||
unsigned isSpecial:1; // there is no cell originating in the row with rowspan=1 and there are at
|
||||
// least 2 cells spanning the row and there is no style height on the row
|
||||
};
|
||||
|
||||
static void
|
||||
UpdateHeights(RowInfo& aRowInfo,
|
||||
nscoord aAdditionalHeight,
|
||||
nscoord& aTotal,
|
||||
nscoord& aUnconstrainedTotal)
|
||||
{
|
||||
aRowInfo.height += aAdditionalHeight;
|
||||
aTotal += aAdditionalHeight;
|
||||
if (!aRowInfo.hasStyleHeight) {
|
||||
aUnconstrainedTotal += aAdditionalHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate the height of rows which have no cells originating in them
|
||||
// except with cells with rowspan > 1. Store the height as negative
|
||||
// to distinguish them from regular rows.
|
||||
void
|
||||
AllocateSpecialHeight(nsIPresContext* aPresContext,
|
||||
nsTableFrame* aTableFrame,
|
||||
nsIFrame* aRowFrame,
|
||||
nscoord& aHeight)
|
||||
nsTableRowGroupFrame::DidResizeRows(nsIPresContext& aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsTableRowFrame* aStartRowFrameIn)
|
||||
{
|
||||
nsIFrame* cellFrame;
|
||||
aRowFrame->FirstChild(aPresContext, nsnull, &cellFrame);
|
||||
while (cellFrame) {
|
||||
nsCOMPtr<nsIAtom> cellType;
|
||||
cellFrame->GetFrameType(getter_AddRefs(cellType));
|
||||
if (nsLayoutAtoms::tableCellFrame == cellType.get()) {
|
||||
PRInt32 rowSpan = aTableFrame->GetEffectiveRowSpan((nsTableCellFrame&)*cellFrame);
|
||||
if (rowSpan > 1) {
|
||||
// use a simple average to allocate the special row. This is not exact,
|
||||
// but much better than nothing.
|
||||
nsSize cellDesSize = ((nsTableCellFrame*)cellFrame)->GetDesiredSize();
|
||||
((nsTableRowFrame*)aRowFrame)->CalculateCellActualSize(cellFrame, cellDesSize.width,
|
||||
cellDesSize.height, cellDesSize.width);
|
||||
PRInt32 propHeight = NSToCoordRound((float)cellDesSize.height / (float)rowSpan);
|
||||
// special rows store the largest negative value
|
||||
aHeight = PR_MIN(aHeight, -propHeight);
|
||||
}
|
||||
}
|
||||
cellFrame->GetNextSibling(&cellFrame);
|
||||
// update the cells spanning rows with their new heights
|
||||
// this is the place where all of the cells in the row get set to the height of the row
|
||||
PRInt32 rowIndex;
|
||||
nsTableRowFrame* rowFrame;
|
||||
nsTableRowFrame* startRowFrame = (aStartRowFrameIn) ? aStartRowFrameIn: GetFirstRow();
|
||||
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
|
||||
rowFrame->DidResize(&aPresContext, aReflowState);
|
||||
}
|
||||
}
|
||||
|
||||
/* CalculateRowHeights provides default heights for all rows in the rowgroup.
|
||||
* Actual row heights are ultimately determined by the table, when the table
|
||||
* height attribute is factored in.
|
||||
*/
|
||||
static PRBool
|
||||
HasMoreThanOneCell(nsTableCellMap* aCellMap,
|
||||
PRInt32 aRowIndex)
|
||||
{
|
||||
if (aCellMap) {
|
||||
CellData* cellData;
|
||||
PRInt32 colIndex = 0;
|
||||
PRInt32 count = 0;
|
||||
do {
|
||||
cellData = aCellMap->GetCellAt(aRowIndex, colIndex);
|
||||
if (cellData && (cellData->GetCellFrame() || cellData->IsRowSpan()))
|
||||
count++;
|
||||
if (count > 1)
|
||||
return PR_TRUE;
|
||||
colIndex++;
|
||||
} while(cellData);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// This calculates the height of rows starting at aStartRowFrameIn and takes into account
|
||||
// style height on the row group, style heights on rows and cells, style heights on rowspans.
|
||||
// Actual row heights will be adjusted later if the table has a style height.
|
||||
// Even if rows don't change height, this method must be called to set the heights of each
|
||||
// cell in the row to the height of its row.
|
||||
void
|
||||
nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
@ -511,280 +552,259 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
|
||||
nsTableRowFrame* aStartRowFrameIn)
|
||||
{
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (NS_FAILED(rv) || nsnull==tableFrame) return;
|
||||
nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (!aPresContext || !tableFrame) return;
|
||||
|
||||
// all table cells have the same top and bottom margins, namely cellSpacingY
|
||||
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
|
||||
float p2t;
|
||||
aPresContext->GetPixelsToTwips(&p2t);
|
||||
|
||||
// find the nearest row to the starting row (including the starting row) that isn't spanned into
|
||||
nsTableRowFrame* startRowFrame = nsnull;
|
||||
nsIFrame* childFrame = GetFirstFrame();
|
||||
PRBool foundFirstRow = PR_FALSE;
|
||||
while (childFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
childFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableRowFrame == frameType.get()) {
|
||||
PRInt32 rowIndex = ((nsTableRowFrame*)childFrame)->GetRowIndex();
|
||||
if (!foundFirstRow || !tableFrame->RowIsSpannedInto(rowIndex)) {
|
||||
startRowFrame = (nsTableRowFrame*)childFrame;
|
||||
if (!aStartRowFrameIn || (aStartRowFrameIn == startRowFrame)) break;
|
||||
// find the nearest row at or before aStartRowFrameIn that isn't spanned into.
|
||||
// If we have a computed height, then we can't compute the heights
|
||||
// incrementally from aStartRowFrameIn, and we must start at the first row.
|
||||
nsTableRowFrame* startRowFrame = GetFirstRow();
|
||||
if (aStartRowFrameIn && (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight)
|
||||
&& (aReflowState.mComputedHeight > 0)) {
|
||||
nsTableRowFrame* rowFrame = startRowFrame;
|
||||
while (rowFrame) {
|
||||
PRInt32 rowIndex = rowFrame->GetRowIndex();
|
||||
if (!tableFrame->RowIsSpannedInto(rowIndex)) {
|
||||
startRowFrame = rowFrame;
|
||||
if (aStartRowFrameIn == startRowFrame)
|
||||
break;
|
||||
}
|
||||
else if (aStartRowFrameIn == (nsTableRowFrame*)childFrame) break;
|
||||
foundFirstRow = PR_TRUE;
|
||||
else if (aStartRowFrameIn == rowFrame)
|
||||
break;
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
if (!startRowFrame) return;
|
||||
|
||||
PRInt32 startRowIndex = startRowFrame->GetRowIndex();
|
||||
|
||||
nsRect startRowRect;
|
||||
startRowFrame->GetRect(startRowRect);
|
||||
nscoord rowGroupHeight = startRowRect.y;
|
||||
// the current row group height is the y origin of the 1st row we are about to calculated a height for
|
||||
nscoord startRowGroupHeight = startRowRect.y;
|
||||
|
||||
PRInt32 numRows = GetRowCount() - (startRowFrame->GetRowIndex() - GetStartRowIndex());
|
||||
// collect the current height of each row. nscoord* rowHeights = nsnull;
|
||||
RowInfo* rowInfo;
|
||||
if (numRows > 0) {
|
||||
rowInfo = new RowInfo[numRows];
|
||||
if (!rowInfo) return;
|
||||
nsCRT::memset (rowInfo, 0, numRows*sizeof(RowInfo));
|
||||
}
|
||||
else return;
|
||||
|
||||
PRBool hasRowSpanningCell = PR_FALSE;
|
||||
PRInt32 numRows = GetRowCount() - (startRowFrame->GetRowIndex() - GetStartRowIndex());
|
||||
// collect the current height of each row. rows which have 0 height because
|
||||
// they have no cells originating in them without rowspans > 1, are referred to as
|
||||
// special rows. The current height of a special row will be a negative number until
|
||||
// it comes time to actually resize frames.
|
||||
nscoord* rowHeights = nsnull;
|
||||
if (numRows > 0) {
|
||||
rowHeights = new nscoord[numRows];
|
||||
if (!rowHeights) return;
|
||||
nsCRT::memset (rowHeights, 0, numRows*sizeof(nscoord));
|
||||
} // else - tree row groups need not have rows directly beneath them
|
||||
nscoord heightOfRows = 0;
|
||||
nscoord heightOfUnStyledRows = 0;
|
||||
// Get the height of each row without considering rowspans. This will be the max of
|
||||
// the largest desired height of each cell, the largest style height of each cell,
|
||||
// the style height of the row.
|
||||
nscoord pctHeightBasis = GetHeightBasis(aReflowState);
|
||||
nsTableRowFrame* rowFrame;
|
||||
PRInt32 rowIndex; // the index in rowInfo, not among the rows in the row group
|
||||
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
|
||||
UpdateHeights(rowInfo[rowIndex], nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctHeightBasis), p2t),
|
||||
heightOfRows, heightOfUnStyledRows);
|
||||
rowInfo[rowIndex].hasStyleHeight = rowFrame->HasStyleHeight();
|
||||
|
||||
// Step 1: get the height of the tallest cell in the row and save it for
|
||||
// pass 2. This height is for table cells that originate in this
|
||||
// row and that don't span into the rows that follow
|
||||
nsIFrame* rowFrame = startRowFrame;
|
||||
PRInt32 rowIndex = 0;
|
||||
|
||||
// For row groups that are split across pages, the first row frame won't
|
||||
// necessarily be index 0
|
||||
PRInt32 startRowIndex = -1;
|
||||
while (rowFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
rowFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableRowFrame == frameType.get()) {
|
||||
if (startRowIndex == -1) {
|
||||
startRowIndex = ((nsTableRowFrame*)rowFrame)->GetRowIndex();
|
||||
}
|
||||
// get the height of the tallest cell in the row (excluding cells that span rows)
|
||||
rowHeights[rowIndex] = ((nsTableRowFrame*)rowFrame)->GetTallestCell();
|
||||
|
||||
// See if a cell spans into the row. If so we'll have to do step 2
|
||||
if (!hasRowSpanningCell) {
|
||||
if (tableFrame->RowIsSpannedInto(rowIndex + startRowIndex)) {
|
||||
hasRowSpanningCell = PR_TRUE;
|
||||
if (!rowInfo[rowIndex].hasStyleHeight) {
|
||||
if (HasMoreThanOneCell(tableFrame->GetCellMap(), rowIndex)) {
|
||||
rowInfo[rowIndex].isSpecial = PR_TRUE;
|
||||
// iteratate the row's cell frames to see if any do not have rowspan > 1
|
||||
nsTableCellFrame* cellFrame = rowFrame->GetFirstCell();
|
||||
while (cellFrame) {
|
||||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(rowIndex + startRowIndex, *cellFrame);
|
||||
if (1 == rowSpan) {
|
||||
rowInfo[rowIndex].isSpecial = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
cellFrame = cellFrame->GetNextCell();
|
||||
}
|
||||
}
|
||||
// special rows need to have some values, so they will get allocations
|
||||
// later. If left at 0, they would get nothing.
|
||||
if (0 == rowHeights[rowIndex]) {
|
||||
AllocateSpecialHeight(aPresContext, tableFrame, rowFrame, rowHeights[rowIndex]);
|
||||
}
|
||||
rowIndex++;
|
||||
}
|
||||
GetNextFrame(rowFrame, &rowFrame); // Get the next row
|
||||
// See if a cell spans into the row. If so we'll have to do the next step
|
||||
if (!hasRowSpanningCell) {
|
||||
if (tableFrame->RowIsSpannedInto(rowIndex + startRowIndex)) {
|
||||
hasRowSpanningCell = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Now account for cells that span rows. A spanning cell's height is the sum of the heights of the
|
||||
// rows it spans, or it's own desired height, whichever is greater.
|
||||
// If the cell's desired height is the larger value, resize the rows and contained
|
||||
// cells by an equal percentage of the additional space.
|
||||
// We go through this loop twice. The first time, we are adjusting cell heights
|
||||
// on the fly. The second time through the loop, we're ensuring that subsequent
|
||||
// row-spanning cells didn't change prior calculations. Since we are guaranteed
|
||||
// to have found the max height spanners the first time through, we know we only
|
||||
// need two passes, not an arbitrary number.
|
||||
nscoord yOrigin = rowGroupHeight;
|
||||
nscoord lastCount = (hasRowSpanningCell) ? 2 : 1;
|
||||
for (PRInt32 counter = 0; counter <= lastCount; counter++) {
|
||||
rowFrame = startRowFrame;
|
||||
rowIndex = 0;
|
||||
while (rowFrame) {
|
||||
nsCOMPtr<nsIAtom> rowType;
|
||||
rowFrame->GetFrameType(getter_AddRefs(rowType));
|
||||
if (nsLayoutAtoms::tableRowFrame == rowType.get()) {
|
||||
if (hasRowSpanningCell) {
|
||||
// check this row for a cell with rowspans
|
||||
nsIFrame* cellFrame;
|
||||
rowFrame->FirstChild(aPresContext, nsnull, &cellFrame);
|
||||
while (cellFrame) {
|
||||
nsCOMPtr<nsIAtom> cellType;
|
||||
cellFrame->GetFrameType(getter_AddRefs(cellType));
|
||||
if (nsLayoutAtoms::tableCellFrame == cellType.get()) {
|
||||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(rowIndex + startRowIndex,
|
||||
(nsTableCellFrame&)*cellFrame);
|
||||
if (rowSpan > 1) { // found a cell with rowspan > 1, determine the height
|
||||
// of the rows it spans
|
||||
nscoord heightOfRowsSpanned = 0;
|
||||
nscoord cellSpacingOfRowsSpanned = 0;
|
||||
PRInt32 spanX;
|
||||
PRBool cellsOrigInSpan = PR_FALSE; // do any cells originate in the spanned rows
|
||||
for (spanX = 0; spanX < rowSpan; spanX++) {
|
||||
PRInt32 rIndex = rowIndex + spanX;
|
||||
if (rowHeights[rIndex] > 0) {
|
||||
// don't consider negative values of special rows
|
||||
heightOfRowsSpanned += rowHeights[rowIndex + spanX];
|
||||
cellsOrigInSpan = PR_TRUE;
|
||||
}
|
||||
if (0 != spanX) {
|
||||
cellSpacingOfRowsSpanned += cellSpacingY;
|
||||
}
|
||||
}
|
||||
nscoord availHeightOfRowsSpanned = heightOfRowsSpanned + cellSpacingOfRowsSpanned;
|
||||
if (hasRowSpanningCell) {
|
||||
// Get the height of cells with rowspans and allocate any extra space to the rows they span
|
||||
// iteratate the child frames and process the row frames among them
|
||||
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
|
||||
if (tableFrame->RowHasSpanningCells(startRowIndex + rowIndex)) {
|
||||
nsTableCellFrame* cellFrame = rowFrame->GetFirstCell();
|
||||
// iteratate the row's cell frames
|
||||
while (cellFrame) {
|
||||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(rowIndex + startRowIndex, *cellFrame);
|
||||
if (rowSpan > 1) { // a cell with rowspan > 1, determine the height of the rows it spans
|
||||
nscoord heightOfRowsSpanned = 0;
|
||||
nscoord heightOfUnStyledRowsSpanned = 0;
|
||||
nscoord numSpecialRowsSpanned = 0;
|
||||
nscoord cellSpacingTotal = 0;
|
||||
PRInt32 spanX;
|
||||
for (spanX = 0; spanX < rowSpan; spanX++) {
|
||||
heightOfRowsSpanned += rowInfo[rowIndex + spanX].height;
|
||||
if (!rowInfo[rowIndex + spanX].hasStyleHeight) {
|
||||
heightOfUnStyledRowsSpanned += rowInfo[rowIndex + spanX].height;
|
||||
}
|
||||
if (0 != spanX) {
|
||||
cellSpacingTotal += cellSpacingY;
|
||||
}
|
||||
if (rowInfo[rowIndex + spanX].isSpecial) {
|
||||
numSpecialRowsSpanned++;
|
||||
}
|
||||
}
|
||||
nscoord heightOfAreaSpanned = heightOfRowsSpanned + cellSpacingTotal;
|
||||
// get the height of the cell
|
||||
nsSize cellFrameSize;
|
||||
cellFrame->GetSize(cellFrameSize);
|
||||
nsSize cellDesSize = cellFrame->GetDesiredSize();
|
||||
rowFrame->CalculateCellActualSize(cellFrame, cellDesSize.width,
|
||||
cellDesSize.height, cellDesSize.width);
|
||||
cellFrameSize.height = cellDesSize.height;
|
||||
if (cellFrame->HasVerticalAlignBaseline()) {
|
||||
// to ensure that a spanning cell with a long descender doesn't
|
||||
// collide with the next row, we need to take into account the shift
|
||||
// that will be done to align the cell on the baseline of the row.
|
||||
cellFrameSize.height += rowFrame->GetMaxCellAscent() - cellFrame->GetDesiredAscent();
|
||||
}
|
||||
|
||||
// see if the cell's height fits within the rows it spans. If this is
|
||||
// pass 1 then use the cell's desired height and not the current height
|
||||
// of its frame. That way this works for incremental reflow, too
|
||||
nsSize cellFrameSize;
|
||||
cellFrame->GetSize(cellFrameSize);
|
||||
if (0 == counter) {
|
||||
nsSize cellDesSize = ((nsTableCellFrame*)cellFrame)->GetDesiredSize();
|
||||
((nsTableRowFrame*)rowFrame)->CalculateCellActualSize(cellFrame, cellDesSize.width,
|
||||
cellDesSize.height, cellDesSize.width);
|
||||
cellFrameSize.height = cellDesSize.height;
|
||||
// see if the cell has 'vertical-align: baseline'
|
||||
if (((nsTableCellFrame*)cellFrame)->HasVerticalAlignBaseline()) {
|
||||
// to ensure that a spanning cell with a long descender doesn't
|
||||
// collide with the next row, we need to take into account the shift
|
||||
// that will be done to align the cell on the baseline of the row.
|
||||
cellFrameSize.height += ((nsTableRowFrame*)rowFrame)->GetMaxCellAscent()
|
||||
- ((nsTableCellFrame*)cellFrame)->GetDesiredAscent();
|
||||
}
|
||||
}
|
||||
|
||||
if (availHeightOfRowsSpanned >= cellFrameSize.height) {
|
||||
// the cell's height fits with the available space of the rows it
|
||||
// spans. Set the cell frame's height
|
||||
cellFrame->SizeTo(aPresContext, cellFrameSize.width, availHeightOfRowsSpanned);
|
||||
// Realign cell content based on new height
|
||||
((nsTableCellFrame*)cellFrame)->VerticallyAlignChild(aPresContext, aReflowState, ((nsTableRowFrame*)rowFrame)->GetMaxCellAscent());
|
||||
}
|
||||
else {
|
||||
// the cell's height is larger than the available space of the rows it
|
||||
// spans so distribute the excess height to the rows affected
|
||||
nscoord excessAvail = cellFrameSize.height - availHeightOfRowsSpanned;
|
||||
nscoord excessBasis = excessAvail;
|
||||
|
||||
nsTableRowFrame* rowFrameToBeResized = (nsTableRowFrame *)rowFrame;
|
||||
// iterate every row starting at last row spanned and up to the row with
|
||||
// the spanning cell. do this bottom up so that special rows can get a full
|
||||
// allocation before other rows.
|
||||
PRInt32 beginRowIndex = rowIndex + rowSpan - 1;
|
||||
for (PRInt32 rowX = beginRowIndex; (rowX >= rowIndex) && (excessAvail > 0); rowX--) {
|
||||
nscoord excessForRow = 0;
|
||||
// special rows gets as much as they can
|
||||
if (rowHeights[rowX] <= 0) {
|
||||
if ((rowX == beginRowIndex) || (!cellsOrigInSpan)) {
|
||||
if (0 == rowHeights[rowX]) {
|
||||
// give it all since no cell originates in the row
|
||||
excessForRow = excessBasis;
|
||||
}
|
||||
else { // don't let the allocation excced what it needs
|
||||
excessForRow = (excessBasis > -rowHeights[rowX]) ? -rowHeights[rowX] : excessBasis;
|
||||
}
|
||||
rowHeights[rowX] = excessForRow;
|
||||
excessBasis -= excessForRow;
|
||||
excessAvail -= excessForRow;
|
||||
if (heightOfAreaSpanned < cellFrameSize.height) {
|
||||
// the cell's height is larger than the available space of the rows it
|
||||
// spans so distribute the excess height to the rows affected
|
||||
nscoord extra = cellFrameSize.height - heightOfAreaSpanned;
|
||||
nscoord extraUsed = 0;
|
||||
if (0 == numSpecialRowsSpanned) {
|
||||
//NS_ASSERTION(heightOfRowsSpanned > 0, "invalid row span situation");
|
||||
PRBool haveUnStyledRowsSpanned = (heightOfUnStyledRowsSpanned > 0);
|
||||
nscoord divisor = (haveUnStyledRowsSpanned)
|
||||
? heightOfUnStyledRowsSpanned : heightOfRowsSpanned;
|
||||
if (divisor > 0) {
|
||||
for (spanX = rowSpan - 1; spanX >= 0; spanX--) {
|
||||
if (!haveUnStyledRowsSpanned || !rowInfo[rowIndex + spanX].hasStyleHeight) {
|
||||
// The amount of additional space each row gets is proportional to its height
|
||||
float percent = ((float)rowInfo[rowIndex + spanX].height) / ((float)divisor);
|
||||
|
||||
// give rows their percentage, except for the first row which gets the remainder
|
||||
nscoord extraForRow = (0 == spanX) ? extra - extraUsed
|
||||
: NSToCoordRound(((float)(extra)) * percent);
|
||||
extraForRow = PR_MIN(nsTableFrame::RoundToPixel(extraForRow, p2t), extra - extraUsed);
|
||||
// update the row height
|
||||
UpdateHeights(rowInfo[rowIndex + spanX], extraForRow, heightOfRows, heightOfUnStyledRows);
|
||||
extraUsed += extraForRow;
|
||||
if (extraUsed >= extra) {
|
||||
NS_ASSERTION((extraUsed == extra), "invalid row height calculation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (cellsOrigInSpan) { // normal rows
|
||||
// The amount of additional space each normal row gets is based on the
|
||||
// percentage of space it occupies, i.e. they don't all get the
|
||||
// same amount of available space
|
||||
float percent = ((float)rowHeights[rowX]) / ((float)heightOfRowsSpanned);
|
||||
|
||||
// give rows their percentage, except for the first row which gets
|
||||
// the remainder
|
||||
excessForRow = (rowX == rowIndex)
|
||||
? excessAvail
|
||||
: NSToCoordRound(((float)(excessBasis)) * percent);
|
||||
// update the row height
|
||||
rowHeights[rowX] += excessForRow;
|
||||
excessAvail -= excessForRow;
|
||||
}
|
||||
// Get the next row frame
|
||||
GetNextRowSibling((nsIFrame**)&rowFrameToBeResized);
|
||||
}
|
||||
// if excessAvail is > 0 it is because !cellsOrigInSpan and the
|
||||
// allocation involving special rows couldn't allocate everything.
|
||||
// just give the remainder to the last row spanned.
|
||||
if (excessAvail > 0) {
|
||||
if (rowHeights[beginRowIndex] >= 0) {
|
||||
rowHeights[beginRowIndex] += excessAvail;
|
||||
}
|
||||
else {
|
||||
rowHeights[beginRowIndex] = excessAvail;
|
||||
}
|
||||
else {
|
||||
// put everything in the last row
|
||||
UpdateHeights(rowInfo[rowIndex + rowSpan - 1], extra, heightOfRows, heightOfUnStyledRows);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// give the extra to the special rows
|
||||
nscoord numSpecialRowsAllocated = 0;
|
||||
for (spanX = rowSpan - 1; spanX >= 0; spanX--) {
|
||||
if (rowInfo[rowIndex + spanX].isSpecial) {
|
||||
// The amount of additional space each degenerate row gets is proportional to the number of them
|
||||
float percent = 1.0f / ((float)numSpecialRowsSpanned);
|
||||
|
||||
// give rows their percentage, except for the first row which gets the remainder
|
||||
nscoord extraForRow = (numSpecialRowsSpanned - 1 == numSpecialRowsAllocated)
|
||||
? extra - extraUsed
|
||||
: NSToCoordRound(((float)(extra)) * percent);
|
||||
extraForRow = PR_MIN(nsTableFrame::RoundToPixel(extraForRow, p2t), extra - extraUsed);
|
||||
// update the row height
|
||||
UpdateHeights(rowInfo[rowIndex + spanX], extraForRow, heightOfRows, heightOfUnStyledRows);
|
||||
extraUsed += extraForRow;
|
||||
if (extraUsed >= extra) {
|
||||
NS_ASSERTION((extraUsed == extra), "invalid row height calculation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cellFrame->GetNextSibling(&cellFrame); // Get the next row child (cell frame)
|
||||
}
|
||||
}
|
||||
|
||||
// If this is the last pass then resize the row to its final size and move the
|
||||
// row's position if the previous rows have caused a shift
|
||||
if (lastCount == counter) {
|
||||
nsRect rowBounds;
|
||||
rowFrame->GetRect(rowBounds);
|
||||
|
||||
PRBool movedFrame = (rowBounds.y != yOrigin);
|
||||
nscoord rowHeight = (rowHeights[rowIndex] > 0) ? rowHeights[rowIndex] : 0;
|
||||
|
||||
// Resize the row to its final size and position
|
||||
rowBounds.y = yOrigin;
|
||||
rowBounds.height = rowHeight;
|
||||
rowFrame->SetRect(aPresContext, rowBounds);
|
||||
|
||||
if (movedFrame) {
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
// set the origin of the next row.
|
||||
yOrigin += rowHeight + cellSpacingY;
|
||||
}
|
||||
|
||||
rowIndex++;
|
||||
}
|
||||
GetNextFrame(rowFrame, &rowFrame); // Get the next rowgroup child (row frame)
|
||||
}
|
||||
}
|
||||
} // if (rowSpan > 1)
|
||||
cellFrame = cellFrame->GetNextCell();
|
||||
} // while (cellFrame)
|
||||
} // if (tableFrame->RowHasSpanningCells(startRowIndex + rowIndex) {
|
||||
} // while (rowFrame)
|
||||
}
|
||||
|
||||
// step 3: notify the rows of their new heights
|
||||
rowFrame = startRowFrame;
|
||||
|
||||
rowIndex = 0;
|
||||
while (rowFrame) {
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) {
|
||||
nsCOMPtr<nsIAtom> rowType;
|
||||
rowFrame->GetFrameType(getter_AddRefs(rowType));
|
||||
if (nsLayoutAtoms::tableRowFrame == rowType.get()) {
|
||||
// Notify the row of the new size
|
||||
((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState);
|
||||
nscoord rowGroupHeight = startRowGroupHeight + heightOfRows + ((numRows - 1) * cellSpacingY);
|
||||
nscoord extraComputedHeight = 0;
|
||||
// if we have a style height, allocate the extra height to unconstrained rows
|
||||
if ((aReflowState.mComputedHeight > rowGroupHeight) &&
|
||||
(NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight)) {
|
||||
extraComputedHeight = aReflowState.mComputedHeight - rowGroupHeight;
|
||||
nscoord extraUsed = 0;
|
||||
PRBool haveUnStyledRows = (heightOfUnStyledRows > 0);
|
||||
nscoord divisor = (haveUnStyledRows)
|
||||
? heightOfUnStyledRows : heightOfRows;
|
||||
if (divisor > 0) {
|
||||
for (rowIndex = 0; rowIndex < numRows; rowIndex++) {
|
||||
if (!haveUnStyledRows || !rowInfo[rowIndex].hasStyleHeight) {
|
||||
// The amount of additional space each row gets is based on the
|
||||
// percentage of space it occupies
|
||||
float percent = ((float)rowInfo[rowIndex].height) / ((float)divisor);
|
||||
// give rows their percentage, except for the last row which gets the remainder
|
||||
nscoord extraForRow = (numRows - 1 == rowIndex)
|
||||
? extraComputedHeight - extraUsed
|
||||
: NSToCoordRound(((float)extraComputedHeight) * percent);
|
||||
extraForRow = PR_MIN(nsTableFrame::RoundToPixel(extraForRow, p2t), extraComputedHeight - extraUsed);
|
||||
// update the row height
|
||||
UpdateHeights(rowInfo[rowIndex], extraForRow, heightOfRows, heightOfUnStyledRows);
|
||||
extraUsed += extraForRow;
|
||||
if (extraUsed >= extraComputedHeight) {
|
||||
NS_ASSERTION((extraUsed == extraComputedHeight), "invalid row height calculation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the running row group height. The height includes frames that
|
||||
// aren't rows as well
|
||||
nsSize rowSize;
|
||||
rowFrame->GetSize(rowSize);
|
||||
rowGroupHeight += rowSize.height;
|
||||
if (0 != rowIndex) {
|
||||
rowGroupHeight += cellSpacingY;
|
||||
}
|
||||
|
||||
GetNextFrame(rowFrame, &rowFrame); // Get the next row
|
||||
rowIndex++;
|
||||
rowGroupHeight = aReflowState.mComputedHeight;
|
||||
}
|
||||
|
||||
nscoord yOrigin = startRowGroupHeight;
|
||||
// update the rows with their (potentially) new heights
|
||||
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
|
||||
nsRect rowBounds;
|
||||
rowFrame->GetRect(rowBounds);
|
||||
|
||||
PRBool movedFrame = (rowBounds.y != yOrigin);
|
||||
nscoord rowHeight = (rowInfo[rowIndex].height > 0) ? rowInfo[rowIndex].height : 0;
|
||||
|
||||
if (movedFrame || (rowHeight != rowBounds.height)) {
|
||||
// Resize the row to its final size and position
|
||||
rowBounds.y = yOrigin;
|
||||
rowBounds.height = rowHeight;
|
||||
rowFrame->SetRect(aPresContext, rowBounds);
|
||||
}
|
||||
if (movedFrame) {
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
yOrigin += rowHeight + cellSpacingY;
|
||||
}
|
||||
|
||||
DidResizeRows(*aPresContext, aReflowState, startRowFrame);
|
||||
|
||||
aDesiredSize.height = rowGroupHeight; // Adjust our desired size
|
||||
delete [] rowHeights; // cleanup
|
||||
delete [] rowInfo; // cleanup
|
||||
}
|
||||
|
||||
|
||||
// Called by IR_TargetIsChild() to adjust the sibling frames that follow
|
||||
// after an incremental reflow of aKidFrame.
|
||||
// This function is not used for paginated mode so we don't need to deal
|
||||
@ -918,31 +938,6 @@ nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
|
||||
return tallestCell;
|
||||
}
|
||||
|
||||
nsIFrame* GetNextRow(nsIFrame& aFrame)
|
||||
{
|
||||
nsIFrame* rowFrame;
|
||||
for (aFrame.GetNextSibling(&rowFrame); rowFrame; rowFrame->GetNextSibling(&rowFrame)) {
|
||||
nsCOMPtr<nsIAtom> fType;
|
||||
rowFrame->GetFrameType(getter_AddRefs(fType));
|
||||
if (nsLayoutAtoms::tableRowFrame == fType.get()) {
|
||||
return rowFrame;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsIFrame* GetFirstRow(nsTableRowGroupFrame& aRowGroupFrame)
|
||||
{
|
||||
for (nsIFrame* rowFrame = aRowGroupFrame.GetFirstFrame(); rowFrame; rowFrame = GetNextRow(*rowFrame)) {
|
||||
nsCOMPtr<nsIAtom> fType;
|
||||
rowFrame->GetFrameType(getter_AddRefs(fType));
|
||||
if (nsLayoutAtoms::tableRowFrame == fType.get()) {
|
||||
return rowFrame;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
@ -971,7 +966,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
|
||||
|
||||
// Walk each of the row frames looking for the first row frame that
|
||||
// doesn't fit in the available space
|
||||
for (nsIFrame* rowFrame = GetFirstRow(*this); rowFrame; rowFrame = GetNextRow(*rowFrame)) {
|
||||
for (nsTableRowFrame* rowFrame = GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) {
|
||||
PRBool rowIsOnCurrentPage = PR_TRUE;
|
||||
PRBool degenerateRow = PR_FALSE;
|
||||
nsRect bounds;
|
||||
@ -995,7 +990,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
|
||||
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
|
||||
rowFrame->SizeTo(aPresContext, desiredSize.width, desiredSize.height);
|
||||
rowFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||
((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState);
|
||||
rowFrame->DidResize(aPresContext, aReflowState);
|
||||
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
// the row frame is incomplete and all of the cells' block frames have split
|
||||
@ -1043,7 +1038,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
|
||||
if (prevRowFrame) {
|
||||
nscoord tallestCell =
|
||||
SplitSpanningCells(*aPresContext, aReflowState, *styleSet, *aTableFrame,
|
||||
*(nsTableRowFrame*)rowFrame, aDesiredSize.height, (nsTableRowFrame*)contRowFrame);
|
||||
*rowFrame, aDesiredSize.height, (nsTableRowFrame*)contRowFrame);
|
||||
if (degenerateRow) {
|
||||
aDesiredSize.height = lastDesiredHeight + aTableFrame->GetCellSpacingY() + tallestCell;
|
||||
}
|
||||
@ -1077,10 +1072,10 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
|
||||
|
||||
nsresult rv=NS_OK;
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (!tableFrame) return NS_ERROR_NULL_POINTER;
|
||||
if (!aPresContext || !tableFrame) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsRowGroupReflowState state(aReflowState, tableFrame);
|
||||
PRBool haveDesiredHeight = PR_FALSE;
|
||||
@ -1111,9 +1106,12 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
|
||||
// reflow, then we need to do this because the table will skip the pass 2 reflow,
|
||||
// but we need to correctly calculate the row group height and we can't if there
|
||||
// are row spans unless we do this step
|
||||
if ((eReflowReason_Initial != aReflowState.reason) ||
|
||||
isTableUnconstrainedReflow ||
|
||||
isPaginated) {
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
DidResizeRows(*aPresContext, aReflowState);
|
||||
}
|
||||
else if ((eReflowReason_Initial != aReflowState.reason) ||
|
||||
isTableUnconstrainedReflow ||
|
||||
isPaginated) {
|
||||
CalculateRowHeights(aPresContext, aDesiredSize, aReflowState);
|
||||
haveDesiredHeight = PR_TRUE;
|
||||
}
|
||||
@ -1124,6 +1122,12 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
|
||||
SplitRowGroup(aPresContext, aDesiredSize, aReflowState, tableFrame, aStatus);
|
||||
}
|
||||
}
|
||||
SetHasStyleHeight((NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) &&
|
||||
(aReflowState.mComputedHeight > 0));
|
||||
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
SetNeedSpecialReflow(PR_FALSE);
|
||||
}
|
||||
|
||||
// just set our width to what was available. The table will calculate the width and not use our value.
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
@ -1318,6 +1322,21 @@ nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsTableRowGroupFrame::GetHeightBasis(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
nscoord result = 0;
|
||||
if ((aReflowState.mComputedHeight > 0) && (aReflowState.mComputedHeight < NS_UNCONSTRAINEDSIZE)) {
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsTableFrame::GetTableFrame((nsIFrame*)this, tableFrame);
|
||||
if (tableFrame) {
|
||||
nscoord cellSpacing = PR_MAX(0, GetRowCount() - 1) * tableFrame->GetCellSpacingY();
|
||||
result -= cellSpacing;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsTableRowGroupFrame::GetHeightOfRows(nsIPresContext* aPresContext)
|
||||
{
|
||||
|
||||
@ -79,9 +79,13 @@ struct nsRowGroupReflowState {
|
||||
{ 0xe940e7bc, 0xb534, 0x11d2, \
|
||||
{ 0x95, 0xa2, 0x0, 0x60, 0xb0, 0xc3, 0x44, 0x14 } }
|
||||
|
||||
// use a bit from nsFrame's frame state bits to determine whether a
|
||||
// use the following bits from nsFrame's frame state
|
||||
|
||||
// thead or tfoot should be repeated on every printed page
|
||||
#define NS_ROWGROUP_REPEATABLE 0x80000000
|
||||
#define NS_ROWGROUP_REPEATABLE 0x80000000
|
||||
#define NS_ROWGROUP_HAS_STYLE_HEIGHT 0x40000000
|
||||
// we need a 3rd pass reflow to deal with pct height nested tables
|
||||
#define NS_ROWGROUP_NEED_SPECIAL_REFLOW 0x20000000
|
||||
/**
|
||||
* nsTableRowGroupFrame is the frame that maps row groups
|
||||
* (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused
|
||||
@ -176,6 +180,10 @@ public:
|
||||
*/
|
||||
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
|
||||
|
||||
NS_IMETHOD IsPercentageBase(PRBool& aBase) const;
|
||||
|
||||
nsTableRowFrame* GetFirstRow();
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD GetFrameName(nsString& aResult) const;
|
||||
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
|
||||
@ -206,6 +214,7 @@ public:
|
||||
* Get the total height of all the row rects
|
||||
*/
|
||||
nscoord GetHeightOfRows(nsIPresContext* aPresContext);
|
||||
nscoord GetHeightBasis(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
// nsILineIterator methods
|
||||
public:
|
||||
@ -255,6 +264,9 @@ protected:
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsTableRowFrame* aStartRowFrameIn = nsnull);
|
||||
|
||||
void DidResizeRows(nsIPresContext& aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsTableRowFrame* aStartRowFrameIn = nsnull);
|
||||
|
||||
/** Incremental Reflow attempts to do column balancing with the minimum number of reflow
|
||||
* commands to child elements. This is done by processing the reflow command,
|
||||
@ -337,8 +349,12 @@ public:
|
||||
virtual nsIFrame* GetLastFrame() { return mFrames.LastChild(); };
|
||||
virtual void GetNextFrame(nsIFrame* aFrame,
|
||||
nsIFrame** aResult) { aFrame->GetNextSibling(aResult); };
|
||||
PRBool IsRepeatable();
|
||||
void SetRepeatable(PRBool aRepeatable);
|
||||
PRBool IsRepeatable() const;
|
||||
void SetRepeatable(PRBool aRepeatable);
|
||||
PRBool HasStyleHeight() const;
|
||||
void SetHasStyleHeight(PRBool aValue);
|
||||
PRBool NeedSpecialReflow() const;
|
||||
void SetNeedSpecialReflow(PRBool aValue);
|
||||
|
||||
#ifdef DEBUG_TABLE_REFLOW_TIMING
|
||||
public:
|
||||
@ -347,7 +363,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
inline PRBool nsTableRowGroupFrame::IsRepeatable()
|
||||
inline PRBool nsTableRowGroupFrame::IsRepeatable() const
|
||||
{
|
||||
return (mState & NS_ROWGROUP_REPEATABLE) == NS_ROWGROUP_REPEATABLE;
|
||||
}
|
||||
@ -361,4 +377,31 @@ inline void nsTableRowGroupFrame::SetRepeatable(PRBool aRepeatable)
|
||||
}
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowGroupFrame::NeedSpecialReflow() const
|
||||
{
|
||||
return (mState & NS_ROWGROUP_NEED_SPECIAL_REFLOW) == NS_ROWGROUP_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
|
||||
inline void nsTableRowGroupFrame::SetNeedSpecialReflow(PRBool aValue)
|
||||
{
|
||||
if (aValue) {
|
||||
mState |= NS_ROWGROUP_NEED_SPECIAL_REFLOW;
|
||||
} else {
|
||||
mState &= ~NS_ROWGROUP_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowGroupFrame::HasStyleHeight() const
|
||||
{
|
||||
return (mState & NS_ROWGROUP_HAS_STYLE_HEIGHT) == NS_ROWGROUP_HAS_STYLE_HEIGHT;
|
||||
}
|
||||
|
||||
inline void nsTableRowGroupFrame::SetHasStyleHeight(PRBool aValue)
|
||||
{
|
||||
if (aValue) {
|
||||
mState |= NS_ROWGROUP_HAS_STYLE_HEIGHT;
|
||||
} else {
|
||||
mState &= ~NS_ROWGROUP_HAS_STYLE_HEIGHT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -337,15 +337,19 @@ nsTableCellMap::RemoveRows(nsIPresContext* aPresContext,
|
||||
PRInt32
|
||||
nsTableCellMap::GetNumCellsOriginatingInRow(PRInt32 aRowIndex)
|
||||
{
|
||||
PRInt32 cellCount = 0;
|
||||
CellData* tempCell;
|
||||
do
|
||||
{
|
||||
tempCell = GetCellAt(aRowIndex,cellCount);
|
||||
if (tempCell)
|
||||
cellCount++;
|
||||
}while(tempCell);
|
||||
return cellCount;
|
||||
PRInt32 originCount = 0;
|
||||
|
||||
CellData* cellData;
|
||||
PRInt32 colIndex = 0;
|
||||
|
||||
do {
|
||||
cellData = GetCellAt(aRowIndex, colIndex);
|
||||
if (cellData && cellData->GetCellFrame())
|
||||
originCount++;
|
||||
colIndex++;
|
||||
} while(cellData);
|
||||
|
||||
return originCount;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
|
||||
@ -91,6 +91,22 @@ nsTableCellFrame::~nsTableCellFrame()
|
||||
#endif
|
||||
}
|
||||
|
||||
nsTableCellFrame*
|
||||
nsTableCellFrame::GetNextCell() const
|
||||
{
|
||||
nsIFrame* childFrame;
|
||||
GetNextSibling(&childFrame);
|
||||
while (childFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
childFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
|
||||
return (nsTableCellFrame*)childFrame;
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableCellFrame::Init(nsIPresContext* aPresContext,
|
||||
nsIContent* aContent,
|
||||
@ -694,6 +710,15 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) &&
|
||||
((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) ||
|
||||
(0 == aReflowState.mComputedHeight)) &&
|
||||
!mPrevInFlow &&
|
||||
nsTableFrame::IsPctHeight(mStyleContext)) {
|
||||
nsTableFrame::NotifyAncestorsOfSpecialReflow(aReflowState);
|
||||
SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
// this should probably be cached somewhere
|
||||
nsCompatibility compatMode;
|
||||
aPresContext->GetCompatibilityMode(&compatMode);
|
||||
@ -714,6 +739,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
/* XXX: remove tableFrame when border-collapse inherits */
|
||||
nsTableFrame* tableFrame=nsnull;
|
||||
rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
nsTableFrame* tableFrameFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
|
||||
|
||||
nsMargin borderPadding = aReflowState.mComputedPadding;
|
||||
nsMargin border;
|
||||
GetCellBorder(border, tableFrame);
|
||||
@ -768,6 +795,10 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
kidSize.width=kidSize.height=kidSize.ascent=kidSize.descent=0;
|
||||
SetPriorAvailWidth(aReflowState.availableWidth);
|
||||
nsIFrame* firstKid = mFrames.FirstChild();
|
||||
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
((nsHTMLReflowState&)aReflowState).mComputedHeight = mRect.height - topInset - bottomInset;
|
||||
}
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, firstKid,
|
||||
availSize);
|
||||
|
||||
@ -898,8 +929,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
|
||||
// if the table allocated extra vertical space to row groups, rows, cells in pagination mode
|
||||
// then use that height as the desired height unless the cell needs to split.
|
||||
nsTableFrame* tableFrameFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
|
||||
if ((NS_FRAME_COMPLETE == aStatus) && tableFrameFirstInFlow->IsThirdPassReflow()) {
|
||||
if ((NS_FRAME_COMPLETE == aStatus) && aReflowState.mFlags.mSpecialTableReflow) {
|
||||
cellHeight = PR_MAX(cellHeight, mRect.height);
|
||||
}
|
||||
// next determine the cell's width
|
||||
@ -942,6 +972,10 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
|
||||
// remember my desired size for this reflow
|
||||
SetDesiredSize(aDesiredSize);
|
||||
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
SetNeedSpecialReflow(PR_FALSE);
|
||||
}
|
||||
|
||||
#if defined DEBUG_TABLE_REFLOW_TIMING
|
||||
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aReflowState, &aDesiredSize, aStatus);
|
||||
#endif
|
||||
|
||||
@ -49,7 +49,8 @@ class nsHTMLValue;
|
||||
/**
|
||||
* Additional frame-state bits
|
||||
*/
|
||||
#define NS_TABLE_CELL_FRAME_CONTENT_EMPTY 0x80000000
|
||||
#define NS_TABLE_CELL_CONTENT_EMPTY 0x80000000
|
||||
#define NS_TABLE_CELL_NEED_SPECIAL_REFLOW 0x40000000
|
||||
|
||||
/**
|
||||
* nsTableCellFrame
|
||||
@ -239,11 +240,16 @@ public:
|
||||
PRBool GetContentEmpty();
|
||||
void SetContentEmpty(PRBool aContentEmpty);
|
||||
|
||||
PRBool NeedSpecialReflow();
|
||||
void SetNeedSpecialReflow(PRBool aContentEmpty);
|
||||
|
||||
// The collapse offset is (0,0) except for cells originating in a row/col which is collapsed
|
||||
void SetCollapseOffsetX(nsIPresContext* aPresContext, nscoord aXOffset);
|
||||
void SetCollapseOffsetY(nsIPresContext* aPresContext, nscoord aYOffset);
|
||||
void GetCollapseOffset(nsIPresContext* aPresContext, nsPoint& aOffset);
|
||||
|
||||
nsTableCellFrame* GetNextCell() const;
|
||||
|
||||
protected:
|
||||
/** implement abstract method on nsHTMLContainerFrame */
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
@ -332,19 +338,33 @@ inline nsSize nsTableCellFrame::GetPass1MaxElementSize() const
|
||||
|
||||
inline PRBool nsTableCellFrame::GetContentEmpty()
|
||||
{
|
||||
return (mState & NS_TABLE_CELL_FRAME_CONTENT_EMPTY) ==
|
||||
NS_TABLE_CELL_FRAME_CONTENT_EMPTY;
|
||||
return (mState & NS_TABLE_CELL_CONTENT_EMPTY) ==
|
||||
NS_TABLE_CELL_CONTENT_EMPTY;
|
||||
}
|
||||
|
||||
inline void nsTableCellFrame::SetContentEmpty(PRBool aContentEmpty)
|
||||
{
|
||||
if (aContentEmpty) {
|
||||
mState |= NS_TABLE_CELL_FRAME_CONTENT_EMPTY;
|
||||
mState |= NS_TABLE_CELL_CONTENT_EMPTY;
|
||||
} else {
|
||||
mState &= ~NS_TABLE_CELL_FRAME_CONTENT_EMPTY;
|
||||
mState &= ~NS_TABLE_CELL_CONTENT_EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
inline PRBool nsTableCellFrame::NeedSpecialReflow()
|
||||
{
|
||||
return (mState & NS_TABLE_CELL_NEED_SPECIAL_REFLOW) ==
|
||||
NS_TABLE_CELL_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
|
||||
inline void nsTableCellFrame::SetNeedSpecialReflow(PRBool aValue)
|
||||
{
|
||||
if (aValue) {
|
||||
mState |= NS_TABLE_CELL_NEED_SPECIAL_REFLOW;
|
||||
} else {
|
||||
mState &= ~NS_TABLE_CELL_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -84,6 +84,7 @@ void nsTableColFrame::SetType(nsTableColType aType) {
|
||||
mBits.mType = aType - eColContent;
|
||||
}
|
||||
|
||||
|
||||
// XXX what about other style besides width
|
||||
nsStyleCoord nsTableColFrame::GetStyleWidth() const
|
||||
{
|
||||
|
||||
@ -1580,8 +1580,15 @@ nsTableFrame::GetSkipSides() const
|
||||
PRBool nsTableFrame::NeedsReflow(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
PRBool result = PR_TRUE;
|
||||
if ((eReflowReason_Incremental == aReflowState.reason) &&
|
||||
(NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight)) {
|
||||
if (eReflowReason_Resize == aReflowState.reason) {
|
||||
if (aReflowState.mFlags.mSpecialTableReflow &&
|
||||
!NeedSpecialReflow() &&
|
||||
!NeedToInitiateSpecialReflow()) {
|
||||
result = PR_FALSE;
|
||||
}
|
||||
}
|
||||
else if ((eReflowReason_Incremental == aReflowState.reason) &&
|
||||
(NS_UNCONSTRAINEDSIZE == aReflowState.availableHeight)) {
|
||||
// It's an incremental reflow and we're in galley mode. Only
|
||||
// do a full reflow if we need to.
|
||||
#ifndef TABLE_REFLOW_COALESCING_OFF
|
||||
@ -1809,6 +1816,30 @@ ProcessRowInserted(nsIPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTableFrame::NotifyAncestorsOfSpecialReflow(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
const nsHTMLReflowState* rs = aReflowState.parentReflowState;
|
||||
while (rs) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
rs->frame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
|
||||
((nsTableCellFrame*)rs->frame)->SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
else if (nsLayoutAtoms::tableRowFrame == frameType.get()) {
|
||||
((nsTableRowFrame*)rs->frame)->SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
else if (nsLayoutAtoms::tableRowGroupFrame == frameType.get()) {
|
||||
((nsTableRowGroupFrame*)rs->frame)->SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
else if (nsLayoutAtoms::tableFrame == frameType.get()) {
|
||||
((nsTableFrame*)rs->frame)->SetNeedToInitiateSpecialReflow(PR_TRUE);
|
||||
break;
|
||||
}
|
||||
rs = rs->parentReflowState;
|
||||
}
|
||||
}
|
||||
|
||||
/* overview:
|
||||
if mFirstPassValid is false, this is our first time through since content was last changed
|
||||
do pass 1
|
||||
@ -1904,36 +1935,57 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRBool needPass3Reflow = PR_FALSE;
|
||||
PRBool haveDesiredHeight = PR_FALSE;
|
||||
PRBool balanced = PR_FALSE;
|
||||
|
||||
// Reflow the entire table. This phase is necessary during a constrained initial reflow
|
||||
// and other reflows which require either a strategy init or balance. This isn't done
|
||||
// during an unconstrained reflow because another reflow will be processed later.
|
||||
if (NeedsReflow(aReflowState) && (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)) {
|
||||
// see if an extra (3rd) reflow will be necessary in pagination mode when there is a specified table height
|
||||
if (isPaginated && !mPrevInFlow && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) {
|
||||
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
||||
if ((tableSpecifiedHeight > 0) &&
|
||||
(tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE)) {
|
||||
needPass3Reflow = PR_TRUE;
|
||||
if (!mPrevInFlow) {
|
||||
// see if an extra reflow will be necessary when there is a pct height but no height on the parent
|
||||
if ( ((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) ||
|
||||
(0 == aReflowState.mComputedHeight)) && IsPctHeight(mStyleContext)) {
|
||||
NotifyAncestorsOfSpecialReflow(aReflowState);
|
||||
SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
// see if an extra reflow will be necessary in pagination mode when there is a specified table height
|
||||
else if (isPaginated && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) {
|
||||
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
||||
if ((tableSpecifiedHeight > 0) &&
|
||||
(tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE)) {
|
||||
SetNeedToInitiateSpecialReflow(PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
// if we need to reflow the table an extra time, then don't constrain the height of the previous reflow
|
||||
nscoord availHeight = (needPass3Reflow) ? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight;
|
||||
nscoord availHeight = !aReflowState.mFlags.mSpecialTableReflow &&
|
||||
(NeedSpecialReflow() | NeedToInitiateSpecialReflow())
|
||||
? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight;
|
||||
|
||||
ReflowTable(aPresContext, aDesiredSize, aReflowState, availHeight, nextReason, doCollapse, balanced, aStatus);
|
||||
|
||||
if (needPass3Reflow) {
|
||||
if (!aReflowState.mFlags.mSpecialTableReflow && NeedToInitiateSpecialReflow() && !NeedSpecialReflow()) {
|
||||
aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState); // distributes extra vertical space to rows
|
||||
SetThirdPassReflow(PR_TRUE); // set it and leave it set for frames that may split
|
||||
((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialTableReflow = PR_TRUE;
|
||||
ReflowTable(aPresContext, aDesiredSize, aReflowState, aReflowState.availableHeight,
|
||||
nextReason, doCollapse, balanced, aStatus);
|
||||
haveDesiredHeight = PR_TRUE;;
|
||||
}
|
||||
}
|
||||
else if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
aDesiredSize.width = mRect.width;
|
||||
aDesiredSize.height = mRect.height;
|
||||
#if defined DEBUG_TABLE_REFLOW_TIMING
|
||||
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aReflowState, &aDesiredSize, aStatus);
|
||||
#endif
|
||||
SetNeedSpecialReflow(PR_FALSE);
|
||||
SetNeedToInitiateSpecialReflow(PR_FALSE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
aDesiredSize.width = GetDesiredWidth();
|
||||
if (!needPass3Reflow) {
|
||||
aDesiredSize.width = GetDesiredWidth();
|
||||
if (!haveDesiredHeight) {
|
||||
aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState);
|
||||
}
|
||||
|
||||
@ -1986,6 +2038,10 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
SetNeedSpecialReflow(PR_FALSE);
|
||||
SetNeedToInitiateSpecialReflow(PR_FALSE);
|
||||
}
|
||||
#if defined DEBUG_TABLE_REFLOW_TIMING
|
||||
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aReflowState, &aDesiredSize, aStatus);
|
||||
#endif
|
||||
@ -3253,81 +3309,6 @@ nsTableFrame::CalcDesiredWidth(const nsHTMLReflowState& aReflowState)
|
||||
return tableWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
get the table height attribute
|
||||
if it is auto, table height = SUM(height of rowgroups)
|
||||
else if (resolved table height attribute > SUM(height of rowgroups))
|
||||
proportionately distribute extra height to each row
|
||||
we assume we are passed in the default table height==the sum of the heights of the table's rowgroups
|
||||
in aDesiredSize.height.
|
||||
*/
|
||||
void
|
||||
nsTableFrame::DistributeSpaceToCells(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame* aRowGroupFrame)
|
||||
{
|
||||
// now that all of the rows have been resized, resize the cells
|
||||
nsTableRowGroupFrame* rowGroupFrame = (nsTableRowGroupFrame*)aRowGroupFrame;
|
||||
nsIFrame * rowFrame = rowGroupFrame->GetFirstFrame();
|
||||
while (rowFrame) {
|
||||
const nsStyleDisplay *rowDisplay;
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
|
||||
((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState);
|
||||
}
|
||||
rowGroupFrame->GetNextFrame(rowFrame, &rowFrame);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTableFrame::DistributeSpaceToRows(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame* aRowGroupFrame,
|
||||
nscoord aSumOfRowHeights,
|
||||
nscoord aExcess,
|
||||
nscoord& aExcessAllocated,
|
||||
nscoord& aRowGroupYPos)
|
||||
{
|
||||
// the rows in rowGroupFrame need to be expanded by rowHeightDelta[i]
|
||||
// and the rowgroup itself needs to be expanded by SUM(row height deltas)
|
||||
nscoord cellSpacingY = GetCellSpacingY();
|
||||
nsTableRowGroupFrame* rowGroupFrame = (nsTableRowGroupFrame*)aRowGroupFrame;
|
||||
nsIFrame* rowFrame = rowGroupFrame->GetFirstFrame();
|
||||
nscoord excessForRowGroup = 0;
|
||||
nscoord y = 0;
|
||||
float p2t;
|
||||
aPresContext->GetPixelsToTwips(&p2t);
|
||||
while (rowFrame) {
|
||||
const nsStyleDisplay *rowDisplay;
|
||||
rowFrame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)rowDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == rowDisplay->mDisplay) {
|
||||
// the row needs to be expanded by the proportion this row contributed to the original height
|
||||
nsRect rowRect;
|
||||
rowFrame->GetRect(rowRect);
|
||||
float percent = ((float)(rowRect.height)) / (float)aSumOfRowHeights;
|
||||
nscoord excessForRow = RoundToPixel(NSToCoordRound((float)aExcess * percent), p2t);
|
||||
excessForRow = PR_MIN(excessForRow, aExcess - aExcessAllocated);
|
||||
|
||||
nsRect newRowRect(rowRect.x, y, rowRect.width, excessForRow + rowRect.height);
|
||||
rowFrame->SetRect(aPresContext, newRowRect);
|
||||
y = newRowRect.YMost() + cellSpacingY;
|
||||
|
||||
aExcessAllocated += excessForRow;
|
||||
excessForRowGroup += excessForRow;
|
||||
}
|
||||
|
||||
rowGroupFrame->GetNextFrame(rowFrame, &rowFrame);
|
||||
}
|
||||
|
||||
nsRect rowGroupRect;
|
||||
aRowGroupFrame->GetRect(rowGroupRect);
|
||||
nsRect newRowGroupRect(rowGroupRect.x, aRowGroupYPos, rowGroupRect.width,
|
||||
excessForRowGroup + rowGroupRect.height);
|
||||
aRowGroupFrame->SetRect(aPresContext, newRowGroupRect);
|
||||
aRowGroupYPos = newRowGroupRect.YMost();
|
||||
|
||||
DistributeSpaceToCells(aPresContext, aReflowState, aRowGroupFrame);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsTableFrame::CalcDesiredHeight(nsIPresContext* aPresContext,
|
||||
@ -3347,65 +3328,239 @@ nsTableFrame::CalcDesiredHeight(nsIPresContext* aPresContext,
|
||||
OrderRowGroups(rowGroups, numRowGroups, nsnull);
|
||||
if (numRowGroups <= 0) return 0;
|
||||
|
||||
nscoord naturalHeight = borderPadding.top + cellSpacingY + borderPadding.bottom;
|
||||
nscoord desiredHeight = borderPadding.top + cellSpacingY + borderPadding.bottom;
|
||||
for (PRUint32 rgX = 0; rgX < numRowGroups; rgX++) {
|
||||
nsIFrame* rg = (nsIFrame*)rowGroups.ElementAt(rgX);
|
||||
if (rg) {
|
||||
nsRect rgRect;
|
||||
rg->GetRect(rgRect);
|
||||
naturalHeight += rgRect.height + cellSpacingY;
|
||||
desiredHeight += rgRect.height + cellSpacingY;
|
||||
}
|
||||
}
|
||||
|
||||
nscoord desiredHeight = naturalHeight;
|
||||
|
||||
// see if a specified table height requires dividing additional space to rows
|
||||
if (!mPrevInFlow) {
|
||||
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
||||
if ((tableSpecifiedHeight > 0) &&
|
||||
(tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE) &&
|
||||
(tableSpecifiedHeight > naturalHeight)) {
|
||||
desiredHeight = tableSpecifiedHeight;
|
||||
|
||||
(tableSpecifiedHeight > desiredHeight)) {
|
||||
// proportionately distribute the excess height to unconstrained rows in each
|
||||
// unconstrained row group.We don't need to do this if it's an unconstrained reflow
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) {
|
||||
// proportionately distribute the excess height to each row. Note that we
|
||||
// don't need to do this if it's an unconstrained reflow
|
||||
nscoord excess = tableSpecifiedHeight - naturalHeight;
|
||||
nscoord sumOfRowHeights = 0;
|
||||
nscoord rowGroupYPos = aReflowState.mComputedBorderPadding.top + cellSpacingY;
|
||||
|
||||
nsAutoVoidArray rowGroups;
|
||||
PRUint32 numRowGroups;
|
||||
OrderRowGroups(rowGroups, numRowGroups, nsnull);
|
||||
|
||||
PRUint32 rgX;
|
||||
for (rgX = 0; rgX < numRowGroups; rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame =
|
||||
GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
if (rgFrame) {
|
||||
sumOfRowHeights += rgFrame->GetHeightOfRows(aPresContext);
|
||||
}
|
||||
}
|
||||
nscoord excessAllocated = 0;
|
||||
for (rgX = 0; rgX < numRowGroups; rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame =
|
||||
GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
if (rgFrame) {
|
||||
DistributeSpaceToRows(aPresContext, aReflowState, rgFrame, sumOfRowHeights,
|
||||
excess, excessAllocated, rowGroupYPos);
|
||||
|
||||
// Make sure child views are properly positioned
|
||||
// XXX what happens if childFrame is a scroll frame and this gets skipped?
|
||||
nsTableFrame::RePositionViews(aPresContext, rgFrame);
|
||||
}
|
||||
rowGroupYPos += cellSpacingY;
|
||||
}
|
||||
DistributeHeightToRows(aPresContext, aReflowState, tableSpecifiedHeight - desiredHeight);
|
||||
}
|
||||
desiredHeight = tableSpecifiedHeight;
|
||||
}
|
||||
}
|
||||
return desiredHeight;
|
||||
}
|
||||
|
||||
static
|
||||
void ResizeCells(nsTableFrame& aTableFrame,
|
||||
nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
nsAutoVoidArray rowGroups;
|
||||
PRUint32 numRowGroups;
|
||||
aTableFrame.OrderRowGroups(rowGroups, numRowGroups, nsnull);
|
||||
|
||||
for (PRUint32 rgX = 0; (rgX < numRowGroups); rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame = aTableFrame.GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
rowFrame->DidResize(aPresContext, aReflowState);
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTableFrame::DistributeHeightToRows(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nscoord aAmount)
|
||||
{
|
||||
float p2t;
|
||||
aPresContext->GetPixelsToTwips(&p2t);
|
||||
|
||||
nscoord cellSpacingY = GetCellSpacingY();
|
||||
|
||||
nscoord sumOfRowHeights = 0;
|
||||
nscoord rowGroupYPos = aReflowState.mComputedBorderPadding.top + cellSpacingY;
|
||||
|
||||
nsVoidArray rowGroups;
|
||||
PRUint32 numRowGroups;
|
||||
OrderRowGroups(rowGroups, numRowGroups, nsnull);
|
||||
|
||||
nscoord amountUsed = 0;
|
||||
// distribute space to each pct height row whose row group doesn't have a computed
|
||||
// height, and base the pct on the table height. If the row group had a computed
|
||||
// height, then this was already done in nsTableRowGroupFrame::CalculateRowHeights
|
||||
nscoord pctBasis = aReflowState.mComputedHeight - (GetCellSpacingY() * (GetRowCount() + 1));
|
||||
nscoord yOriginRG = aReflowState.mComputedBorderPadding.top + GetCellSpacingY();
|
||||
nscoord yEndRG = yOriginRG;
|
||||
PRUint32 rgX;
|
||||
for (rgX = 0; (rgX < numRowGroups); rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
nscoord amountUsedByRG = 0;
|
||||
nscoord yOriginRow = 0;
|
||||
nsRect rgRect;
|
||||
rgFrame->GetRect(rgRect);
|
||||
if (rgFrame && !rgFrame->HasStyleHeight()) {
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
nsRect rowRect;
|
||||
rowFrame->GetRect(rowRect);
|
||||
if ((amountUsed < aAmount) && rowFrame->HasPctHeight()) {
|
||||
nscoord pctHeight = nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctBasis), p2t);
|
||||
nscoord amountForRow = PR_MIN(aAmount - amountUsed, pctHeight - rowRect.height);
|
||||
if (amountForRow > 0) {
|
||||
rowRect.height += amountForRow;
|
||||
rowFrame->SetRect(aPresContext, rowRect);
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
amountUsed += amountForRow;
|
||||
amountUsedByRG += amountForRow;
|
||||
//rowFrame->DidResize(aPresContext, aReflowState);
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (amountUsed > 0) {
|
||||
rowFrame->MoveTo(aPresContext, rowRect.x, yOriginRow);
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
}
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
if (amountUsed > 0) {
|
||||
rgRect.y = yOriginRG;
|
||||
rgRect.height += amountUsedByRG;
|
||||
rgFrame->SetRect(aPresContext, rgRect);
|
||||
}
|
||||
}
|
||||
else if (amountUsed > 0) {
|
||||
rgFrame->MoveTo(aPresContext, 0, yOriginRG);
|
||||
// Make sure child views are properly positioned
|
||||
nsTableFrame::RePositionViews(aPresContext, rgFrame);
|
||||
}
|
||||
yOriginRG = yEndRG;
|
||||
}
|
||||
|
||||
if (amountUsed >= aAmount) {
|
||||
ResizeCells(*this, aPresContext, aReflowState);
|
||||
return;
|
||||
}
|
||||
|
||||
// get the first row without a style height where its row group has an unconstrianed height
|
||||
nsTableRowGroupFrame* firstUnStyledRG = nsnull;
|
||||
nsTableRowFrame* firstUnStyledRow = nsnull;
|
||||
for (rgX = 0; (rgX < numRowGroups) && !firstUnStyledRG; rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
if (rgFrame && !rgFrame->HasStyleHeight()) {
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
if (!rowFrame->HasStyleHeight()) {
|
||||
firstUnStyledRG = rgFrame;
|
||||
firstUnStyledRow = rowFrame;
|
||||
break;
|
||||
}
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsTableRowFrame* lastElligibleRow = nsnull;
|
||||
// accumulate the correct divisor. This will be the total of all unstyled rows inside
|
||||
// unstyled row groups, unless there are none, in which case, it will be all rows
|
||||
nscoord divisor = 0;
|
||||
for (rgX = 0; rgX < numRowGroups; rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
if (rgFrame && (!firstUnStyledRG || !rgFrame->HasStyleHeight())) {
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
if (!firstUnStyledRG || !rowFrame->HasStyleHeight()) {
|
||||
nsRect rowRect;
|
||||
rowFrame->GetRect(rowRect);
|
||||
divisor += rowRect.height;
|
||||
lastElligibleRow = rowFrame;
|
||||
}
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (divisor <= 0) {
|
||||
NS_ASSERTION(PR_FALSE, "invlaid divisor");
|
||||
return;
|
||||
}
|
||||
|
||||
// allocate the extra height to the unstyled row groups and rows
|
||||
pctBasis = aAmount - amountUsed;
|
||||
yOriginRG = aReflowState.mComputedBorderPadding.top + cellSpacingY;
|
||||
yEndRG = yOriginRG;
|
||||
for (rgX = 0; rgX < numRowGroups; rgX++) {
|
||||
nsTableRowGroupFrame* rgFrame = GetRowGroupFrame((nsIFrame*)rowGroups.ElementAt(rgX));
|
||||
if (!rgFrame) continue;
|
||||
nscoord amountUsedByRG = 0;
|
||||
nscoord yOriginRow = 0;
|
||||
nsRect rgRect;
|
||||
rgFrame->GetRect(rgRect);
|
||||
// see if there is an eligible row group
|
||||
if (!firstUnStyledRG || !rgFrame->HasStyleHeight()) {
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
nsRect rowRect;
|
||||
rowFrame->GetRect(rowRect);
|
||||
// see if there is an eligible row
|
||||
if (!firstUnStyledRow || !rowFrame->HasStyleHeight()) {
|
||||
// The amount of additional space each row gets is proportional to its height
|
||||
float percent = rowRect.height / ((float)divisor);
|
||||
// give rows their percentage, except for the last row which gets the remainder
|
||||
nscoord amountForRow = (rowFrame == lastElligibleRow)
|
||||
? aAmount - amountUsed : NSToCoordRound(((float)(pctBasis)) * percent);
|
||||
amountForRow = PR_MIN(nsTableFrame::RoundToPixel(amountForRow, p2t), aAmount - amountUsed);
|
||||
// update the row height
|
||||
nsRect newRowRect(rowRect.x, yOriginRow, rowRect.width, rowRect.height + amountForRow);
|
||||
rowFrame->SetRect(aPresContext, newRowRect);
|
||||
yOriginRow += newRowRect.height + cellSpacingY;
|
||||
yEndRG += newRowRect.height + cellSpacingY;
|
||||
|
||||
amountUsed += amountForRow;
|
||||
amountUsedByRG += amountForRow;
|
||||
NS_ASSERTION((amountUsed <= aAmount), "invalid row allocation");
|
||||
//rowFrame->DidResize(aPresContext, aReflowState);
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
else {
|
||||
if (amountUsed > 0) {
|
||||
rowFrame->MoveTo(aPresContext, rowRect.x, yOriginRow);
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
yOriginRow += rowRect.height + cellSpacingY;
|
||||
yEndRG += rowRect.height + cellSpacingY;
|
||||
}
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
if (amountUsed > 0) {
|
||||
rgRect.y = yOriginRG;
|
||||
rgRect.height += amountUsedByRG;
|
||||
rgFrame->SetRect(aPresContext, rgRect);
|
||||
}
|
||||
// Make sure child views are properly positioned
|
||||
// XXX what happens if childFrame is a scroll frame and this gets skipped? see also below
|
||||
}
|
||||
else if (amountUsed > 0) {
|
||||
rgFrame->MoveTo(aPresContext, 0, yOriginRG);
|
||||
// Make sure child views are properly positioned
|
||||
nsTableFrame::RePositionViews(aPresContext, rgFrame);
|
||||
}
|
||||
yOriginRG = yEndRG;
|
||||
}
|
||||
|
||||
ResizeCells(*this, aPresContext, aReflowState);
|
||||
}
|
||||
|
||||
static void
|
||||
UpdateCol(nsTableFrame& aTableFrame,
|
||||
nsTableColFrame& aColFrame,
|
||||
@ -3435,6 +3590,17 @@ UpdateCol(nsTableFrame& aTableFrame,
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsTableFrame::IsPctHeight(nsIStyleContext* aStyleContext)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
if (aStyleContext) {
|
||||
nsStylePosition* position = (nsStylePosition*)aStyleContext->GetStyleData(eStyleStruct_Position);
|
||||
result = (eStyleUnit_Percent == position->mHeight.GetUnit());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsTableFrame::CellChangedWidth(const nsTableCellFrame& aCellFrame,
|
||||
nscoord aPrevCellMin,
|
||||
@ -4370,9 +4536,20 @@ NS_IMETHODIMP nsTableFrame::GetTableSize(PRInt32& aRowCount, PRInt32& aColCount)
|
||||
PRInt32 nsTableFrame::GetNumCellsOriginatingInCol(PRInt32 aColIndex) const
|
||||
{
|
||||
nsTableCellMap* cellMap = GetCellMap();
|
||||
return cellMap->GetNumCellsOriginatingInCol(aColIndex);
|
||||
if (cellMap)
|
||||
return cellMap->GetNumCellsOriginatingInCol(aColIndex);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
PRInt32 nsTableFrame::GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const
|
||||
{
|
||||
nsTableCellMap* cellMap = GetCellMap();
|
||||
if (cellMap)
|
||||
return cellMap->GetNumCellsOriginatingInRow(aRowIndex);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************
|
||||
@ -4477,7 +4654,11 @@ void nsTableFrame::DebugReflow(nsIFrame* aFrame,
|
||||
if (!aMetrics) { // start
|
||||
PrettyUC(aState.availableWidth, width);
|
||||
PrettyUC(aState.availableHeight, height);
|
||||
printf("r=%d a=%s,%s ", aState.reason, width, height);
|
||||
printf("r=%d ", aState.reason);
|
||||
if (aState.mFlags.mSpecialTableReflow) {
|
||||
printf("special ");
|
||||
}
|
||||
printf("a=%s,%s ", width, height);
|
||||
PrettyUC(aState.mComputedWidth, width);
|
||||
PrettyUC(aState.mComputedHeight, height);
|
||||
printf("c=%s,%s ", width, height);
|
||||
|
||||
@ -207,6 +207,8 @@ public:
|
||||
float aPixelToTwips,
|
||||
nsPixelRound aRound= eAlwaysRoundUp);
|
||||
|
||||
static void NotifyAncestorsOfSpecialReflow(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
NS_IMETHOD IsPercentageBase(PRBool& aBase) const;
|
||||
|
||||
static nsresult AppendDirtyReflowCommand(nsIPresShell* aPresShell,
|
||||
@ -258,6 +260,7 @@ public:
|
||||
nsIAtom* aChildType);
|
||||
PRBool IsAutoWidth(PRBool* aIsPctWidth = nsnull);
|
||||
PRBool IsAutoHeight();
|
||||
static PRBool IsPctHeight(nsIStyleContext* aStyleContext);
|
||||
|
||||
/** @return PR_TRUE if aDisplayType represents a rowgroup of any sort
|
||||
* (header, footer, or body)
|
||||
@ -491,14 +494,18 @@ public:
|
||||
PRInt32* aColSpan = nsnull);
|
||||
|
||||
PRInt32 GetNumCellsOriginatingInCol(PRInt32 aColIndex) const;
|
||||
PRInt32 GetNumCellsOriginatingInRow(PRInt32 aRowIndex) const;
|
||||
|
||||
PRBool HasPctCol() const;
|
||||
void SetHasPctCol(PRBool aValue);
|
||||
|
||||
PRBool HasCellSpanningPctCol() const;
|
||||
void SetHasCellSpanningPctCol(PRBool aValue);
|
||||
// is this the 3rd reflow due to a height on a table in pagination mode.
|
||||
PRBool IsThirdPassReflow() const;
|
||||
|
||||
PRBool NeedSpecialReflow() const;
|
||||
void SetNeedSpecialReflow(PRBool aValue);
|
||||
PRBool NeedToInitiateSpecialReflow() const;
|
||||
void SetNeedToInitiateSpecialReflow(PRBool aValue);
|
||||
|
||||
protected:
|
||||
|
||||
@ -527,7 +534,6 @@ protected:
|
||||
void SetDescendantReflowedNotTimeout(PRBool aValue);
|
||||
PRBool RequestedTimeoutReflow() const;
|
||||
void SetRequestedTimeoutReflow(PRBool aValue);
|
||||
void SetThirdPassReflow(PRBool aValue);
|
||||
|
||||
void InterruptNotification(nsIPresContext* aPresContext,
|
||||
PRBool aIsRequest);
|
||||
@ -652,18 +658,12 @@ protected:
|
||||
// reflow state, and for the table attributes and parent
|
||||
nscoord CalcDesiredHeight(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState);
|
||||
// The following two functions are helpers for CalcDesiredHeight
|
||||
|
||||
// The following is a helper for CalcDesiredHeight
|
||||
|
||||
void DistributeSpaceToCells(nsIPresContext* aPresContext,
|
||||
void DistributeHeightToRows(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame* aRowGroupFrame);
|
||||
void DistributeSpaceToRows(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame* aRowGroupFrame,
|
||||
nscoord aSumOfRowHeights,
|
||||
nscoord aExcess,
|
||||
nscoord& aExcessAllocated,
|
||||
nscoord& aRowGroupYPos);
|
||||
nscoord aAmount);
|
||||
|
||||
void PlaceChild(nsIPresContext* aPresContext,
|
||||
nsTableReflowState& aReflowState,
|
||||
@ -830,8 +830,6 @@ public: /* ----- Cell Map public methods ----- */
|
||||
// percentage height cells
|
||||
void ComputePercentBasisForRows(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
nscoord GetPercentBasisForRows();
|
||||
|
||||
nscoord GetMinWidth() const;
|
||||
void SetMinWidth(nscoord aWidth);
|
||||
|
||||
@ -895,8 +893,9 @@ protected:
|
||||
// targeted at us, as an optimization.
|
||||
unsigned mRequestedTimeoutReflow:1;
|
||||
unsigned mRowInserted:1;
|
||||
unsigned mThirdPassReflow:1;
|
||||
int : 21; // unused
|
||||
unsigned mNeedSpecialReflow:1;
|
||||
unsigned mNeedToInitiateSpecialReflow:1;
|
||||
int : 19; // unused
|
||||
} mBits;
|
||||
|
||||
nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
|
||||
@ -941,11 +940,6 @@ inline PRBool nsTableFrame::IsRowGroup(PRInt32 aDisplayType) const
|
||||
(NS_STYLE_DISPLAY_TABLE_ROW_GROUP == aDisplayType));
|
||||
}
|
||||
|
||||
inline nscoord nsTableFrame::GetPercentBasisForRows()
|
||||
{
|
||||
return mPercentBasisForRows;
|
||||
}
|
||||
|
||||
inline void nsTableFrame::SetHadInitialReflow(PRBool aValue)
|
||||
{
|
||||
mBits.mHadInitialReflow = aValue;
|
||||
@ -1006,16 +1000,25 @@ inline void nsTableFrame::SetRequestedTimeoutReflow(PRBool aValue)
|
||||
mBits.mRequestedTimeoutReflow = (unsigned)aValue;
|
||||
}
|
||||
|
||||
inline PRBool nsTableFrame::IsThirdPassReflow() const
|
||||
inline PRBool nsTableFrame::NeedSpecialReflow() const
|
||||
{
|
||||
return (PRBool)mBits.mThirdPassReflow;
|
||||
return (PRBool)mBits.mNeedSpecialReflow;
|
||||
}
|
||||
|
||||
inline void nsTableFrame::SetThirdPassReflow(PRBool aValue)
|
||||
inline void nsTableFrame::SetNeedSpecialReflow(PRBool aValue)
|
||||
{
|
||||
mBits.mThirdPassReflow = (unsigned)aValue;
|
||||
mBits.mNeedSpecialReflow = (unsigned)aValue;
|
||||
}
|
||||
|
||||
inline PRBool nsTableFrame::NeedToInitiateSpecialReflow() const
|
||||
{
|
||||
return (PRBool)mBits.mNeedToInitiateSpecialReflow;
|
||||
}
|
||||
|
||||
inline void nsTableFrame::SetNeedToInitiateSpecialReflow(PRBool aValue)
|
||||
{
|
||||
mBits.mNeedToInitiateSpecialReflow = (unsigned)aValue;
|
||||
}
|
||||
inline PRBool nsTableFrame::IsRowInserted() const
|
||||
{
|
||||
return (PRBool)mBits.mRowInserted;
|
||||
|
||||
@ -94,6 +94,42 @@ nsTableCellReflowState::nsTableCellReflowState(nsIPresContext* aPresCon
|
||||
FixUp(aAvailSpace);
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::SetFixedHeight(nscoord aValue)
|
||||
{
|
||||
if (!HasPctHeight()) {
|
||||
nscoord height = PR_MAX(0, aValue);
|
||||
if (HasFixedHeight()) {
|
||||
if (height > mStyleHeight) {
|
||||
mStyleHeight = height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mStyleHeight = height;
|
||||
if (height > 0) {
|
||||
SetHasFixedHeight(PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::SetPctHeight(float aPctValue)
|
||||
{
|
||||
nscoord height = PR_MAX(0, NSToCoordRound(aPctValue * 100.0f));
|
||||
if (HasPctHeight()) {
|
||||
if (height > mStyleHeight) {
|
||||
mStyleHeight = height;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mStyleHeight = height;
|
||||
if (height > 0.0f) {
|
||||
SetHasPctHeight(PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsTableCellReflowState::FixUp(const nsSize& aAvailSpace)
|
||||
{
|
||||
// fix the mComputed values during a pass 2 reflow since the cell can be a percentage base
|
||||
@ -121,15 +157,13 @@ TallestCellGotShorter(nscoord aOld,
|
||||
return ((aNew < aOld) && (aOld == aTallest));
|
||||
}
|
||||
|
||||
/* ----------- nsTableRowpFrame ---------- */
|
||||
/* ----------- nsTableRowFrame ---------- */
|
||||
|
||||
nsTableRowFrame::nsTableRowFrame()
|
||||
: nsHTMLContainerFrame(),
|
||||
mAllBits(0)
|
||||
: nsHTMLContainerFrame()
|
||||
{
|
||||
mBits.mMinRowSpan = 1;
|
||||
mBits.mRowIndex = 0;
|
||||
ResetTallestCell(0);
|
||||
mBits.mRowIndex = mBits.mFirstInserted = 0;
|
||||
ResetHeight(0);
|
||||
#ifdef DEBUG_TABLE_REFLOW_TIMING
|
||||
mTimer = new nsReflowTimer(this);
|
||||
#endif
|
||||
@ -329,6 +363,20 @@ GetHeightOfRowsSpannedBelowFirst(nsTableCellFrame& aTableCellFrame,
|
||||
return height;
|
||||
}
|
||||
|
||||
nsTableCellFrame*
|
||||
nsTableRowFrame::GetFirstCell()
|
||||
{
|
||||
nsIFrame* childFrame = mFrames.FirstChild();
|
||||
while (childFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
childFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
|
||||
return (nsTableCellFrame*)childFrame;
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-reflow hook. This is where the table row does its post-processing
|
||||
@ -390,43 +438,53 @@ nscoord nsTableRowFrame::GetMaxCellAscent() const
|
||||
return mMaxCellAscent;
|
||||
}
|
||||
|
||||
#if 0 // nobody uses this
|
||||
// returns max-descent amongst all cells that have 'vertical-align: baseline'
|
||||
// does *not* include cells with rowspans
|
||||
nscoord nsTableRowFrame::GetMaxCellDescent() const
|
||||
nscoord
|
||||
nsTableRowFrame::GetHeight(nscoord aPctBasis) const
|
||||
{
|
||||
return mMaxCellDescent;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** returns the height of the tallest child in this row (ignoring any cell with rowspans) */
|
||||
nscoord nsTableRowFrame::GetTallestCell() const
|
||||
{
|
||||
return mTallestCell;
|
||||
nscoord height = 0;
|
||||
if ((aPctBasis > 0) && HasPctHeight()) {
|
||||
height = NSToCoordRound(GetPctHeight() * (float)aPctBasis);
|
||||
}
|
||||
else if (HasFixedHeight()) {
|
||||
height = GetFixedHeight();
|
||||
}
|
||||
return PR_MAX(height, GetContentHeight());
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::ResetTallestCell(nscoord aRowStyleHeight)
|
||||
nsTableRowFrame::ResetHeight(nscoord aFixedHeight)
|
||||
{
|
||||
mTallestCell = (NS_UNCONSTRAINEDSIZE == aRowStyleHeight) ? 0 : aRowStyleHeight;
|
||||
SetHasFixedHeight(PR_FALSE);
|
||||
SetHasPctHeight(PR_FALSE);
|
||||
SetFixedHeight(0);
|
||||
SetContentHeight(0);
|
||||
|
||||
if (aFixedHeight > 0) {
|
||||
SetFixedHeight(aFixedHeight);
|
||||
}
|
||||
|
||||
mMaxCellAscent = 0;
|
||||
mMaxCellDescent = 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::SetTallestCell(nscoord aHeight,
|
||||
nscoord aAscent,
|
||||
nscoord aDescent,
|
||||
nsTableFrame* aTableFrame,
|
||||
nsTableCellFrame* aCellFrame)
|
||||
nsTableRowFrame::UpdateHeight(nscoord aHeight,
|
||||
nscoord aAscent,
|
||||
nscoord aDescent,
|
||||
nsTableFrame* aTableFrame,
|
||||
nsTableCellFrame* aCellFrame)
|
||||
{
|
||||
NS_ASSERTION((aTableFrame && aCellFrame) , "invalid call");
|
||||
if (!aTableFrame || !aCellFrame) {
|
||||
NS_ASSERTION(PR_FALSE , "invalid call");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aHeight != NS_UNCONSTRAINEDSIZE) {
|
||||
if (!(aCellFrame->HasVerticalAlignBaseline())) { // only the cell's height matters
|
||||
if (mTallestCell < aHeight) {
|
||||
if (GetHeight() < aHeight) {
|
||||
PRInt32 rowSpan = aTableFrame->GetEffectiveRowSpan(*aCellFrame);
|
||||
if (rowSpan == 1) {
|
||||
mTallestCell = aHeight;
|
||||
SetContentHeight(aHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,21 +502,23 @@ nsTableRowFrame::SetTallestCell(nscoord aHeight,
|
||||
}
|
||||
}
|
||||
// keep the tallest height in sync
|
||||
if (mTallestCell < mMaxCellAscent + mMaxCellDescent) {
|
||||
mTallestCell = mMaxCellAscent + mMaxCellDescent;
|
||||
if (GetHeight() < mMaxCellAscent + mMaxCellDescent) {
|
||||
SetContentHeight(mMaxCellAscent + mMaxCellDescent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowFrame::CalcTallestCell()
|
||||
nscoord
|
||||
nsTableRowFrame::CalcHeight(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (NS_FAILED(rv)) return;
|
||||
if (!tableFrame) return 0;
|
||||
|
||||
ResetTallestCell(0);
|
||||
nscoord computedHeight = (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight)
|
||||
? 0 : aReflowState.mComputedHeight;
|
||||
ResetHeight(computedHeight);
|
||||
|
||||
for (nsIFrame* kidFrame = mFrames.FirstChild(); kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
@ -470,9 +530,10 @@ nsTableRowFrame::CalcTallestCell()
|
||||
// height may have changed, adjust descent to absorb any excess difference
|
||||
nscoord ascent = ((nsTableCellFrame *)kidFrame)->GetDesiredAscent();
|
||||
nscoord descent = desSize.height - ascent;
|
||||
SetTallestCell(desSize.height, ascent, descent, tableFrame, (nsTableCellFrame*)kidFrame);
|
||||
UpdateHeight(desSize.height, ascent, descent, tableFrame, (nsTableCellFrame*)kidFrame);
|
||||
}
|
||||
}
|
||||
return GetHeight();
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -648,49 +709,6 @@ nsTableRowFrame::GetFrameForPoint(nsIPresContext* aPresContext,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* GetMinRowSpan is needed for deviant cases where every cell in a row has a rowspan > 1.
|
||||
* It sets mMinRowSpan, which is used in FixMinCellHeight
|
||||
*/
|
||||
void nsTableRowFrame::GetMinRowSpan(nsTableFrame *aTableFrame)
|
||||
{
|
||||
PRInt32 minRowSpan=-1;
|
||||
nsIFrame* frame = mFrames.FirstChild();
|
||||
while (frame)
|
||||
{
|
||||
const nsStyleDisplay *kidDisplay;
|
||||
frame->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)kidDisplay));
|
||||
if (NS_STYLE_DISPLAY_TABLE_CELL == kidDisplay->mDisplay)
|
||||
{
|
||||
PRInt32 rowSpan = aTableFrame->GetEffectiveRowSpan((nsTableCellFrame &)*frame);
|
||||
if (-1==minRowSpan)
|
||||
minRowSpan = rowSpan;
|
||||
else if (minRowSpan>rowSpan)
|
||||
minRowSpan = rowSpan;
|
||||
}
|
||||
frame->GetNextSibling(&frame);
|
||||
}
|
||||
mBits.mMinRowSpan = unsigned(minRowSpan);
|
||||
}
|
||||
|
||||
void nsTableRowFrame::FixMinCellHeight(nsTableFrame *aTableFrame)
|
||||
{
|
||||
nsIFrame* frame = mFrames.FirstChild();
|
||||
while (frame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
frame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableCellFrame == frameType.get()) {
|
||||
PRInt32 rowSpan = aTableFrame->GetEffectiveRowSpan((nsTableCellFrame &)*frame);
|
||||
if (PRInt32(mBits.mMinRowSpan) == rowSpan) {
|
||||
nsRect rect;
|
||||
frame->GetRect(rect);
|
||||
if (rect.height > mTallestCell)
|
||||
mTallestCell = rect.height;
|
||||
}
|
||||
}
|
||||
frame->GetNextSibling(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the cell's actual size given its pass2 desired width and height.
|
||||
// Takes into account the specified height (in the style), and any special logic
|
||||
// needed for backwards compatibility.
|
||||
@ -701,37 +719,37 @@ nsTableRowFrame::CalculateCellActualSize(nsIFrame* aCellFrame,
|
||||
nscoord& aDesiredHeight,
|
||||
nscoord aAvailWidth)
|
||||
{
|
||||
nscoord specifiedHeight = 0;
|
||||
const nsStylePosition* position;
|
||||
nscoord specifiedHeight = 0;
|
||||
|
||||
// Get the height specified in the style information
|
||||
const nsStylePosition* position;
|
||||
aCellFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position);
|
||||
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (!tableFrame) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan((nsTableCellFrame&)*aCellFrame);
|
||||
|
||||
switch (position->mHeight.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
specifiedHeight = position->mHeight.GetCoordValue();
|
||||
if (1 == rowSpan)
|
||||
SetFixedHeight(specifiedHeight);
|
||||
break;
|
||||
case eStyleUnit_Percent: {
|
||||
nsTableFrame* table = nsnull;
|
||||
nsTableFrame::GetTableFrame(this, table);
|
||||
if (table) {
|
||||
nscoord basis = table->GetPercentBasisForRows();
|
||||
if (basis > 0) {
|
||||
float percent = position->mHeight.GetPercentValue();
|
||||
specifiedHeight = NSToCoordRound(percent * ((float)basis));
|
||||
}
|
||||
}
|
||||
if (1 == rowSpan)
|
||||
SetPctHeight(position->mHeight.GetPercentValue());
|
||||
// pct heights are handled when all of the cells are finished, so don't set specifiedHeight
|
||||
break;
|
||||
}
|
||||
case eStyleUnit_Inherit:
|
||||
// XXX for now, do nothing
|
||||
case eStyleUnit_Auto:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// If the specified height is greater than the desired height, then use the
|
||||
// specified height
|
||||
// If the specified height is greater than the desired height, then use the specified height
|
||||
if (specifiedHeight > aDesiredHeight)
|
||||
aDesiredHeight = specifiedHeight;
|
||||
|
||||
@ -865,6 +883,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
PRInt32 prevColIndex = firstPrevColIndex;
|
||||
nscoord x = 0; // running total of children x offset
|
||||
|
||||
nsTableFrame* tableFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
|
||||
PRBool isAutoLayout = tableFrame->IsAutoLayout();
|
||||
PRBool needToNotifyTable = PR_TRUE;
|
||||
// Reflow each of our existing cell frames
|
||||
@ -874,14 +893,21 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
nsFrameState frameState;
|
||||
kidFrame->GetFrameState(&frameState);
|
||||
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
kidFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
|
||||
// See if we should only reflow the dirty child frames
|
||||
PRBool doReflowChild = PR_TRUE;
|
||||
if (aDirtyOnly && ((frameState & NS_FRAME_IS_DIRTY) == 0)) {
|
||||
doReflowChild = PR_FALSE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
kidFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
if (!isPaginated && (nsLayoutAtoms::tableCellFrame == frameType.get() &&
|
||||
!((nsTableCellFrame*)kidFrame)->NeedSpecialReflow())) {
|
||||
kidFrame = iter.Next();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Reflow the child frame
|
||||
if (doReflowChild) {
|
||||
@ -919,7 +945,9 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
if ((availCellWidth != cellFrame->GetPriorAvailWidth()) ||
|
||||
(cellDesiredSize.width > cellFrame->GetPriorAvailWidth()) ||
|
||||
(eReflowReason_StyleChange == aReflowState.reason) ||
|
||||
isPaginated) {
|
||||
isPaginated ||
|
||||
(aReflowState.mFlags.mSpecialTableReflow && cellFrame->NeedSpecialReflow()) ||
|
||||
HasPctHeight()) {
|
||||
// Reflow the cell to fit the available width, height
|
||||
nsSize kidAvailSize(availColWidth, aReflowState.availableHeight);
|
||||
nsReflowReason reason = eReflowReason_Resize;
|
||||
@ -1002,7 +1030,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
// height may have changed, adjust descent to absorb any excess difference
|
||||
nscoord ascent = cellFrame->GetDesiredAscent();
|
||||
nscoord descent = desiredSize.height - ascent;
|
||||
SetTallestCell(desiredSize.height, ascent, descent, tableFrame, cellFrame);
|
||||
UpdateHeight(desiredSize.height, ascent, descent, tableFrame, cellFrame);
|
||||
|
||||
// Place the child
|
||||
if (NS_UNCONSTRAINEDSIZE != availColWidth) {
|
||||
@ -1037,8 +1065,7 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
|
||||
// just set our width to what was available. The table will calculate the width and not use our value.
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
CalcTallestCell();
|
||||
aDesiredSize.height = GetTallestCell();
|
||||
aDesiredSize.height = CalcHeight(aReflowState);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -1050,7 +1077,7 @@ NS_METHOD nsTableRowFrame::IncrementalReflow(nsIPresContext* aPresConte
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
CalcTallestCell(); // need to recalculate it based on last reflow sizes
|
||||
CalcHeight(aReflowState); // need to recalculate it based on last reflow sizes
|
||||
|
||||
// determine if this frame is the target or not
|
||||
nsIFrame* target = nsnull;
|
||||
@ -1193,7 +1220,7 @@ nsTableRowFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
|
||||
if (!hasVerticalAlignBaseline) {
|
||||
// only the height matters
|
||||
tallestCellGotShorter =
|
||||
TallestCellGotShorter(oldCellDesSize.height, cellMet.height, mTallestCell);
|
||||
TallestCellGotShorter(oldCellDesSize.height, cellMet.height, GetHeight());
|
||||
}
|
||||
else {
|
||||
// the ascent matters
|
||||
@ -1209,10 +1236,10 @@ nsTableRowFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
if (tallestCellGotShorter) {
|
||||
CalcTallestCell();
|
||||
CalcHeight(aReflowState);
|
||||
}
|
||||
else {
|
||||
SetTallestCell(cellMet.height, cellMet.ascent, cellMet.descent, &aTableFrame, cellFrame);
|
||||
UpdateHeight(cellMet.height, cellMet.ascent, cellMet.descent, &aTableFrame, cellFrame);
|
||||
}
|
||||
|
||||
// if the cell's desired size didn't changed, our height is unchanged
|
||||
@ -1232,7 +1259,7 @@ nsTableRowFrame::IR_TargetIsChild(nsIPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
}
|
||||
aDesiredSize.height = (aDesiredSize.mNothingChanged) ? mRect.height : GetTallestCell();
|
||||
aDesiredSize.height = (aDesiredSize.mNothingChanged) ? mRect.height : GetHeight();
|
||||
if (1 == rowSpan) {
|
||||
cellMet.height = aDesiredSize.height;
|
||||
}
|
||||
@ -1308,25 +1335,19 @@ nsTableRowFrame::Reflow(nsIPresContext* aPresContext,
|
||||
rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (!tableFrame) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) && !mPrevInFlow) {
|
||||
// see if an extra reflow will be necessary when there is a pct height but no height on the parent
|
||||
if ( ((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) ||
|
||||
(0 == aReflowState.mComputedHeight)) &&
|
||||
nsTableFrame::IsPctHeight(mStyleContext)) {
|
||||
nsTableFrame::NotifyAncestorsOfSpecialReflow(aReflowState);
|
||||
SetNeedSpecialReflow(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
switch (aReflowState.reason) {
|
||||
case eReflowReason_Initial:
|
||||
rv = ReflowChildren(aPresContext, aDesiredSize, aReflowState, *tableFrame, aStatus, PR_FALSE);
|
||||
#ifdef WHY
|
||||
if (!tableFrame->IsAutoLayout()) {
|
||||
// this resize reflow is necessary to place the cells correctly in the case of rowspans and colspans.
|
||||
// It is very efficient. It does not actually need to pass a reflow down to the cells.
|
||||
nsSize availSpace(aReflowState.availableWidth, aReflowState.availableHeight);
|
||||
nsHTMLReflowState resizeReflowState(aPresContext,
|
||||
(const nsHTMLReflowState&)(*(aReflowState.parentReflowState)),
|
||||
(nsIFrame *)this,
|
||||
availSpace,
|
||||
eReflowReason_Resize);
|
||||
RowReflowState rowResizeReflowState(resizeReflowState, tableFrame);
|
||||
rv = ReflowChildren(aPresContext, aDesiredSize, rowResizeReflowState, aStatus);
|
||||
}
|
||||
#endif
|
||||
//GetMinRowSpan(tableFrame);
|
||||
//FixMinCellHeight(tableFrame);
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
break;
|
||||
|
||||
@ -1343,6 +1364,10 @@ nsTableRowFrame::Reflow(nsIPresContext* aPresContext,
|
||||
// just set our width to what was available. The table will calculate the width and not use our value.
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
SetNeedSpecialReflow(PR_FALSE);
|
||||
}
|
||||
|
||||
#if defined DEBUG_TABLE_REFLOW_TIMING
|
||||
nsTableFrame::DebugReflow(this, (nsHTMLReflowState&)aReflowState, &aDesiredSize, aStatus);
|
||||
#endif
|
||||
@ -1463,6 +1488,21 @@ nsTableRowFrame::GetFrameType(nsIAtom** aType) const
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsTableRowFrame*
|
||||
nsTableRowFrame::GetNextRow() const
|
||||
{
|
||||
nsIFrame* childFrame;
|
||||
GetNextSibling(&childFrame);
|
||||
while (childFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
childFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableRowFrame == frameType.get()) {
|
||||
return (nsTableRowFrame*)childFrame;
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
/* ----- global methods ----- */
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ class nsTableCellFrame;
|
||||
class nsReflowTimer;
|
||||
#endif
|
||||
|
||||
#define NS_TABLE_MAX_ROW_INDEX (1<<19)
|
||||
#define NS_ROW_NEED_SPECIAL_REFLOW 0x20000000
|
||||
#define NS_ROW_FRAME_PAINT_SKIP_ROW 0x00000001
|
||||
#define NS_ROW_FRAME_PAINT_SKIP_CELLS 0x00000002
|
||||
|
||||
@ -121,6 +121,8 @@ public:
|
||||
nsFramePaintLayer aWhichLayer,
|
||||
nsIFrame** aFrame);
|
||||
|
||||
nsTableCellFrame* GetFirstCell() ;
|
||||
|
||||
/** calls Reflow for all of its child cells.
|
||||
* Cells with rowspan=1 are all set to the same height and stacked horizontally.
|
||||
* <P> Cells are not split unless absolutely necessary.
|
||||
@ -155,19 +157,17 @@ public:
|
||||
PRUint32* aResult) const;
|
||||
#endif
|
||||
|
||||
void SetTallestCell(nscoord aHeight,
|
||||
nscoord aAscent,
|
||||
nscoord aDescent,
|
||||
nsTableFrame* aTableFrame = nsnull,
|
||||
nsTableCellFrame* aCellFrame = nsnull);
|
||||
void UpdateHeight(nscoord aHeight,
|
||||
nscoord aAscent,
|
||||
nscoord aDescent,
|
||||
nsTableFrame* aTableFrame = nsnull,
|
||||
nsTableCellFrame* aCellFrame = nsnull);
|
||||
|
||||
void ResetTallestCell(nscoord aRowStyleHeight);
|
||||
void ResetHeight(nscoord aRowStyleHeight);
|
||||
|
||||
// calculate the tallest child when the previous tallest child gets shorter
|
||||
void CalcTallestCell();
|
||||
|
||||
/** returns the tallest child in this row (ignoring any cell with rowspans) */
|
||||
nscoord GetTallestCell() const;
|
||||
// calculate the height, considering content height of the
|
||||
// cells and the style height of the row and cells, excluding pct heights
|
||||
nscoord CalcHeight(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
// Support for cells with 'vertical-align: baseline'.
|
||||
|
||||
@ -210,14 +210,38 @@ public:
|
||||
|
||||
void RemoveCellFrame(nsTableCellFrame* aFrame);
|
||||
|
||||
nsresult CalculateCellActualSize(nsIFrame* aRowFrame,
|
||||
nscoord& aDesiredWidth,
|
||||
nscoord& aDesiredHeight,
|
||||
nscoord aAvailWidth);
|
||||
nsresult CalculateCellActualSize(nsIFrame* aRowFrame,
|
||||
nscoord& aDesiredWidth,
|
||||
nscoord& aDesiredHeight,
|
||||
nscoord aAvailWidth);
|
||||
|
||||
PRBool IsFirstInserted() const;
|
||||
void SetFirstInserted(PRBool aValue);
|
||||
|
||||
PRBool NeedSpecialReflow() const;
|
||||
void SetNeedSpecialReflow(PRBool aValue);
|
||||
|
||||
PRBool GetContentHeight() const;
|
||||
void SetContentHeight(nscoord aTwipValue);
|
||||
|
||||
PRBool HasStyleHeight() const;
|
||||
|
||||
PRBool HasFixedHeight() const;
|
||||
void SetHasFixedHeight(PRBool aValue);
|
||||
|
||||
PRBool HasPctHeight() const;
|
||||
void SetHasPctHeight(PRBool aValue);
|
||||
|
||||
nscoord GetFixedHeight() const;
|
||||
void SetFixedHeight(nscoord aValue);
|
||||
|
||||
float GetPctHeight() const;
|
||||
void SetPctHeight(float aPctValue);
|
||||
|
||||
nscoord GetHeight(nscoord aBasis = 0) const;
|
||||
|
||||
nsTableRowFrame* GetNextRow() const;
|
||||
|
||||
protected:
|
||||
|
||||
/** protected constructor.
|
||||
@ -262,10 +286,6 @@ protected:
|
||||
|
||||
// row-specific methods
|
||||
|
||||
void GetMinRowSpan(nsTableFrame *aTableFrame);
|
||||
|
||||
void FixMinCellHeight(nsTableFrame *aTableFrame);
|
||||
|
||||
nscoord ComputeCellXOffset(const nsHTMLReflowState& aState,
|
||||
nsIFrame* aKidFrame,
|
||||
const nsMargin& aKidMargin) const;
|
||||
@ -280,19 +300,18 @@ protected:
|
||||
nsReflowStatus& aStatus,
|
||||
PRBool aDirtyOnly = PR_FALSE);
|
||||
|
||||
public:
|
||||
struct RowBits {
|
||||
int mRowIndex:20;
|
||||
unsigned mMinRowSpan:11; // the smallest row span among all my child cells
|
||||
unsigned mFirstInserted; // if true, then it was the top most newly inserted row
|
||||
};
|
||||
|
||||
private:
|
||||
union {
|
||||
PRUint32 mAllBits;
|
||||
RowBits mBits;
|
||||
};
|
||||
nscoord mTallestCell; // not my height, but the height of my tallest child
|
||||
struct RowBits {
|
||||
unsigned mRowIndex:29;
|
||||
unsigned mHasFixedHeight:1; // set if the dominating style height on the row or any cell is pixel based
|
||||
unsigned mHasPctHeight:1; // set if the dominating style height on the row or any cell is pct based
|
||||
unsigned mFirstInserted:1; // if true, then it was the top most newly inserted row
|
||||
} mBits;
|
||||
|
||||
nscoord mContentHeight; // the desired height based on the content of the tallest cell in the row
|
||||
nscoord mStyleHeight; // the height based on a style pct on either the row or any cell if mHasPctHeight
|
||||
// is set, otherwise the height based on a style pixel height on the row or any
|
||||
// cell if mHasFixedHeight is set
|
||||
|
||||
// max-ascent and max-descent amongst all cells that have 'vertical-align: baseline'
|
||||
nscoord mMaxCellAscent; // does include cells with rowspan > 1
|
||||
@ -311,7 +330,6 @@ inline PRInt32 nsTableRowFrame::GetRowIndex() const
|
||||
|
||||
inline void nsTableRowFrame::SetRowIndex (int aRowIndex)
|
||||
{
|
||||
NS_PRECONDITION(aRowIndex < NS_TABLE_MAX_ROW_INDEX, "unexpected row index");
|
||||
mBits.mRowIndex = aRowIndex;
|
||||
}
|
||||
|
||||
@ -325,4 +343,68 @@ inline void nsTableRowFrame::SetFirstInserted(PRBool aValue)
|
||||
mBits.mFirstInserted = aValue;
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowFrame::HasStyleHeight() const
|
||||
{
|
||||
return (PRBool)mBits.mHasFixedHeight || (PRBool)mBits.mHasPctHeight;
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowFrame::HasFixedHeight() const
|
||||
{
|
||||
return (PRBool)mBits.mHasFixedHeight;
|
||||
}
|
||||
|
||||
inline void nsTableRowFrame::SetHasFixedHeight(PRBool aValue)
|
||||
{
|
||||
mBits.mHasFixedHeight = aValue;
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowFrame::HasPctHeight() const
|
||||
{
|
||||
return (PRBool)mBits.mHasPctHeight;
|
||||
}
|
||||
|
||||
inline void nsTableRowFrame::SetHasPctHeight(PRBool aValue)
|
||||
{
|
||||
mBits.mHasPctHeight = aValue;
|
||||
}
|
||||
|
||||
inline nscoord nsTableRowFrame::GetContentHeight() const
|
||||
{
|
||||
return mContentHeight;
|
||||
}
|
||||
|
||||
inline void nsTableRowFrame::SetContentHeight(nscoord aValue)
|
||||
{
|
||||
mContentHeight = aValue;
|
||||
}
|
||||
|
||||
inline nscoord nsTableRowFrame::GetFixedHeight() const
|
||||
{
|
||||
if (mBits.mHasFixedHeight && !mBits.mHasPctHeight)
|
||||
return mStyleHeight;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline float nsTableRowFrame::GetPctHeight() const
|
||||
{
|
||||
if (mBits.mHasPctHeight)
|
||||
return (float)mStyleHeight / 100.0f;
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowFrame::NeedSpecialReflow() const
|
||||
{
|
||||
return (mState & NS_ROW_NEED_SPECIAL_REFLOW) == NS_ROW_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
|
||||
inline void nsTableRowFrame::SetNeedSpecialReflow(PRBool aValue)
|
||||
{
|
||||
if (aValue) {
|
||||
mState |= NS_ROW_NEED_SPECIAL_REFLOW;
|
||||
} else {
|
||||
mState &= ~NS_ROW_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -105,6 +105,13 @@ nsTableRowGroupFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTableRowGroupFrame::IsPercentageBase(PRBool& aBase) const
|
||||
{
|
||||
aBase = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsTableRowGroupFrame::GetRowCount()
|
||||
{
|
||||
@ -362,6 +369,9 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
|
||||
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
|
||||
|
||||
PRBool isPaginated;
|
||||
aPresContext->IsPaginated(&isPaginated);
|
||||
|
||||
if (aFirstRowReflowed) {
|
||||
*aFirstRowReflowed = nsnull;
|
||||
}
|
||||
@ -369,8 +379,11 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
PRBool adjustSiblings = PR_TRUE;
|
||||
nsIFrame* kidFrame = (aStartFrame) ? aStartFrame : mFrames.FirstChild();
|
||||
|
||||
for ( ; kidFrame; ) {
|
||||
nsTableFrame* tableFirstInFlow = (nsTableFrame*)tableFrame->GetFirstInFlow();
|
||||
for ( ; kidFrame; kidFrame->GetNextSibling(&kidFrame)) {
|
||||
// Get the frame state bits
|
||||
nsCOMPtr<nsIAtom> kidType;
|
||||
kidFrame->GetFrameType(getter_AddRefs(kidType));
|
||||
nsFrameState frameState;
|
||||
kidFrame->GetFrameState(&frameState);
|
||||
|
||||
@ -379,6 +392,12 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
if (aDirtyOnly && ((frameState & NS_FRAME_IS_DIRTY) == 0)) {
|
||||
doReflowChild = PR_FALSE;
|
||||
}
|
||||
if (aReflowState.reflowState.mFlags.mSpecialTableReflow) {
|
||||
if (!isPaginated && (nsLayoutAtoms::tableRowFrame == kidType.get() &&
|
||||
!((nsTableRowFrame*)kidFrame)->NeedSpecialReflow())) {
|
||||
doReflowChild = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Reflow the row frame
|
||||
if (doReflowChild) {
|
||||
@ -413,9 +432,7 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
lastReflowedRow = kidFrame;
|
||||
|
||||
if (aFirstRowReflowed && !*aFirstRowReflowed) {
|
||||
nsCOMPtr<nsIAtom> fType;
|
||||
kidFrame->GetFrameType(getter_AddRefs(fType));
|
||||
if (nsLayoutAtoms::tableRowFrame == fType.get()) {
|
||||
if (nsLayoutAtoms::tableRowFrame == kidType.get()) {
|
||||
*aFirstRowReflowed = (nsTableRowFrame*)kidFrame;
|
||||
}
|
||||
}
|
||||
@ -432,8 +449,6 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
kidFrame->GetSize(kidSize);
|
||||
aReflowState.y += kidSize.height + cellSpacingY;
|
||||
}
|
||||
|
||||
kidFrame->GetNextSibling(&kidFrame); // Get the next child
|
||||
}
|
||||
|
||||
// adjust the rows after the ones that were reflowed
|
||||
@ -454,56 +469,82 @@ nsTableRowGroupFrame::ReflowChildren(nsIPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsTableRowGroupFrame::GetNextRowSibling(nsIFrame** aRowFrame)
|
||||
nsTableRowFrame*
|
||||
nsTableRowGroupFrame::GetFirstRow()
|
||||
{
|
||||
if (!*aRowFrame) return;
|
||||
GetNextFrame(*aRowFrame, aRowFrame);
|
||||
while(*aRowFrame) {
|
||||
const nsStyleDisplay *display;
|
||||
(*aRowFrame)->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display));
|
||||
if (NS_STYLE_DISPLAY_TABLE_ROW == display->mDisplay) {
|
||||
return;
|
||||
nsIFrame* childFrame = GetFirstFrame();
|
||||
while (childFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
childFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableRowFrame == frameType.get()) {
|
||||
return (nsTableRowFrame*)childFrame;
|
||||
}
|
||||
GetNextFrame(*aRowFrame, aRowFrame);
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
||||
struct RowInfo {
|
||||
unsigned height:30;
|
||||
unsigned hasStyleHeight:1;
|
||||
unsigned isSpecial:1; // there is no cell originating in the row with rowspan=1 and there are at
|
||||
// least 2 cells spanning the row and there is no style height on the row
|
||||
};
|
||||
|
||||
static void
|
||||
UpdateHeights(RowInfo& aRowInfo,
|
||||
nscoord aAdditionalHeight,
|
||||
nscoord& aTotal,
|
||||
nscoord& aUnconstrainedTotal)
|
||||
{
|
||||
aRowInfo.height += aAdditionalHeight;
|
||||
aTotal += aAdditionalHeight;
|
||||
if (!aRowInfo.hasStyleHeight) {
|
||||
aUnconstrainedTotal += aAdditionalHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate the height of rows which have no cells originating in them
|
||||
// except with cells with rowspan > 1. Store the height as negative
|
||||
// to distinguish them from regular rows.
|
||||
void
|
||||
AllocateSpecialHeight(nsIPresContext* aPresContext,
|
||||
nsTableFrame* aTableFrame,
|
||||
nsIFrame* aRowFrame,
|
||||
nscoord& aHeight)
|
||||
nsTableRowGroupFrame::DidResizeRows(nsIPresContext& aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsTableRowFrame* aStartRowFrameIn)
|
||||
{
|
||||
nsIFrame* cellFrame;
|
||||
aRowFrame->FirstChild(aPresContext, nsnull, &cellFrame);
|
||||
while (cellFrame) {
|
||||
nsCOMPtr<nsIAtom> cellType;
|
||||
cellFrame->GetFrameType(getter_AddRefs(cellType));
|
||||
if (nsLayoutAtoms::tableCellFrame == cellType.get()) {
|
||||
PRInt32 rowSpan = aTableFrame->GetEffectiveRowSpan((nsTableCellFrame&)*cellFrame);
|
||||
if (rowSpan > 1) {
|
||||
// use a simple average to allocate the special row. This is not exact,
|
||||
// but much better than nothing.
|
||||
nsSize cellDesSize = ((nsTableCellFrame*)cellFrame)->GetDesiredSize();
|
||||
((nsTableRowFrame*)aRowFrame)->CalculateCellActualSize(cellFrame, cellDesSize.width,
|
||||
cellDesSize.height, cellDesSize.width);
|
||||
PRInt32 propHeight = NSToCoordRound((float)cellDesSize.height / (float)rowSpan);
|
||||
// special rows store the largest negative value
|
||||
aHeight = PR_MIN(aHeight, -propHeight);
|
||||
}
|
||||
}
|
||||
cellFrame->GetNextSibling(&cellFrame);
|
||||
// update the cells spanning rows with their new heights
|
||||
// this is the place where all of the cells in the row get set to the height of the row
|
||||
PRInt32 rowIndex;
|
||||
nsTableRowFrame* rowFrame;
|
||||
nsTableRowFrame* startRowFrame = (aStartRowFrameIn) ? aStartRowFrameIn: GetFirstRow();
|
||||
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
|
||||
rowFrame->DidResize(&aPresContext, aReflowState);
|
||||
}
|
||||
}
|
||||
|
||||
/* CalculateRowHeights provides default heights for all rows in the rowgroup.
|
||||
* Actual row heights are ultimately determined by the table, when the table
|
||||
* height attribute is factored in.
|
||||
*/
|
||||
static PRBool
|
||||
HasMoreThanOneCell(nsTableCellMap* aCellMap,
|
||||
PRInt32 aRowIndex)
|
||||
{
|
||||
if (aCellMap) {
|
||||
CellData* cellData;
|
||||
PRInt32 colIndex = 0;
|
||||
PRInt32 count = 0;
|
||||
do {
|
||||
cellData = aCellMap->GetCellAt(aRowIndex, colIndex);
|
||||
if (cellData && (cellData->GetCellFrame() || cellData->IsRowSpan()))
|
||||
count++;
|
||||
if (count > 1)
|
||||
return PR_TRUE;
|
||||
colIndex++;
|
||||
} while(cellData);
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// This calculates the height of rows starting at aStartRowFrameIn and takes into account
|
||||
// style height on the row group, style heights on rows and cells, style heights on rowspans.
|
||||
// Actual row heights will be adjusted later if the table has a style height.
|
||||
// Even if rows don't change height, this method must be called to set the heights of each
|
||||
// cell in the row to the height of its row.
|
||||
void
|
||||
nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
@ -511,280 +552,259 @@ nsTableRowGroupFrame::CalculateRowHeights(nsIPresContext* aPresContext,
|
||||
nsTableRowFrame* aStartRowFrameIn)
|
||||
{
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsresult rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (NS_FAILED(rv) || nsnull==tableFrame) return;
|
||||
nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (!aPresContext || !tableFrame) return;
|
||||
|
||||
// all table cells have the same top and bottom margins, namely cellSpacingY
|
||||
nscoord cellSpacingY = tableFrame->GetCellSpacingY();
|
||||
float p2t;
|
||||
aPresContext->GetPixelsToTwips(&p2t);
|
||||
|
||||
// find the nearest row to the starting row (including the starting row) that isn't spanned into
|
||||
nsTableRowFrame* startRowFrame = nsnull;
|
||||
nsIFrame* childFrame = GetFirstFrame();
|
||||
PRBool foundFirstRow = PR_FALSE;
|
||||
while (childFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
childFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableRowFrame == frameType.get()) {
|
||||
PRInt32 rowIndex = ((nsTableRowFrame*)childFrame)->GetRowIndex();
|
||||
if (!foundFirstRow || !tableFrame->RowIsSpannedInto(rowIndex)) {
|
||||
startRowFrame = (nsTableRowFrame*)childFrame;
|
||||
if (!aStartRowFrameIn || (aStartRowFrameIn == startRowFrame)) break;
|
||||
// find the nearest row at or before aStartRowFrameIn that isn't spanned into.
|
||||
// If we have a computed height, then we can't compute the heights
|
||||
// incrementally from aStartRowFrameIn, and we must start at the first row.
|
||||
nsTableRowFrame* startRowFrame = GetFirstRow();
|
||||
if (aStartRowFrameIn && (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight)
|
||||
&& (aReflowState.mComputedHeight > 0)) {
|
||||
nsTableRowFrame* rowFrame = startRowFrame;
|
||||
while (rowFrame) {
|
||||
PRInt32 rowIndex = rowFrame->GetRowIndex();
|
||||
if (!tableFrame->RowIsSpannedInto(rowIndex)) {
|
||||
startRowFrame = rowFrame;
|
||||
if (aStartRowFrameIn == startRowFrame)
|
||||
break;
|
||||
}
|
||||
else if (aStartRowFrameIn == (nsTableRowFrame*)childFrame) break;
|
||||
foundFirstRow = PR_TRUE;
|
||||
else if (aStartRowFrameIn == rowFrame)
|
||||
break;
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
childFrame->GetNextSibling(&childFrame);
|
||||
}
|
||||
if (!startRowFrame) return;
|
||||
|
||||
PRInt32 startRowIndex = startRowFrame->GetRowIndex();
|
||||
|
||||
nsRect startRowRect;
|
||||
startRowFrame->GetRect(startRowRect);
|
||||
nscoord rowGroupHeight = startRowRect.y;
|
||||
// the current row group height is the y origin of the 1st row we are about to calculated a height for
|
||||
nscoord startRowGroupHeight = startRowRect.y;
|
||||
|
||||
PRInt32 numRows = GetRowCount() - (startRowFrame->GetRowIndex() - GetStartRowIndex());
|
||||
// collect the current height of each row. nscoord* rowHeights = nsnull;
|
||||
RowInfo* rowInfo;
|
||||
if (numRows > 0) {
|
||||
rowInfo = new RowInfo[numRows];
|
||||
if (!rowInfo) return;
|
||||
nsCRT::memset (rowInfo, 0, numRows*sizeof(RowInfo));
|
||||
}
|
||||
else return;
|
||||
|
||||
PRBool hasRowSpanningCell = PR_FALSE;
|
||||
PRInt32 numRows = GetRowCount() - (startRowFrame->GetRowIndex() - GetStartRowIndex());
|
||||
// collect the current height of each row. rows which have 0 height because
|
||||
// they have no cells originating in them without rowspans > 1, are referred to as
|
||||
// special rows. The current height of a special row will be a negative number until
|
||||
// it comes time to actually resize frames.
|
||||
nscoord* rowHeights = nsnull;
|
||||
if (numRows > 0) {
|
||||
rowHeights = new nscoord[numRows];
|
||||
if (!rowHeights) return;
|
||||
nsCRT::memset (rowHeights, 0, numRows*sizeof(nscoord));
|
||||
} // else - tree row groups need not have rows directly beneath them
|
||||
nscoord heightOfRows = 0;
|
||||
nscoord heightOfUnStyledRows = 0;
|
||||
// Get the height of each row without considering rowspans. This will be the max of
|
||||
// the largest desired height of each cell, the largest style height of each cell,
|
||||
// the style height of the row.
|
||||
nscoord pctHeightBasis = GetHeightBasis(aReflowState);
|
||||
nsTableRowFrame* rowFrame;
|
||||
PRInt32 rowIndex; // the index in rowInfo, not among the rows in the row group
|
||||
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
|
||||
UpdateHeights(rowInfo[rowIndex], nsTableFrame::RoundToPixel(rowFrame->GetHeight(pctHeightBasis), p2t),
|
||||
heightOfRows, heightOfUnStyledRows);
|
||||
rowInfo[rowIndex].hasStyleHeight = rowFrame->HasStyleHeight();
|
||||
|
||||
// Step 1: get the height of the tallest cell in the row and save it for
|
||||
// pass 2. This height is for table cells that originate in this
|
||||
// row and that don't span into the rows that follow
|
||||
nsIFrame* rowFrame = startRowFrame;
|
||||
PRInt32 rowIndex = 0;
|
||||
|
||||
// For row groups that are split across pages, the first row frame won't
|
||||
// necessarily be index 0
|
||||
PRInt32 startRowIndex = -1;
|
||||
while (rowFrame) {
|
||||
nsCOMPtr<nsIAtom> frameType;
|
||||
rowFrame->GetFrameType(getter_AddRefs(frameType));
|
||||
if (nsLayoutAtoms::tableRowFrame == frameType.get()) {
|
||||
if (startRowIndex == -1) {
|
||||
startRowIndex = ((nsTableRowFrame*)rowFrame)->GetRowIndex();
|
||||
}
|
||||
// get the height of the tallest cell in the row (excluding cells that span rows)
|
||||
rowHeights[rowIndex] = ((nsTableRowFrame*)rowFrame)->GetTallestCell();
|
||||
|
||||
// See if a cell spans into the row. If so we'll have to do step 2
|
||||
if (!hasRowSpanningCell) {
|
||||
if (tableFrame->RowIsSpannedInto(rowIndex + startRowIndex)) {
|
||||
hasRowSpanningCell = PR_TRUE;
|
||||
if (!rowInfo[rowIndex].hasStyleHeight) {
|
||||
if (HasMoreThanOneCell(tableFrame->GetCellMap(), rowIndex)) {
|
||||
rowInfo[rowIndex].isSpecial = PR_TRUE;
|
||||
// iteratate the row's cell frames to see if any do not have rowspan > 1
|
||||
nsTableCellFrame* cellFrame = rowFrame->GetFirstCell();
|
||||
while (cellFrame) {
|
||||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(rowIndex + startRowIndex, *cellFrame);
|
||||
if (1 == rowSpan) {
|
||||
rowInfo[rowIndex].isSpecial = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
cellFrame = cellFrame->GetNextCell();
|
||||
}
|
||||
}
|
||||
// special rows need to have some values, so they will get allocations
|
||||
// later. If left at 0, they would get nothing.
|
||||
if (0 == rowHeights[rowIndex]) {
|
||||
AllocateSpecialHeight(aPresContext, tableFrame, rowFrame, rowHeights[rowIndex]);
|
||||
}
|
||||
rowIndex++;
|
||||
}
|
||||
GetNextFrame(rowFrame, &rowFrame); // Get the next row
|
||||
// See if a cell spans into the row. If so we'll have to do the next step
|
||||
if (!hasRowSpanningCell) {
|
||||
if (tableFrame->RowIsSpannedInto(rowIndex + startRowIndex)) {
|
||||
hasRowSpanningCell = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Now account for cells that span rows. A spanning cell's height is the sum of the heights of the
|
||||
// rows it spans, or it's own desired height, whichever is greater.
|
||||
// If the cell's desired height is the larger value, resize the rows and contained
|
||||
// cells by an equal percentage of the additional space.
|
||||
// We go through this loop twice. The first time, we are adjusting cell heights
|
||||
// on the fly. The second time through the loop, we're ensuring that subsequent
|
||||
// row-spanning cells didn't change prior calculations. Since we are guaranteed
|
||||
// to have found the max height spanners the first time through, we know we only
|
||||
// need two passes, not an arbitrary number.
|
||||
nscoord yOrigin = rowGroupHeight;
|
||||
nscoord lastCount = (hasRowSpanningCell) ? 2 : 1;
|
||||
for (PRInt32 counter = 0; counter <= lastCount; counter++) {
|
||||
rowFrame = startRowFrame;
|
||||
rowIndex = 0;
|
||||
while (rowFrame) {
|
||||
nsCOMPtr<nsIAtom> rowType;
|
||||
rowFrame->GetFrameType(getter_AddRefs(rowType));
|
||||
if (nsLayoutAtoms::tableRowFrame == rowType.get()) {
|
||||
if (hasRowSpanningCell) {
|
||||
// check this row for a cell with rowspans
|
||||
nsIFrame* cellFrame;
|
||||
rowFrame->FirstChild(aPresContext, nsnull, &cellFrame);
|
||||
while (cellFrame) {
|
||||
nsCOMPtr<nsIAtom> cellType;
|
||||
cellFrame->GetFrameType(getter_AddRefs(cellType));
|
||||
if (nsLayoutAtoms::tableCellFrame == cellType.get()) {
|
||||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(rowIndex + startRowIndex,
|
||||
(nsTableCellFrame&)*cellFrame);
|
||||
if (rowSpan > 1) { // found a cell with rowspan > 1, determine the height
|
||||
// of the rows it spans
|
||||
nscoord heightOfRowsSpanned = 0;
|
||||
nscoord cellSpacingOfRowsSpanned = 0;
|
||||
PRInt32 spanX;
|
||||
PRBool cellsOrigInSpan = PR_FALSE; // do any cells originate in the spanned rows
|
||||
for (spanX = 0; spanX < rowSpan; spanX++) {
|
||||
PRInt32 rIndex = rowIndex + spanX;
|
||||
if (rowHeights[rIndex] > 0) {
|
||||
// don't consider negative values of special rows
|
||||
heightOfRowsSpanned += rowHeights[rowIndex + spanX];
|
||||
cellsOrigInSpan = PR_TRUE;
|
||||
}
|
||||
if (0 != spanX) {
|
||||
cellSpacingOfRowsSpanned += cellSpacingY;
|
||||
}
|
||||
}
|
||||
nscoord availHeightOfRowsSpanned = heightOfRowsSpanned + cellSpacingOfRowsSpanned;
|
||||
if (hasRowSpanningCell) {
|
||||
// Get the height of cells with rowspans and allocate any extra space to the rows they span
|
||||
// iteratate the child frames and process the row frames among them
|
||||
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
|
||||
if (tableFrame->RowHasSpanningCells(startRowIndex + rowIndex)) {
|
||||
nsTableCellFrame* cellFrame = rowFrame->GetFirstCell();
|
||||
// iteratate the row's cell frames
|
||||
while (cellFrame) {
|
||||
PRInt32 rowSpan = tableFrame->GetEffectiveRowSpan(rowIndex + startRowIndex, *cellFrame);
|
||||
if (rowSpan > 1) { // a cell with rowspan > 1, determine the height of the rows it spans
|
||||
nscoord heightOfRowsSpanned = 0;
|
||||
nscoord heightOfUnStyledRowsSpanned = 0;
|
||||
nscoord numSpecialRowsSpanned = 0;
|
||||
nscoord cellSpacingTotal = 0;
|
||||
PRInt32 spanX;
|
||||
for (spanX = 0; spanX < rowSpan; spanX++) {
|
||||
heightOfRowsSpanned += rowInfo[rowIndex + spanX].height;
|
||||
if (!rowInfo[rowIndex + spanX].hasStyleHeight) {
|
||||
heightOfUnStyledRowsSpanned += rowInfo[rowIndex + spanX].height;
|
||||
}
|
||||
if (0 != spanX) {
|
||||
cellSpacingTotal += cellSpacingY;
|
||||
}
|
||||
if (rowInfo[rowIndex + spanX].isSpecial) {
|
||||
numSpecialRowsSpanned++;
|
||||
}
|
||||
}
|
||||
nscoord heightOfAreaSpanned = heightOfRowsSpanned + cellSpacingTotal;
|
||||
// get the height of the cell
|
||||
nsSize cellFrameSize;
|
||||
cellFrame->GetSize(cellFrameSize);
|
||||
nsSize cellDesSize = cellFrame->GetDesiredSize();
|
||||
rowFrame->CalculateCellActualSize(cellFrame, cellDesSize.width,
|
||||
cellDesSize.height, cellDesSize.width);
|
||||
cellFrameSize.height = cellDesSize.height;
|
||||
if (cellFrame->HasVerticalAlignBaseline()) {
|
||||
// to ensure that a spanning cell with a long descender doesn't
|
||||
// collide with the next row, we need to take into account the shift
|
||||
// that will be done to align the cell on the baseline of the row.
|
||||
cellFrameSize.height += rowFrame->GetMaxCellAscent() - cellFrame->GetDesiredAscent();
|
||||
}
|
||||
|
||||
// see if the cell's height fits within the rows it spans. If this is
|
||||
// pass 1 then use the cell's desired height and not the current height
|
||||
// of its frame. That way this works for incremental reflow, too
|
||||
nsSize cellFrameSize;
|
||||
cellFrame->GetSize(cellFrameSize);
|
||||
if (0 == counter) {
|
||||
nsSize cellDesSize = ((nsTableCellFrame*)cellFrame)->GetDesiredSize();
|
||||
((nsTableRowFrame*)rowFrame)->CalculateCellActualSize(cellFrame, cellDesSize.width,
|
||||
cellDesSize.height, cellDesSize.width);
|
||||
cellFrameSize.height = cellDesSize.height;
|
||||
// see if the cell has 'vertical-align: baseline'
|
||||
if (((nsTableCellFrame*)cellFrame)->HasVerticalAlignBaseline()) {
|
||||
// to ensure that a spanning cell with a long descender doesn't
|
||||
// collide with the next row, we need to take into account the shift
|
||||
// that will be done to align the cell on the baseline of the row.
|
||||
cellFrameSize.height += ((nsTableRowFrame*)rowFrame)->GetMaxCellAscent()
|
||||
- ((nsTableCellFrame*)cellFrame)->GetDesiredAscent();
|
||||
}
|
||||
}
|
||||
|
||||
if (availHeightOfRowsSpanned >= cellFrameSize.height) {
|
||||
// the cell's height fits with the available space of the rows it
|
||||
// spans. Set the cell frame's height
|
||||
cellFrame->SizeTo(aPresContext, cellFrameSize.width, availHeightOfRowsSpanned);
|
||||
// Realign cell content based on new height
|
||||
((nsTableCellFrame*)cellFrame)->VerticallyAlignChild(aPresContext, aReflowState, ((nsTableRowFrame*)rowFrame)->GetMaxCellAscent());
|
||||
}
|
||||
else {
|
||||
// the cell's height is larger than the available space of the rows it
|
||||
// spans so distribute the excess height to the rows affected
|
||||
nscoord excessAvail = cellFrameSize.height - availHeightOfRowsSpanned;
|
||||
nscoord excessBasis = excessAvail;
|
||||
|
||||
nsTableRowFrame* rowFrameToBeResized = (nsTableRowFrame *)rowFrame;
|
||||
// iterate every row starting at last row spanned and up to the row with
|
||||
// the spanning cell. do this bottom up so that special rows can get a full
|
||||
// allocation before other rows.
|
||||
PRInt32 beginRowIndex = rowIndex + rowSpan - 1;
|
||||
for (PRInt32 rowX = beginRowIndex; (rowX >= rowIndex) && (excessAvail > 0); rowX--) {
|
||||
nscoord excessForRow = 0;
|
||||
// special rows gets as much as they can
|
||||
if (rowHeights[rowX] <= 0) {
|
||||
if ((rowX == beginRowIndex) || (!cellsOrigInSpan)) {
|
||||
if (0 == rowHeights[rowX]) {
|
||||
// give it all since no cell originates in the row
|
||||
excessForRow = excessBasis;
|
||||
}
|
||||
else { // don't let the allocation excced what it needs
|
||||
excessForRow = (excessBasis > -rowHeights[rowX]) ? -rowHeights[rowX] : excessBasis;
|
||||
}
|
||||
rowHeights[rowX] = excessForRow;
|
||||
excessBasis -= excessForRow;
|
||||
excessAvail -= excessForRow;
|
||||
if (heightOfAreaSpanned < cellFrameSize.height) {
|
||||
// the cell's height is larger than the available space of the rows it
|
||||
// spans so distribute the excess height to the rows affected
|
||||
nscoord extra = cellFrameSize.height - heightOfAreaSpanned;
|
||||
nscoord extraUsed = 0;
|
||||
if (0 == numSpecialRowsSpanned) {
|
||||
//NS_ASSERTION(heightOfRowsSpanned > 0, "invalid row span situation");
|
||||
PRBool haveUnStyledRowsSpanned = (heightOfUnStyledRowsSpanned > 0);
|
||||
nscoord divisor = (haveUnStyledRowsSpanned)
|
||||
? heightOfUnStyledRowsSpanned : heightOfRowsSpanned;
|
||||
if (divisor > 0) {
|
||||
for (spanX = rowSpan - 1; spanX >= 0; spanX--) {
|
||||
if (!haveUnStyledRowsSpanned || !rowInfo[rowIndex + spanX].hasStyleHeight) {
|
||||
// The amount of additional space each row gets is proportional to its height
|
||||
float percent = ((float)rowInfo[rowIndex + spanX].height) / ((float)divisor);
|
||||
|
||||
// give rows their percentage, except for the first row which gets the remainder
|
||||
nscoord extraForRow = (0 == spanX) ? extra - extraUsed
|
||||
: NSToCoordRound(((float)(extra)) * percent);
|
||||
extraForRow = PR_MIN(nsTableFrame::RoundToPixel(extraForRow, p2t), extra - extraUsed);
|
||||
// update the row height
|
||||
UpdateHeights(rowInfo[rowIndex + spanX], extraForRow, heightOfRows, heightOfUnStyledRows);
|
||||
extraUsed += extraForRow;
|
||||
if (extraUsed >= extra) {
|
||||
NS_ASSERTION((extraUsed == extra), "invalid row height calculation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (cellsOrigInSpan) { // normal rows
|
||||
// The amount of additional space each normal row gets is based on the
|
||||
// percentage of space it occupies, i.e. they don't all get the
|
||||
// same amount of available space
|
||||
float percent = ((float)rowHeights[rowX]) / ((float)heightOfRowsSpanned);
|
||||
|
||||
// give rows their percentage, except for the first row which gets
|
||||
// the remainder
|
||||
excessForRow = (rowX == rowIndex)
|
||||
? excessAvail
|
||||
: NSToCoordRound(((float)(excessBasis)) * percent);
|
||||
// update the row height
|
||||
rowHeights[rowX] += excessForRow;
|
||||
excessAvail -= excessForRow;
|
||||
}
|
||||
// Get the next row frame
|
||||
GetNextRowSibling((nsIFrame**)&rowFrameToBeResized);
|
||||
}
|
||||
// if excessAvail is > 0 it is because !cellsOrigInSpan and the
|
||||
// allocation involving special rows couldn't allocate everything.
|
||||
// just give the remainder to the last row spanned.
|
||||
if (excessAvail > 0) {
|
||||
if (rowHeights[beginRowIndex] >= 0) {
|
||||
rowHeights[beginRowIndex] += excessAvail;
|
||||
}
|
||||
else {
|
||||
rowHeights[beginRowIndex] = excessAvail;
|
||||
}
|
||||
else {
|
||||
// put everything in the last row
|
||||
UpdateHeights(rowInfo[rowIndex + rowSpan - 1], extra, heightOfRows, heightOfUnStyledRows);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// give the extra to the special rows
|
||||
nscoord numSpecialRowsAllocated = 0;
|
||||
for (spanX = rowSpan - 1; spanX >= 0; spanX--) {
|
||||
if (rowInfo[rowIndex + spanX].isSpecial) {
|
||||
// The amount of additional space each degenerate row gets is proportional to the number of them
|
||||
float percent = 1.0f / ((float)numSpecialRowsSpanned);
|
||||
|
||||
// give rows their percentage, except for the first row which gets the remainder
|
||||
nscoord extraForRow = (numSpecialRowsSpanned - 1 == numSpecialRowsAllocated)
|
||||
? extra - extraUsed
|
||||
: NSToCoordRound(((float)(extra)) * percent);
|
||||
extraForRow = PR_MIN(nsTableFrame::RoundToPixel(extraForRow, p2t), extra - extraUsed);
|
||||
// update the row height
|
||||
UpdateHeights(rowInfo[rowIndex + spanX], extraForRow, heightOfRows, heightOfUnStyledRows);
|
||||
extraUsed += extraForRow;
|
||||
if (extraUsed >= extra) {
|
||||
NS_ASSERTION((extraUsed == extra), "invalid row height calculation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cellFrame->GetNextSibling(&cellFrame); // Get the next row child (cell frame)
|
||||
}
|
||||
}
|
||||
|
||||
// If this is the last pass then resize the row to its final size and move the
|
||||
// row's position if the previous rows have caused a shift
|
||||
if (lastCount == counter) {
|
||||
nsRect rowBounds;
|
||||
rowFrame->GetRect(rowBounds);
|
||||
|
||||
PRBool movedFrame = (rowBounds.y != yOrigin);
|
||||
nscoord rowHeight = (rowHeights[rowIndex] > 0) ? rowHeights[rowIndex] : 0;
|
||||
|
||||
// Resize the row to its final size and position
|
||||
rowBounds.y = yOrigin;
|
||||
rowBounds.height = rowHeight;
|
||||
rowFrame->SetRect(aPresContext, rowBounds);
|
||||
|
||||
if (movedFrame) {
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
// set the origin of the next row.
|
||||
yOrigin += rowHeight + cellSpacingY;
|
||||
}
|
||||
|
||||
rowIndex++;
|
||||
}
|
||||
GetNextFrame(rowFrame, &rowFrame); // Get the next rowgroup child (row frame)
|
||||
}
|
||||
}
|
||||
} // if (rowSpan > 1)
|
||||
cellFrame = cellFrame->GetNextCell();
|
||||
} // while (cellFrame)
|
||||
} // if (tableFrame->RowHasSpanningCells(startRowIndex + rowIndex) {
|
||||
} // while (rowFrame)
|
||||
}
|
||||
|
||||
// step 3: notify the rows of their new heights
|
||||
rowFrame = startRowFrame;
|
||||
|
||||
rowIndex = 0;
|
||||
while (rowFrame) {
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) {
|
||||
nsCOMPtr<nsIAtom> rowType;
|
||||
rowFrame->GetFrameType(getter_AddRefs(rowType));
|
||||
if (nsLayoutAtoms::tableRowFrame == rowType.get()) {
|
||||
// Notify the row of the new size
|
||||
((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState);
|
||||
nscoord rowGroupHeight = startRowGroupHeight + heightOfRows + ((numRows - 1) * cellSpacingY);
|
||||
nscoord extraComputedHeight = 0;
|
||||
// if we have a style height, allocate the extra height to unconstrained rows
|
||||
if ((aReflowState.mComputedHeight > rowGroupHeight) &&
|
||||
(NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight)) {
|
||||
extraComputedHeight = aReflowState.mComputedHeight - rowGroupHeight;
|
||||
nscoord extraUsed = 0;
|
||||
PRBool haveUnStyledRows = (heightOfUnStyledRows > 0);
|
||||
nscoord divisor = (haveUnStyledRows)
|
||||
? heightOfUnStyledRows : heightOfRows;
|
||||
if (divisor > 0) {
|
||||
for (rowIndex = 0; rowIndex < numRows; rowIndex++) {
|
||||
if (!haveUnStyledRows || !rowInfo[rowIndex].hasStyleHeight) {
|
||||
// The amount of additional space each row gets is based on the
|
||||
// percentage of space it occupies
|
||||
float percent = ((float)rowInfo[rowIndex].height) / ((float)divisor);
|
||||
// give rows their percentage, except for the last row which gets the remainder
|
||||
nscoord extraForRow = (numRows - 1 == rowIndex)
|
||||
? extraComputedHeight - extraUsed
|
||||
: NSToCoordRound(((float)extraComputedHeight) * percent);
|
||||
extraForRow = PR_MIN(nsTableFrame::RoundToPixel(extraForRow, p2t), extraComputedHeight - extraUsed);
|
||||
// update the row height
|
||||
UpdateHeights(rowInfo[rowIndex], extraForRow, heightOfRows, heightOfUnStyledRows);
|
||||
extraUsed += extraForRow;
|
||||
if (extraUsed >= extraComputedHeight) {
|
||||
NS_ASSERTION((extraUsed == extraComputedHeight), "invalid row height calculation");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the running row group height. The height includes frames that
|
||||
// aren't rows as well
|
||||
nsSize rowSize;
|
||||
rowFrame->GetSize(rowSize);
|
||||
rowGroupHeight += rowSize.height;
|
||||
if (0 != rowIndex) {
|
||||
rowGroupHeight += cellSpacingY;
|
||||
}
|
||||
|
||||
GetNextFrame(rowFrame, &rowFrame); // Get the next row
|
||||
rowIndex++;
|
||||
rowGroupHeight = aReflowState.mComputedHeight;
|
||||
}
|
||||
|
||||
nscoord yOrigin = startRowGroupHeight;
|
||||
// update the rows with their (potentially) new heights
|
||||
for (rowFrame = startRowFrame, rowIndex = 0; rowFrame; rowFrame = rowFrame->GetNextRow(), rowIndex++) {
|
||||
nsRect rowBounds;
|
||||
rowFrame->GetRect(rowBounds);
|
||||
|
||||
PRBool movedFrame = (rowBounds.y != yOrigin);
|
||||
nscoord rowHeight = (rowInfo[rowIndex].height > 0) ? rowInfo[rowIndex].height : 0;
|
||||
|
||||
if (movedFrame || (rowHeight != rowBounds.height)) {
|
||||
// Resize the row to its final size and position
|
||||
rowBounds.y = yOrigin;
|
||||
rowBounds.height = rowHeight;
|
||||
rowFrame->SetRect(aPresContext, rowBounds);
|
||||
}
|
||||
if (movedFrame) {
|
||||
nsTableFrame::RePositionViews(aPresContext, rowFrame);
|
||||
}
|
||||
yOrigin += rowHeight + cellSpacingY;
|
||||
}
|
||||
|
||||
DidResizeRows(*aPresContext, aReflowState, startRowFrame);
|
||||
|
||||
aDesiredSize.height = rowGroupHeight; // Adjust our desired size
|
||||
delete [] rowHeights; // cleanup
|
||||
delete [] rowInfo; // cleanup
|
||||
}
|
||||
|
||||
|
||||
// Called by IR_TargetIsChild() to adjust the sibling frames that follow
|
||||
// after an incremental reflow of aKidFrame.
|
||||
// This function is not used for paginated mode so we don't need to deal
|
||||
@ -918,31 +938,6 @@ nsTableRowGroupFrame::SplitSpanningCells(nsIPresContext& aPresContext,
|
||||
return tallestCell;
|
||||
}
|
||||
|
||||
nsIFrame* GetNextRow(nsIFrame& aFrame)
|
||||
{
|
||||
nsIFrame* rowFrame;
|
||||
for (aFrame.GetNextSibling(&rowFrame); rowFrame; rowFrame->GetNextSibling(&rowFrame)) {
|
||||
nsCOMPtr<nsIAtom> fType;
|
||||
rowFrame->GetFrameType(getter_AddRefs(fType));
|
||||
if (nsLayoutAtoms::tableRowFrame == fType.get()) {
|
||||
return rowFrame;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsIFrame* GetFirstRow(nsTableRowGroupFrame& aRowGroupFrame)
|
||||
{
|
||||
for (nsIFrame* rowFrame = aRowGroupFrame.GetFirstFrame(); rowFrame; rowFrame = GetNextRow(*rowFrame)) {
|
||||
nsCOMPtr<nsIAtom> fType;
|
||||
rowFrame->GetFrameType(getter_AddRefs(fType));
|
||||
if (nsLayoutAtoms::tableRowFrame == fType.get()) {
|
||||
return rowFrame;
|
||||
}
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
@ -971,7 +966,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
|
||||
|
||||
// Walk each of the row frames looking for the first row frame that
|
||||
// doesn't fit in the available space
|
||||
for (nsIFrame* rowFrame = GetFirstRow(*this); rowFrame; rowFrame = GetNextRow(*rowFrame)) {
|
||||
for (nsTableRowFrame* rowFrame = GetFirstRow(); rowFrame; rowFrame = rowFrame->GetNextRow()) {
|
||||
PRBool rowIsOnCurrentPage = PR_TRUE;
|
||||
PRBool degenerateRow = PR_FALSE;
|
||||
nsRect bounds;
|
||||
@ -995,7 +990,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
|
||||
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
|
||||
rowFrame->SizeTo(aPresContext, desiredSize.width, desiredSize.height);
|
||||
rowFrame->DidReflow(aPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||
((nsTableRowFrame *)rowFrame)->DidResize(aPresContext, aReflowState);
|
||||
rowFrame->DidResize(aPresContext, aReflowState);
|
||||
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
// the row frame is incomplete and all of the cells' block frames have split
|
||||
@ -1043,7 +1038,7 @@ nsTableRowGroupFrame::SplitRowGroup(nsIPresContext* aPresContext,
|
||||
if (prevRowFrame) {
|
||||
nscoord tallestCell =
|
||||
SplitSpanningCells(*aPresContext, aReflowState, *styleSet, *aTableFrame,
|
||||
*(nsTableRowFrame*)rowFrame, aDesiredSize.height, (nsTableRowFrame*)contRowFrame);
|
||||
*rowFrame, aDesiredSize.height, (nsTableRowFrame*)contRowFrame);
|
||||
if (degenerateRow) {
|
||||
aDesiredSize.height = lastDesiredHeight + aTableFrame->GetCellSpacingY() + tallestCell;
|
||||
}
|
||||
@ -1077,10 +1072,10 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
|
||||
|
||||
nsresult rv=NS_OK;
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
rv = nsTableFrame::GetTableFrame(this, tableFrame);
|
||||
if (!tableFrame) return NS_ERROR_NULL_POINTER;
|
||||
if (!aPresContext || !tableFrame) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsRowGroupReflowState state(aReflowState, tableFrame);
|
||||
PRBool haveDesiredHeight = PR_FALSE;
|
||||
@ -1111,9 +1106,12 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
|
||||
// reflow, then we need to do this because the table will skip the pass 2 reflow,
|
||||
// but we need to correctly calculate the row group height and we can't if there
|
||||
// are row spans unless we do this step
|
||||
if ((eReflowReason_Initial != aReflowState.reason) ||
|
||||
isTableUnconstrainedReflow ||
|
||||
isPaginated) {
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
DidResizeRows(*aPresContext, aReflowState);
|
||||
}
|
||||
else if ((eReflowReason_Initial != aReflowState.reason) ||
|
||||
isTableUnconstrainedReflow ||
|
||||
isPaginated) {
|
||||
CalculateRowHeights(aPresContext, aDesiredSize, aReflowState);
|
||||
haveDesiredHeight = PR_TRUE;
|
||||
}
|
||||
@ -1124,6 +1122,12 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
|
||||
SplitRowGroup(aPresContext, aDesiredSize, aReflowState, tableFrame, aStatus);
|
||||
}
|
||||
}
|
||||
SetHasStyleHeight((NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) &&
|
||||
(aReflowState.mComputedHeight > 0));
|
||||
|
||||
if (aReflowState.mFlags.mSpecialTableReflow) {
|
||||
SetNeedSpecialReflow(PR_FALSE);
|
||||
}
|
||||
|
||||
// just set our width to what was available. The table will calculate the width and not use our value.
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
@ -1318,6 +1322,21 @@ nsTableRowGroupFrame::IR_TargetIsMe(nsIPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsTableRowGroupFrame::GetHeightBasis(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
nscoord result = 0;
|
||||
if ((aReflowState.mComputedHeight > 0) && (aReflowState.mComputedHeight < NS_UNCONSTRAINEDSIZE)) {
|
||||
nsTableFrame* tableFrame = nsnull;
|
||||
nsTableFrame::GetTableFrame((nsIFrame*)this, tableFrame);
|
||||
if (tableFrame) {
|
||||
nscoord cellSpacing = PR_MAX(0, GetRowCount() - 1) * tableFrame->GetCellSpacingY();
|
||||
result -= cellSpacing;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsTableRowGroupFrame::GetHeightOfRows(nsIPresContext* aPresContext)
|
||||
{
|
||||
|
||||
@ -79,9 +79,13 @@ struct nsRowGroupReflowState {
|
||||
{ 0xe940e7bc, 0xb534, 0x11d2, \
|
||||
{ 0x95, 0xa2, 0x0, 0x60, 0xb0, 0xc3, 0x44, 0x14 } }
|
||||
|
||||
// use a bit from nsFrame's frame state bits to determine whether a
|
||||
// use the following bits from nsFrame's frame state
|
||||
|
||||
// thead or tfoot should be repeated on every printed page
|
||||
#define NS_ROWGROUP_REPEATABLE 0x80000000
|
||||
#define NS_ROWGROUP_REPEATABLE 0x80000000
|
||||
#define NS_ROWGROUP_HAS_STYLE_HEIGHT 0x40000000
|
||||
// we need a 3rd pass reflow to deal with pct height nested tables
|
||||
#define NS_ROWGROUP_NEED_SPECIAL_REFLOW 0x20000000
|
||||
/**
|
||||
* nsTableRowGroupFrame is the frame that maps row groups
|
||||
* (HTML tags THEAD, TFOOT, and TBODY). This class cannot be reused
|
||||
@ -176,6 +180,10 @@ public:
|
||||
*/
|
||||
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
|
||||
|
||||
NS_IMETHOD IsPercentageBase(PRBool& aBase) const;
|
||||
|
||||
nsTableRowFrame* GetFirstRow();
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD GetFrameName(nsString& aResult) const;
|
||||
NS_IMETHOD SizeOf(nsISizeOfHandler* aSizer, PRUint32* aResult) const;
|
||||
@ -206,6 +214,7 @@ public:
|
||||
* Get the total height of all the row rects
|
||||
*/
|
||||
nscoord GetHeightOfRows(nsIPresContext* aPresContext);
|
||||
nscoord GetHeightBasis(const nsHTMLReflowState& aReflowState);
|
||||
|
||||
// nsILineIterator methods
|
||||
public:
|
||||
@ -255,6 +264,9 @@ protected:
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsTableRowFrame* aStartRowFrameIn = nsnull);
|
||||
|
||||
void DidResizeRows(nsIPresContext& aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsTableRowFrame* aStartRowFrameIn = nsnull);
|
||||
|
||||
/** Incremental Reflow attempts to do column balancing with the minimum number of reflow
|
||||
* commands to child elements. This is done by processing the reflow command,
|
||||
@ -337,8 +349,12 @@ public:
|
||||
virtual nsIFrame* GetLastFrame() { return mFrames.LastChild(); };
|
||||
virtual void GetNextFrame(nsIFrame* aFrame,
|
||||
nsIFrame** aResult) { aFrame->GetNextSibling(aResult); };
|
||||
PRBool IsRepeatable();
|
||||
void SetRepeatable(PRBool aRepeatable);
|
||||
PRBool IsRepeatable() const;
|
||||
void SetRepeatable(PRBool aRepeatable);
|
||||
PRBool HasStyleHeight() const;
|
||||
void SetHasStyleHeight(PRBool aValue);
|
||||
PRBool NeedSpecialReflow() const;
|
||||
void SetNeedSpecialReflow(PRBool aValue);
|
||||
|
||||
#ifdef DEBUG_TABLE_REFLOW_TIMING
|
||||
public:
|
||||
@ -347,7 +363,7 @@ public:
|
||||
};
|
||||
|
||||
|
||||
inline PRBool nsTableRowGroupFrame::IsRepeatable()
|
||||
inline PRBool nsTableRowGroupFrame::IsRepeatable() const
|
||||
{
|
||||
return (mState & NS_ROWGROUP_REPEATABLE) == NS_ROWGROUP_REPEATABLE;
|
||||
}
|
||||
@ -361,4 +377,31 @@ inline void nsTableRowGroupFrame::SetRepeatable(PRBool aRepeatable)
|
||||
}
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowGroupFrame::NeedSpecialReflow() const
|
||||
{
|
||||
return (mState & NS_ROWGROUP_NEED_SPECIAL_REFLOW) == NS_ROWGROUP_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
|
||||
inline void nsTableRowGroupFrame::SetNeedSpecialReflow(PRBool aValue)
|
||||
{
|
||||
if (aValue) {
|
||||
mState |= NS_ROWGROUP_NEED_SPECIAL_REFLOW;
|
||||
} else {
|
||||
mState &= ~NS_ROWGROUP_NEED_SPECIAL_REFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
inline PRBool nsTableRowGroupFrame::HasStyleHeight() const
|
||||
{
|
||||
return (mState & NS_ROWGROUP_HAS_STYLE_HEIGHT) == NS_ROWGROUP_HAS_STYLE_HEIGHT;
|
||||
}
|
||||
|
||||
inline void nsTableRowGroupFrame::SetHasStyleHeight(PRBool aValue)
|
||||
{
|
||||
if (aValue) {
|
||||
mState |= NS_ROWGROUP_HAS_STYLE_HEIGHT;
|
||||
} else {
|
||||
mState &= ~NS_ROWGROUP_HAS_STYLE_HEIGHT;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user