diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index b5f2083eae8..5294e35cc91 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -1159,41 +1159,6 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext, return rv; } - -// XXXldb why do we check vertical and horizontal at the same time? Don't -// we usually care about one or the other? -static PRBool -IsPercentageAwareChild(const nsIFrame* aFrame) -{ - NS_ASSERTION(aFrame, "null frame is not allowed"); - - const nsStyleMargin* margin = aFrame->GetStyleMargin(); - if (nsLineLayout::IsPercentageUnitSides(&margin->mMargin)) { - return PR_TRUE; - } - - const nsStylePadding* padding = aFrame->GetStylePadding(); - if (nsLineLayout::IsPercentageUnitSides(&padding->mPadding)) { - return PR_TRUE; - } - - // Note that borders can't be aware of percentages - - const nsStylePosition* pos = aFrame->GetStylePosition(); - - 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() - || nsLineLayout::IsPercentageUnitSides(&pos->mOffset)) { // XXX need more here!!! - return PR_TRUE; - } - - return PR_FALSE; -} - PRBool nsBlockFrame::CheckForCollapsedBottomMarginFromClearanceLine() { @@ -1473,9 +1438,6 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState) // We let child blocks make their own decisions the same // way we are here. if (line->IsBlock() || - // XXXldb We need HasPercentageDescendant, not HasPercentageChild!!! - // ... but is that what ResizeReflowOptimizationDisabled does? - line->HasPercentageChild() || line->HasFloats() || (line != mLines.back() && !line->HasBreakAfter()) || line->ResizeReflowOptimizationDisabled() || @@ -3233,7 +3195,8 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, LineReflowStatus lineReflowStatus = LINE_REFLOW_OK; PRInt32 i; nsIFrame* frame = aLine->mFirstChild; - aLine->SetHasPercentageChild(PR_FALSE); // To be set by ReflowInlineFrame below + aLine->EnableResizeReflowOptimization(); + // Determine whether this is a line of placeholders for out-of-flow // continuations PRBool isContinuingPlaceholders = PR_FALSE; @@ -3426,11 +3389,6 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState, printf(" reflowingFirstLetter=%s\n", reflowingFirstLetter ? "on" : "off"); #endif - // Remember if we have a percentage aware child on this line - if (IsPercentageAwareChild(aFrame)) { - aLine->SetHasPercentageChild(PR_TRUE); - } - // Reflow the inline frame nsReflowStatus frameReflowStatus; PRBool pushedFrame; diff --git a/mozilla/layout/generic/nsHTMLReflowState.cpp b/mozilla/layout/generic/nsHTMLReflowState.cpp index 071e474e500..43710fc93c4 100644 --- a/mozilla/layout/generic/nsHTMLReflowState.cpp +++ b/mozilla/layout/generic/nsHTMLReflowState.cpp @@ -325,6 +325,10 @@ nsHTMLReflowState::InitResizeFlags(nsPresContext* aPresContext) // become fixed, but an entire descendant chain of percentage heights // to become fixed. if ((mStylePosition->mHeight.GetUnit() == eStyleUnit_Percent || + mStylePosition->mMinHeight.GetUnit() == eStyleUnit_Percent || + mStylePosition->mMaxHeight.GetUnit() == eStyleUnit_Percent || + mStylePosition->mOffset.GetTopUnit() == eStyleUnit_Percent || + mStylePosition->mOffset.GetBottomUnit() == eStyleUnit_Percent || frame->IsBoxFrame()) && mCBReflowState) { const nsHTMLReflowState *rs = this; diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp index e19429239aa..e56cbeda675 100644 --- a/mozilla/layout/generic/nsInlineFrame.cpp +++ b/mozilla/layout/generic/nsInlineFrame.cpp @@ -515,35 +515,6 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, return rv; } -static -void SetContainsPercentAwareChild(nsIFrame *aFrame) -{ - aFrame->AddStateBits(NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD); -} - -static -void MarkPercentAwareFrame(nsPresContext *aPresContext, - nsInlineFrame *aInline, - nsIFrame *aFrame) -{ - if (aFrame->IsFrameOfType(nsIFrame::eReplaced)) - { // aFrame is a replaced element, check it's style - if (nsLineLayout::IsPercentageAwareReplacedElement(aPresContext, aFrame)) { - SetContainsPercentAwareChild(aInline); - } - } - else - { - if (aFrame->GetFirstChild(nsnull)) - { // aFrame is an inline container frame, check my frame state - if (aFrame->GetStateBits() & 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 nsInlineFrame::ReflowInlineFrame(nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, @@ -557,15 +528,6 @@ nsInlineFrame::ReflowInlineFrame(nsPresContext* aPresContext, nsresult rv = lineLayout->ReflowFrame(aFrame, aStatus, 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)) { return rv; } diff --git a/mozilla/layout/generic/nsInlineFrame.h b/mozilla/layout/generic/nsInlineFrame.h index 2d91d696e36..71b53326855 100644 --- a/mozilla/layout/generic/nsInlineFrame.h +++ b/mozilla/layout/generic/nsInlineFrame.h @@ -52,26 +52,24 @@ class nsAnonymousBlockFrame; #define nsInlineFrameSuper nsHTMLContainerFrame -#define NS_INLINE_FRAME_CONTAINS_PERCENT_AWARE_CHILD 0x00100000 - // NS_INLINE_FRAME_HARD_TEXT_OFFSETS is used for access keys, where what // would normally be 1 text frame is split into 3 sets of an inline parent // and text child (the pre access key text, the underlined key text, and // the post access key text). The offsets of the 3 text frame children // are set in nsCSSFrameConstructor -#define NS_INLINE_FRAME_HARD_TEXT_OFFSETS 0x00200000 +#define NS_INLINE_FRAME_HARD_TEXT_OFFSETS 0x00100000 /** In Bidi left (or right) margin/padding/border should be applied to left * (or right) most frame (or a continuation frame). * This state value shows if this frame is left (or right) most continuation * or not. */ -#define NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET 0x00400000 +#define NS_INLINE_FRAME_BIDI_VISUAL_STATE_IS_SET 0x00200000 -#define NS_INLINE_FRAME_BIDI_VISUAL_IS_LEFT_MOST 0x00800000 +#define NS_INLINE_FRAME_BIDI_VISUAL_IS_LEFT_MOST 0x00400000 -#define NS_INLINE_FRAME_BIDI_VISUAL_IS_RIGHT_MOST 0x01000000 +#define NS_INLINE_FRAME_BIDI_VISUAL_IS_RIGHT_MOST 0x00800000 /** * Inline frame class. diff --git a/mozilla/layout/generic/nsLineBox.h b/mozilla/layout/generic/nsLineBox.h index 95a2c0c3bdd..8be5907adce 100644 --- a/mozilla/layout/generic/nsLineBox.h +++ b/mozilla/layout/generic/nsLineBox.h @@ -308,15 +308,6 @@ public: return mFlags.mImpactedByFloat; } - // mHasPercentageChild bit - void SetHasPercentageChild(PRBool aOn) { - NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!"); - mFlags.mHasPercentageChild = aOn; - } - PRBool HasPercentageChild() const { - return mFlags.mHasPercentageChild; - } - // mLineWrapped bit void SetLineWrapped(PRBool aOn) { NS_ASSERTION((PR_FALSE==aOn || PR_TRUE==aOn), "somebody is playing fast and loose with bools and bits!"); @@ -507,7 +498,6 @@ public: PRUint32 mHasClearance : 1; PRUint32 mBlock : 1; PRUint32 mImpactedByFloat : 1; - PRUint32 mHasPercentageChild : 1; PRUint32 mLineWrapped: 1; 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 mEmptyCacheValid: 1; diff --git a/mozilla/layout/generic/nsLineLayout.cpp b/mozilla/layout/generic/nsLineLayout.cpp index bb6f4fbbb5d..813d5838fb1 100644 --- a/mozilla/layout/generic/nsLineLayout.cpp +++ b/mozilla/layout/generic/nsLineLayout.cpp @@ -689,6 +689,75 @@ nsLineLayout::LineIsBreakable() const return PR_FALSE; } +// Checks all four sides for percentage units. This means it should +// only be used for things (margin, padding) where percentages on top +// and bottom depend on the *width* just like percentages on left and +// right. +static PRBool +HasPercentageUnitSide(const nsStyleSides& aSides) +{ + NS_FOR_CSS_SIDES(side) { + if (eStyleUnit_Percent == aSides.GetUnit(side)) + return PR_TRUE; + } + return PR_FALSE; +} + +static PRBool +IsPercentageAware(const nsIFrame* aFrame) +{ + NS_ASSERTION(aFrame, "null frame is not allowed"); + + nsIAtom *fType = aFrame->GetType(); + if (fType == nsGkAtoms::textFrame) { + // None of these things can ever be true for text frames. + return PR_FALSE; + } + + // Some of these things don't apply to non-replaced inline frames + // (that is, fType == nsGkAtoms::inlineFrame || fType == + // nsGkAtoms::positionedInlineFrame), but we won't bother making + // things unnecessarily complicated, since they'll probably be set + // quite rarely. + + const nsStyleMargin* margin = aFrame->GetStyleMargin(); + if (HasPercentageUnitSide(margin->mMargin)) { + return PR_TRUE; + } + + const nsStylePadding* padding = aFrame->GetStylePadding(); + if (HasPercentageUnitSide(padding->mPadding)) { + return PR_TRUE; + } + + // Note that borders can't be aware of percentages + + const nsStylePosition* pos = aFrame->GetStylePosition(); + + if (eStyleUnit_Percent == pos->mWidth.GetUnit() || + eStyleUnit_Percent == pos->mMaxWidth.GetUnit() || + eStyleUnit_Percent == pos->mMinWidth.GetUnit() || + eStyleUnit_Percent == pos->mOffset.GetRightUnit() || + eStyleUnit_Percent == pos->mOffset.GetLeftUnit()) { + return PR_TRUE; + } + + if (eStyleUnit_Auto == pos->mWidth.GetUnit()) { + // We need to check for frames that shrink-wrap when they're auto + // width. + const nsStyleDisplay* disp = aFrame->GetStyleDisplay(); + if (disp->mDisplay == NS_STYLE_DISPLAY_INLINE_BLOCK || + disp->mDisplay == NS_STYLE_DISPLAY_INLINE_TABLE || + fType == nsGkAtoms::HTMLButtonControlFrame || + fType == nsGkAtoms::gfxButtonControlFrame || + fType == nsGkAtoms::fieldSetFrame) { + return PR_TRUE; + } + } + + return PR_FALSE; +} + nsresult nsLineLayout::ReflowFrame(nsIFrame* aFrame, nsReflowStatus& aReflowStatus, @@ -713,6 +782,14 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, printf("\n"); #endif + // See if this frame depends on the width of its containing block. If + // so, disable resize reflow optimizations for the line. (Note that, + // to be conservative, we do this if we *try* to fit a frame on a + // line, even if we don't succeed.) + if (IsPercentageAware(aFrame)) { + mLineBox->DisableResizeReflowOptimization(); + } + // Compute the available size for the frame. This available width // includes room for the side margins. // For now, set the available height to unconstrained always. @@ -1323,75 +1400,6 @@ nsLineLayout::DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent) #define VALIGN_TOP 1 #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(nsPresContext *aPresContext, - nsIFrame* aFrame) -{ - if (aFrame->IsFrameOfType(nsIFrame::eReplaced)) - { - nsIAtom* frameType = aFrame->GetType(); - if (nsGkAtoms::brFrame != frameType && - nsGkAtoms::textFrame != frameType) - { - const nsStyleMargin* margin = aFrame->GetStyleMargin(); - if (IsPercentageUnitSides(&margin->mMargin)) { - return PR_TRUE; - } - - const nsStylePadding* padding = aFrame->GetStylePadding(); - if (IsPercentageUnitSides(&padding->mPadding)) { - return PR_TRUE; - } - - // Borders aren't percentage aware - - const nsStylePosition* pos = aFrame->GetStylePosition(); - 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(nsPresContext *aPresContext, nsIFrame *aFrame) -{ - if (aFrame->IsFrameOfType(nsIFrame::eReplaced)) { - if (nsLineLayout::IsPercentageAwareReplacedElement(aPresContext, aFrame)) { - return PR_TRUE; - } - } - else - { - nsIFrame *child = aFrame->GetFirstChild(nsnull); - if (child) - { // aFrame is an inline container frame, check my frame state - if (aFrame->GetStateBits() & 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 nsLineLayout::VerticalAlignLine() { @@ -1503,14 +1511,6 @@ nsLineLayout::VerticalAlignLine() nscoord distanceFromTop = pfd->mBounds.y - mTopEdge; 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==mLineBox->ResizeReflowOptimizationDisabled()) && - pfd->mFrameType & NS_CSS_FRAME_TYPE_INLINE) - { - if (IsPercentageAwareFrame(mPresContext, pfd->mFrame)) - mLineBox->DisableResizeReflowOptimization(); - } } // Fill in returned line-box and max-element-width data diff --git a/mozilla/layout/generic/nsLineLayout.h b/mozilla/layout/generic/nsLineLayout.h index bdfc223b3d7..e5c2fd2a5e6 100644 --- a/mozilla/layout/generic/nsLineLayout.h +++ b/mozilla/layout/generic/nsLineLayout.h @@ -313,12 +313,6 @@ public: static PRBool TreatFrameAsBlock(nsIFrame* aFrame); - static PRBool IsPercentageUnitSides(const nsStyleSides* aSides); - - static PRBool IsPercentageAwareReplacedElement(nsPresContext *aPresContext, - nsIFrame *aFrame); - - //---------------------------------------- nsPresContext* mPresContext;