bug 125543 - Prevent row groups from splitting in the reflow preceeding a special height reflow. Cells are only notified that they should observe a percent height element if the element is inside the table's cell. Percent height elements inside the body will have a height based on the page height when printing. sr=kin, r=alexsavulov.

This commit is contained in:
karnaze%netscape.com 2002-04-10 21:32:41 +00:00
Родитель bd5c05e266
Коммит 01900c25dc
18 изменённых файлов: 250 добавлений и 120 удалений

Просмотреть файл

@ -48,14 +48,18 @@ class nsIPresContext;
/**
* This interface is supported by frames that need to provide computed height
* values to children during reflow which would otherwise not happen. Currently only
* tables support this.
* table cells support this.
*/
class nsIPercentHeightObserver : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPERCENTHEIGHTOBSERVER_IID)
NS_IMETHOD NotifyPercentHeight(const nsHTMLReflowState& aReflowState) = 0;
// Notify the observer that aReflowState has no computed height, but it has a percent height
virtual void NotifyPercentHeight(const nsHTMLReflowState& aReflowState) = 0;
// Ask the observer if it should observe aReflowState.frame
virtual PRBool NeedsToObserve(const nsHTMLReflowState& aReflowState) = 0;
};
#endif // nsIPercentHeightObserver_h___

Просмотреть файл

@ -48,14 +48,18 @@ class nsIPresContext;
/**
* This interface is supported by frames that need to provide computed height
* values to children during reflow which would otherwise not happen. Currently only
* tables support this.
* table cells support this.
*/
class nsIPercentHeightObserver : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPERCENTHEIGHTOBSERVER_IID)
NS_IMETHOD NotifyPercentHeight(const nsHTMLReflowState& aReflowState) = 0;
// Notify the observer that aReflowState has no computed height, but it has a percent height
virtual void NotifyPercentHeight(const nsHTMLReflowState& aReflowState) = 0;
// Ask the observer if it should observe aReflowState.frame
virtual PRBool NeedsToObserve(const nsHTMLReflowState& aReflowState) = 0;
};
#endif // nsIPercentHeightObserver_h___

Просмотреть файл

@ -1828,20 +1828,24 @@ nsFrame::DidReflow(nsIPresContext* aPresContext,
NS_FRAME_HAS_DIRTY_CHILDREN);
}
// Notify the percent height observer if this is an initial or resize constrained reflow
// Notify the percent height observer if this is an initial or resize reflow (XXX
// it should probably be any type of reflow, but this would need further testing)
// and there is a percent height but no computed height. The observer may be able to
// initiate another reflow with a computed height. This happens in the case where a table
// cell has no computed height but can fabricate one when the cell height is known.
if (aReflowState && (aReflowState->mPercentHeightObserver) && // an observer
((eReflowReason_Initial == aReflowState->reason) || // initial or resize reflow
(eReflowReason_Resize == aReflowState->reason)) &&
(NS_UNCONSTRAINEDSIZE != aReflowState->availableWidth) && // constrained width reflow
((NS_UNCONSTRAINEDSIZE == aReflowState->mComputedHeight) || // no computed height
(0 == aReflowState->mComputedHeight)) &&
aReflowState->mStylePosition && // percent height
(eStyleUnit_Percent == aReflowState->mStylePosition->mHeight.GetUnit())) {
aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState);
nsIFrame* prevInFlow;
GetPrevInFlow(&prevInFlow);
if (!prevInFlow) { // 1st in flow
aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState);
}
}
return NS_OK;

Просмотреть файл

