зеркало из https://github.com/mozilla/gecko-dev.git
New and improved vertical alignment code
This commit is contained in:
Родитель
9a915024a8
Коммит
2719cddbf8
|
@ -23,7 +23,6 @@
|
||||||
#include "nsISpaceManager.h"
|
#include "nsISpaceManager.h"
|
||||||
#include "nsIStyleContext.h"
|
#include "nsIStyleContext.h"
|
||||||
|
|
||||||
#include "nsCSSLayout.h"
|
|
||||||
#include "nsFrameReflowState.h"
|
#include "nsFrameReflowState.h"
|
||||||
#include "nsHTMLContainerFrame.h"
|
#include "nsHTMLContainerFrame.h"
|
||||||
#include "nsHTMLIIDs.h"
|
#include "nsHTMLIIDs.h"
|
||||||
|
@ -33,11 +32,11 @@
|
||||||
// frames falling outside the parent frame and wrap them in a view
|
// frames falling outside the parent frame and wrap them in a view
|
||||||
// when it happens.
|
// when it happens.
|
||||||
|
|
||||||
// XXX move the nsCSSLayout alignment code here? Will body frame be
|
|
||||||
// using it?
|
|
||||||
|
|
||||||
// XXX handle DIR=right-to-left
|
// XXX handle DIR=right-to-left
|
||||||
|
|
||||||
|
// XXX remove support for block reflow from this and move it into its
|
||||||
|
// own class (nsBlockReflow?)
|
||||||
|
|
||||||
nsInlineReflow::nsInlineReflow(nsLineLayout& aLineLayout,
|
nsInlineReflow::nsInlineReflow(nsLineLayout& aLineLayout,
|
||||||
nsFrameReflowState& aOuterReflowState,
|
nsFrameReflowState& aOuterReflowState,
|
||||||
nsHTMLContainerFrame* aOuterFrame,
|
nsHTMLContainerFrame* aOuterFrame,
|
||||||
|
@ -51,12 +50,15 @@ nsInlineReflow::nsInlineReflow(nsLineLayout& aLineLayout,
|
||||||
mSpaceManager = aLineLayout.mSpaceManager;
|
mSpaceManager = aLineLayout.mSpaceManager;
|
||||||
NS_ASSERTION(nsnull != mSpaceManager, "caller must have space manager");
|
NS_ASSERTION(nsnull != mSpaceManager, "caller must have space manager");
|
||||||
mOuterFrame = aOuterFrame;
|
mOuterFrame = aOuterFrame;
|
||||||
mFrameData = mFrameDataBuf;
|
mFrameDataBase = mFrameDataBuf;
|
||||||
mNumFrameData = sizeof(mFrameDataBuf) / sizeof(mFrameDataBuf[0]);
|
mNumFrameData = sizeof(mFrameDataBuf) / sizeof(mFrameDataBuf[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsInlineReflow::~nsInlineReflow()
|
nsInlineReflow::~nsInlineReflow()
|
||||||
{
|
{
|
||||||
|
if (mFrameDataBase != mFrameDataBuf) {
|
||||||
|
delete [] mFrameDataBase;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -71,7 +73,6 @@ nsInlineReflow::Init(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
|
||||||
mRightEdge = aX + aWidth;
|
mRightEdge = aX + aWidth;
|
||||||
}
|
}
|
||||||
mTopEdge = aY;
|
mTopEdge = aY;
|
||||||
mY = aY;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE == aHeight) {
|
if (NS_UNCONSTRAINEDSIZE == aHeight) {
|
||||||
mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +84,7 @@ nsInlineReflow::Init(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight)
|
||||||
|
|
||||||
mIsBlock = PR_FALSE;
|
mIsBlock = PR_FALSE;
|
||||||
mIsFirstChild = PR_FALSE;
|
mIsFirstChild = PR_FALSE;
|
||||||
mFirstFrame = nsnull;
|
mFrameData = nsnull;
|
||||||
mFrameNum = 0;
|
mFrameNum = 0;
|
||||||
mMaxElementSize.width = 0;
|
mMaxElementSize.width = 0;
|
||||||
mMaxElementSize.height = 0;
|
mMaxElementSize.height = 0;
|
||||||
|
@ -107,7 +108,6 @@ nsInlineReflow::UpdateBand(nscoord aX, nscoord aY,
|
||||||
mRightEdge = aX + aWidth;
|
mRightEdge = aX + aWidth;
|
||||||
}
|
}
|
||||||
mTopEdge = aY;
|
mTopEdge = aY;
|
||||||
mY = aY;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE == aHeight) {
|
if (NS_UNCONSTRAINEDSIZE == aHeight) {
|
||||||
mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,8 @@ nsInlineReflow::UpdateFrames()
|
||||||
{
|
{
|
||||||
if (NS_STYLE_DIRECTION_LTR == mOuterReflowState.mDirection) {
|
if (NS_STYLE_DIRECTION_LTR == mOuterReflowState.mDirection) {
|
||||||
if (mPlacedLeftFloater) {
|
if (mPlacedLeftFloater) {
|
||||||
nsIFrame* frame = mFirstFrame;
|
// XXX revise loop
|
||||||
|
nsIFrame* frame = mFrameDataBase->mFrame;
|
||||||
PRInt32 n = mFrameNum;
|
PRInt32 n = mFrameNum;
|
||||||
while (--n >= 0) {
|
while (--n >= 0) {
|
||||||
nsRect r;
|
nsRect r;
|
||||||
|
@ -145,8 +146,8 @@ nsInlineReflow::GetDisplay()
|
||||||
if (nsnull != mDisplay) {
|
if (nsnull != mDisplay) {
|
||||||
return mDisplay;
|
return mDisplay;
|
||||||
}
|
}
|
||||||
mFrame->GetStyleData(eStyleStruct_Display,
|
mFrameData->mFrame->GetStyleData(eStyleStruct_Display,
|
||||||
(const nsStyleStruct*&)mDisplay);
|
(const nsStyleStruct*&)mDisplay);
|
||||||
return mDisplay;
|
return mDisplay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,8 +157,8 @@ nsInlineReflow::GetPosition()
|
||||||
if (nsnull != mPosition) {
|
if (nsnull != mPosition) {
|
||||||
return mPosition;
|
return mPosition;
|
||||||
}
|
}
|
||||||
mFrame->GetStyleData(eStyleStruct_Position,
|
mFrameData->mFrame->GetStyleData(eStyleStruct_Position,
|
||||||
(const nsStyleStruct*&)mPosition);
|
(const nsStyleStruct*&)mPosition);
|
||||||
return mPosition;
|
return mPosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,11 +168,12 @@ nsInlineReflow::GetSpacing()
|
||||||
if (nsnull != mSpacing) {
|
if (nsnull != mSpacing) {
|
||||||
return mSpacing;
|
return mSpacing;
|
||||||
}
|
}
|
||||||
mFrame->GetStyleData(eStyleStruct_Spacing,
|
mFrameData->mFrame->GetStyleData(eStyleStruct_Spacing,
|
||||||
(const nsStyleStruct*&)mSpacing);
|
(const nsStyleStruct*&)mSpacing);
|
||||||
return mSpacing;
|
return mSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX use frameType instead after constructing a reflow state
|
||||||
PRBool
|
PRBool
|
||||||
nsInlineReflow::TreatFrameAsBlockFrame()
|
nsInlineReflow::TreatFrameAsBlockFrame()
|
||||||
{
|
{
|
||||||
|
@ -197,23 +199,37 @@ nsInlineReflow::TreatFrameAsBlockFrame()
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
nsresult
|
||||||
nsInlineReflow::SetFrame(nsIFrame* aFrame)
|
nsInlineReflow::SetFrame(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
if (nsnull == mFirstFrame) {
|
// Make sure we have a PerFrameData for this frame
|
||||||
mFirstFrame = aFrame;
|
PRInt32 frameNum = mFrameNum;
|
||||||
|
if (frameNum == mNumFrameData) {
|
||||||
|
mNumFrameData *= 2;
|
||||||
|
PerFrameData* newData = new PerFrameData[mNumFrameData];
|
||||||
|
if (nsnull == newData) {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
nsCRT::memcpy(newData, mFrameDataBase, sizeof(PerFrameData) * frameNum);
|
||||||
|
if (mFrameDataBase != mFrameDataBuf) {
|
||||||
|
delete [] mFrameDataBase;
|
||||||
|
}
|
||||||
|
mFrameDataBase = newData;
|
||||||
}
|
}
|
||||||
|
mFrameData = mFrameDataBase + mFrameNum;
|
||||||
|
|
||||||
// We can break before the frame if we placed at least one frame on
|
// We can break before the frame if we placed at least one frame on
|
||||||
// the line.
|
// the line.
|
||||||
mCanBreakBeforeFrame = mLineLayout.GetPlacedFrames() > 0;
|
mCanBreakBeforeFrame = mLineLayout.GetPlacedFrames() > 0;
|
||||||
|
|
||||||
mFrame = aFrame;
|
mFrameData->mFrame = aFrame;
|
||||||
mDisplay = nsnull;
|
mDisplay = nsnull;
|
||||||
mSpacing = nsnull;
|
mSpacing = nsnull;
|
||||||
mPosition = nsnull;
|
mPosition = nsnull;
|
||||||
mTreatFrameAsBlock = TreatFrameAsBlockFrame();
|
mTreatFrameAsBlock = TreatFrameAsBlockFrame();
|
||||||
mIsInlineAware = PR_FALSE;
|
mIsInlineAware = PR_FALSE;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsReflowStatus
|
nsReflowStatus
|
||||||
|
@ -226,7 +242,10 @@ nsInlineReflow::ReflowFrame(nsIFrame* aFrame)
|
||||||
: nsnull);
|
: nsnull);
|
||||||
|
|
||||||
// Prepare for reflowing the frame
|
// Prepare for reflowing the frame
|
||||||
SetFrame(aFrame);
|
nsresult rv = SetFrame(aFrame);
|
||||||
|
if (NS_OK != rv) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
// Do a quick check and see if we are trying to place a block on a
|
// Do a quick check and see if we are trying to place a block on a
|
||||||
// line that already has a placed frame on it.
|
// line that already has a placed frame on it.
|
||||||
|
@ -265,18 +284,20 @@ nsInlineReflow::ReflowFrame(nsIFrame* aFrame)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX looks more like a method on PerFrameData?
|
||||||
void
|
void
|
||||||
nsInlineReflow::CalculateMargins()
|
nsInlineReflow::CalculateMargins()
|
||||||
{
|
{
|
||||||
|
PerFrameData* pfd = mFrameData;
|
||||||
const nsStyleSpacing* spacing = GetSpacing();
|
const nsStyleSpacing* spacing = GetSpacing();
|
||||||
if (mTreatFrameAsBlock) {
|
if (mTreatFrameAsBlock) {
|
||||||
mMarginFlags = CalculateBlockMarginsFor(mPresContext, mFrame, spacing,
|
pfd->mMarginFlags = CalculateBlockMarginsFor(mPresContext, pfd->mFrame,
|
||||||
mMargin);
|
spacing, pfd->mMargin);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Get the margins from the style system
|
// Get the margins from the style system
|
||||||
spacing->CalcMarginFor(mFrame, mMargin);
|
spacing->CalcMarginFor(pfd->mFrame, pfd->mMargin);
|
||||||
mMarginFlags = 0;
|
pfd->mMarginFlags = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +344,7 @@ void
|
||||||
nsInlineReflow::ApplyTopLeftMargins()
|
nsInlineReflow::ApplyTopLeftMargins()
|
||||||
{
|
{
|
||||||
mFrameX = mX;
|
mFrameX = mX;
|
||||||
mFrameY = mY;
|
mFrameY = mTopEdge;
|
||||||
|
|
||||||
// Compute left margin
|
// Compute left margin
|
||||||
nscoord leftMargin = 0;
|
nscoord leftMargin = 0;
|
||||||
|
@ -340,7 +361,7 @@ nsInlineReflow::ApplyTopLeftMargins()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NS_STYLE_FLOAT_NONE:
|
case NS_STYLE_FLOAT_NONE:
|
||||||
leftMargin = mMargin.left;
|
leftMargin = mFrameData->mMargin.left;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mFrameX += leftMargin;
|
mFrameX += leftMargin;
|
||||||
|
@ -349,18 +370,20 @@ nsInlineReflow::ApplyTopLeftMargins()
|
||||||
PRBool
|
PRBool
|
||||||
nsInlineReflow::ComputeAvailableSize()
|
nsInlineReflow::ComputeAvailableSize()
|
||||||
{
|
{
|
||||||
|
PerFrameData* pfd = mFrameData;
|
||||||
|
|
||||||
// Compute the available size from the outer's perspective
|
// Compute the available size from the outer's perspective
|
||||||
if (NS_UNCONSTRAINEDSIZE == mRightEdge) {
|
if (NS_UNCONSTRAINEDSIZE == mRightEdge) {
|
||||||
mFrameAvailSize.width = NS_UNCONSTRAINEDSIZE;
|
mFrameAvailSize.width = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mFrameAvailSize.width = mRightEdge - mFrameX - mMargin.right;
|
mFrameAvailSize.width = mRightEdge - mFrameX - pfd->mMargin.right;
|
||||||
}
|
}
|
||||||
if (NS_UNCONSTRAINEDSIZE == mBottomEdge) {
|
if (NS_UNCONSTRAINEDSIZE == mBottomEdge) {
|
||||||
mFrameAvailSize.height = NS_UNCONSTRAINEDSIZE;
|
mFrameAvailSize.height = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mFrameAvailSize.height = mBottomEdge - mFrameY - mMargin.bottom;
|
mFrameAvailSize.height = mBottomEdge - mFrameY - pfd->mMargin.bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Give up now if there is no chance. Note that we allow a reflow if
|
// Give up now if there is no chance. Note that we allow a reflow if
|
||||||
|
@ -389,19 +412,20 @@ nsInlineReflow::ReflowFrame(nsHTMLReflowMetrics& aMetrics,
|
||||||
// line). In this case the reason will be wrong so we need to check
|
// line). In this case the reason will be wrong so we need to check
|
||||||
// the frame state.
|
// the frame state.
|
||||||
nsReflowReason reason = eReflowReason_Resize;
|
nsReflowReason reason = eReflowReason_Resize;
|
||||||
|
nsIFrame* frame = mFrameData->mFrame;
|
||||||
nsFrameState state;
|
nsFrameState state;
|
||||||
mFrame->GetFrameState(state);
|
frame->GetFrameState(state);
|
||||||
if (NS_FRAME_FIRST_REFLOW & state) {
|
if (NS_FRAME_FIRST_REFLOW & state) {
|
||||||
reason = eReflowReason_Initial;
|
reason = eReflowReason_Initial;
|
||||||
}
|
}
|
||||||
else if (mOuterReflowState.mNextRCFrame == mFrame) {
|
else if (mOuterReflowState.mNextRCFrame == frame) {
|
||||||
reason = eReflowReason_Incremental;
|
reason = eReflowReason_Incremental;
|
||||||
// Make sure we only incrementally reflow once
|
// Make sure we only incrementally reflow once
|
||||||
mOuterReflowState.mNextRCFrame = nsnull;
|
mOuterReflowState.mNextRCFrame = nsnull;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup reflow state for reflowing the frame
|
// Setup reflow state for reflowing the frame
|
||||||
nsHTMLReflowState reflowState(mPresContext, mFrame, mOuterReflowState,
|
nsHTMLReflowState reflowState(mPresContext, frame, mOuterReflowState,
|
||||||
mFrameAvailSize);
|
mFrameAvailSize);
|
||||||
if (!mTreatFrameAsBlock) {
|
if (!mTreatFrameAsBlock) {
|
||||||
mIsInlineAware = PR_TRUE;
|
mIsInlineAware = PR_TRUE;
|
||||||
|
@ -415,7 +439,7 @@ nsInlineReflow::ReflowFrame(nsHTMLReflowMetrics& aMetrics,
|
||||||
nscoord y = mFrameY;
|
nscoord y = mFrameY;
|
||||||
nsIHTMLReflow* htmlReflow;
|
nsIHTMLReflow* htmlReflow;
|
||||||
|
|
||||||
mFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow);
|
frame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow);
|
||||||
htmlReflow->WillReflow(mPresContext);
|
htmlReflow->WillReflow(mPresContext);
|
||||||
|
|
||||||
aBounds.x = x;
|
aBounds.x = x;
|
||||||
|
@ -442,8 +466,8 @@ nsInlineReflow::ReflowFrame(nsHTMLReflowMetrics& aMetrics,
|
||||||
// the NS_FRAME_FIRST_REFLOW bit is cleared so that never give it an
|
// the NS_FRAME_FIRST_REFLOW bit is cleared so that never give it an
|
||||||
// initial reflow reason again.
|
// initial reflow reason again.
|
||||||
if (eReflowReason_Initial == reason) {
|
if (eReflowReason_Initial == reason) {
|
||||||
mFrame->GetFrameState(state);
|
frame->GetFrameState(state);
|
||||||
mFrame->SetFrameState(state & ~NS_FRAME_FIRST_REFLOW);
|
frame->SetFrameState(state & ~NS_FRAME_FIRST_REFLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NS_INLINE_IS_BREAK_BEFORE(aStatus)) {
|
if (!NS_INLINE_IS_BREAK_BEFORE(aStatus)) {
|
||||||
|
@ -453,21 +477,21 @@ nsInlineReflow::ReflowFrame(nsHTMLReflowMetrics& aMetrics,
|
||||||
// a next-in-flow where it ends up).
|
// a next-in-flow where it ends up).
|
||||||
if (NS_FRAME_IS_COMPLETE(aStatus)) {
|
if (NS_FRAME_IS_COMPLETE(aStatus)) {
|
||||||
nsIFrame* kidNextInFlow;
|
nsIFrame* kidNextInFlow;
|
||||||
mFrame->GetNextInFlow(kidNextInFlow);
|
frame->GetNextInFlow(kidNextInFlow);
|
||||||
if (nsnull != kidNextInFlow) {
|
if (nsnull != kidNextInFlow) {
|
||||||
// Remove all of the childs next-in-flows. Make sure that we ask
|
// Remove all of the childs next-in-flows. Make sure that we ask
|
||||||
// the right parent to do the removal (it's possible that the
|
// the right parent to do the removal (it's possible that the
|
||||||
// parent is not this because we are executing pullup code)
|
// parent is not this because we are executing pullup code)
|
||||||
nsHTMLContainerFrame* parent;
|
nsHTMLContainerFrame* parent;
|
||||||
mFrame->GetGeometricParent((nsIFrame*&) parent);
|
frame->GetGeometricParent((nsIFrame*&) parent);
|
||||||
parent->DeleteChildsNextInFlow(mPresContext, mFrame);
|
parent->DeleteChildsNextInFlow(mPresContext, frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
|
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
|
||||||
("nsInlineReflow::ReflowFrame: frame=%p reflowStatus=%x %saware",
|
("nsInlineReflow::ReflowFrame: frame=%p reflowStatus=%x %saware",
|
||||||
mFrame, aStatus, mIsInlineAware ? "" :"not "));
|
frame, aStatus, mIsInlineAware ? "" :"not "));
|
||||||
|
|
||||||
return !NS_INLINE_IS_BREAK_BEFORE(aStatus);
|
return !NS_INLINE_IS_BREAK_BEFORE(aStatus);
|
||||||
}
|
}
|
||||||
|
@ -487,6 +511,8 @@ nsInlineReflow::CanPlaceFrame(nsHTMLReflowMetrics& aMetrics,
|
||||||
nsRect& aBounds,
|
nsRect& aBounds,
|
||||||
nsReflowStatus& aStatus)
|
nsReflowStatus& aStatus)
|
||||||
{
|
{
|
||||||
|
PerFrameData* pfd = mFrameData;
|
||||||
|
|
||||||
// Compute right margin to use
|
// Compute right margin to use
|
||||||
mRightMargin = 0;
|
mRightMargin = 0;
|
||||||
if (0 != aBounds.width) {
|
if (0 != aBounds.width) {
|
||||||
|
@ -503,7 +529,7 @@ nsInlineReflow::CanPlaceFrame(nsHTMLReflowMetrics& aMetrics,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NS_STYLE_FLOAT_NONE:
|
case NS_STYLE_FLOAT_NONE:
|
||||||
mRightMargin = mMargin.right;
|
mRightMargin = pfd->mMargin.right;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -553,6 +579,8 @@ nsInlineReflow::CanPlaceFrame(nsHTMLReflowMetrics& aMetrics,
|
||||||
void
|
void
|
||||||
nsInlineReflow::PlaceFrame(nsHTMLReflowMetrics& aMetrics, nsRect& aBounds)
|
nsInlineReflow::PlaceFrame(nsHTMLReflowMetrics& aMetrics, nsRect& aBounds)
|
||||||
{
|
{
|
||||||
|
PerFrameData* pfd = mFrameData;
|
||||||
|
|
||||||
// Remember this for later...
|
// Remember this for later...
|
||||||
if (mTreatFrameAsBlock) {
|
if (mTreatFrameAsBlock) {
|
||||||
mIsBlock = PR_TRUE;
|
mIsBlock = PR_TRUE;
|
||||||
|
@ -565,10 +593,11 @@ nsInlineReflow::PlaceFrame(nsHTMLReflowMetrics& aMetrics, nsRect& aBounds)
|
||||||
aBounds.y = 0;
|
aBounds.y = 0;
|
||||||
emptyFrame = PR_TRUE;
|
emptyFrame = PR_TRUE;
|
||||||
}
|
}
|
||||||
mFrame->SetRect(aBounds);
|
pfd->mBounds = aBounds;
|
||||||
|
|
||||||
// Record ascent and update max-ascent and max-descent values
|
// Record ascent and update max-ascent and max-descent values
|
||||||
SetFrameData(aMetrics);
|
pfd->mAscent = aMetrics.ascent;
|
||||||
|
pfd->mDescent = aMetrics.descent;
|
||||||
mFrameNum++;
|
mFrameNum++;
|
||||||
|
|
||||||
// If the band was updated during the reflow of that frame then we
|
// If the band was updated during the reflow of that frame then we
|
||||||
|
@ -598,7 +627,7 @@ nsInlineReflow::PlaceFrame(nsHTMLReflowMetrics& aMetrics, nsRect& aBounds)
|
||||||
if (!emptyFrame) {
|
if (!emptyFrame) {
|
||||||
// Inform line layout that we have placed a non-empty frame
|
// Inform line layout that we have placed a non-empty frame
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
mLineLayout.AddPlacedFrame(mFrame);
|
mLineLayout.AddPlacedFrame(mFrameData->mFrame);
|
||||||
#else
|
#else
|
||||||
mLineLayout.AddPlacedFrame();
|
mLineLayout.AddPlacedFrame();
|
||||||
#endif
|
#endif
|
||||||
|
@ -617,266 +646,263 @@ nsInlineReflow::PlaceFrame(nsHTMLReflowMetrics& aMetrics, nsRect& aBounds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Store away the ascent value associated with the current frame
|
|
||||||
*/
|
|
||||||
nsresult
|
|
||||||
nsInlineReflow::SetFrameData(const nsHTMLReflowMetrics& aMetrics)
|
|
||||||
{
|
|
||||||
PRInt32 frameNum = mFrameNum;
|
|
||||||
if (frameNum == mNumFrameData) {
|
|
||||||
mNumFrameData *= 2;
|
|
||||||
PerFrameData* newData = new PerFrameData[mNumFrameData];
|
|
||||||
if (nsnull == newData) {
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
}
|
|
||||||
nsCRT::memcpy(newData, mFrameData, sizeof(PerFrameData) * frameNum);
|
|
||||||
if (mFrameData != mFrameDataBuf) {
|
|
||||||
delete [] mFrameData;
|
|
||||||
}
|
|
||||||
mFrameData = newData;
|
|
||||||
}
|
|
||||||
PerFrameData* pfd = &mFrameData[frameNum];
|
|
||||||
pfd->mAscent = aMetrics.ascent;
|
|
||||||
pfd->mDescent = aMetrics.descent;
|
|
||||||
pfd->mMargin = mMargin;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX what about ebina's center vs. ncsa-center?
|
// XXX what about ebina's center vs. ncsa-center?
|
||||||
|
|
||||||
void
|
void
|
||||||
nsInlineReflow::VerticalAlignFrames(nsRect& aLineBox,
|
nsInlineReflow::VerticalAlignFrames(nsRect& aLineBox,
|
||||||
nscoord& aMaxAscent,
|
nscoord& aMaxAscent,
|
||||||
nscoord& aMaxDescent)
|
nscoord& aMaxDescent)
|
||||||
{
|
{
|
||||||
nscoord x = mLeftEdge;
|
PerFrameData* pfd0 = mFrameDataBase;
|
||||||
nscoord y0 = mTopEdge;
|
PerFrameData* end = pfd0 + mFrameNum;
|
||||||
nscoord width = mX - mLeftEdge;
|
|
||||||
|
|
||||||
GetScents(aMaxAscent, aMaxDescent);
|
// Short circuit 99% of this when this code has reflowed a single
|
||||||
nscoord height = aMaxAscent + aMaxDescent;
|
// block frame.
|
||||||
|
aLineBox.x = mLeftEdge;
|
||||||
if (mFrameNum > 1) {
|
aLineBox.y = mTopEdge;
|
||||||
// Only when we have more than one frame should we do vertical
|
aLineBox.width = mX - mLeftEdge;
|
||||||
// alignment. Sometimes we will have 2 frames with the second one
|
if (mTreatFrameAsBlock) {
|
||||||
// being a block; we don't vertically align then either. This
|
aLineBox.height = pfd0->mBounds.height;
|
||||||
// happens when the first frame is nothing but compressed
|
aMaxAscent = pfd0->mAscent;
|
||||||
// whitespace.
|
aMaxDescent = pfd0->mDescent;
|
||||||
const nsStyleFont* font;
|
pfd0->mFrame->SetRect(aLineBox);
|
||||||
mOuterFrame->GetStyleData(eStyleStruct_Font,
|
return;
|
||||||
(const nsStyleStruct*&)font);
|
|
||||||
|
|
||||||
// Determine minimum and maximum y values for the line and
|
|
||||||
// perform alignment of all children except those requesting bottom
|
|
||||||
// alignment. The second pass will align bottom children (if any)
|
|
||||||
nsIFontMetrics* fm = mPresContext.GetMetricsFor(font->mFont);
|
|
||||||
nsIFrame* kid = mFirstFrame;
|
|
||||||
nsRect kidRect;
|
|
||||||
nscoord minY = y0;
|
|
||||||
nscoord maxY = y0;
|
|
||||||
PRIntn pass2Kids = 0;
|
|
||||||
PRIntn kidCount = mFrameNum;
|
|
||||||
PerFrameData* pfd = mFrameData;
|
|
||||||
for (; --kidCount >= 0; pfd++) {
|
|
||||||
nscoord kidAscent = pfd->mAscent;
|
|
||||||
|
|
||||||
const nsStyleText* textStyle;
|
|
||||||
kid->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
|
|
||||||
nsStyleUnit verticalAlignUnit = textStyle->mVerticalAlign.GetUnit();
|
|
||||||
PRUint8 verticalAlignEnum = NS_STYLE_VERTICAL_ALIGN_BASELINE;
|
|
||||||
|
|
||||||
kid->GetRect(kidRect);
|
|
||||||
|
|
||||||
// Vertically align the child
|
|
||||||
nscoord kidYTop = 0;
|
|
||||||
|
|
||||||
PRBool isPass2Kid = PR_FALSE;
|
|
||||||
nscoord fontParam;
|
|
||||||
switch (verticalAlignUnit) {
|
|
||||||
case eStyleUnit_Coord:
|
|
||||||
// According to the spec, a positive value "raises" the box by
|
|
||||||
// the given distance while a negative value "lowers" the box
|
|
||||||
// by the given distance. Since Y coordinates increase towards
|
|
||||||
// the bottom of the screen we reverse the sign. All of the
|
|
||||||
// raising and lowering is done relative to the baseline, so
|
|
||||||
// we start our adjustments there.
|
|
||||||
kidYTop = aMaxAscent - kidAscent; // get baseline first
|
|
||||||
kidYTop -= textStyle->mVerticalAlign.GetCoordValue();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStyleUnit_Percent:
|
|
||||||
pass2Kids++;
|
|
||||||
isPass2Kid = PR_TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eStyleUnit_Enumerated:
|
|
||||||
verticalAlignEnum = textStyle->mVerticalAlign.GetIntValue();
|
|
||||||
switch (verticalAlignEnum) {
|
|
||||||
default:
|
|
||||||
case NS_STYLE_VERTICAL_ALIGN_BASELINE:
|
|
||||||
// Align the kid's baseline at the max baseline
|
|
||||||
kidYTop = aMaxAscent - kidAscent;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NS_STYLE_VERTICAL_ALIGN_TOP:
|
|
||||||
// Align the top of the kid with the top of the line box
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NS_STYLE_VERTICAL_ALIGN_SUB:
|
|
||||||
// Align the child's baseline on the superscript baseline
|
|
||||||
fm->GetSubscriptOffset(fontParam);
|
|
||||||
kidYTop = aMaxAscent + fontParam - kidAscent;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NS_STYLE_VERTICAL_ALIGN_SUPER:
|
|
||||||
// Align the child's baseline on the subscript baseline
|
|
||||||
fm->GetSuperscriptOffset(fontParam);
|
|
||||||
kidYTop = aMaxAscent - fontParam - kidAscent;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
|
|
||||||
pass2Kids++;
|
|
||||||
isPass2Kid = PR_TRUE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
|
|
||||||
// Align the midpoint of the box with 1/2 the parent's x-height
|
|
||||||
fm->GetXHeight(fontParam);
|
|
||||||
kidYTop = aMaxAscent - (fontParam / 2) - (kidRect.height/2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
|
|
||||||
fm->GetMaxDescent(fontParam);
|
|
||||||
kidYTop = aMaxAscent + fontParam - kidRect.height;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
|
|
||||||
fm->GetMaxAscent(fontParam);
|
|
||||||
kidYTop = aMaxAscent - fontParam;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Align the kid's baseline at the max baseline
|
|
||||||
kidYTop = aMaxAscent - kidAscent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX or grow the box - which is it? */
|
|
||||||
if (kidYTop < 0) {
|
|
||||||
kidYTop = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Place kid and update min and max Y values
|
|
||||||
if (!isPass2Kid) {
|
|
||||||
nscoord y = y0 + kidYTop;
|
|
||||||
if (y < minY) minY = y;
|
|
||||||
kid->MoveTo(kidRect.x, y);
|
|
||||||
y += kidRect.height;
|
|
||||||
if (y > maxY) maxY = y;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nscoord y = y0 + kidRect.height;
|
|
||||||
if (y > maxY) maxY = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
kid->GetNextSibling(kid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now compute the final line-height
|
|
||||||
nscoord lineHeight = maxY - minY;
|
|
||||||
|
|
||||||
if (0 != pass2Kids) {
|
|
||||||
// Position all of the bottom aligned children
|
|
||||||
kidCount = mFrameNum;
|
|
||||||
kid = mFirstFrame;
|
|
||||||
pfd = mFrameData;
|
|
||||||
for (; --kidCount >= 0; pfd++) {
|
|
||||||
nscoord kidAscent = pfd->mAscent;
|
|
||||||
|
|
||||||
// Get kid's vertical align style data
|
|
||||||
const nsStyleText* textStyle;
|
|
||||||
kid->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
|
|
||||||
nsStyleUnit verticalAlignUnit = textStyle->mVerticalAlign.GetUnit();
|
|
||||||
|
|
||||||
if (eStyleUnit_Percent == verticalAlignUnit) {
|
|
||||||
// According to the spec, a positive value "raises" the box by
|
|
||||||
// the given distance while a negative value "lowers" the box
|
|
||||||
// by the given distance. Since Y coordinates increase towards
|
|
||||||
// the bottom of the screen we reverse the sign. All of the
|
|
||||||
// raising and lowering is done relative to the baseline, so
|
|
||||||
// we start our adjustments there.
|
|
||||||
nscoord kidYTop = aMaxAscent - kidAscent; // get baseline first
|
|
||||||
kidYTop -=
|
|
||||||
nscoord(textStyle->mVerticalAlign.GetPercentValue() * lineHeight);
|
|
||||||
kid->GetRect(kidRect);
|
|
||||||
kid->MoveTo(kidRect.x, y0 + kidYTop);
|
|
||||||
if (--pass2Kids == 0) {
|
|
||||||
// Stop on last pass2 kid
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (verticalAlignUnit == eStyleUnit_Enumerated) {
|
|
||||||
PRUint8 verticalAlignEnum = textStyle->mVerticalAlign.GetIntValue();
|
|
||||||
// Vertically align the child
|
|
||||||
if (NS_STYLE_VERTICAL_ALIGN_BOTTOM == verticalAlignEnum) {
|
|
||||||
// Place kid along the bottom
|
|
||||||
kid->GetRect(kidRect);
|
|
||||||
kid->MoveTo(kidRect.x, y0 + lineHeight - kidRect.height);
|
|
||||||
if (--pass2Kids == 0) {
|
|
||||||
// Stop on last pass2 kid
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kid->GetNextSibling(kid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_RELEASE(fm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
aLineBox.x = x;
|
// Get the parent elements font in case we need it
|
||||||
aLineBox.y = y0;
|
const nsStyleFont* font;
|
||||||
aLineBox.width = width;
|
mOuterFrame->GetStyleData(eStyleStruct_Font,
|
||||||
aLineBox.height = height;
|
(const nsStyleStruct*&)font);
|
||||||
|
nsIFontMetrics* fm = mPresContext.GetMetricsFor(font->mFont);
|
||||||
|
|
||||||
|
// Examine each and determine the minYTop, the maxYBottom and the
|
||||||
|
// maximum height. We will use these values to determine the final
|
||||||
|
// height of the line box and then position each frame.
|
||||||
|
nscoord minYTop = 0;
|
||||||
|
nscoord maxYBottom = 0;
|
||||||
|
nscoord maxHeight = 0;
|
||||||
|
PRBool haveTBFrames = PR_FALSE;
|
||||||
|
PerFrameData* pfd;
|
||||||
|
for (pfd = pfd0; pfd < end; pfd++) {
|
||||||
|
PRUint8 verticalAlignEnum;
|
||||||
|
nscoord fontParam;
|
||||||
|
|
||||||
|
nsIFrame* frame = pfd->mFrame;
|
||||||
|
|
||||||
|
// yTop = Y coordinate for the top of frame box <B>relative</B> to
|
||||||
|
// the baseline of the linebox which is assumed to be at Y=0
|
||||||
|
nscoord yTop;
|
||||||
|
|
||||||
|
// Compute the effective height of the box applying the top and
|
||||||
|
// bottom margins
|
||||||
|
nscoord height = pfd->mBounds.height + pfd->mMargin.top +
|
||||||
|
pfd->mMargin.bottom;
|
||||||
|
if (height > maxHeight) {
|
||||||
|
maxHeight = pfd->mBounds.height;
|
||||||
|
}
|
||||||
|
pfd->mAscent += pfd->mMargin.top;
|
||||||
|
|
||||||
|
const nsStyleText* textStyle;
|
||||||
|
frame->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
|
||||||
|
nsStyleUnit verticalAlignUnit = textStyle->mVerticalAlign.GetUnit();
|
||||||
|
|
||||||
|
switch (verticalAlignUnit) {
|
||||||
|
case eStyleUnit_Enumerated:
|
||||||
|
verticalAlignEnum = textStyle->mVerticalAlign.GetIntValue();
|
||||||
|
switch (verticalAlignEnum) {
|
||||||
|
default:
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_BASELINE:
|
||||||
|
yTop = -pfd->mAscent;
|
||||||
|
break;
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_SUB:
|
||||||
|
// Align the frames baseline on the subscript baseline
|
||||||
|
fm->GetSubscriptOffset(fontParam);
|
||||||
|
yTop = fontParam - pfd->mAscent;
|
||||||
|
break;
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_SUPER:
|
||||||
|
// Align the frames baseline on the superscript baseline
|
||||||
|
fm->GetSuperscriptOffset(fontParam);
|
||||||
|
yTop = -fontParam - pfd->mAscent;
|
||||||
|
break;
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_TOP:
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
|
||||||
|
// THESE ARE DONE DURING PASS2
|
||||||
|
haveTBFrames = PR_TRUE;
|
||||||
|
continue;
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
|
||||||
|
// Align the midpoint of the frame with 1/2 the parents x-height
|
||||||
|
fm->GetXHeight(fontParam);
|
||||||
|
yTop = -(fontParam / 2) - (pfd->mBounds.height/2);
|
||||||
|
break;
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_TEXT_BOTTOM:
|
||||||
|
fm->GetMaxDescent(fontParam);
|
||||||
|
yTop = fontParam - pfd->mBounds.height;
|
||||||
|
break;
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_TEXT_TOP:
|
||||||
|
fm->GetMaxAscent(fontParam);
|
||||||
|
yTop = -fontParam;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case eStyleUnit_Coord:
|
||||||
|
// According to the CSS2 spec (10.8.1), a positive value
|
||||||
|
// "raises" the box by the given distance while a negative value
|
||||||
|
// "lowers" the box by the given distance. Since Y coordinates
|
||||||
|
// increase towards the bottom of the screen we reverse the
|
||||||
|
// sign. All of the raising and lowering is done relative to the
|
||||||
|
// baseline, so we start our adjustments there.
|
||||||
|
yTop = -pfd->mAscent - textStyle->mVerticalAlign.GetCoordValue();
|
||||||
|
break;
|
||||||
|
case eStyleUnit_Percent:
|
||||||
|
// The percentage is relative to the line-height of the element
|
||||||
|
// itself. The line-height will be the final height of the
|
||||||
|
// inline element (CSS2 10.8.1 says that the line-height defines
|
||||||
|
// the precise height of inline non-replaced elements).
|
||||||
|
yTop = -pfd->mAscent -
|
||||||
|
nscoord(textStyle->mVerticalAlign.GetPercentValue() * pfd->mBounds.height);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
yTop = -pfd->mAscent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pfd->mBounds.y = yTop;
|
||||||
|
if (yTop < minYTop) {
|
||||||
|
minYTop = yTop;
|
||||||
|
}
|
||||||
|
// yBottom = Y coordinate for the bottom of the frame box, again
|
||||||
|
// relative to the baseline where Y=0
|
||||||
|
nscoord yBottom = yTop + height;
|
||||||
|
if (yBottom > maxYBottom) {
|
||||||
|
maxYBottom = yBottom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once we have finished the above abs(minYTop) represents the
|
||||||
|
// maximum ascent of the line box.
|
||||||
|
|
||||||
|
// XXX what about positive minY?
|
||||||
|
nscoord lineHeight = maxYBottom - minYTop;
|
||||||
|
if (lineHeight < maxHeight) {
|
||||||
|
// This ensures that any object aligned top/bottom will update the
|
||||||
|
// line height properly since they don't impact the minY or
|
||||||
|
// maxYBottom values.
|
||||||
|
lineHeight = maxHeight;
|
||||||
|
}
|
||||||
|
aLineBox.height = lineHeight;
|
||||||
|
nscoord maxAscent = -minYTop;
|
||||||
|
|
||||||
|
// Pass2 - position each of the frames
|
||||||
|
for (pfd = pfd0; pfd < end; pfd++) {
|
||||||
|
nsIFrame* frame = pfd->mFrame;
|
||||||
|
const nsStyleText* textStyle;
|
||||||
|
frame->GetStyleData(eStyleStruct_Text, (const nsStyleStruct*&)textStyle);
|
||||||
|
nsStyleUnit verticalAlignUnit = textStyle->mVerticalAlign.GetUnit();
|
||||||
|
if (eStyleUnit_Enumerated == verticalAlignUnit) {
|
||||||
|
PRUint8 verticalAlignEnum = textStyle->mVerticalAlign.GetIntValue();
|
||||||
|
switch (verticalAlignEnum) {
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_TOP:
|
||||||
|
// XXX negative top margins on these will do weird things, maybe?
|
||||||
|
pfd->mBounds.y = mTopEdge + pfd->mMargin.top;
|
||||||
|
break;
|
||||||
|
case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
|
||||||
|
pfd->mBounds.y = mTopEdge + lineHeight - pfd->mBounds.height;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pfd->mBounds.y = mTopEdge + maxAscent + pfd->mBounds.y -
|
||||||
|
pfd->mMargin.top;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pfd->mBounds.y = mTopEdge + maxAscent + pfd->mBounds.y -
|
||||||
|
pfd->mMargin.top;
|
||||||
|
}
|
||||||
|
frame->SetRect(pfd->mBounds);
|
||||||
|
}
|
||||||
|
aMaxAscent = maxAscent;
|
||||||
|
aMaxDescent = lineHeight - maxAscent;
|
||||||
|
|
||||||
|
// XXX Now we can apply 1/2 the line-height...
|
||||||
|
NS_RELEASE(fm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsInlineReflow::HorizontalAlignFrames(const nsRect& aLineBox)
|
nsInlineReflow::HorizontalAlignFrames(const nsRect& aLineBox)
|
||||||
{
|
{
|
||||||
const nsStyleText* styleText = mOuterReflowState.mStyleText;
|
const nsStyleText* styleText = mOuterReflowState.mStyleText;
|
||||||
nsCSSLayout::HorizontallyPlaceChildren(&mPresContext,
|
nscoord maxWidth = mRightEdge - mLeftEdge;
|
||||||
mOuterFrame,
|
if (aLineBox.width < maxWidth) {
|
||||||
styleText->mTextAlign,
|
nscoord dx = 0;
|
||||||
mOuterReflowState.mDirection,
|
switch (styleText->mTextAlign) {
|
||||||
mFirstFrame, mFrameNum,
|
case NS_STYLE_TEXT_ALIGN_DEFAULT:
|
||||||
aLineBox.width,
|
if (NS_STYLE_DIRECTION_LTR == mOuterReflowState.mDirection) {
|
||||||
mRightEdge - mLeftEdge);
|
// default alignment for left-to-right is left so do nothing
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Fall through to align right case for default alignment
|
||||||
|
// used when the direction is right-to-left.
|
||||||
|
|
||||||
|
case NS_STYLE_TEXT_ALIGN_RIGHT:
|
||||||
|
dx = maxWidth - aLineBox.width;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NS_STYLE_TEXT_ALIGN_LEFT:
|
||||||
|
case NS_STYLE_TEXT_ALIGN_JUSTIFY:
|
||||||
|
// Default layout has everything aligned left
|
||||||
|
return;
|
||||||
|
|
||||||
|
case NS_STYLE_TEXT_ALIGN_CENTER:
|
||||||
|
dx = (maxWidth - aLineBox.width) / 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position children
|
||||||
|
PerFrameData* pfd = mFrameDataBase;
|
||||||
|
PerFrameData* end = pfd + mFrameNum;
|
||||||
|
nsPoint origin;
|
||||||
|
for (; pfd < end; pfd++) {
|
||||||
|
nsIFrame* kid = pfd->mFrame;;
|
||||||
|
kid->GetOrigin(origin);
|
||||||
|
kid->MoveTo(origin.x + dx, origin.y);
|
||||||
|
kid->GetNextSibling(kid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsInlineReflow::RelativePositionFrames()
|
nsInlineReflow::RelativePositionFrames()
|
||||||
{
|
{
|
||||||
nsCSSLayout::RelativePositionChildren(&mPresContext,
|
nsPoint origin;
|
||||||
mOuterFrame,
|
PerFrameData* pfd = mFrameDataBase;
|
||||||
mFirstFrame, mFrameNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nsInlineReflow::GetScents(nscoord& aMaxAscent, nscoord& aMaxDescent)
|
|
||||||
{
|
|
||||||
PerFrameData* pfd = mFrameData;
|
|
||||||
PerFrameData* end = pfd + mFrameNum;
|
PerFrameData* end = pfd + mFrameNum;
|
||||||
nscoord maxAscent = 0;
|
for (; pfd < end; pfd++) {
|
||||||
nscoord maxDescent = 0;
|
nsIFrame* kid = pfd->mFrame;
|
||||||
while (pfd < end) {
|
const nsStylePosition* kidPosition;
|
||||||
if (pfd->mAscent > maxAscent) maxAscent = pfd->mAscent;
|
kid->GetStyleData(eStyleStruct_Position,
|
||||||
if (pfd->mDescent > maxDescent) maxDescent = pfd->mDescent;
|
(const nsStyleStruct*&)kidPosition);
|
||||||
pfd++;
|
if (NS_STYLE_POSITION_RELATIVE == kidPosition->mPosition) {
|
||||||
|
kid->GetOrigin(origin);
|
||||||
|
nscoord dx = 0;
|
||||||
|
switch (kidPosition->mLeftOffset.GetUnit()) {
|
||||||
|
case eStyleUnit_Percent:
|
||||||
|
printf("XXX: not yet implemented: % relative position\n");
|
||||||
|
case eStyleUnit_Auto:
|
||||||
|
break;
|
||||||
|
case eStyleUnit_Coord:
|
||||||
|
dx = kidPosition->mLeftOffset.GetCoordValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nscoord dy = 0;
|
||||||
|
switch (kidPosition->mTopOffset.GetUnit()) {
|
||||||
|
case eStyleUnit_Percent:
|
||||||
|
printf("XXX: not yet implemented: % relative position\n");
|
||||||
|
case eStyleUnit_Auto:
|
||||||
|
break;
|
||||||
|
case eStyleUnit_Coord:
|
||||||
|
dy = kidPosition->mTopOffset.GetCoordValue();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
kid->MoveTo(origin.x + dx, origin.y + dy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
aMaxAscent = maxAscent;
|
|
||||||
aMaxDescent = maxDescent;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,8 +64,6 @@ public:
|
||||||
|
|
||||||
void RelativePositionFrames();
|
void RelativePositionFrames();
|
||||||
|
|
||||||
void GetScents(nscoord& aMaxAscent, nscoord& aMaxDescent);
|
|
||||||
|
|
||||||
PRInt32 GetCurrentFrameNum() const { return mFrameNum; }
|
PRInt32 GetCurrentFrameNum() const { return mFrameNum; }
|
||||||
|
|
||||||
void ChangeFrameCount(PRInt32 aCount) {
|
void ChangeFrameCount(PRInt32 aCount) {
|
||||||
|
@ -83,11 +81,17 @@ public:
|
||||||
|
|
||||||
nscoord GetCarriedOutMarginFlags() const { return mCarriedOutMarginFlags; }
|
nscoord GetCarriedOutMarginFlags() const { return mCarriedOutMarginFlags; }
|
||||||
|
|
||||||
nscoord GetTopMargin() const { return mMargin.top; }
|
nscoord GetTopMargin() const {
|
||||||
|
return mFrameData->mMargin.top;
|
||||||
|
}
|
||||||
|
|
||||||
nscoord GetBottomMargin() const { return mMargin.bottom; }
|
nscoord GetBottomMargin() const {
|
||||||
|
return mFrameData->mMargin.bottom;
|
||||||
|
}
|
||||||
|
|
||||||
PRUintn GetMarginFlags() const { return mMarginFlags; }
|
PRUintn GetMarginFlags() const {
|
||||||
|
return mFrameData->mMarginFlags;
|
||||||
|
}
|
||||||
|
|
||||||
static PRUintn CalculateBlockMarginsFor(nsIPresContext& aPresContext,
|
static PRUintn CalculateBlockMarginsFor(nsIPresContext& aPresContext,
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
|
@ -101,7 +105,7 @@ public:
|
||||||
static nscoord MaxMargin(nscoord a, nscoord b);
|
static nscoord MaxMargin(nscoord a, nscoord b);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SetFrame(nsIFrame* aFrame);
|
nsresult SetFrame(nsIFrame* aFrame);
|
||||||
|
|
||||||
PRBool TreatFrameAsBlockFrame();
|
PRBool TreatFrameAsBlockFrame();
|
||||||
|
|
||||||
|
@ -127,8 +131,6 @@ protected:
|
||||||
|
|
||||||
void PlaceFrame(nsHTMLReflowMetrics& aMetrics, nsRect& aBounds);
|
void PlaceFrame(nsHTMLReflowMetrics& aMetrics, nsRect& aBounds);
|
||||||
|
|
||||||
nsresult SetFrameData(const nsHTMLReflowMetrics& aMetrics);
|
|
||||||
|
|
||||||
void UpdateFrames();
|
void UpdateFrames();
|
||||||
|
|
||||||
// The outer frame that contains the frames that we reflow.
|
// The outer frame that contains the frames that we reflow.
|
||||||
|
@ -139,21 +141,33 @@ protected:
|
||||||
nsIPresContext& mPresContext;
|
nsIPresContext& mPresContext;
|
||||||
PRBool mOuterIsBlock;
|
PRBool mOuterIsBlock;
|
||||||
|
|
||||||
nsIFrame* mFirstFrame;
|
|
||||||
PRIntn mFrameNum;
|
PRIntn mFrameNum;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For each frame reflowed, we keep this state around
|
||||||
|
*/
|
||||||
struct PerFrameData {
|
struct PerFrameData {
|
||||||
|
nsIFrame* mFrame;
|
||||||
|
|
||||||
nscoord mAscent; // computed ascent value
|
nscoord mAscent; // computed ascent value
|
||||||
nscoord mDescent; // computed descent value
|
nscoord mDescent; // computed descent value
|
||||||
|
|
||||||
nsMargin mMargin; // computed margin value
|
nsMargin mMargin; // computed margin value
|
||||||
|
PRUintn mMarginFlags;
|
||||||
|
|
||||||
|
// Location and size of frame after its reflowed but before it is
|
||||||
|
// positioned finally by VerticalAlignFrames
|
||||||
|
nsRect mBounds;
|
||||||
|
|
||||||
|
nsSize mMaxElementSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
PerFrameData* mFrameData;
|
PerFrameData* mFrameData;
|
||||||
|
PerFrameData* mFrameDataBase;
|
||||||
PerFrameData mFrameDataBuf[20];
|
PerFrameData mFrameDataBuf[20];
|
||||||
PRIntn mNumFrameData;
|
PRIntn mNumFrameData;
|
||||||
|
|
||||||
// Current frame state
|
// Current frame state
|
||||||
nsIFrame* mFrame;
|
|
||||||
const nsStyleSpacing* mSpacing;
|
const nsStyleSpacing* mSpacing;
|
||||||
const nsStylePosition* mPosition;
|
const nsStylePosition* mPosition;
|
||||||
const nsStyleDisplay* mDisplay;
|
const nsStyleDisplay* mDisplay;
|
||||||
|
@ -174,8 +188,6 @@ protected:
|
||||||
|
|
||||||
// The frame's computed margin values (includes auto value
|
// The frame's computed margin values (includes auto value
|
||||||
// computation)
|
// computation)
|
||||||
nsMargin mMargin;
|
|
||||||
PRUintn mMarginFlags;
|
|
||||||
nscoord mRightMargin;/* XXX */
|
nscoord mRightMargin;/* XXX */
|
||||||
nscoord mCarriedOutTopMargin;
|
nscoord mCarriedOutTopMargin;
|
||||||
nscoord mCarriedOutBottomMargin;
|
nscoord mCarriedOutBottomMargin;
|
||||||
|
@ -190,7 +202,6 @@ protected:
|
||||||
nscoord mRightEdge;
|
nscoord mRightEdge;
|
||||||
|
|
||||||
nscoord mTopEdge;
|
nscoord mTopEdge;
|
||||||
nscoord mY;
|
|
||||||
nscoord mBottomEdge;
|
nscoord mBottomEdge;
|
||||||
|
|
||||||
PRBool mUpdatedBand;
|
PRBool mUpdatedBand;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче