Changed InitConstraints() to handle inline, block-level, and floated elements

(replaced and non-replaced)
This commit is contained in:
troy%netscape.com 1998-12-31 23:07:00 +00:00
Родитель ad72a0397b
Коммит c30da1d1ee
2 изменённых файлов: 162 добавлений и 92 удалений

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

@ -168,6 +168,59 @@ nsHTMLReflowState::DetermineFrameType(nsIPresContext& aPresContext)
}
}
// Helper function that re-calculates the left and right margin based on
// the width of the containing block, the border/padding, and the computed
// width.
//
// This function is called by InitConstraints() when the 'width' property
// has a value other than 'auto'
void
nsHTMLReflowState::CalculateLeftRightMargin(const nsHTMLReflowState* aContainingBlockRS,
const nsStyleSpacing* aSpacing,
nscoord aComputedWidth,
const nsMargin& aBorderPadding,
nscoord& aComputedLeftMargin,
nscoord& aComputedRightMargin)
{
PRBool isAutoLeftMargin = eStyleUnit_Auto == aSpacing->mMargin.GetLeftUnit();
PRBool isAutoRightMargin = eStyleUnit_Auto == aSpacing->mMargin.GetRightUnit();
// Calculate how much space is available for margins
nscoord availMarginSpace = aContainingBlockRS->computedWidth - aComputedWidth -
aBorderPadding.left - aBorderPadding.right;
// See whether we're over constrained
if (!isAutoLeftMargin && !isAutoRightMargin) {
// Neither margin is 'auto' so we're over constrained. Use the
// 'direction' property to tell which margin to ignore
const nsStyleDisplay* display;
frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
if (NS_STYLE_DIRECTION_LTR == display->mDirection) {
isAutoRightMargin = PR_TRUE;
} else {
isAutoLeftMargin = PR_TRUE;
}
}
if (isAutoLeftMargin) {
if (isAutoRightMargin) {
// Both margins are 'auto' so their computed values are equal
if (availMarginSpace <= 0) {
aComputedLeftMargin = aComputedRightMargin = 0;
} else {
aComputedLeftMargin = (availMarginSpace + 1) / 2;
aComputedRightMargin = availMarginSpace - aComputedLeftMargin;
}
} else {
aComputedLeftMargin = PR_MAX(0, availMarginSpace - aComputedRightMargin);
}
} else if (isAutoRightMargin) {
aComputedRightMargin = PR_MAX(0, availMarginSpace - aComputedLeftMargin);
}
}
void
nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext)
{
@ -185,22 +238,18 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext)
computedTopMargin = margin.top;
computedBottomMargin = margin.bottom;
// Calculate the line height.
// XXX Do we need to do this for all elements or just inline non-replaced
// elements?
mLineHeight = CalcLineHeight(aPresContext, frame);
// Some frame types are not constrained by width/height style
// attributes. Return if the frame is one of those types.
switch (frameType) {
case eCSSFrameType_Unknown:
return;
case eCSSFrameType_Inline:
if (eCSSFrameType_Inline == frameType) {
// 'width' property doesn't apply to inline non-replaced elements. The
// 'height' is given by the element's 'line-height' value
if (mLineHeight >= 0) {
computedHeight = mLineHeight;
}
return;
default:
break;
return; // nothing else to compute
}
// If this is the root frame then set the computed width and
@ -210,8 +259,7 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext)
computedHeight = maxSize.height;
} else {
// Get the containing block reflow state, because we'll need its
// computed width
// Get the containing block reflow state
const nsHTMLReflowState* cbrs =
GetContainingBlockReflowState(parentReflowState);
NS_ASSERTION(nsnull != cbrs, "no containing block");
@ -220,8 +268,8 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext)
// calculating the computed width and height
nscoord containingBlockWidth = cbrs->computedWidth;
nscoord containingBlockHeight = cbrs->computedHeight;
PRIntn widthUnit = pos->mWidth.GetUnit();
PRIntn heightUnit = pos->mHeight.GetUnit();
nsStyleUnit widthUnit = pos->mWidth.GetUnit();
nsStyleUnit heightUnit = pos->mHeight.GetUnit();
// Check for a percentage based height
if (eStyleUnit_Percent == heightUnit) {
@ -232,86 +280,82 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext)
}
}
// Compute border and padding
nsMargin borderPadding;
ComputeBorderPaddingFor(frame, parentReflowState, borderPadding);
// Get the spacing style information
const nsStyleSpacing* spacing;
frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
// Compute the content width
PRBool isAutoLeftMargin = eStyleUnit_Auto == spacing->mMargin.GetLeftUnit();
PRBool isAutoRightMargin = eStyleUnit_Auto == spacing->mMargin.GetRightUnit();
if (eStyleUnit_Auto == widthUnit) {
// 'auto' values for left or right margins become 0
if (isAutoLeftMargin) {
computedLeftMargin = 0;
// Calculate the computed width and height. This varies by frame type
if ((eCSSFrameType_InlineReplaced == frameType) ||
(eCSSFrameType_FloatingReplaced == frameType)) {
// Inline replaced element and floating replaced element are basically
// treated the same
if (eStyleUnit_Auto == widthUnit) {
// A specified value of 'auto' uses the element's intrinsic width
computedWidth = NS_INTRINSICSIZE;
} else {
ComputeHorizontalValue(*cbrs, widthUnit, pos->mWidth, computedWidth);
}
if (isAutoRightMargin) {
computedRightMargin = 0;
if (eStyleUnit_Auto == heightUnit) {
// A specified value of 'auto' uses the element's intrinsic height
computedHeight = NS_INTRINSICSIZE;
} else {
ComputeVerticalValue(*cbrs, heightUnit, pos->mHeight, computedHeight);
}
computedWidth = containingBlockWidth - computedLeftMargin -
computedRightMargin - borderPadding.left - borderPadding.right;
} else if (eCSSFrameType_Floating == frameType) {
// Floating non-replaced element
if (eStyleUnit_Auto == widthUnit) {
// A specified value of 'auto' becomes a computed width of 0
computedWidth = 0;
} else {
ComputeHorizontalValue(*cbrs, widthUnit, pos->mWidth, computedWidth);
}
if (eStyleUnit_Auto == heightUnit) {
computedHeight = NS_AUTOHEIGHT; // let it choose its height
} else {
ComputeVerticalValue(*cbrs, heightUnit, pos->mHeight, computedHeight);
}
} else {
if (eStyleUnit_Coord == widthUnit) {
computedWidth = pos->mWidth.GetCoordValue();
} else if (eStyleUnit_Percent == widthUnit) {
computedWidth = nscoord(pos->mWidth.GetPercentValue() * containingBlockWidth);
// Block-level elements and absolutely positioned elements
const nsStyleSpacing* spacing;
frame->GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct*&)spacing);
// Compute border and padding
nsMargin borderPadding;
ComputeBorderPaddingFor(frame, parentReflowState, borderPadding);
// Compute the content width
if (eStyleUnit_Auto == widthUnit) {
if (eCSSFrameType_BlockReplaced == frameType) {
// Block-level replaced element in the flow. A specified value of 'auto'
// uses the element's intrinsic width
computedWidth = NS_INTRINSICSIZE;
} else {
// Block-level non-replaced element in the flow. 'auto' values for
// margin-left and margin-right become 0 and the sum of the areas must
// equal the width of the containing block
computedWidth = containingBlockWidth - computedLeftMargin - computedRightMargin -
borderPadding.left - borderPadding.right;
}
} else {
NS_ASSERTION(PR_FALSE, "unexpected width constraint");
ComputeHorizontalValue(*cbrs, widthUnit, pos->mWidth, computedWidth);
// Calculate the computed left and right margin again taking into
// account the computed width, border/padding, and width of the
// containing block
CalculateLeftRightMargin(cbrs, spacing, computedWidth, borderPadding,
computedLeftMargin, computedRightMargin);
}
// Calculate the computed left and right margin
nscoord extra = containingBlockWidth - computedWidth - borderPadding.left -
borderPadding.right;
// See whether we're over constrained
if (!isAutoLeftMargin && !isAutoRightMargin) {
// Neither margin is 'auto' so we're over constrained. Use the
// 'direction' property to tell which margin to ignore
const nsStyleDisplay* display;
frame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display);
if (NS_STYLE_DIRECTION_LTR == display->mDirection) {
isAutoRightMargin = PR_TRUE;
// Compute the content height
if (eStyleUnit_Auto == heightUnit) {
if (eCSSFrameType_BlockReplaced == frameType) {
computedHeight = NS_INTRINSICSIZE;
} else {
isAutoLeftMargin = PR_TRUE;
computedHeight = NS_AUTOHEIGHT;
}
} else {
ComputeVerticalValue(*cbrs, heightUnit, pos->mHeight, computedHeight);
}
if (isAutoLeftMargin) {
if (isAutoRightMargin) {
// Both margins are 'auto' so their computed values are equal
if (extra <= 0) {
computedLeftMargin = computedRightMargin = 0;
} else {
computedLeftMargin = (extra + 1) / 2;
computedRightMargin = extra - computedLeftMargin;
}
} else {
computedLeftMargin = PR_MAX(0, extra - computedRightMargin);
}
} else if (isAutoRightMargin) {
computedRightMargin = PR_MAX(0, extra - computedLeftMargin);
}
}
// Compute the content height
switch (heightUnit) {
case eStyleUnit_Coord:
computedHeight = pos->mHeight.GetCoordValue();
break;
case eStyleUnit_Percent:
computedHeight = nscoord(pos->mHeight.GetPercentValue() * containingBlockHeight);
break;
case eStyleUnit_Auto:
computedHeight = NS_AUTOHEIGHT;
break;
}
}
}
@ -387,7 +431,7 @@ nsHTMLReflowState::CalcLineHeight(nsIPresContext& aPresContext,
void
nsHTMLReflowState::ComputeHorizontalValue(const nsHTMLReflowState& aRS,
nsStyleUnit aUnit,
nsStyleCoord& aCoord,
const nsStyleCoord& aCoord,
nscoord& aResult)
{
aResult = 0;
@ -395,21 +439,30 @@ nsHTMLReflowState::ComputeHorizontalValue(const nsHTMLReflowState& aRS,
nscoord width = aRS.computedWidth;
float pct = aCoord.GetPercentValue();
aResult = NSToCoordFloor(width * pct);
} else if (eStyleUnit_Coord == aUnit) {
aResult = aCoord.GetCoordValue();
}
}
void
nsHTMLReflowState::ComputeVerticalValue(const nsHTMLReflowState& aRS,
nsStyleUnit aUnit,
nsStyleCoord& aCoord,
const nsStyleCoord& aCoord,
nscoord& aResult)
{
aResult = 0;
if (eStyleUnit_Percent == aUnit) {
// XXX temporary!
nscoord width = aRS.computedWidth;
// Verify no one is trying to calculate a percentage based height against
// a height that's shrink wrapping to its content. In that case they should
// treat the specified value like 'auto'
NS_ASSERTION(NS_AUTOHEIGHT != aRS.computedHeight, "unexpected containing block height");
nscoord height = aRS.computedHeight;
float pct = aCoord.GetPercentValue();
aResult = NSToCoordFloor(width * pct);
aResult = NSToCoordFloor(height * pct);
} else if (eStyleUnit_Coord == aUnit) {
aResult = aCoord.GetCoordValue();
}
}

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

@ -25,6 +25,7 @@
class nsISpaceManager;
class nsBlockFrame;
class nsLineLayout;
struct nsStyleSpacing;
// IID for the nsIHTMLFrame interface
// a6cf9069-15b3-11d2-932e-00805f8add32
@ -122,8 +123,15 @@ enum nsCSSFrameType {
//----------------------------------------------------------------------
// XXX I think these should be NS_UNCONSTRAINEDSIZE instead, but that causes
// problems for tables
#if 0
#define NS_INTRINSICSIZE NS_UNCONSTRAINEDSIZE
#define NS_AUTOHEIGHT NS_UNCONSTRAINEDSIZE
#else
#define NS_INTRINSICSIZE 0
#define NS_AUTOHEIGHT 0
#endif
/**
* HTML version of the reflow state.
@ -320,12 +328,21 @@ protected:
void InitConstraints(nsIPresContext& aPresContext);
void CalculateLeftRightMargin(const nsHTMLReflowState* aContainingBlockRS,
const nsStyleSpacing* aSpacing,
nscoord aComputedWidth,
const nsMargin& aBorderPadding,
nscoord& aComputedLeftMargin,
nscoord& aComputedRightMargin);
static void ComputeHorizontalValue(const nsHTMLReflowState& aReflowState,
nsStyleUnit aUnit, nsStyleCoord& aCoord,
nsStyleUnit aUnit,
const nsStyleCoord& aCoord,
nscoord& aResult);
static void ComputeVerticalValue(const nsHTMLReflowState& aReflowState,
nsStyleUnit aUnit, nsStyleCoord& aCoord,
nsStyleUnit aUnit,
const nsStyleCoord& aCoord,
nscoord& aResult);
};