r=karnaze
The problem was we were over-eager in optimizing away a resize reflow for lines
that contain %-aware children.  We were only looking at the first-level children
of a line, not all the children.  Now, we compute a bit for each inline container
based on it's children, true if any of them are %-aware wrt any width measurement.
We propogate this bit upwards to a bit on the line itself, and check this bit during reflow.
This commit is contained in:
buster%netscape.com 2000-09-11 20:46:44 +00:00
Родитель a7d77f33f2
Коммит 37e900a62c
16 изменённых файлов: 374 добавлений и 104 удалений

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

@ -158,6 +158,7 @@ InitDebugFlags()
#undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete" #undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete"
#undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements #undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements
#undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate #undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate
#undef REALLY_NOISY_REFLOW // some extra debug info
#endif #endif
@ -781,7 +782,8 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsMargin& borderPadding = BorderPadding(); const nsMargin& borderPadding = BorderPadding();
if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType) { if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType)
{
if (mBand.GetFloaterCount()) { if (mBand.GetFloaterCount()) {
// Use the float-edge property to determine how the child block // Use the float-edge property to determine how the child block
// will interact with the floater. // will interact with the floater.
@ -2006,15 +2008,6 @@ HaveAutoWidth(const nsHTMLReflowState& aReflowState)
} }
static PRBool
IsPercentageUnitSides(const nsStyleSides* aSides)
{
return eStyleUnit_Percent == aSides->GetLeftUnit()
|| eStyleUnit_Percent == aSides->GetRightUnit()
|| eStyleUnit_Percent == aSides->GetTopUnit()
|| eStyleUnit_Percent == aSides->GetBottomUnit();
}
static PRBool static PRBool
IsPercentageAwareChild(const nsIFrame* aFrame) IsPercentageAwareChild(const nsIFrame* aFrame)
{ {
@ -2024,9 +2017,9 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
return PR_TRUE; // just to be on the safe side return PR_TRUE; // just to be on the safe side
} }
if (IsPercentageUnitSides(&space->mMargin) if (nsLineLayout::IsPercentageUnitSides(&space->mMargin)
|| IsPercentageUnitSides(&space->mPadding) || nsLineLayout::IsPercentageUnitSides(&space->mPadding)
|| IsPercentageUnitSides(&space->mBorderRadius)) { || nsLineLayout::IsPercentageUnitSides(&space->mBorderRadius)) {
return PR_TRUE; return PR_TRUE;
} }
@ -2042,7 +2035,7 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
|| eStyleUnit_Percent == pos->mHeight.GetUnit() || eStyleUnit_Percent == pos->mHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMinHeight.GetUnit() || eStyleUnit_Percent == pos->mMinHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMaxHeight.GetUnit() || eStyleUnit_Percent == pos->mMaxHeight.GetUnit()
|| IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!! || nsLineLayout::IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!!
return PR_TRUE; return PR_TRUE;
} }
@ -2600,6 +2593,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
// newlines. Therefore, we don't need to reflow the line. // newlines. Therefore, we don't need to reflow the line.
} }
else if ((line->mNext && !line->HasBreak()) || else if ((line->mNext && !line->HasBreak()) ||
line->ResizeReflowOptimizationDisabled() ||
line->HasFloaters() || line->IsImpactedByFloater() || line->HasFloaters() || line->IsImpactedByFloater() ||
line->HasPercentageChild() || line->HasPercentageChild() ||
(line->mBounds.XMost() > newAvailWidth)) { (line->mBounds.XMost() > newAvailWidth)) {

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

@ -158,6 +158,7 @@ InitDebugFlags()
#undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete" #undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete"
#undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements #undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements
#undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate #undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate
#undef REALLY_NOISY_REFLOW // some extra debug info
#endif #endif
@ -781,7 +782,8 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsMargin& borderPadding = BorderPadding(); const nsMargin& borderPadding = BorderPadding();
if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType) { if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType)
{
if (mBand.GetFloaterCount()) { if (mBand.GetFloaterCount()) {
// Use the float-edge property to determine how the child block // Use the float-edge property to determine how the child block
// will interact with the floater. // will interact with the floater.
@ -2006,15 +2008,6 @@ HaveAutoWidth(const nsHTMLReflowState& aReflowState)
} }
static PRBool
IsPercentageUnitSides(const nsStyleSides* aSides)
{
return eStyleUnit_Percent == aSides->GetLeftUnit()
|| eStyleUnit_Percent == aSides->GetRightUnit()
|| eStyleUnit_Percent == aSides->GetTopUnit()
|| eStyleUnit_Percent == aSides->GetBottomUnit();
}
static PRBool static PRBool
IsPercentageAwareChild(const nsIFrame* aFrame) IsPercentageAwareChild(const nsIFrame* aFrame)
{ {
@ -2024,9 +2017,9 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
return PR_TRUE; // just to be on the safe side return PR_TRUE; // just to be on the safe side
} }
if (IsPercentageUnitSides(&space->mMargin) if (nsLineLayout::IsPercentageUnitSides(&space->mMargin)
|| IsPercentageUnitSides(&space->mPadding) || nsLineLayout::IsPercentageUnitSides(&space->mPadding)
|| IsPercentageUnitSides(&space->mBorderRadius)) { || nsLineLayout::IsPercentageUnitSides(&space->mBorderRadius)) {
return PR_TRUE; return PR_TRUE;
} }
@ -2042,7 +2035,7 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
|| eStyleUnit_Percent == pos->mHeight.GetUnit() || eStyleUnit_Percent == pos->mHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMinHeight.GetUnit() || eStyleUnit_Percent == pos->mMinHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMaxHeight.GetUnit() || eStyleUnit_Percent == pos->mMaxHeight.GetUnit()
|| IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!! || nsLineLayout::IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!!
return PR_TRUE; return PR_TRUE;
} }
@ -2600,6 +2593,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
// newlines. Therefore, we don't need to reflow the line. // newlines. Therefore, we don't need to reflow the line.
} }
else if ((line->mNext && !line->HasBreak()) || else if ((line->mNext && !line->HasBreak()) ||
line->ResizeReflowOptimizationDisabled() ||
line->HasFloaters() || line->IsImpactedByFloater() || line->HasFloaters() || line->IsImpactedByFloater() ||
line->HasPercentageChild() || line->HasPercentageChild() ||
(line->mBounds.XMost() > newAvailWidth)) { (line->mBounds.XMost() > newAvailWidth)) {

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

@ -158,6 +158,7 @@ InitDebugFlags()
#undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete" #undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete"
#undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements #undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements
#undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate #undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate
#undef REALLY_NOISY_REFLOW // some extra debug info
#endif #endif
@ -781,7 +782,8 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsMargin& borderPadding = BorderPadding(); const nsMargin& borderPadding = BorderPadding();
if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType) { if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType)
{
if (mBand.GetFloaterCount()) { if (mBand.GetFloaterCount()) {
// Use the float-edge property to determine how the child block // Use the float-edge property to determine how the child block
// will interact with the floater. // will interact with the floater.
@ -2006,15 +2008,6 @@ HaveAutoWidth(const nsHTMLReflowState& aReflowState)
} }
static PRBool
IsPercentageUnitSides(const nsStyleSides* aSides)
{
return eStyleUnit_Percent == aSides->GetLeftUnit()
|| eStyleUnit_Percent == aSides->GetRightUnit()
|| eStyleUnit_Percent == aSides->GetTopUnit()
|| eStyleUnit_Percent == aSides->GetBottomUnit();
}
static PRBool static PRBool
IsPercentageAwareChild(const nsIFrame* aFrame) IsPercentageAwareChild(const nsIFrame* aFrame)
{ {
@ -2024,9 +2017,9 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
return PR_TRUE; // just to be on the safe side return PR_TRUE; // just to be on the safe side
} }
if (IsPercentageUnitSides(&space->mMargin) if (nsLineLayout::IsPercentageUnitSides(&space->mMargin)
|| IsPercentageUnitSides(&space->mPadding) || nsLineLayout::IsPercentageUnitSides(&space->mPadding)
|| IsPercentageUnitSides(&space->mBorderRadius)) { || nsLineLayout::IsPercentageUnitSides(&space->mBorderRadius)) {
return PR_TRUE; return PR_TRUE;
} }
@ -2042,7 +2035,7 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
|| eStyleUnit_Percent == pos->mHeight.GetUnit() || eStyleUnit_Percent == pos->mHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMinHeight.GetUnit() || eStyleUnit_Percent == pos->mMinHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMaxHeight.GetUnit() || eStyleUnit_Percent == pos->mMaxHeight.GetUnit()
|| IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!! || nsLineLayout::IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!!
return PR_TRUE; return PR_TRUE;
} }
@ -2600,6 +2593,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
// newlines. Therefore, we don't need to reflow the line. // newlines. Therefore, we don't need to reflow the line.
} }
else if ((line->mNext && !line->HasBreak()) || else if ((line->mNext && !line->HasBreak()) ||
line->ResizeReflowOptimizationDisabled() ||
line->HasFloaters() || line->IsImpactedByFloater() || line->HasFloaters() || line->IsImpactedByFloater() ||
line->HasPercentageChild() || line->HasPercentageChild() ||
(line->mBounds.XMost() > newAvailWidth)) { (line->mBounds.XMost() > newAvailWidth)) {

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

@ -549,6 +549,41 @@ nsInlineFrame::ReflowFrames(nsIPresContext* aPresContext,
return rv; return rv;
} }
static
void SetContainsPercentAwareChild(nsIFrame *aFrame)
{
nsFrameState myFrameState;
aFrame->GetFrameState(&myFrameState);
aFrame->SetFrameState(myFrameState | NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD);
}
static
void MarkPercentAwareFrame(nsIPresContext *aPresContext,
nsInlineFrame *aInline,
nsIFrame *aFrame)
{
nsFrameState childFrameState;
aFrame->GetFrameState(&childFrameState);
if (childFrameState & NS_FRAME_REPLACED_ELEMENT)
{ // aFrame is a replaced element, check it's style
if (nsLineLayout::IsPercentageAwareReplacedElement(aPresContext, aFrame)) {
SetContainsPercentAwareChild(aInline);
}
}
else
{
nsIFrame *child;
aFrame->FirstChild(aPresContext, nsnull, &child);
if (child)
{ // aFrame is an inline container frame, check my frame state
if (childFrameState & NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD) {
SetContainsPercentAwareChild(aInline); // if a child container is effected, so am I
}
}
// else frame is a leaf that we don't care about
}
}
nsresult nsresult
nsInlineFrame::ReflowInlineFrame(nsIPresContext* aPresContext, nsInlineFrame::ReflowInlineFrame(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
@ -561,6 +596,15 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext* aPresContext,
PRBool pushedFrame; PRBool pushedFrame;
nsresult rv = lineLayout->ReflowFrame(aFrame, &irs.mNextRCFrame, aStatus, nsresult rv = lineLayout->ReflowFrame(aFrame, &irs.mNextRCFrame, aStatus,
nsnull, pushedFrame); nsnull, pushedFrame);
/* This next block is for bug 28811
Test the child frame for %-awareness,
and mark this frame with a bit if it is %-aware.
Don't bother if this frame is already marked
*/
if (!(mState & NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD)) {
MarkPercentAwareFrame(aPresContext, this, aFrame);
}
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return rv; return rv;
} }

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

@ -33,6 +33,8 @@ class nsAnonymousBlockFrame;
#define nsInlineFrameSuper nsHTMLContainerFrame #define nsInlineFrameSuper nsHTMLContainerFrame
#define NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD 0X00010000
/** /**
* Inline frame class. * Inline frame class.
* *
@ -95,7 +97,7 @@ protected:
nsIFrame* mNextRCFrame; nsIFrame* mNextRCFrame;
nsIFrame* mPrevFrame; nsIFrame* mPrevFrame;
nsInlineFrame* mNextInFlow; nsInlineFrame* mNextInFlow;
PRBool mSetParentPointer; // when reflowing child frame first set its PRPackedBool mSetParentPointer; // when reflowing child frame first set its
// parent frame pointer // parent frame pointer
InlineReflowState() { InlineReflowState() {
@ -129,6 +131,7 @@ protected:
virtual void PushFrames(nsIPresContext* aPresContext, virtual void PushFrames(nsIPresContext* aPresContext,
nsIFrame* aFromChild, nsIFrame* aFromChild,
nsIFrame* aPrevSibling); nsIFrame* aPrevSibling);
}; };
//---------------------------------------------------------------------- //----------------------------------------------------------------------

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

@ -136,7 +136,7 @@ protected:
//---------------------------------------------------------------------- //----------------------------------------------------------------------
#define LINE_MAX_BREAK_TYPE ((1 << 4) - 1) #define LINE_MAX_BREAK_TYPE ((1 << 4) - 1)
#define LINE_MAX_CHILD_COUNT ((1 << 21) - 1) #define LINE_MAX_CHILD_COUNT ((1 << 20) - 1)
#if NS_STYLE_CLEAR_LAST_VALUE > 15 #if NS_STYLE_CLEAR_LAST_VALUE > 15
need to rearrange the mBits bitfield; need to rearrange the mBits bitfield;
@ -232,6 +232,17 @@ public:
return mFlags.mForceInvalidate; return mFlags.mForceInvalidate;
} }
// mResizeReflowOptimizationDisabled bit
void DisableResizeReflowOptimization() {
mFlags.mResizeReflowOptimizationDisabled = PR_TRUE;
}
void EnableResizeReflowOptimization() {
mFlags.mResizeReflowOptimizationDisabled = PR_FALSE;
}
PRBool ResizeReflowOptimizationDisabled() const {
return mFlags.mResizeReflowOptimizationDisabled;
}
// mChildCount value // mChildCount value
PRInt32 GetChildCount() const { PRInt32 GetChildCount() const {
return (PRInt32) mFlags.mChildCount; return (PRInt32) mFlags.mChildCount;
@ -337,11 +348,11 @@ public:
PRUint32 mTrimmed : 1; PRUint32 mTrimmed : 1;
PRUint32 mHasPercentageChild : 1; PRUint32 mHasPercentageChild : 1;
PRUint32 mLineWrapped: 1; PRUint32 mLineWrapped: 1;
PRUint32 mForceInvalidate: 1; PRUint32 mForceInvalidate: 1; // default 0 = means this line handles it's own invalidation. 1 = always invalidate this entire line
PRUint32 mResizeReflowOptimizationDisabled: 1; // default 0 = means that the opt potentially applies to this line. 1 = never skip reflowing this line for a resize reflow
PRUint32 mBreakType : 4; PRUint32 mBreakType : 4;
PRUint32 mChildCount : 21; PRUint32 mChildCount : 20;
}; };
struct ExtraData { struct ExtraData {
@ -442,7 +453,7 @@ protected:
nsLineBox** mLines; nsLineBox** mLines;
PRInt32 mIndex; PRInt32 mIndex;
PRInt32 mNumLines; PRInt32 mNumLines;
PRBool mRightToLeft; PRPackedBool mRightToLeft;
}; };
#endif /* nsLineBox_h___ */ #endif /* nsLineBox_h___ */

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

@ -26,6 +26,7 @@
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsLineLayout.h" #include "nsLineLayout.h"
#include "nsBlockFrame.h" #include "nsBlockFrame.h"
#include "nsInlineFrame.h"
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsHTMLContainerFrame.h" #include "nsHTMLContainerFrame.h"
#include "nsHTMLIIDs.h" #include "nsHTMLIIDs.h"
@ -1548,6 +1549,86 @@ nsLineLayout::DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent)
#define VALIGN_TOP 1 #define VALIGN_TOP 1
#define VALIGN_BOTTOM 2 #define VALIGN_BOTTOM 2
PRBool
nsLineLayout::IsPercentageUnitSides(const nsStyleSides* aSides)
{
return eStyleUnit_Percent == aSides->GetLeftUnit()
|| eStyleUnit_Percent == aSides->GetRightUnit()
|| eStyleUnit_Percent == aSides->GetTopUnit()
|| eStyleUnit_Percent == aSides->GetBottomUnit();
}
PRBool
nsLineLayout::IsPercentageAwareReplacedElement(nsIPresContext *aPresContext,
nsIFrame* aFrame)
{
nsFrameState frameState;
aFrame->GetFrameState(&frameState);
if (frameState & NS_FRAME_REPLACED_ELEMENT)
{
nsCOMPtr<nsIAtom> frameType;
aFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::brFrame != frameType &&
nsLayoutAtoms::textFrame != frameType)
{
const nsStyleSpacing* space;
nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing,(const nsStyleStruct*&) space);
if (NS_FAILED(rv)) {
return PR_TRUE; // just to be on the safe side
}
if (IsPercentageUnitSides(&space->mMargin)
|| IsPercentageUnitSides(&space->mPadding)
|| IsPercentageUnitSides(&space->mBorderRadius)) {
return PR_TRUE;
}
const nsStylePosition* pos;
rv = aFrame->GetStyleData(eStyleStruct_Position,(const nsStyleStruct*&) pos);
if (NS_FAILED(rv)) {
return PR_TRUE; // just to be on the safe side
}
if (eStyleUnit_Percent == pos->mWidth.GetUnit()
|| eStyleUnit_Percent == pos->mMaxWidth.GetUnit()
|| eStyleUnit_Percent == pos->mMinWidth.GetUnit()
|| eStyleUnit_Percent == pos->mHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMinHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMaxHeight.GetUnit()
|| IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!!
return PR_TRUE;
}
}
}
return PR_FALSE;
}
PRBool IsPercentageAwareFrame(nsIPresContext *aPresContext, nsIFrame *aFrame)
{
nsFrameState childFrameState;
aFrame->GetFrameState(&childFrameState);
if (childFrameState & NS_FRAME_REPLACED_ELEMENT) {
if (nsLineLayout::IsPercentageAwareReplacedElement(aPresContext, aFrame)) {
return PR_TRUE;
}
}
else
{
nsIFrame *child;
aFrame->FirstChild(aPresContext, nsnull, &child);
if (child)
{ // aFrame is an inline container frame, check my frame state
if (childFrameState & NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD) {
return PR_TRUE;
}
}
// else it's a frame we just don't care about
}
return PR_FALSE;
}
void void
nsLineLayout::VerticalAlignFrames(nsLineBox* aLineBox, nsLineLayout::VerticalAlignFrames(nsLineBox* aLineBox,
nsSize& aMaxElementSizeResult, nsSize& aMaxElementSizeResult,
@ -1684,6 +1765,14 @@ nsLineLayout::VerticalAlignFrames(nsLineBox* aLineBox,
nscoord distanceFromTop = pfd->mBounds.y - mTopEdge; nscoord distanceFromTop = pfd->mBounds.y - mTopEdge;
PlaceTopBottomFrames(span, distanceFromTop, lineHeight); PlaceTopBottomFrames(span, distanceFromTop, lineHeight);
} }
// check to see if the frame is an inline replace element
// and if it is percent-aware. If so, mark the line.
if ((PR_FALSE==aLineBox->ResizeReflowOptimizationDisabled()) &&
pfd->mFrameType & NS_CSS_FRAME_TYPE_INLINE)
{
if (IsPercentageAwareFrame(mPresContext, pfd->mFrame))
aLineBox->DisableResizeReflowOptimization();
}
pfd = pfd->mNext; pfd = pfd->mNext;
} }

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