@ -50,6 +50,7 @@
#include "nsImageFrame.h"
#include "nsIPref.h"
#include "nsIServiceManager.h"
#include "nsIPercentHeightObserver.h"
#define IS_TABLE_CELL(frameType)\
((nsLayoutAtoms::tableCellFrame == frameType) || (nsLayoutAtoms::bcTableCellFrame == frameType))
@ -163,7 +164,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
mSpaceManager = aParentReflowState.mSpaceManager;
mLineLayout = aParentReflowState.mLineLayout;
mFlags.mIsTopOfPage = aParentReflowState.mFlags.mIsTopOfPage;
mPercentHeightObserver = aParentReflowState.mPercentHeightObserver;
mPercentHeightObserver = (aParentReflowState.mPercentHeightObserver &&
aParentReflowState.mPercentHeightObserver->NeedsToObserve(*this))
? aParentReflowState.mPercentHeightObserver : nsnull;
mPercentHeightReflowInitiator = aParentReflowState.mPercentHeightReflowInitiator;
if (aInit) {
@ -195,7 +198,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
mSpaceManager = aParentReflowState.mSpaceManager;
mLineLayout = aParentReflowState.mLineLayout;
mFlags.mIsTopOfPage = aParentReflowState.mFlags.mIsTopOfPage;
mPercentHeightObserver = aParentReflowState.mPercentHeightObserver;
mPercentHeightObserver = (aParentReflowState.mPercentHeightObserver &&
aParentReflowState.mPercentHeightObserver->NeedsToObserve(*this))
? aParentReflowState.mPercentHeightObserver : nsnull;
mPercentHeightReflowInitiator = aParentReflowState.mPercentHeightReflowInitiator;
Init(aPresContext);
@ -226,7 +231,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
mSpaceManager = aParentReflowState.mSpaceManager;
mLineLayout = aParentReflowState.mLineLayout;
mFlags.mIsTopOfPage = aParentReflowState.mFlags.mIsTopOfPage;
mPercentHeightObserver = aParentReflowState.mPercentHeightObserver;
mPercentHeightObserver = (aParentReflowState.mPercentHeightObserver &&
aParentReflowState.mPercentHeightObserver->NeedsToObserve(*this))
? aParentReflowState.mPercentHeightObserver : nsnull;
mPercentHeightReflowInitiator = aParentReflowState.mPercentHeightReflowInitiator;
Init(aPresContext, aContainingBlockWidth, aContainingBlockHeight);
@ -1367,7 +1374,7 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
nscoord result = 0;
const nsHTMLReflowState* rs = &aReflowState;
for (; rs; rs = (nsHTMLReflowState *)(rs->parentReflowState)) {
for (; rs && rs->frame; rs = (nsHTMLReflowState *)(rs->parentReflowState)) {
nsCOMPtr<nsIAtom> frameType;
rs->frame->GetFrameType(getter_AddRefs(frameType));
// if the ancestor is auto height then skip it and continue up if it
@ -1405,18 +1412,28 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
rs = scrollState;
}
}
else if (nsLayoutAtoms::pageContentFrame == frameType.get()) {
nsIFrame* prevInFlow;
rs->frame->GetPrevInFlow(&prevInFlow);
// only use the page content frame for a height basis if it is the first in flow
if (prevInFlow)
break;
}
else {
break;
}
// if the ancestor has a computed height, it is the percent base
result = rs->mComputedHeight;
// if the ancestor is the page content frame then the percent base is
// the avail height, otherwise it is the computed height
result = (nsLayoutAtoms::pageContentFrame == frameType.get())
? rs->availableHeight : rs->mComputedHeight;
// if unconstrained - don't sutract borders - would result in huge height
if (NS_AUTOHEIGHT == result) return result;
// if we got to the canvas frame, then subtract out
// if we got to the canvas or page content frame, then subtract out
// margin/border/padding for the BODY and HTML elements
if (nsLayoutAtoms::canvasFrame == frameType.get()) {
if ((nsLayoutAtoms::canvasFrame == frameType.get()) ||
(nsLayoutAtoms::pageContentFrame == frameType.get())) {
result -= GetVerticalMarginBorderPadding(firstBlockRS);
result -= GetVerticalMarginBorderPadding(firstAreaRS);

Просмотреть файл

@ -1828,20 +1828,24 @@ nsFrame::DidReflow(nsIPresContext* aPresContext,
NS_FRAME_HAS_DIRTY_CHILDREN);
}
// Notify the percent height observer if this is an initial or resize constrained reflow
// Notify the percent height observer if this is an initial or resize reflow (XXX
// it should probably be any type of reflow, but this would need further testing)
// and there is a percent height but no computed height. The observer may be able to
// initiate another reflow with a computed height. This happens in the case where a table
// cell has no computed height but can fabricate one when the cell height is known.
if (aReflowState && (aReflowState->mPercentHeightObserver) && // an observer
((eReflowReason_Initial == aReflowState->reason) || // initial or resize reflow
(eReflowReason_Resize == aReflowState->reason)) &&
(NS_UNCONSTRAINEDSIZE != aReflowState->availableWidth) && // constrained width reflow
((NS_UNCONSTRAINEDSIZE == aReflowState->mComputedHeight) || // no computed height
(0 == aReflowState->mComputedHeight)) &&
aReflowState->mStylePosition && // percent height
(eStyleUnit_Percent == aReflowState->mStylePosition->mHeight.GetUnit())) {
aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState);
nsIFrame* prevInFlow;
GetPrevInFlow(&prevInFlow);
if (!prevInFlow) { // 1st in flow
aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState);
}
}
return NS_OK;

