зеркало из https://github.com/mozilla/gecko-dev.git
Changed InitConstraints() to handle inline, block-level, and floated elements
(replaced and non-replaced)
This commit is contained in:
Родитель
ad72a0397b
Коммит
c30da1d1ee
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче