diff --git a/mozilla/content/html/style/src/nsComputedDOMStyle.cpp b/mozilla/content/html/style/src/nsComputedDOMStyle.cpp index 2a5448ec743..ac80a57430c 100644 --- a/mozilla/content/html/style/src/nsComputedDOMStyle.cpp +++ b/mozilla/content/html/style/src/nsComputedDOMStyle.cpp @@ -53,6 +53,7 @@ #include "nsCSSKeywords.h" #include "nsDOMCSSRect.h" #include "nsLayoutAtoms.h" +#include "nsHTMLReflowState.h" #include "nsThemeConstants.h" #include "nsPresContext.h" @@ -1834,7 +1835,8 @@ nsComputedDOMStyle::GetTextIndent(nsIFrame *aFrame, break; case eStyleUnit_Percent: { - nsIFrame *container = GetContainingBlock(aFrame); + nsIFrame *container = + nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { val->SetTwips(container->GetSize().width * text->mTextIndent.GetPercentValue()); @@ -2694,7 +2696,7 @@ nsComputedDOMStyle::GetMaxHeight(nsIFrame *aFrame, nscoord minHeight = 0; if (positionData->mMinHeight.GetUnit() == eStyleUnit_Percent) { - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { size = container->GetSize(); minHeight = nscoord(size.height * @@ -2711,7 +2713,7 @@ nsComputedDOMStyle::GetMaxHeight(nsIFrame *aFrame, break; case eStyleUnit_Percent: if (!container) { - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { size = container->GetSize(); } else { @@ -2754,7 +2756,7 @@ nsComputedDOMStyle::GetMaxWidth(nsIFrame *aFrame, nscoord minWidth = 0; if (positionData->mMinWidth.GetUnit() == eStyleUnit_Percent) { - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { size = container->GetSize(); minWidth = nscoord(size.width * @@ -2771,7 +2773,7 @@ nsComputedDOMStyle::GetMaxWidth(nsIFrame *aFrame, break; case eStyleUnit_Percent: if (!container) { - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { size = container->GetSize(); } else { @@ -2815,7 +2817,7 @@ nsComputedDOMStyle::GetMinHeight(nsIFrame *aFrame, val->SetTwips(positionData->mMinHeight.GetCoordValue()); break; case eStyleUnit_Percent: - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { val->SetTwips(container->GetSize().height * positionData->mMinHeight.GetPercentValue()); @@ -2855,7 +2857,7 @@ nsComputedDOMStyle::GetMinWidth(nsIFrame *aFrame, val->SetTwips(positionData->mMinWidth.GetCoordValue()); break; case eStyleUnit_Percent: - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { val->SetTwips(container->GetSize().width * positionData->mMinWidth.GetPercentValue()); @@ -2949,7 +2951,7 @@ nsComputedDOMStyle::GetAbsoluteOffset(PRUint8 aSide, nsIFrame* aFrame, nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue(); NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY); - nsIFrame* container = GetContainingBlock(aFrame); + nsIFrame* container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { nscoord margin = GetMarginWidthCoordFor(aSide, aFrame); nscoord border = GetBorderWidthCoordFor(aSide, container); @@ -3063,7 +3065,7 @@ nsComputedDOMStyle::GetRelativeOffset(PRUint8 aSide, nsIFrame* aFrame, val->SetTwips(sign * coord.GetCoordValue()); break; case eStyleUnit_Percent: - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { nsMargin border; nsMargin padding; @@ -3164,25 +3166,6 @@ nsComputedDOMStyle::FlushPendingReflows() } } -nsIFrame* -nsComputedDOMStyle::GetContainingBlock(nsIFrame *aFrame) -{ - if (!aFrame) { - // Tell caller that they have no containing block, seeing as they - // are not being displayed - - return nsnull; - } - - nsIFrame* container = aFrame; - do { - container = container->GetParent(); - } while (container && !container->IsContainingBlock()); - - NS_POSTCONDITION(container, "Frame has no containing block"); - return container; -} - nsresult nsComputedDOMStyle::GetStyleData(nsStyleStructID aID, const nsStyleStruct*& aStyleStruct, diff --git a/mozilla/content/html/style/src/nsComputedDOMStyle.h b/mozilla/content/html/style/src/nsComputedDOMStyle.h index d1da51a4962..75ca16b953d 100644 --- a/mozilla/content/html/style/src/nsComputedDOMStyle.h +++ b/mozilla/content/html/style/src/nsComputedDOMStyle.h @@ -76,8 +76,6 @@ public: private: void FlushPendingReflows(); - nsIFrame* GetContainingBlock(nsIFrame *aFrame); - nsresult GetStyleData(nsStyleStructID aID, const nsStyleStruct*& aStyleStruct, nsIFrame* aFrame=0); diff --git a/mozilla/content/shared/src/nsStyleStruct.cpp b/mozilla/content/shared/src/nsStyleStruct.cpp index 67626d0e0da..211e88be223 100644 --- a/mozilla/content/shared/src/nsStyleStruct.cpp +++ b/mozilla/content/shared/src/nsStyleStruct.cpp @@ -50,6 +50,7 @@ #include "nsIPresShell.h" #include "nsIFrame.h" #include "nsLayoutAtoms.h" +#include "nsHTMLReflowState.h" #include "prenv.h" #include "nsBidiUtils.h" @@ -79,26 +80,23 @@ inline nscoord CalcSideFor(const nsIFrame* aFrame, const nsStyleCoord& aCoord, case eStyleUnit_Percent: { nscoord baseWidth = 0; - nsIFrame* frame = aFrame->GetParent(); - while (frame) { - if (frame->IsContainingBlock()) { - baseWidth = frame->GetSize().width; - // subtract border of containing block - nsMargin border; - frame->GetStyleBorder()->CalcBorderFor(frame, border); - baseWidth -= (border.left + border.right); - // if aFrame is not absolutely positioned, subtract - // padding of containing block - const nsStyleDisplay* displayData = aFrame->GetStyleDisplay(); - if (displayData->mPosition != NS_STYLE_POSITION_ABSOLUTE && - displayData->mPosition != NS_STYLE_POSITION_FIXED) { - nsMargin padding; - frame->GetStylePadding()->CalcPaddingFor(frame, padding); - baseWidth -= (padding.left + padding.right); - } - break; + nsIFrame* frame = + nsHTMLReflowState::GetContainingBlockFor(aFrame); + if (frame) { + baseWidth = frame->GetSize().width; + // subtract border of containing block + nsMargin border; + frame->GetStyleBorder()->CalcBorderFor(frame, border); + baseWidth -= (border.left + border.right); + // if aFrame is not absolutely positioned, subtract + // padding of containing block + const nsStyleDisplay* displayData = aFrame->GetStyleDisplay(); + if (displayData->mPosition != NS_STYLE_POSITION_ABSOLUTE && + displayData->mPosition != NS_STYLE_POSITION_FIXED) { + nsMargin padding; + frame->GetStylePadding()->CalcPaddingFor(frame, padding); + baseWidth -= (padding.left + padding.right); } - frame = frame->GetParent(); } result = (nscoord)((float)baseWidth * aCoord.GetPercentValue()); } diff --git a/mozilla/layout/base/public/nsHTMLReflowState.h b/mozilla/layout/base/public/nsHTMLReflowState.h index d5271674c5b..a8d6d3ec4ee 100644 --- a/mozilla/layout/base/public/nsHTMLReflowState.h +++ b/mozilla/layout/base/public/nsHTMLReflowState.h @@ -322,6 +322,13 @@ struct nsHTMLReflowState { static nscoord GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState); + /** + * Find the containing block of aFrame. This may return null if + * there isn't one (but that should really only happen for root + * frames). + */ + static const nsIFrame* GetContainingBlockFor(const nsIFrame* aFrame); + /** * Get the page box reflow state, starting from a frames * parent reflow state (the parent reflow state may or may not end diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index ebd5c775ba5..c5a75f980c4 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -5529,12 +5529,44 @@ nsBlockFrame::PaintTextDecorationLines(nsIRenderingContext& aRenderingContext, nscoord aSize) { aRenderingContext.SetColor(aColor); - for (nsLineList::iterator line = begin_lines(), line_end = end_lines(); + for (nsLineList::iterator line = begin_lines(), line_start = line, + line_end = end_lines(); line != line_end; ++line) { if (!line->IsBlock()) { - aRenderingContext.FillRect(line->mBounds.x, - line->mBounds.y + line->GetAscent() - aOffset, - line->mBounds.width, aSize); + nscoord start = line->mBounds.x; + nscoord width = line->mBounds.width; + + if (line == line_start) { + // Adjust for the text-indent. See similar code in + // nsLineLayout::BeginLineReflow. + nscoord indent = 0; + const nsStyleText* styleText = GetStyleText(); + nsStyleUnit unit = styleText->mTextIndent.GetUnit(); + if (eStyleUnit_Coord == unit) { + indent = styleText->mTextIndent.GetCoordValue(); + } else if (eStyleUnit_Percent == unit) { + // It's a percentage of the containing block width. + nsIFrame* containingBlock = + nsHTMLReflowState::GetContainingBlockFor(this); + NS_ASSERTION(containingBlock, "Must have containing block!"); + indent = nscoord(styleText->mTextIndent.GetPercentValue() * + containingBlock->GetRect().width); + } + + // Adjust the start position and the width of the decoration by the + // value of the indent. Note that indent can be negative; that's OK. + // It'll just increase the width (which can also happen to be + // negative!). + start += indent; + width -= indent; + } + + // Only paint if we have a positive width + if (width > 0) { + aRenderingContext.FillRect(start, + line->mBounds.y + line->GetAscent() - aOffset, + width, aSize); + } } } } diff --git a/mozilla/layout/generic/nsHTMLReflowState.cpp b/mozilla/layout/generic/nsHTMLReflowState.cpp index c2b87df3de9..cf63950398f 100644 --- a/mozilla/layout/generic/nsHTMLReflowState.cpp +++ b/mozilla/layout/generic/nsHTMLReflowState.cpp @@ -358,6 +358,7 @@ nsHTMLReflowState::GetPageBoxReflowState(const nsHTMLReflowState* aParentRS) return nsnull; } +/* static */ nscoord nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState) { @@ -367,6 +368,23 @@ nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aRefl return rs->mComputedWidth; } +/* static */ +nsIFrame* +nsHTMLReflowState::GetContainingBlockFor(const nsIFrame* aFrame) +{ + NS_PRECONDITION(aFrame, "Must have frame to work with"); + nsIFrame* container = aFrame->GetParent(); + if (aFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) { + // Absolutely positioned frames are just kids of their containing + // blocks (which may happen to be inlines). + return container; + } + while (container && !container->IsContainingBlock()) { + container = container->GetParent(); + } + return container; +} + void nsHTMLReflowState::InitFrameType() { diff --git a/mozilla/layout/generic/nsHTMLReflowState.h b/mozilla/layout/generic/nsHTMLReflowState.h index d5271674c5b..a8d6d3ec4ee 100644 --- a/mozilla/layout/generic/nsHTMLReflowState.h +++ b/mozilla/layout/generic/nsHTMLReflowState.h @@ -322,6 +322,13 @@ struct nsHTMLReflowState { static nscoord GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState); + /** + * Find the containing block of aFrame. This may return null if + * there isn't one (but that should really only happen for root + * frames). + */ + static const nsIFrame* GetContainingBlockFor(const nsIFrame* aFrame); + /** * Get the page box reflow state, starting from a frames * parent reflow state (the parent reflow state may or may not end diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index ebd5c775ba5..c5a75f980c4 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -5529,12 +5529,44 @@ nsBlockFrame::PaintTextDecorationLines(nsIRenderingContext& aRenderingContext, nscoord aSize) { aRenderingContext.SetColor(aColor); - for (nsLineList::iterator line = begin_lines(), line_end = end_lines(); + for (nsLineList::iterator line = begin_lines(), line_start = line, + line_end = end_lines(); line != line_end; ++line) { if (!line->IsBlock()) { - aRenderingContext.FillRect(line->mBounds.x, - line->mBounds.y + line->GetAscent() - aOffset, - line->mBounds.width, aSize); + nscoord start = line->mBounds.x; + nscoord width = line->mBounds.width; + + if (line == line_start) { + // Adjust for the text-indent. See similar code in + // nsLineLayout::BeginLineReflow. + nscoord indent = 0; + const nsStyleText* styleText = GetStyleText(); + nsStyleUnit unit = styleText->mTextIndent.GetUnit(); + if (eStyleUnit_Coord == unit) { + indent = styleText->mTextIndent.GetCoordValue(); + } else if (eStyleUnit_Percent == unit) { + // It's a percentage of the containing block width. + nsIFrame* containingBlock = + nsHTMLReflowState::GetContainingBlockFor(this); + NS_ASSERTION(containingBlock, "Must have containing block!"); + indent = nscoord(styleText->mTextIndent.GetPercentValue() * + containingBlock->GetRect().width); + } + + // Adjust the start position and the width of the decoration by the + // value of the indent. Note that indent can be negative; that's OK. + // It'll just increase the width (which can also happen to be + // negative!). + start += indent; + width -= indent; + } + + // Only paint if we have a positive width + if (width > 0) { + aRenderingContext.FillRect(start, + line->mBounds.y + line->GetAscent() - aOffset, + width, aSize); + } } } } diff --git a/mozilla/layout/html/base/src/nsHTMLReflowState.cpp b/mozilla/layout/html/base/src/nsHTMLReflowState.cpp index c2b87df3de9..cf63950398f 100644 --- a/mozilla/layout/html/base/src/nsHTMLReflowState.cpp +++ b/mozilla/layout/html/base/src/nsHTMLReflowState.cpp @@ -358,6 +358,7 @@ nsHTMLReflowState::GetPageBoxReflowState(const nsHTMLReflowState* aParentRS) return nsnull; } +/* static */ nscoord nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState) { @@ -367,6 +368,23 @@ nsHTMLReflowState::GetContainingBlockContentWidth(const nsHTMLReflowState* aRefl return rs->mComputedWidth; } +/* static */ +nsIFrame* +nsHTMLReflowState::GetContainingBlockFor(const nsIFrame* aFrame) +{ + NS_PRECONDITION(aFrame, "Must have frame to work with"); + nsIFrame* container = aFrame->GetParent(); + if (aFrame->GetStyleDisplay()->IsAbsolutelyPositioned()) { + // Absolutely positioned frames are just kids of their containing + // blocks (which may happen to be inlines). + return container; + } + while (container && !container->IsContainingBlock()) { + container = container->GetParent(); + } + return container; +} + void nsHTMLReflowState::InitFrameType() { diff --git a/mozilla/layout/style/nsComputedDOMStyle.cpp b/mozilla/layout/style/nsComputedDOMStyle.cpp index 2a5448ec743..ac80a57430c 100644 --- a/mozilla/layout/style/nsComputedDOMStyle.cpp +++ b/mozilla/layout/style/nsComputedDOMStyle.cpp @@ -53,6 +53,7 @@ #include "nsCSSKeywords.h" #include "nsDOMCSSRect.h" #include "nsLayoutAtoms.h" +#include "nsHTMLReflowState.h" #include "nsThemeConstants.h" #include "nsPresContext.h" @@ -1834,7 +1835,8 @@ nsComputedDOMStyle::GetTextIndent(nsIFrame *aFrame, break; case eStyleUnit_Percent: { - nsIFrame *container = GetContainingBlock(aFrame); + nsIFrame *container = + nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { val->SetTwips(container->GetSize().width * text->mTextIndent.GetPercentValue()); @@ -2694,7 +2696,7 @@ nsComputedDOMStyle::GetMaxHeight(nsIFrame *aFrame, nscoord minHeight = 0; if (positionData->mMinHeight.GetUnit() == eStyleUnit_Percent) { - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { size = container->GetSize(); minHeight = nscoord(size.height * @@ -2711,7 +2713,7 @@ nsComputedDOMStyle::GetMaxHeight(nsIFrame *aFrame, break; case eStyleUnit_Percent: if (!container) { - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { size = container->GetSize(); } else { @@ -2754,7 +2756,7 @@ nsComputedDOMStyle::GetMaxWidth(nsIFrame *aFrame, nscoord minWidth = 0; if (positionData->mMinWidth.GetUnit() == eStyleUnit_Percent) { - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { size = container->GetSize(); minWidth = nscoord(size.width * @@ -2771,7 +2773,7 @@ nsComputedDOMStyle::GetMaxWidth(nsIFrame *aFrame, break; case eStyleUnit_Percent: if (!container) { - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { size = container->GetSize(); } else { @@ -2815,7 +2817,7 @@ nsComputedDOMStyle::GetMinHeight(nsIFrame *aFrame, val->SetTwips(positionData->mMinHeight.GetCoordValue()); break; case eStyleUnit_Percent: - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { val->SetTwips(container->GetSize().height * positionData->mMinHeight.GetPercentValue()); @@ -2855,7 +2857,7 @@ nsComputedDOMStyle::GetMinWidth(nsIFrame *aFrame, val->SetTwips(positionData->mMinWidth.GetCoordValue()); break; case eStyleUnit_Percent: - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { val->SetTwips(container->GetSize().width * positionData->mMinWidth.GetPercentValue()); @@ -2949,7 +2951,7 @@ nsComputedDOMStyle::GetAbsoluteOffset(PRUint8 aSide, nsIFrame* aFrame, nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue(); NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY); - nsIFrame* container = GetContainingBlock(aFrame); + nsIFrame* container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { nscoord margin = GetMarginWidthCoordFor(aSide, aFrame); nscoord border = GetBorderWidthCoordFor(aSide, container); @@ -3063,7 +3065,7 @@ nsComputedDOMStyle::GetRelativeOffset(PRUint8 aSide, nsIFrame* aFrame, val->SetTwips(sign * coord.GetCoordValue()); break; case eStyleUnit_Percent: - container = GetContainingBlock(aFrame); + container = nsHTMLReflowState::GetContainingBlockFor(aFrame); if (container) { nsMargin border; nsMargin padding; @@ -3164,25 +3166,6 @@ nsComputedDOMStyle::FlushPendingReflows() } } -nsIFrame* -nsComputedDOMStyle::GetContainingBlock(nsIFrame *aFrame) -{ - if (!aFrame) { - // Tell caller that they have no containing block, seeing as they - // are not being displayed - - return nsnull; - } - - nsIFrame* container = aFrame; - do { - container = container->GetParent(); - } while (container && !container->IsContainingBlock()); - - NS_POSTCONDITION(container, "Frame has no containing block"); - return container; -} - nsresult nsComputedDOMStyle::GetStyleData(nsStyleStructID aID, const nsStyleStruct*& aStyleStruct, diff --git a/mozilla/layout/style/nsComputedDOMStyle.h b/mozilla/layout/style/nsComputedDOMStyle.h index d1da51a4962..75ca16b953d 100644 --- a/mozilla/layout/style/nsComputedDOMStyle.h +++ b/mozilla/layout/style/nsComputedDOMStyle.h @@ -76,8 +76,6 @@ public: private: void FlushPendingReflows(); - nsIFrame* GetContainingBlock(nsIFrame *aFrame); - nsresult GetStyleData(nsStyleStructID aID, const nsStyleStruct*& aStyleStruct, nsIFrame* aFrame=0); diff --git a/mozilla/layout/style/nsStyleStruct.cpp b/mozilla/layout/style/nsStyleStruct.cpp index 67626d0e0da..211e88be223 100644 --- a/mozilla/layout/style/nsStyleStruct.cpp +++ b/mozilla/layout/style/nsStyleStruct.cpp @@ -50,6 +50,7 @@ #include "nsIPresShell.h" #include "nsIFrame.h" #include "nsLayoutAtoms.h" +#include "nsHTMLReflowState.h" #include "prenv.h" #include "nsBidiUtils.h" @@ -79,26 +80,23 @@ inline nscoord CalcSideFor(const nsIFrame* aFrame, const nsStyleCoord& aCoord, case eStyleUnit_Percent: { nscoord baseWidth = 0; - nsIFrame* frame = aFrame->GetParent(); - while (frame) { - if (frame->IsContainingBlock()) { - baseWidth = frame->GetSize().width; - // subtract border of containing block - nsMargin border; - frame->GetStyleBorder()->CalcBorderFor(frame, border); - baseWidth -= (border.left + border.right); - // if aFrame is not absolutely positioned, subtract - // padding of containing block - const nsStyleDisplay* displayData = aFrame->GetStyleDisplay(); - if (displayData->mPosition != NS_STYLE_POSITION_ABSOLUTE && - displayData->mPosition != NS_STYLE_POSITION_FIXED) { - nsMargin padding; - frame->GetStylePadding()->CalcPaddingFor(frame, padding); - baseWidth -= (padding.left + padding.right); - } - break; + nsIFrame* frame = + nsHTMLReflowState::GetContainingBlockFor(aFrame); + if (frame) { + baseWidth = frame->GetSize().width; + // subtract border of containing block + nsMargin border; + frame->GetStyleBorder()->CalcBorderFor(frame, border); + baseWidth -= (border.left + border.right); + // if aFrame is not absolutely positioned, subtract + // padding of containing block + const nsStyleDisplay* displayData = aFrame->GetStyleDisplay(); + if (displayData->mPosition != NS_STYLE_POSITION_ABSOLUTE && + displayData->mPosition != NS_STYLE_POSITION_FIXED) { + nsMargin padding; + frame->GetStylePadding()->CalcPaddingFor(frame, padding); + baseWidth -= (padding.left + padding.right); } - frame = frame->GetParent(); } result = (nscoord)((float)baseWidth * aCoord.GetPercentValue()); }