Add a utility method for finding the containing block to nsHTMLReflowState, and

make use of it in fixing the text-decoration drawing on blocks to deal with
negative text-indent.  Bug 263374, r+sr=dbaron


git-svn-id: svn://10.0.0.236/trunk@165766 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bzbarsky%mit.edu
2004-11-25 02:43:28 +00:00
parent cfb3ee96f4
commit 4c07e20fbe
12 changed files with 178 additions and 106 deletions

View File

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

View File

@@ -76,8 +76,6 @@ public:
private:
void FlushPendingReflows();
nsIFrame* GetContainingBlock(nsIFrame *aFrame);
nsresult GetStyleData(nsStyleStructID aID,
const nsStyleStruct*& aStyleStruct,
nsIFrame* aFrame=0);

View File

@@ -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());
}

View File

@@ -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
* <B>parent</B> reflow state (the parent reflow state may or may not end

View File

@@ -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);
}
}
}
}

View File

@@ -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()
{

View File

@@ -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
* <B>parent</B> reflow state (the parent reflow state may or may not end

View File

@@ -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);
}
}
}
}

View File

@@ -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()
{

View File

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

View File

@@ -76,8 +76,6 @@ public:
private:
void FlushPendingReflows();
nsIFrame* GetContainingBlock(nsIFrame *aFrame);
nsresult GetStyleData(nsStyleStructID aID,
const nsStyleStruct*& aStyleStruct,
nsIFrame* aFrame=0);

View File

@@ -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());
}