Combine the code that tests inlines for dependence on the containing block width in order to disable resize reflow optimizations, and add to that code things that shrink wrap (inline-block, inline-table, buttons, fieldsets). Also move the percentage-height tests out, and into InitResizeFlags. b=163504 r+sr=bzbarsky

git-svn-id: svn://10.0.0.236/trunk@219046 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
dbaron%dbaron.org
2007-01-27 18:40:26 +00:00
parent 3052400d5e
commit c380d24c54
7 changed files with 87 additions and 181 deletions

View File

@@ -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