Просмотреть файл

@ -50,6 +50,7 @@
#include "nsImageFrame.h"
#include "nsIPref.h"
#include "nsIServiceManager.h"
#include "nsIPercentHeightObserver.h"
#define IS_TABLE_CELL(frameType)\
((nsLayoutAtoms::tableCellFrame == frameType) || (nsLayoutAtoms::bcTableCellFrame == frameType))
@ -163,7 +164,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
mSpaceManager = aParentReflowState.mSpaceManager;
mLineLayout = aParentReflowState.mLineLayout;
mFlags.mIsTopOfPage = aParentReflowState.mFlags.mIsTopOfPage;
mPercentHeightObserver = aParentReflowState.mPercentHeightObserver;
mPercentHeightObserver = (aParentReflowState.mPercentHeightObserver &&
aParentReflowState.mPercentHeightObserver->NeedsToObserve(*this))
? aParentReflowState.mPercentHeightObserver : nsnull;
mPercentHeightReflowInitiator = aParentReflowState.mPercentHeightReflowInitiator;
if (aInit) {
@ -195,7 +198,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
mSpaceManager = aParentReflowState.mSpaceManager;
mLineLayout = aParentReflowState.mLineLayout;
mFlags.mIsTopOfPage = aParentReflowState.mFlags.mIsTopOfPage;
mPercentHeightObserver = aParentReflowState.mPercentHeightObserver;
mPercentHeightObserver = (aParentReflowState.mPercentHeightObserver &&
aParentReflowState.mPercentHeightObserver->NeedsToObserve(*this))
? aParentReflowState.mPercentHeightObserver : nsnull;
mPercentHeightReflowInitiator = aParentReflowState.mPercentHeightReflowInitiator;
Init(aPresContext);
@ -226,7 +231,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext,
mSpaceManager = aParentReflowState.mSpaceManager;
mLineLayout = aParentReflowState.mLineLayout;
mFlags.mIsTopOfPage = aParentReflowState.mFlags.mIsTopOfPage;
mPercentHeightObserver = aParentReflowState.mPercentHeightObserver;
mPercentHeightObserver = (aParentReflowState.mPercentHeightObserver &&
aParentReflowState.mPercentHeightObserver->NeedsToObserve(*this))
? aParentReflowState.mPercentHeightObserver : nsnull;
mPercentHeightReflowInitiator = aParentReflowState.mPercentHeightReflowInitiator;
Init(aPresContext, aContainingBlockWidth, aContainingBlockHeight);
@ -1367,7 +1374,7 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
nscoord result = 0;
const nsHTMLReflowState* rs = &aReflowState;
for (; rs; rs = (nsHTMLReflowState *)(rs->parentReflowState)) {
for (; rs && rs->frame; rs = (nsHTMLReflowState *)(rs->parentReflowState)) {
nsCOMPtr<nsIAtom> frameType;
rs->frame->GetFrameType(getter_AddRefs(frameType));
// if the ancestor is auto height then skip it and continue up if it
@ -1405,18 +1412,28 @@ CalcQuirkContainingBlockHeight(const nsHTMLReflowState& aReflowState,
rs = scrollState;
}
}
else if (nsLayoutAtoms::pageContentFrame == frameType.get()) {
nsIFrame* prevInFlow;
rs->frame->GetPrevInFlow(&prevInFlow);
// only use the page content frame for a height basis if it is the first in flow
if (prevInFlow)
break;
}
else {
break;
}
// if the ancestor has a computed height, it is the percent base
result = rs->mComputedHeight;
// if the ancestor is the page content frame then the percent base is
// the avail height, otherwise it is the computed height
result = (nsLayoutAtoms::pageContentFrame == frameType.get())
? rs->availableHeight : rs->mComputedHeight;
// if unconstrained - don't sutract borders - would result in huge height
if (NS_AUTOHEIGHT == result) return result;
// if we got to the canvas frame, then subtract out
// if we got to the canvas or page content frame, then subtract out
// margin/border/padding for the BODY and HTML elements
if (nsLayoutAtoms::canvasFrame == frameType.get()) {
if ((nsLayoutAtoms::canvasFrame == frameType.get()) ||
(nsLayoutAtoms::pageContentFrame == frameType.get())) {
result -= GetVerticalMarginBorderPadding(firstBlockRS);
result -= GetVerticalMarginBorderPadding(firstAreaRS);

Просмотреть файл

@ -156,7 +156,7 @@ NoComputedHeightBetween(const nsHTMLReflowState& aReflowState,
// nsIPercentHeightObserver methods
nsresult
void
nsTableCellFrame::NotifyPercentHeight(const nsHTMLReflowState& aReflowState)
{
if (!NeedSpecialReflow()) {
@ -166,17 +166,36 @@ nsTableCellFrame::NotifyPercentHeight(const nsHTMLReflowState& aReflowState)
// initiating frame and the cell.
for (const nsHTMLReflowState* rs = aReflowState.parentReflowState; rs; rs = rs->parentReflowState) {
if ((NS_UNCONSTRAINEDSIZE != rs->mComputedHeight) && (0 != rs->mComputedHeight)) {
return NS_OK;
return;
}
// stop when we reach the cell frame
if (rs->frame == this) {
nsTableFrame::RequestSpecialHeightReflow(*rs);
return NS_OK;
return;
}
}
NS_ASSERTION(PR_FALSE, "program error in NotifyPercentHeight");
}
return NS_OK;
}
// The cell needs to observe its block and things inside its block but nothing below that
PRBool
nsTableCellFrame::NeedsToObserve(const nsHTMLReflowState& aReflowState)
{
PRBool result = PR_FALSE;
const nsHTMLReflowState* parentRS = aReflowState.parentReflowState;
if (parentRS && (parentRS->mPercentHeightObserver == this)) { // cell observes the parent
result = PR_TRUE;
parentRS = parentRS->parentReflowState;
if (parentRS && (parentRS->mPercentHeightObserver == this)) { // cell observers the grand parent
parentRS = parentRS->parentReflowState;
if (parentRS && (parentRS->mPercentHeightObserver == this)) {
// cell observes the great grand parent, so we have gone too deep
result = PR_FALSE;
}
}
}
return result;
}
nsresult
@ -798,7 +817,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
nsresult rv = NS_OK;
// see if a special height reflow needs to occur due to having a pct height
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
if (!NeedSpecialReflow())
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
// this should probably be cached somewhere
nsCompatibility compatMode;
@ -883,8 +903,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
nscoord computedPaginatedHeight = 0;
if (aReflowState.mFlags.mSpecialHeightReflow ||
(HadSpecialReflow() && ((eReflowReason_Incremental == aReflowState.reason) ||
(eReflowReason_Resize == aReflowState.reason)))) {
(HadSpecialReflow() && (eReflowReason_Incremental == aReflowState.reason))) {
((nsHTMLReflowState&)aReflowState).mComputedHeight = mRect.height - topInset - bottomInset;
DISPLAY_REFLOW_CHANGE();
}

Просмотреть файл

@ -116,8 +116,10 @@ public:
nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD NotifyPercentHeight(const nsHTMLReflowState& aReflowState);
virtual void NotifyPercentHeight(const nsHTMLReflowState& aReflowState);
virtual PRBool NeedsToObserve(const nsHTMLReflowState& aReflowState);
void InitCellFrame(PRInt32 aColIndex);

Просмотреть файл

@ -1898,11 +1898,10 @@ nsTableFrame::CheckRequestSpecialHeightReflow(const nsHTMLReflowState& aReflowSt
nsIFrame* prevInFlow;
aReflowState.frame->GetPrevInFlow(&prevInFlow);
if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) && // not first pass reflow
!prevInFlow && // 1st in flow && // 1st in flow
if (!prevInFlow && // 1st in flow && // 1st in flow
((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) || // no computed height
(0 == aReflowState.mComputedHeight)) &&
::IsPctStyleHeight(aReflowState.mStylePosition)) { // pct height
::IsPctStyleHeight(aReflowState.mStylePosition)) { // pct height
if (::AncestorsHaveStyleHeight(aReflowState)) {
nsTableFrame::RequestSpecialHeightReflow(aReflowState);
@ -2056,6 +2055,10 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
}
nsresult rv = NS_OK;
// see if a special height reflow needs to occur due to having a pct height
if (!NeedSpecialReflow())
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
// see if collapsing borders need to be calculated
if (!mPrevInFlow && IsBorderCollapse() && NeedToCalcBCBorders()) {
GET_TWIPS_TO_PIXELS(aPresContext, p2t);
@ -2132,35 +2135,33 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
// 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)) {
if (!mPrevInFlow) {
// see if an extra reflow will be necessary when the table is nested, there is a pct height,
// no computed height, but a height on the containing table
if ( ((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) ||
(0 == aReflowState.mComputedHeight)) &&
IsPctHeight(mStyleContext)) {
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
}
// 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(aPresContext, aReflowState);
if ((tableSpecifiedHeight > 0) &&
(tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE)) {
SetNeedToInitiateSpecialReflow(PR_TRUE);
}
// see if an extra reflow will be necessary in pagination mode when there is a specified table height
if (isPaginated && !mPrevInFlow && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) {
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aPresContext, 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 = !aReflowState.mFlags.mSpecialHeightReflow &&
(NeedSpecialReflow() | NeedToInitiateSpecialReflow())
? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight;
nsIFrame* lastChildReflowed = nsnull;
PRBool willInitiateSpecialReflow =
((NeedToInitiateSpecialReflow() || InitiatedSpecialReflow()) &&
(aReflowState.mFlags.mSpecialHeightReflow || !NeedSpecialReflow()));
nsIFrame* lastChildReflowed;
ReflowTable(aPresContext, aDesiredSize, aReflowState, availHeight, nextReason,
lastChildReflowed, doCollapse, balanced, aStatus);
// do the pass 2 reflow unless this is a special height reflow and we will be
// initiating a special height reflow
if (!(aReflowState.mFlags.mSpecialHeightReflow && willInitiateSpecialReflow)) {
// if we need to initiate a special height reflow, then don't constrain the
// height of the reflow before that
nscoord availHeight = (willInitiateSpecialReflow)
? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight;
if (NeedToInitiateSpecialReflow() &&
(aReflowState.mFlags.mSpecialHeightReflow || !NeedSpecialReflow())) {
aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState); // distributes extra vertical space to rows
ReflowTable(aPresContext, aDesiredSize, aReflowState, availHeight, nextReason,
lastChildReflowed, doCollapse, balanced, aStatus);
}
if (willInitiateSpecialReflow && NS_FRAME_IS_COMPLETE(aStatus)) {
// distribute extra vertical space to rows
aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState);
((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialHeightReflow = PR_TRUE;
// save the previous special height reflow initiator, install us as the new one
nsIFrame* specialReflowInitiator = aReflowState.mPercentHeightReflowInitiator;
@ -2171,6 +2172,8 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
nextReason, lastChildReflowed, doCollapse, balanced, aStatus);
// restore the previous special height reflow initiator
((nsHTMLReflowState&)aReflowState).mPercentHeightReflowInitiator = specialReflowInitiator;
// XXX We should call SetInitiatedSpecialReflow(PR_FALSE) at some point, but it is difficult to tell when
SetInitiatedSpecialReflow(PR_TRUE);
if (lastChildReflowed && NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
// if there is an incomplete child, then set the desired height to include it but not the next one

Просмотреть файл

@ -554,9 +554,13 @@ public:
PRBool NeedSpecialReflow() const;
void SetNeedSpecialReflow(PRBool aValue);
PRBool NeedToInitiateSpecialReflow() const;
void SetNeedToInitiateSpecialReflow(PRBool aValue);
PRBool InitiatedSpecialReflow() const;
void SetInitiatedSpecialReflow(PRBool aValue);
protected:
/** protected constructor.
@ -955,8 +959,9 @@ protected:
unsigned mRowInserted:1;
unsigned mNeedSpecialReflow:1;
unsigned mNeedToInitiateSpecialReflow:1;
unsigned mInitiatedSpecialReflow:1;
unsigned mNeedToCalcBCBorders:1;
unsigned : 18; // unused
unsigned : 17; // unused
} mBits;
nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
@ -1079,6 +1084,17 @@ inline void nsTableFrame::SetNeedToInitiateSpecialReflow(PRBool aValue)
{
mBits.mNeedToInitiateSpecialReflow = (unsigned)aValue;
}
inline PRBool nsTableFrame::InitiatedSpecialReflow() const
{
return (PRBool)mBits.mInitiatedSpecialReflow;
}
inline void nsTableFrame::SetInitiatedSpecialReflow(PRBool aValue)
{
mBits.mInitiatedSpecialReflow = (unsigned)aValue;
}
inline PRBool nsTableFrame::IsRowInserted() const
{
return (PRBool)mBits.mRowInserted;

Просмотреть файл

@ -992,13 +992,14 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
nsIFrame* kidNextInFlow;
kidFrame->GetNextInFlow(&kidNextInFlow);
nsSize cellDesiredSize = cellFrame->GetDesiredSize();
if ((availCellWidth != cellFrame->GetPriorAvailWidth()) ||
if ((availCellWidth != cellFrame->GetPriorAvailWidth()) ||
(cellDesiredSize.width > cellFrame->GetPriorAvailWidth()) ||
(eReflowReason_StyleChange == aReflowState.reason) ||
isPaginated ||
(aReflowState.mFlags.mSpecialHeightReflow && cellFrame->NeedSpecialReflow()) ||
HasPctHeight() ||
notifyStyleChange ){
(!aReflowState.mFlags.mSpecialHeightReflow && cellFrame->HadSpecialReflow()) ||
HasPctHeight() ||
notifyStyleChange) {
// Reflow the cell to fit the available width, height
nsSize kidAvailSize(availColWidth, aReflowState.availableHeight);
nsReflowReason reason = eReflowReason_Resize;
@ -1443,7 +1444,8 @@ nsTableRowFrame::Reflow(nsIPresContext* aPresContext,
if (!tableFrame) return NS_ERROR_NULL_POINTER;
// see if a special height reflow needs to occur due to having a pct height
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
if (!NeedSpecialReflow())
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
switch (aReflowState.reason) {
case eReflowReason_Initial:

Просмотреть файл

@ -1186,16 +1186,14 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
PRBool isPaginated;
aPresContext->IsPaginated(&isPaginated);
// If this is a special height reflow, set our desired size to what is was previously and return
// if we will be getting another special height reflow. In paginated mode, SetNeedSpecialReflow(PR_TRUE)
// may not have been called if reflow was a result of having a height on the containing table
if (nsTableFrame::IsPrematureSpecialHeightReflow(aReflowState, mRect, NeedSpecialReflow() || isPaginated, aDesiredSize))
return NS_OK;
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (!aPresContext || !tableFrame) return NS_ERROR_NULL_POINTER;
// see if a special height reflow needs to occur due to having a pct height
if (!NeedSpecialReflow())
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
nsRowGroupReflowState state(aReflowState, tableFrame);
PRBool haveDesiredHeight = PR_FALSE;

Просмотреть файл

@ -156,7 +156,7 @@ NoComputedHeightBetween(const nsHTMLReflowState& aReflowState,
// nsIPercentHeightObserver methods
nsresult
void
nsTableCellFrame::NotifyPercentHeight(const nsHTMLReflowState& aReflowState)
{
if (!NeedSpecialReflow()) {
@ -166,17 +166,36 @@ nsTableCellFrame::NotifyPercentHeight(const nsHTMLReflowState& aReflowState)
// initiating frame and the cell.
for (const nsHTMLReflowState* rs = aReflowState.parentReflowState; rs; rs = rs->parentReflowState) {
if ((NS_UNCONSTRAINEDSIZE != rs->mComputedHeight) && (0 != rs->mComputedHeight)) {
return NS_OK;
return;
}
// stop when we reach the cell frame
if (rs->frame == this) {
nsTableFrame::RequestSpecialHeightReflow(*rs);
return NS_OK;
return;
}
}
NS_ASSERTION(PR_FALSE, "program error in NotifyPercentHeight");
}
return NS_OK;
}
// The cell needs to observe its block and things inside its block but nothing below that
PRBool
nsTableCellFrame::NeedsToObserve(const nsHTMLReflowState& aReflowState)
{
PRBool result = PR_FALSE;
const nsHTMLReflowState* parentRS = aReflowState.parentReflowState;
if (parentRS && (parentRS->mPercentHeightObserver == this)) { // cell observes the parent
result = PR_TRUE;
parentRS = parentRS->parentReflowState;
if (parentRS && (parentRS->mPercentHeightObserver == this)) { // cell observers the grand parent
parentRS = parentRS->parentReflowState;
if (parentRS && (parentRS->mPercentHeightObserver == this)) {
// cell observes the great grand parent, so we have gone too deep
result = PR_FALSE;
}
}
}
return result;
}
nsresult
@ -798,7 +817,8 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
nsresult rv = NS_OK;
// see if a special height reflow needs to occur due to having a pct height
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
if (!NeedSpecialReflow())
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
// this should probably be cached somewhere
nsCompatibility compatMode;
@ -883,8 +903,7 @@ NS_METHOD nsTableCellFrame::Reflow(nsIPresContext* aPresContext,
nscoord computedPaginatedHeight = 0;
if (aReflowState.mFlags.mSpecialHeightReflow ||
(HadSpecialReflow() && ((eReflowReason_Incremental == aReflowState.reason) ||
(eReflowReason_Resize == aReflowState.reason)))) {
(HadSpecialReflow() && (eReflowReason_Incremental == aReflowState.reason))) {
((nsHTMLReflowState&)aReflowState).mComputedHeight = mRect.height - topInset - bottomInset;
DISPLAY_REFLOW_CHANGE();
}

Просмотреть файл

@ -116,8 +116,10 @@ public:
nsIAtom* aListName,
nsIFrame* aOldFrame);
NS_IMETHOD NotifyPercentHeight(const nsHTMLReflowState& aReflowState);
virtual void NotifyPercentHeight(const nsHTMLReflowState& aReflowState);
virtual PRBool NeedsToObserve(const nsHTMLReflowState& aReflowState);
void InitCellFrame(PRInt32 aColIndex);

Просмотреть файл

@ -1898,11 +1898,10 @@ nsTableFrame::CheckRequestSpecialHeightReflow(const nsHTMLReflowState& aReflowSt
nsIFrame* prevInFlow;
aReflowState.frame->GetPrevInFlow(&prevInFlow);
if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth) && // not first pass reflow
!prevInFlow && // 1st in flow && // 1st in flow
if (!prevInFlow && // 1st in flow && // 1st in flow
((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) || // no computed height
(0 == aReflowState.mComputedHeight)) &&
::IsPctStyleHeight(aReflowState.mStylePosition)) { // pct height
::IsPctStyleHeight(aReflowState.mStylePosition)) { // pct height
if (::AncestorsHaveStyleHeight(aReflowState)) {
nsTableFrame::RequestSpecialHeightReflow(aReflowState);
@ -2056,6 +2055,10 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
}
nsresult rv = NS_OK;
// see if a special height reflow needs to occur due to having a pct height
if (!NeedSpecialReflow())
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
// see if collapsing borders need to be calculated
if (!mPrevInFlow && IsBorderCollapse() && NeedToCalcBCBorders()) {
GET_TWIPS_TO_PIXELS(aPresContext, p2t);
@ -2132,35 +2135,33 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
// 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)) {
if (!mPrevInFlow) {
// see if an extra reflow will be necessary when the table is nested, there is a pct height,
// no computed height, but a height on the containing table
if ( ((NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) ||
(0 == aReflowState.mComputedHeight)) &&
IsPctHeight(mStyleContext)) {
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
}
// 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(aPresContext, aReflowState);
if ((tableSpecifiedHeight > 0) &&
(tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE)) {
SetNeedToInitiateSpecialReflow(PR_TRUE);
}
// see if an extra reflow will be necessary in pagination mode when there is a specified table height
if (isPaginated && !mPrevInFlow && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) {
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aPresContext, 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 = !aReflowState.mFlags.mSpecialHeightReflow &&
(NeedSpecialReflow() | NeedToInitiateSpecialReflow())
? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight;
nsIFrame* lastChildReflowed = nsnull;
PRBool willInitiateSpecialReflow =
((NeedToInitiateSpecialReflow() || InitiatedSpecialReflow()) &&
(aReflowState.mFlags.mSpecialHeightReflow || !NeedSpecialReflow()));
nsIFrame* lastChildReflowed;
ReflowTable(aPresContext, aDesiredSize, aReflowState, availHeight, nextReason,
lastChildReflowed, doCollapse, balanced, aStatus);
// do the pass 2 reflow unless this is a special height reflow and we will be
// initiating a special height reflow
if (!(aReflowState.mFlags.mSpecialHeightReflow && willInitiateSpecialReflow)) {
// if we need to initiate a special height reflow, then don't constrain the
// height of the reflow before that
nscoord availHeight = (willInitiateSpecialReflow)
? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight;
if (NeedToInitiateSpecialReflow() &&
(aReflowState.mFlags.mSpecialHeightReflow || !NeedSpecialReflow())) {
aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState); // distributes extra vertical space to rows
ReflowTable(aPresContext, aDesiredSize, aReflowState, availHeight, nextReason,
lastChildReflowed, doCollapse, balanced, aStatus);
}
if (willInitiateSpecialReflow && NS_FRAME_IS_COMPLETE(aStatus)) {
// distribute extra vertical space to rows
aDesiredSize.height = CalcDesiredHeight(aPresContext, aReflowState);
((nsHTMLReflowState::ReflowStateFlags&)aReflowState.mFlags).mSpecialHeightReflow = PR_TRUE;
// save the previous special height reflow initiator, install us as the new one
nsIFrame* specialReflowInitiator = aReflowState.mPercentHeightReflowInitiator;
@ -2171,6 +2172,8 @@ NS_METHOD nsTableFrame::Reflow(nsIPresContext* aPresContext,
nextReason, lastChildReflowed, doCollapse, balanced, aStatus);
// restore the previous special height reflow initiator
((nsHTMLReflowState&)aReflowState).mPercentHeightReflowInitiator = specialReflowInitiator;
// XXX We should call SetInitiatedSpecialReflow(PR_FALSE) at some point, but it is difficult to tell when
SetInitiatedSpecialReflow(PR_TRUE);
if (lastChildReflowed && NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
// if there is an incomplete child, then set the desired height to include it but not the next one

Просмотреть файл

@ -554,9 +554,13 @@ public:
PRBool NeedSpecialReflow() const;
void SetNeedSpecialReflow(PRBool aValue);
PRBool NeedToInitiateSpecialReflow() const;
void SetNeedToInitiateSpecialReflow(PRBool aValue);
PRBool InitiatedSpecialReflow() const;
void SetInitiatedSpecialReflow(PRBool aValue);
protected:
/** protected constructor.
@ -955,8 +959,9 @@ protected:
unsigned mRowInserted:1;
unsigned mNeedSpecialReflow:1;
unsigned mNeedToInitiateSpecialReflow:1;
unsigned mInitiatedSpecialReflow:1;
unsigned mNeedToCalcBCBorders:1;
unsigned : 18; // unused
unsigned : 17; // unused
} mBits;
nsTableCellMap* mCellMap; // maintains the relationships between rows, cols, and cells
@ -1079,6 +1084,17 @@ inline void nsTableFrame::SetNeedToInitiateSpecialReflow(PRBool aValue)
{
mBits.mNeedToInitiateSpecialReflow = (unsigned)aValue;
}
inline PRBool nsTableFrame::InitiatedSpecialReflow() const
{
return (PRBool)mBits.mInitiatedSpecialReflow;
}
inline void nsTableFrame::SetInitiatedSpecialReflow(PRBool aValue)
{
mBits.mInitiatedSpecialReflow = (unsigned)aValue;
}
inline PRBool nsTableFrame::IsRowInserted() const
{
return (PRBool)mBits.mRowInserted;

Просмотреть файл

@ -992,13 +992,14 @@ nsTableRowFrame::ReflowChildren(nsIPresContext* aPresContext,
nsIFrame* kidNextInFlow;
kidFrame->GetNextInFlow(&kidNextInFlow);
nsSize cellDesiredSize = cellFrame->GetDesiredSize();
if ((availCellWidth != cellFrame->GetPriorAvailWidth()) ||
if ((availCellWidth != cellFrame->GetPriorAvailWidth()) ||
(cellDesiredSize.width > cellFrame->GetPriorAvailWidth()) ||
(eReflowReason_StyleChange == aReflowState.reason) ||
isPaginated ||
(aReflowState.mFlags.mSpecialHeightReflow && cellFrame->NeedSpecialReflow()) ||
HasPctHeight() ||
notifyStyleChange ){
(!aReflowState.mFlags.mSpecialHeightReflow && cellFrame->HadSpecialReflow()) ||
HasPctHeight() ||
notifyStyleChange) {
// Reflow the cell to fit the available width, height
nsSize kidAvailSize(availColWidth, aReflowState.availableHeight);
nsReflowReason reason = eReflowReason_Resize;
@ -1443,7 +1444,8 @@ nsTableRowFrame::Reflow(nsIPresContext* aPresContext,
if (!tableFrame) return NS_ERROR_NULL_POINTER;
// see if a special height reflow needs to occur due to having a pct height
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
if (!NeedSpecialReflow())
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
switch (aReflowState.reason) {
case eReflowReason_Initial:

Просмотреть файл

@ -1186,16 +1186,14 @@ nsTableRowGroupFrame::Reflow(nsIPresContext* aPresContext,
PRBool isPaginated;
aPresContext->IsPaginated(&isPaginated);
// If this is a special height reflow, set our desired size to what is was previously and return
// if we will be getting another special height reflow. In paginated mode, SetNeedSpecialReflow(PR_TRUE)
// may not have been called if reflow was a result of having a height on the containing table
if (nsTableFrame::IsPrematureSpecialHeightReflow(aReflowState, mRect, NeedSpecialReflow() || isPaginated, aDesiredSize))
return NS_OK;
nsTableFrame* tableFrame = nsnull;
rv = nsTableFrame::GetTableFrame(this, tableFrame);
if (!aPresContext || !tableFrame) return NS_ERROR_NULL_POINTER;
// see if a special height reflow needs to occur due to having a pct height
if (!NeedSpecialReflow())
nsTableFrame::CheckRequestSpecialHeightReflow(aReflowState);
nsRowGroupReflowState state(aReflowState, tableFrame);
PRBool haveDesiredHeight = PR_FALSE;