Define new API's to compute margin/border/padding/border+padding and handle percentages correctly
git-svn-id: svn://10.0.0.236/trunk@15012 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
74b2e97658
commit
257cb2e34e
@ -25,15 +25,14 @@
|
||||
#include "nsHTMLAtoms.h"
|
||||
|
||||
const nsHTMLReflowState*
|
||||
nsHTMLReflowState::GetContainingBlockReflowState() const
|
||||
nsHTMLReflowState::GetContainingBlockReflowState(const nsReflowState* aParentRS)
|
||||
{
|
||||
const nsReflowState* rs = parentReflowState;
|
||||
while (nsnull != rs) {
|
||||
if (nsnull != rs->frame) {
|
||||
while (nsnull != aParentRS) {
|
||||
if (nsnull != aParentRS->frame) {
|
||||
const nsStyleDisplay* display;
|
||||
nsresult rv;
|
||||
rv = rs->frame->GetStyleData(eStyleStruct_Display,
|
||||
(const nsStyleStruct*&) display);
|
||||
rv = aParentRS->frame->GetStyleData(eStyleStruct_Display,
|
||||
(const nsStyleStruct*&) display);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != display)) {
|
||||
switch (display->mDisplay) {
|
||||
case NS_STYLE_DISPLAY_BLOCK:
|
||||
@ -41,20 +40,28 @@ nsHTMLReflowState::GetContainingBlockReflowState() const
|
||||
case NS_STYLE_DISPLAY_RUN_IN:
|
||||
case NS_STYLE_DISPLAY_LIST_ITEM:
|
||||
// XXX This cast is Not Good
|
||||
return (const nsHTMLReflowState*)rs;
|
||||
return (const nsHTMLReflowState*)aParentRS;
|
||||
}
|
||||
}
|
||||
}
|
||||
rs = rs->parentReflowState;
|
||||
aParentRS = aParentRS->parentReflowState;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
const nsHTMLReflowState*
|
||||
nsHTMLReflowState::GetPageBoxReflowState(const nsReflowState* aParentRS)
|
||||
{
|
||||
// XXX write me as soon as we can ask a frame if it's a page frame...
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsHTMLReflowState::GetContainingBlockContentWidth() const
|
||||
{
|
||||
nscoord width = 0;
|
||||
const nsHTMLReflowState* rs = GetContainingBlockReflowState();
|
||||
const nsHTMLReflowState* rs =
|
||||
GetContainingBlockReflowState(parentReflowState);
|
||||
if (nsnull != rs) {
|
||||
if (rs->HaveFixedContentWidth()) {
|
||||
width = rs->minWidth;
|
||||
@ -71,7 +78,9 @@ nsHTMLReflowState::GetContainingBlockContentWidth() const
|
||||
(const nsStyleStruct*&) spacing);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != spacing)) {
|
||||
nsMargin borderPadding;
|
||||
spacing->CalcBorderPaddingFor(rs->frame, borderPadding);
|
||||
rs->ComputeBorderPaddingFor(rs->frame,
|
||||
(nsHTMLReflowState*) rs->parentReflowState,
|
||||
borderPadding);
|
||||
width -= borderPadding.left + borderPadding.right;
|
||||
}
|
||||
}
|
||||
@ -301,6 +310,205 @@ nsHTMLReflowState::InitConstraints(nsIPresContext& aPresContext)
|
||||
// (section 10.3/10.6 of the spec)
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLReflowState::ComputeHorizontalValue(const nsHTMLReflowState& aRS,
|
||||
nsStyleUnit aUnit,
|
||||
nsStyleCoord& aCoord,
|
||||
nscoord& aResult)
|
||||
{
|
||||
aResult = 0;
|
||||
if (eStyleUnit_Percent == aUnit) {
|
||||
nscoord width = aRS.GetContainingBlockContentWidth();
|
||||
float pct = aCoord.GetPercentValue();
|
||||
aResult = NSToCoordFloor(width * pct);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLReflowState::ComputeVerticalValue(const nsHTMLReflowState& aRS,
|
||||
nsStyleUnit aUnit,
|
||||
nsStyleCoord& aCoord,
|
||||
nscoord& aResult)
|
||||
{
|
||||
aResult = 0;
|
||||
if (eStyleUnit_Percent == aUnit) {
|
||||
// XXX temporary!
|
||||
nscoord width = aRS.GetContainingBlockContentWidth();
|
||||
float pct = aCoord.GetPercentValue();
|
||||
aResult = NSToCoordFloor(width * pct);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLReflowState::ComputeMarginFor(nsIFrame* aFrame,
|
||||
const nsReflowState* aParentRS,
|
||||
nsMargin& aResult)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
nsresult rv;
|
||||
rv = aFrame->GetStyleData(eStyleStruct_Spacing,
|
||||
(const nsStyleStruct*&) spacing);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != spacing)) {
|
||||
// If style style can provide us the margin directly, then use it.
|
||||
if (!spacing->GetMargin(aResult) && (nsnull != aParentRS)) {
|
||||
// We have to compute the value (because it's uncomputable by
|
||||
// the style code).
|
||||
const nsHTMLReflowState* rs = GetContainingBlockReflowState(aParentRS);
|
||||
if (nsnull != rs) {
|
||||
nsStyleCoord left, right;
|
||||
ComputeHorizontalValue(*rs, spacing->mMargin.GetLeftUnit(),
|
||||
spacing->mMargin.GetLeft(left), aResult.left);
|
||||
ComputeHorizontalValue(*rs, spacing->mMargin.GetRightUnit(),
|
||||
spacing->mMargin.GetRight(right),
|
||||
aResult.right);
|
||||
}
|
||||
else {
|
||||
aResult.left = 0;
|
||||
aResult.right = 0;
|
||||
}
|
||||
|
||||
const nsHTMLReflowState* rs2 = GetPageBoxReflowState(aParentRS);
|
||||
nsStyleCoord top, bottom;
|
||||
if (nsnull != rs2) {
|
||||
// According to the CSS2 spec, margin percentages are
|
||||
// calculated with respect to the *height* of the containing
|
||||
// block when in a paginated context.
|
||||
ComputeVerticalValue(*rs2, spacing->mMargin.GetTopUnit(),
|
||||
spacing->mMargin.GetTop(top), aResult.top);
|
||||
ComputeVerticalValue(*rs2, spacing->mMargin.GetBottomUnit(),
|
||||
spacing->mMargin.GetBottom(bottom),
|
||||
aResult.bottom);
|
||||
}
|
||||
else if (nsnull != rs) {
|
||||
// According to the CSS2 spec, margin percentages are
|
||||
// calculated with respect to the *width* of the containing
|
||||
// block, even for margin-top and margin-bottom.
|
||||
ComputeHorizontalValue(*rs, spacing->mMargin.GetTopUnit(),
|
||||
spacing->mMargin.GetTop(top), aResult.top);
|
||||
ComputeHorizontalValue(*rs, spacing->mMargin.GetBottomUnit(),
|
||||
spacing->mMargin.GetBottom(bottom),
|
||||
aResult.bottom);
|
||||
}
|
||||
else {
|
||||
aResult.top = 0;
|
||||
aResult.bottom = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLReflowState::ComputePaddingFor(nsIFrame* aFrame,
|
||||
const nsReflowState* aParentRS,
|
||||
nsMargin& aResult)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
nsresult rv;
|
||||
rv = aFrame->GetStyleData(eStyleStruct_Spacing,
|
||||
(const nsStyleStruct*&) spacing);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != spacing)) {
|
||||
// If style can provide us the padding directly, then use it.
|
||||
if (!spacing->GetPadding(aResult) && (nsnull != aParentRS)) {
|
||||
// We have to compute the value (because it's uncomputable by
|
||||
// the style code).
|
||||
const nsHTMLReflowState* rs = GetContainingBlockReflowState(aParentRS);
|
||||
if (nsnull != rs) {
|
||||
nsStyleCoord left, right, top, bottom;
|
||||
ComputeHorizontalValue(*rs, spacing->mPadding.GetLeftUnit(),
|
||||
spacing->mPadding.GetLeft(left), aResult.left);
|
||||
ComputeHorizontalValue(*rs, spacing->mPadding.GetRightUnit(),
|
||||
spacing->mPadding.GetRight(right),
|
||||
aResult.right);
|
||||
|
||||
// According to the CSS2 spec, padding percentages are
|
||||
// calculated with respect to the *width* of the containing
|
||||
// block, even for padding-top and padding-bottom.
|
||||
ComputeHorizontalValue(*rs, spacing->mPadding.GetTopUnit(),
|
||||
spacing->mPadding.GetTop(top), aResult.top);
|
||||
ComputeHorizontalValue(*rs, spacing->mPadding.GetBottomUnit(),
|
||||
spacing->mPadding.GetBottom(bottom),
|
||||
aResult.bottom);
|
||||
}
|
||||
else {
|
||||
aResult.SizeTo(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
aResult.SizeTo(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLReflowState::ComputeBorderFor(nsIFrame* aFrame,
|
||||
nsMargin& aResult)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
nsresult rv;
|
||||
rv = aFrame->GetStyleData(eStyleStruct_Spacing,
|
||||
(const nsStyleStruct*&) spacing);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != spacing)) {
|
||||
// If style can provide us the border directly, then use it.
|
||||
if (!spacing->GetBorder(aResult)) {
|
||||
// CSS2 has no percentage borders
|
||||
aResult.SizeTo(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
aResult.SizeTo(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLReflowState::ComputeBorderPaddingFor(nsIFrame* aFrame,
|
||||
const nsReflowState* aParentRS,
|
||||
nsMargin& aResult)
|
||||
{
|
||||
const nsStyleSpacing* spacing;
|
||||
nsresult rv;
|
||||
rv = aFrame->GetStyleData(eStyleStruct_Spacing,
|
||||
(const nsStyleStruct*&) spacing);
|
||||
if (NS_SUCCEEDED(rv) && (nsnull != spacing)) {
|
||||
nsMargin b, p;
|
||||
|
||||
// If style style can provide us the margin directly, then use it.
|
||||
if (!spacing->GetBorder(b)) {
|
||||
b.SizeTo(0, 0, 0, 0);
|
||||
}
|
||||
if (!spacing->GetPadding(p) && (nsnull != aParentRS)) {
|
||||
// We have to compute the value (because it's uncomputable by
|
||||
// the style code).
|
||||
const nsHTMLReflowState* rs = GetContainingBlockReflowState(aParentRS);
|
||||
if (nsnull != rs) {
|
||||
nsStyleCoord left, right, top, bottom;
|
||||
ComputeHorizontalValue(*rs, spacing->mPadding.GetLeftUnit(),
|
||||
spacing->mPadding.GetLeft(left), p.left);
|
||||
ComputeHorizontalValue(*rs, spacing->mPadding.GetRightUnit(),
|
||||
spacing->mPadding.GetRight(right), p.right);
|
||||
|
||||
// According to the CSS2 spec, padding percentages are
|
||||
// calculated with respect to the *width* of the containing
|
||||
// block, even for padding-top and padding-bottom.
|
||||
ComputeHorizontalValue(*rs, spacing->mPadding.GetTopUnit(),
|
||||
spacing->mPadding.GetTop(top), p.top);
|
||||
ComputeHorizontalValue(*rs, spacing->mPadding.GetBottomUnit(),
|
||||
spacing->mPadding.GetBottom(bottom), p.bottom);
|
||||
}
|
||||
else {
|
||||
p.SizeTo(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
aResult.top = b.top + p.top;
|
||||
aResult.right = b.right + p.right;
|
||||
aResult.bottom = b.bottom + p.bottom;
|
||||
aResult.left = b.left + p.left;
|
||||
}
|
||||
else {
|
||||
aResult.SizeTo(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsFrameReflowState::nsFrameReflowState(nsIPresContext& aPresContext,
|
||||
@ -329,7 +537,9 @@ nsFrameReflowState::nsFrameReflowState(nsIPresContext& aPresContext,
|
||||
(const nsStyleStruct*&) mStyleSpacing);
|
||||
|
||||
// Calculate our border and padding value
|
||||
mStyleSpacing->CalcBorderPaddingFor(frame, mBorderPadding);
|
||||
ComputeBorderPaddingFor(frame,
|
||||
(nsHTMLReflowState*)parentReflowState,
|
||||
mBorderPadding);
|
||||
|
||||
// Set mNoWrap flag
|
||||
switch (mStyleText->mWhiteSpace) {
|
||||
@ -359,3 +569,27 @@ nsFrameReflowState::nsFrameReflowState(nsIPresContext& aPresContext,
|
||||
nsFrameReflowState::~nsFrameReflowState()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameReflowState::SetupChildReflowState(nsHTMLReflowState& aChildRS)
|
||||
{
|
||||
// Get reflow reason set correctly. It's possible that a child was
|
||||
// created and then it was decided that it could not be reflowed
|
||||
// (for example, a block frame that isn't at the start of a
|
||||
// line). In this case the reason will be wrong so we need to check
|
||||
// the frame state.
|
||||
nsReflowReason reason = eReflowReason_Resize;
|
||||
nsIFrame* frame = aChildRS.frame;
|
||||
nsFrameState state;
|
||||
frame->GetFrameState(state);
|
||||
if (NS_FRAME_FIRST_REFLOW & state) {
|
||||
reason = eReflowReason_Initial;
|
||||
}
|
||||
else if (mNextRCFrame == frame) {
|
||||
reason = eReflowReason_Incremental;
|
||||
// Make sure we only incrementally reflow once
|
||||
mNextRCFrame = nsnull;/* XXX bad coupling */
|
||||
}
|
||||
aChildRS.reason = reason;
|
||||
}
|
||||
|
||||
|
||||
@ -35,6 +35,8 @@ public:
|
||||
const nsHTMLReflowMetrics& aMetrics);
|
||||
~nsFrameReflowState();
|
||||
|
||||
void SetupChildReflowState(nsHTMLReflowState& aChildReflowState);
|
||||
|
||||
nsIPresContext& mPresContext;
|
||||
nsIFrame* mNextRCFrame;
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#include "nsIFrameReflow.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsStyleCoord.h"
|
||||
#include "nsRect.h"
|
||||
class nsISpaceManager;
|
||||
class nsBlockFrame;
|
||||
@ -225,7 +226,62 @@ struct nsHTMLReflowState : nsReflowState {
|
||||
|
||||
nscoord GetContainingBlockContentWidth() const;
|
||||
|
||||
const nsHTMLReflowState* GetContainingBlockReflowState() const;
|
||||
/**
|
||||
* Get the containing block reflow state, starting from a frames
|
||||
* <B>parent</B> reflow state (the parent reflow state may or may not end
|
||||
* up being the containing block reflow state)
|
||||
*/
|
||||
static const nsHTMLReflowState*
|
||||
GetContainingBlockReflowState(const nsReflowState* aParentRS);
|
||||
|
||||
/**
|
||||
* Get the page box reflow state, starting from a frames
|
||||
* <B>parent</B> reflow state (the parent reflow state may or may not end
|
||||
* up being the containing block reflow state)
|
||||
*/
|
||||
static const nsHTMLReflowState*
|
||||
GetPageBoxReflowState(const nsReflowState* aParentRS);
|
||||
|
||||
/**
|
||||
* Compute the margin for <TT>aFrame</TT>. If a percentage needs to
|
||||
* be computed it will be computed by finding the containing block,
|
||||
* use GetContainingBlockReflowState. aParentReflowState is aFrame's
|
||||
* parent's reflow state. The resulting computed margin is returned
|
||||
* in aResult.
|
||||
*/
|
||||
static void ComputeMarginFor(nsIFrame* aFrame,
|
||||
const nsReflowState* aParentReflowState,
|
||||
nsMargin& aResult);
|
||||
|
||||
/**
|
||||
* Compute the padding for <TT>aFrame</TT>. If a percentage needs to
|
||||
* be computed it will be computed by finding the containing block,
|
||||
* use GetContainingBlockReflowState. aParentReflowState is aFrame's
|
||||
* parent's reflow state. The resulting computed padding is returned
|
||||
* in aResult.
|
||||
*/
|
||||
static void ComputePaddingFor(nsIFrame* aFrame,
|
||||
const nsReflowState* aParentReflowState,
|
||||
nsMargin& aResult);
|
||||
|
||||
/**
|
||||
* Compute the border for <TT>aFrame</TT>.The resulting computed
|
||||
* padding is returned in aResult.
|
||||
*/
|
||||
static void ComputeBorderFor(nsIFrame* aFrame,
|
||||
nsMargin& aResult);
|
||||
|
||||
/**
|
||||
* Compute the border plus padding for <TT>aFrame</TT>. If a
|
||||
* percentage needs to be computed it will be computed by finding
|
||||
* the containing block, use GetContainingBlockReflowState.
|
||||
* aParentReflowState is aFrame's
|
||||
* parent's reflow state. The resulting computed border plus padding
|
||||
* is returned in aResult.
|
||||
*/
|
||||
static void ComputeBorderPaddingFor(nsIFrame* aFrame,
|
||||
const nsReflowState* aParentRS,
|
||||
nsMargin& aResult);
|
||||
|
||||
protected:
|
||||
// This method initializes the widthConstraint, heightConstraint and
|
||||
@ -242,6 +298,14 @@ protected:
|
||||
void DetermineFrameType(nsIPresContext& aPresContext);
|
||||
|
||||
void InitConstraints(nsIPresContext& aPresContext);
|
||||
|
||||
static void ComputeHorizontalValue(const nsHTMLReflowState& aReflowState,
|
||||
nsStyleUnit aUnit, nsStyleCoord& aCoord,
|
||||
nscoord& aResult);
|
||||
|
||||
static void ComputeVerticalValue(const nsHTMLReflowState& aReflowState,
|
||||
nsStyleUnit aUnit, nsStyleCoord& aCoord,
|
||||
nscoord& aResult);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user