@ -251,6 +251,12 @@ public:
static PRBool TreatFrameAsBlock(nsIFrame* aFrame); static PRBool TreatFrameAsBlock(nsIFrame* aFrame);
static PRBool IsPercentageUnitSides(const nsStyleSides* aSides);
static PRBool IsPercentageAwareReplacedElement(nsIPresContext *aPresContext,
nsIFrame *aFrame);
//---------------------------------------- //----------------------------------------
nsIPresContext* mPresContext; nsIPresContext* mPresContext;

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

@ -158,6 +158,7 @@ InitDebugFlags()
#undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete" #undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete"
#undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements #undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements
#undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate #undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate
#undef REALLY_NOISY_REFLOW // some extra debug info
#endif #endif
@ -781,7 +782,8 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsMargin& borderPadding = BorderPadding(); const nsMargin& borderPadding = BorderPadding();
if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType) { if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType)
{
if (mBand.GetFloaterCount()) { if (mBand.GetFloaterCount()) {
// Use the float-edge property to determine how the child block // Use the float-edge property to determine how the child block
// will interact with the floater. // will interact with the floater.
@ -2006,15 +2008,6 @@ HaveAutoWidth(const nsHTMLReflowState& aReflowState)
} }
static PRBool
IsPercentageUnitSides(const nsStyleSides* aSides)
{
return eStyleUnit_Percent == aSides->GetLeftUnit()
|| eStyleUnit_Percent == aSides->GetRightUnit()
|| eStyleUnit_Percent == aSides->GetTopUnit()
|| eStyleUnit_Percent == aSides->GetBottomUnit();
}
static PRBool static PRBool
IsPercentageAwareChild(const nsIFrame* aFrame) IsPercentageAwareChild(const nsIFrame* aFrame)
{ {
@ -2024,9 +2017,9 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
return PR_TRUE; // just to be on the safe side return PR_TRUE; // just to be on the safe side
} }
if (IsPercentageUnitSides(&space->mMargin) if (nsLineLayout::IsPercentageUnitSides(&space->mMargin)
|| IsPercentageUnitSides(&space->mPadding) || nsLineLayout::IsPercentageUnitSides(&space->mPadding)
|| IsPercentageUnitSides(&space->mBorderRadius)) { || nsLineLayout::IsPercentageUnitSides(&space->mBorderRadius)) {
return PR_TRUE; return PR_TRUE;
} }
@ -2042,7 +2035,7 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
|| eStyleUnit_Percent == pos->mHeight.GetUnit() || eStyleUnit_Percent == pos->mHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMinHeight.GetUnit() || eStyleUnit_Percent == pos->mMinHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMaxHeight.GetUnit() || eStyleUnit_Percent == pos->mMaxHeight.GetUnit()
|| IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!! || nsLineLayout::IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!!
return PR_TRUE; return PR_TRUE;
} }
@ -2600,6 +2593,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
// newlines. Therefore, we don't need to reflow the line. // newlines. Therefore, we don't need to reflow the line.
} }
else if ((line->mNext && !line->HasBreak()) || else if ((line->mNext && !line->HasBreak()) ||
line->ResizeReflowOptimizationDisabled() ||
line->HasFloaters() || line->IsImpactedByFloater() || line->HasFloaters() || line->IsImpactedByFloater() ||
line->HasPercentageChild() || line->HasPercentageChild() ||
(line->mBounds.XMost() > newAvailWidth)) { (line->mBounds.XMost() > newAvailWidth)) {

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

@ -158,6 +158,7 @@ InitDebugFlags()
#undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete" #undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete"
#undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements #undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements
#undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate #undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate
#undef REALLY_NOISY_REFLOW // some extra debug info
#endif #endif
@ -781,7 +782,8 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsMargin& borderPadding = BorderPadding(); const nsMargin& borderPadding = BorderPadding();
if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType) { if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType)
{
if (mBand.GetFloaterCount()) { if (mBand.GetFloaterCount()) {
// Use the float-edge property to determine how the child block // Use the float-edge property to determine how the child block
// will interact with the floater. // will interact with the floater.
@ -2006,15 +2008,6 @@ HaveAutoWidth(const nsHTMLReflowState& aReflowState)
} }
static PRBool
IsPercentageUnitSides(const nsStyleSides* aSides)
{
return eStyleUnit_Percent == aSides->GetLeftUnit()
|| eStyleUnit_Percent == aSides->GetRightUnit()
|| eStyleUnit_Percent == aSides->GetTopUnit()
|| eStyleUnit_Percent == aSides->GetBottomUnit();
}
static PRBool static PRBool
IsPercentageAwareChild(const nsIFrame* aFrame) IsPercentageAwareChild(const nsIFrame* aFrame)
{ {
@ -2024,9 +2017,9 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
return PR_TRUE; // just to be on the safe side return PR_TRUE; // just to be on the safe side
} }
if (IsPercentageUnitSides(&space->mMargin) if (nsLineLayout::IsPercentageUnitSides(&space->mMargin)
|| IsPercentageUnitSides(&space->mPadding) || nsLineLayout::IsPercentageUnitSides(&space->mPadding)
|| IsPercentageUnitSides(&space->mBorderRadius)) { || nsLineLayout::IsPercentageUnitSides(&space->mBorderRadius)) {
return PR_TRUE; return PR_TRUE;
} }
@ -2042,7 +2035,7 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
|| eStyleUnit_Percent == pos->mHeight.GetUnit() || eStyleUnit_Percent == pos->mHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMinHeight.GetUnit() || eStyleUnit_Percent == pos->mMinHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMaxHeight.GetUnit() || eStyleUnit_Percent == pos->mMaxHeight.GetUnit()
|| IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!! || nsLineLayout::IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!!
return PR_TRUE; return PR_TRUE;
} }
@ -2600,6 +2593,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
// newlines. Therefore, we don't need to reflow the line. // newlines. Therefore, we don't need to reflow the line.
} }
else if ((line->mNext && !line->HasBreak()) || else if ((line->mNext && !line->HasBreak()) ||
line->ResizeReflowOptimizationDisabled() ||
line->HasFloaters() || line->IsImpactedByFloater() || line->HasFloaters() || line->IsImpactedByFloater() ||
line->HasPercentageChild() || line->HasPercentageChild() ||
(line->mBounds.XMost() > newAvailWidth)) { (line->mBounds.XMost() > newAvailWidth)) {

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

@ -158,6 +158,7 @@ InitDebugFlags()
#undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete" #undef REFLOW_STATUS_COVERAGE // I think this is most useful for printing, to see which frames return "incomplete"
#undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements #undef NOISY_SPACEMANAGER // enables debug output for space manager use, useful for analysing reflow of floaters and positioned elements
#undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate #undef NOISY_BLOCK_INVALIDATE // enables debug output for all calls to invalidate
#undef REALLY_NOISY_REFLOW // some extra debug info
#endif #endif
@ -781,7 +782,8 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
const nsMargin& borderPadding = BorderPadding(); const nsMargin& borderPadding = BorderPadding();
if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType) { if (NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType)
{
if (mBand.GetFloaterCount()) { if (mBand.GetFloaterCount()) {
// Use the float-edge property to determine how the child block // Use the float-edge property to determine how the child block
// will interact with the floater. // will interact with the floater.
@ -2006,15 +2008,6 @@ HaveAutoWidth(const nsHTMLReflowState& aReflowState)
} }
static PRBool
IsPercentageUnitSides(const nsStyleSides* aSides)
{
return eStyleUnit_Percent == aSides->GetLeftUnit()
|| eStyleUnit_Percent == aSides->GetRightUnit()
|| eStyleUnit_Percent == aSides->GetTopUnit()
|| eStyleUnit_Percent == aSides->GetBottomUnit();
}
static PRBool static PRBool
IsPercentageAwareChild(const nsIFrame* aFrame) IsPercentageAwareChild(const nsIFrame* aFrame)
{ {
@ -2024,9 +2017,9 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
return PR_TRUE; // just to be on the safe side return PR_TRUE; // just to be on the safe side
} }
if (IsPercentageUnitSides(&space->mMargin) if (nsLineLayout::IsPercentageUnitSides(&space->mMargin)
|| IsPercentageUnitSides(&space->mPadding) || nsLineLayout::IsPercentageUnitSides(&space->mPadding)
|| IsPercentageUnitSides(&space->mBorderRadius)) { || nsLineLayout::IsPercentageUnitSides(&space->mBorderRadius)) {
return PR_TRUE; return PR_TRUE;
} }
@ -2042,7 +2035,7 @@ IsPercentageAwareChild(const nsIFrame* aFrame)
|| eStyleUnit_Percent == pos->mHeight.GetUnit() || eStyleUnit_Percent == pos->mHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMinHeight.GetUnit() || eStyleUnit_Percent == pos->mMinHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMaxHeight.GetUnit() || eStyleUnit_Percent == pos->mMaxHeight.GetUnit()
|| IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!! || nsLineLayout::IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!!
return PR_TRUE; return PR_TRUE;
} }
@ -2600,6 +2593,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
// newlines. Therefore, we don't need to reflow the line. // newlines. Therefore, we don't need to reflow the line.
} }
else if ((line->mNext && !line->HasBreak()) || else if ((line->mNext && !line->HasBreak()) ||
line->ResizeReflowOptimizationDisabled() ||
line->HasFloaters() || line->IsImpactedByFloater() || line->HasFloaters() || line->IsImpactedByFloater() ||
line->HasPercentageChild() || line->HasPercentageChild() ||
(line->mBounds.XMost() > newAvailWidth)) { (line->mBounds.XMost() > newAvailWidth)) {

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

@ -549,6 +549,41 @@ nsInlineFrame::ReflowFrames(nsIPresContext* aPresContext,
return rv; return rv;
} }
static
void SetContainsPercentAwareChild(nsIFrame *aFrame)
{
nsFrameState myFrameState;
aFrame->GetFrameState(&myFrameState);
aFrame->SetFrameState(myFrameState | NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD);
}
static
void MarkPercentAwareFrame(nsIPresContext *aPresContext,
nsInlineFrame *aInline,
nsIFrame *aFrame)
{
nsFrameState childFrameState;
aFrame->GetFrameState(&childFrameState);
if (childFrameState & NS_FRAME_REPLACED_ELEMENT)
{ // aFrame is a replaced element, check it's style
if (nsLineLayout::IsPercentageAwareReplacedElement(aPresContext, aFrame)) {
SetContainsPercentAwareChild(aInline);
}
}
else
{
nsIFrame *child;
aFrame->FirstChild(aPresContext, nsnull, &child);
if (child)
{ // aFrame is an inline container frame, check my frame state
if (childFrameState & NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD) {
SetContainsPercentAwareChild(aInline); // if a child container is effected, so am I
}
}
// else frame is a leaf that we don't care about
}
}
nsresult nsresult
nsInlineFrame::ReflowInlineFrame(nsIPresContext* aPresContext, nsInlineFrame::ReflowInlineFrame(nsIPresContext* aPresContext,
const nsHTMLReflowState& aReflowState, const nsHTMLReflowState& aReflowState,
@ -561,6 +596,15 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext* aPresContext,
PRBool pushedFrame; PRBool pushedFrame;
nsresult rv = lineLayout->ReflowFrame(aFrame, &irs.mNextRCFrame, aStatus, nsresult rv = lineLayout->ReflowFrame(aFrame, &irs.mNextRCFrame, aStatus,
nsnull, pushedFrame); nsnull, pushedFrame);
/* This next block is for bug 28811
Test the child frame for %-awareness,
and mark this frame with a bit if it is %-aware.
Don't bother if this frame is already marked
*/
if (!(mState & NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD)) {
MarkPercentAwareFrame(aPresContext, this, aFrame);
}
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return rv; return rv;
} }

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

@ -33,6 +33,8 @@ class nsAnonymousBlockFrame;
#define nsInlineFrameSuper nsHTMLContainerFrame #define nsInlineFrameSuper nsHTMLContainerFrame
#define NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD 0X00010000
/** /**
* Inline frame class. * Inline frame class.
* *
@ -95,7 +97,7 @@ protected:
nsIFrame* mNextRCFrame; nsIFrame* mNextRCFrame;
nsIFrame* mPrevFrame; nsIFrame* mPrevFrame;
nsInlineFrame* mNextInFlow; nsInlineFrame* mNextInFlow;
PRBool mSetParentPointer; // when reflowing child frame first set its PRPackedBool mSetParentPointer; // when reflowing child frame first set its
// parent frame pointer // parent frame pointer
InlineReflowState() { InlineReflowState() {
@ -129,6 +131,7 @@ protected:
virtual void PushFrames(nsIPresContext* aPresContext, virtual void PushFrames(nsIPresContext* aPresContext,
nsIFrame* aFromChild, nsIFrame* aFromChild,
nsIFrame* aPrevSibling); nsIFrame* aPrevSibling);
}; };
//---------------------------------------------------------------------- //----------------------------------------------------------------------

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

@ -136,7 +136,7 @@ protected:
//---------------------------------------------------------------------- //----------------------------------------------------------------------
#define LINE_MAX_BREAK_TYPE ((1 << 4) - 1) #define LINE_MAX_BREAK_TYPE ((1 << 4) - 1)
#define LINE_MAX_CHILD_COUNT ((1 << 21) - 1) #define LINE_MAX_CHILD_COUNT ((1 << 20) - 1)
#if NS_STYLE_CLEAR_LAST_VALUE > 15 #if NS_STYLE_CLEAR_LAST_VALUE > 15
need to rearrange the mBits bitfield; need to rearrange the mBits bitfield;
@ -232,6 +232,17 @@ public:
return mFlags.mForceInvalidate; return mFlags.mForceInvalidate;
} }
// mResizeReflowOptimizationDisabled bit
void DisableResizeReflowOptimization() {
mFlags.mResizeReflowOptimizationDisabled = PR_TRUE;
}
void EnableResizeReflowOptimization() {
mFlags.mResizeReflowOptimizationDisabled = PR_FALSE;
}
PRBool ResizeReflowOptimizationDisabled() const {
return mFlags.mResizeReflowOptimizationDisabled;
}
// mChildCount value // mChildCount value
PRInt32 GetChildCount() const { PRInt32 GetChildCount() const {
return (PRInt32) mFlags.mChildCount; return (PRInt32) mFlags.mChildCount;
@ -337,11 +348,11 @@ public:
PRUint32 mTrimmed : 1; PRUint32 mTrimmed : 1;
PRUint32 mHasPercentageChild : 1; PRUint32 mHasPercentageChild : 1;
PRUint32 mLineWrapped: 1; PRUint32 mLineWrapped: 1;
PRUint32 mForceInvalidate: 1; PRUint32 mForceInvalidate: 1; // default 0 = means this line handles it's own invalidation. 1 = always invalidate this entire line
PRUint32 mResizeReflowOptimizationDisabled: 1; // default 0 = means that the opt potentially applies to this line. 1 = never skip reflowing this line for a resize reflow
PRUint32 mBreakType : 4; PRUint32 mBreakType : 4;
PRUint32 mChildCount : 21; PRUint32 mChildCount : 20;
}; };
struct ExtraData { struct ExtraData {
@ -442,7 +453,7 @@ protected:
nsLineBox** mLines; nsLineBox** mLines;
PRInt32 mIndex; PRInt32 mIndex;
PRInt32 mNumLines; PRInt32 mNumLines;
PRBool mRightToLeft; PRPackedBool mRightToLeft;
}; };
#endif /* nsLineBox_h___ */ #endif /* nsLineBox_h___ */

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

@ -26,6 +26,7 @@
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsLineLayout.h" #include "nsLineLayout.h"
#include "nsBlockFrame.h" #include "nsBlockFrame.h"
#include "nsInlineFrame.h"
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsHTMLContainerFrame.h" #include "nsHTMLContainerFrame.h"
#include "nsHTMLIIDs.h" #include "nsHTMLIIDs.h"
@ -1548,6 +1549,86 @@ nsLineLayout::DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent)
#define VALIGN_TOP 1 #define VALIGN_TOP 1
#define VALIGN_BOTTOM 2 #define VALIGN_BOTTOM 2
PRBool
nsLineLayout::IsPercentageUnitSides(const nsStyleSides* aSides)
{
return eStyleUnit_Percent == aSides->GetLeftUnit()
|| eStyleUnit_Percent == aSides->GetRightUnit()
|| eStyleUnit_Percent == aSides->GetTopUnit()
|| eStyleUnit_Percent == aSides->GetBottomUnit();
}
PRBool
nsLineLayout::IsPercentageAwareReplacedElement(nsIPresContext *aPresContext,
nsIFrame* aFrame)
{
nsFrameState frameState;
aFrame->GetFrameState(&frameState);
if (frameState & NS_FRAME_REPLACED_ELEMENT)
{
nsCOMPtr<nsIAtom> frameType;
aFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::brFrame != frameType &&
nsLayoutAtoms::textFrame != frameType)
{
const nsStyleSpacing* space;
nsresult rv = aFrame->GetStyleData(eStyleStruct_Spacing,(const nsStyleStruct*&) space);
if (NS_FAILED(rv)) {
return PR_TRUE; // just to be on the safe side
}
if (IsPercentageUnitSides(&space->mMargin)
|| IsPercentageUnitSides(&space->mPadding)
|| IsPercentageUnitSides(&space->mBorderRadius)) {
return PR_TRUE;
}
const nsStylePosition* pos;
rv = aFrame->GetStyleData(eStyleStruct_Position,(const nsStyleStruct*&) pos);
if (NS_FAILED(rv)) {
return PR_TRUE; // just to be on the safe side
}
if (eStyleUnit_Percent == pos->mWidth.GetUnit()
|| eStyleUnit_Percent == pos->mMaxWidth.GetUnit()
|| eStyleUnit_Percent == pos->mMinWidth.GetUnit()
|| eStyleUnit_Percent == pos->mHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMinHeight.GetUnit()
|| eStyleUnit_Percent == pos->mMaxHeight.GetUnit()
|| IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!!
return PR_TRUE;
}
}
}
return PR_FALSE;
}
PRBool IsPercentageAwareFrame(nsIPresContext *aPresContext, nsIFrame *aFrame)
{
nsFrameState childFrameState;
aFrame->GetFrameState(&childFrameState);
if (childFrameState & NS_FRAME_REPLACED_ELEMENT) {
if (nsLineLayout::IsPercentageAwareReplacedElement(aPresContext, aFrame)) {
return PR_TRUE;
}
}
else
{
nsIFrame *child;
aFrame->FirstChild(aPresContext, nsnull, &child);
if (child)
{ // aFrame is an inline container frame, check my frame state
if (childFrameState & NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD) {
return PR_TRUE;
}
}
// else it's a frame we just don't care about
}
return PR_FALSE;
}
void void
nsLineLayout::VerticalAlignFrames(nsLineBox* aLineBox, nsLineLayout::VerticalAlignFrames(nsLineBox* aLineBox,
nsSize& aMaxElementSizeResult, nsSize& aMaxElementSizeResult,
@ -1684,6 +1765,14 @@ nsLineLayout::VerticalAlignFrames(nsLineBox* aLineBox,
nscoord distanceFromTop = pfd->mBounds.y - mTopEdge; nscoord distanceFromTop = pfd->mBounds.y - mTopEdge;
PlaceTopBottomFrames(span, distanceFromTop, lineHeight); PlaceTopBottomFrames(span, distanceFromTop, lineHeight);
} }
// check to see if the frame is an inline replace element
// and if it is percent-aware. If so, mark the line.
if ((PR_FALSE==aLineBox->ResizeReflowOptimizationDisabled()) &&
pfd->mFrameType & NS_CSS_FRAME_TYPE_INLINE)
{
if (IsPercentageAwareFrame(mPresContext, pfd->mFrame))
aLineBox->DisableResizeReflowOptimization();
}
pfd = pfd->mNext; pfd = pfd->mNext;
} }

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

@ -251,6 +251,12 @@ public:
static PRBool TreatFrameAsBlock(nsIFrame* aFrame); static PRBool TreatFrameAsBlock(nsIFrame* aFrame);
static PRBool IsPercentageUnitSides(const nsStyleSides* aSides);
static PRBool IsPercentageAwareReplacedElement(nsIPresContext *aPresContext,
nsIFrame *aFrame);
//---------------------------------------- //----------------------------------------
nsIPresContext* mPresContext; nsIPresContext* mPresContext;