mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 10:33:33 +00:00
Updated
This commit is contained in:
parent
a2f088f0b2
commit
2c54f1bfe8
@ -22,15 +22,20 @@
|
|||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsIContentDelegate.h"
|
#include "nsIContentDelegate.h"
|
||||||
#include "nsIPresContext.h"
|
#include "nsIPresContext.h"
|
||||||
|
#include "nsISpaceManager.h"
|
||||||
#include "nsIPtr.h"
|
#include "nsIPtr.h"
|
||||||
#include "nsAbsoluteFrame.h"
|
#include "nsAbsoluteFrame.h"
|
||||||
#include "nsPlaceholderFrame.h"
|
#include "nsPlaceholderFrame.h"
|
||||||
|
#include "nsCSSLayout.h"
|
||||||
|
#include "nsCRT.h"
|
||||||
|
|
||||||
#undef NOISY_REFLOW
|
#undef NOISY_REFLOW
|
||||||
|
|
||||||
static NS_DEFINE_IID(kStyleDisplaySID, NS_STYLEDISPLAY_SID);
|
static NS_DEFINE_IID(kStyleDisplaySID, NS_STYLEDISPLAY_SID);
|
||||||
|
static NS_DEFINE_IID(kStyleFontSID, NS_STYLEFONT_SID);
|
||||||
static NS_DEFINE_IID(kStylePositionSID, NS_STYLEPOSITION_SID);
|
static NS_DEFINE_IID(kStylePositionSID, NS_STYLEPOSITION_SID);
|
||||||
static NS_DEFINE_IID(kStyleSpacingSID, NS_STYLESPACING_SID);
|
static NS_DEFINE_IID(kStyleSpacingSID, NS_STYLESPACING_SID);
|
||||||
|
static NS_DEFINE_IID(kStyleTextSID, NS_STYLETEXT_SID);
|
||||||
|
|
||||||
NS_DEF_PTR(nsIContent);
|
NS_DEF_PTR(nsIContent);
|
||||||
NS_DEF_PTR(nsIStyleContext);
|
NS_DEF_PTR(nsIStyleContext);
|
||||||
@ -44,6 +49,8 @@ nsLineData::nsLineData()
|
|||||||
mFirstContentOffset = 0;
|
mFirstContentOffset = 0;
|
||||||
mLastContentOffset = 0;
|
mLastContentOffset = 0;
|
||||||
mLastContentIsComplete = PR_TRUE;
|
mLastContentIsComplete = PR_TRUE;
|
||||||
|
mHasBullet = PR_FALSE;
|
||||||
|
mIsBlock = PR_FALSE;
|
||||||
mBounds.SetRect(0, 0, 0, 0);
|
mBounds.SetRect(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,34 +67,66 @@ nsLineData::UnlinkLine()
|
|||||||
if (nsnull != prevLine) prevLine->mNextLine = nextLine;
|
if (nsnull != prevLine) prevLine->mNextLine = nextLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
void
|
||||||
nsLineData::Verify() const
|
nsLineData::MoveLineBy(nscoord dx, nscoord dy)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(0 != mChildCount, "empty line");
|
nsIFrame* kid = mFirstChild;
|
||||||
NS_ASSERTION(nsnull != mFirstChild, "empty line");
|
nsPoint pt;
|
||||||
|
for (PRInt32 i = mChildCount; --i >= 0; ) {
|
||||||
|
kid->GetOrigin(pt);
|
||||||
|
pt.x += dx;
|
||||||
|
pt.y += dy;
|
||||||
|
kid->MoveTo(pt.x, pt.y);
|
||||||
|
kid->GetNextSibling(kid);
|
||||||
|
}
|
||||||
|
mBounds.MoveBy(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
nsIFrame* nextLinesFirstChild = nsnull;
|
nsresult
|
||||||
|
nsLineData::Verify(PRBool aFinalCheck) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(mNextLine != this, "bad line linkage");
|
||||||
|
NS_ASSERTION(mPrevLine != this, "bad line linkage");
|
||||||
|
if (nsnull != mPrevLine) {
|
||||||
|
NS_ASSERTION(mPrevLine->mNextLine == this, "bad line linkage");
|
||||||
|
}
|
||||||
if (nsnull != mNextLine) {
|
if (nsnull != mNextLine) {
|
||||||
nextLinesFirstChild = mNextLine->mFirstChild;
|
NS_ASSERTION(mNextLine->mPrevLine == this, "bad line linkage");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that number of children are ok and that the index in parent
|
if (aFinalCheck) {
|
||||||
// information agrees with the content offsets.
|
NS_ASSERTION(0 != mChildCount, "empty line");
|
||||||
PRInt32 offset = mFirstContentOffset;
|
NS_ASSERTION(nsnull != mFirstChild, "empty line");
|
||||||
PRInt32 len = 0;
|
|
||||||
nsIFrame* child = mFirstChild;
|
nsIFrame* nextLinesFirstChild = nsnull;
|
||||||
while ((nsnull != child) && (child != nextLinesFirstChild)) {
|
if (nsnull != mNextLine) {
|
||||||
PRInt32 indexInParent;
|
nextLinesFirstChild = mNextLine->mFirstChild;
|
||||||
child->GetIndexInParent(indexInParent);
|
|
||||||
NS_ASSERTION(indexInParent == offset, "bad line offsets");
|
|
||||||
len++;
|
|
||||||
if (len != mChildCount) {
|
|
||||||
offset++;
|
|
||||||
}
|
}
|
||||||
child->GetNextSibling(child);
|
|
||||||
|
|
||||||
|
// Check that number of children are ok and that the index in parent
|
||||||
|
// information agrees with the content offsets.
|
||||||
|
PRInt32 offset = mFirstContentOffset;
|
||||||
|
PRInt32 len = 0;
|
||||||
|
nsIFrame* child = mFirstChild;
|
||||||
|
if (mHasBullet) {
|
||||||
|
// Skip bullet
|
||||||
|
child->GetNextSibling(child);
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
while ((nsnull != child) && (child != nextLinesFirstChild)) {
|
||||||
|
PRInt32 indexInParent;
|
||||||
|
child->GetIndexInParent(indexInParent);
|
||||||
|
NS_ASSERTION(indexInParent == offset, "bad line offsets");
|
||||||
|
len++;
|
||||||
|
if (len != mChildCount) {
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
child->GetNextSibling(child);
|
||||||
|
}
|
||||||
|
NS_ASSERTION(offset == mLastContentOffset, "bad mLastContentOffset");
|
||||||
|
NS_ASSERTION(len == mChildCount, "bad child count");
|
||||||
}
|
}
|
||||||
NS_ASSERTION(offset == mLastContentOffset, "bad mLastContentOffset");
|
|
||||||
NS_ASSERTION(len == mChildCount, "bad child count");
|
|
||||||
|
|
||||||
// XXX verify content offsets and mLastContentIsComplete
|
// XXX verify content offsets and mLastContentIsComplete
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -155,49 +194,51 @@ nsLineData::List(FILE* out, PRInt32 aIndent) const
|
|||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
nsLineLayout::nsLineLayout()
|
nsLineLayout::nsLineLayout(nsBlockReflowState& aState)
|
||||||
{
|
{
|
||||||
mBlockContent = nsnull;
|
mBlock = aState.mBlock;
|
||||||
|
mSpaceManager = aState.mSpaceManager;
|
||||||
|
mBlock->GetContent(mBlockContent);
|
||||||
|
mPresContext = aState.mPresContext;
|
||||||
|
mBlockIsPseudo = aState.mBlockIsPseudo;
|
||||||
|
mUnconstrainedWidth = aState.mUnconstrainedWidth;
|
||||||
|
mUnconstrainedHeight = aState.mUnconstrainedHeight;
|
||||||
|
mMaxElementSizePointer = aState.mMaxElementSizePointer;
|
||||||
|
|
||||||
|
mAscents = mAscentBuf;
|
||||||
|
mMaxAscents = sizeof(mAscentBuf) / sizeof(mAscentBuf[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsLineLayout::~nsLineLayout()
|
nsLineLayout::~nsLineLayout()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mBlockContent);
|
NS_IF_RELEASE(mBlockContent);
|
||||||
|
if (mAscents != mAscentBuf) {
|
||||||
|
delete [] mAscents;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsLineLayout::Initialize(nsBlockReflowState& aState,
|
nsLineLayout::Initialize(nsBlockReflowState& aState, nsLineData* aLine)
|
||||||
nsLineData* aLine,
|
|
||||||
const nsRect& aAvailSpace)
|
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
mPresContext = aState.mPresContext;
|
|
||||||
mBlock = aState.mBlock;
|
|
||||||
mBlockIsPseudo = aState.mBlockIsPseudo;
|
|
||||||
mBlock->GetContent(mBlockContent);
|
|
||||||
mLine = aLine;
|
mLine = aLine;
|
||||||
mKidPrevInFlow = nsnull;
|
mKidPrevInFlow = nsnull;
|
||||||
mNewFrames = 0;
|
mNewFrames = 0;
|
||||||
mKidIndex = aLine->mFirstContentOffset;
|
mKidIndex = aLine->mFirstContentOffset;
|
||||||
|
|
||||||
mReflowData.mX = aAvailSpace.x;
|
|
||||||
mReflowData.mAvailWidth = aAvailSpace.width;
|
|
||||||
mReflowData.mMaxElementSize.width = 0;
|
mReflowData.mMaxElementSize.width = 0;
|
||||||
mReflowData.mMaxElementSize.height = 0;
|
mReflowData.mMaxElementSize.height = 0;
|
||||||
mReflowData.mMaxAscent = nsnull;
|
mReflowData.mMaxAscent = nsnull;
|
||||||
mReflowData.mMaxDescent = nsnull;
|
mReflowData.mMaxDescent = nsnull;
|
||||||
|
|
||||||
mUnconstrainedWidth = aState.mUnconstrainedWidth;
|
SetReflowSpace(aState.mCurrentBand.availSpace);
|
||||||
mUnconstrainedHeight = aState.mUnconstrainedHeight;
|
mY = aState.mY;
|
||||||
mY = aState.mY;/* XXX ??? */
|
mMaxHeight = aState.mAvailSize.height;
|
||||||
mLineHeight = 0;
|
mReflowDataChanged = PR_FALSE;
|
||||||
mAvailHeight = aState.mAvailHeight;
|
|
||||||
mMaxElementSizePointer = aState.mMaxElementSizePointer;
|
|
||||||
mX0 = aAvailSpace.x;
|
|
||||||
|
|
||||||
mAscents = mAscentBuf;
|
mLineHeight = 0;
|
||||||
mMaxAscents = sizeof(mAscentBuf) / sizeof(mAscentBuf[0]);
|
mAscentNum = 0;
|
||||||
|
|
||||||
mKidFrame = nsnull;
|
mKidFrame = nsnull;
|
||||||
mPrevKidFrame = nsnull;
|
mPrevKidFrame = nsnull;
|
||||||
@ -207,10 +248,41 @@ nsLineLayout::Initialize(nsBlockReflowState& aState,
|
|||||||
mWordStartOffset = 0;
|
mWordStartOffset = 0;
|
||||||
|
|
||||||
mSkipLeadingWhiteSpace = PR_TRUE;
|
mSkipLeadingWhiteSpace = PR_TRUE;
|
||||||
|
mColumn = 0;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsLineLayout::SetReflowSpace(nsRect& aAvailableSpaceRect)
|
||||||
|
{
|
||||||
|
mReflowData.mX = aAvailableSpaceRect.x;
|
||||||
|
mReflowData.mAvailWidth = aAvailableSpaceRect.width;
|
||||||
|
mX0 = mReflowData.mX;
|
||||||
|
mMaxWidth = mReflowData.mAvailWidth;
|
||||||
|
mReflowDataChanged = PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsLineLayout::AddAscent(nscoord aAscent)
|
||||||
|
{
|
||||||
|
if (mAscentNum == mMaxAscents) {
|
||||||
|
mMaxAscents *= 2;
|
||||||
|
nscoord* newAscents = new nscoord[mMaxAscents];
|
||||||
|
if (nsnull != newAscents) {
|
||||||
|
nsCRT::memcpy(newAscents, mAscents, sizeof(nscoord) * mAscentNum);
|
||||||
|
if (mAscents != mAscentBuf) {
|
||||||
|
delete [] mAscents;
|
||||||
|
}
|
||||||
|
mAscents = newAscents;
|
||||||
|
} else {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mAscents[mAscentNum++] = aAscent;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsIFrame*
|
nsIFrame*
|
||||||
nsLineLayout::GetWordStartParent()
|
nsLineLayout::GetWordStartParent()
|
||||||
{
|
{
|
||||||
@ -248,7 +320,7 @@ nsLineLayout::WordBreakReflow()
|
|||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsSize kidAvailSize;
|
nsSize kidAvailSize;
|
||||||
kidAvailSize.width = mReflowData.mAvailWidth;
|
kidAvailSize.width = mReflowData.mAvailWidth;
|
||||||
kidAvailSize.height = mAvailHeight;
|
kidAvailSize.height = mMaxHeight;
|
||||||
if (!mUnconstrainedWidth) {
|
if (!mUnconstrainedWidth) {
|
||||||
nsIStyleContextPtr kidSC;
|
nsIStyleContextPtr kidSC;
|
||||||
rv = frame->GetStyleContext(mPresContext, kidSC.AssignRef());
|
rv = frame->GetStyleContext(mPresContext, kidSC.AssignRef());
|
||||||
@ -271,9 +343,9 @@ nsLineLayout::WordBreakReflow()
|
|||||||
if (nsnull != mMaxElementSizePointer) {
|
if (nsnull != mMaxElementSizePointer) {
|
||||||
kidMaxElementSize = &maxElementSize;
|
kidMaxElementSize = &maxElementSize;
|
||||||
}
|
}
|
||||||
rv = mBlock->ReflowLineChild(frame, mPresContext, kidSize,
|
rv = mBlock->ReflowInlineChild(frame, mPresContext, kidSize,
|
||||||
kidAvailSize, kidMaxElementSize,
|
kidAvailSize, kidMaxElementSize,
|
||||||
kidReflowStatus);
|
kidReflowStatus);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -316,7 +388,7 @@ nsLineLayout::ReflowChild()
|
|||||||
// Get the available size to reflow the child into
|
// Get the available size to reflow the child into
|
||||||
nsSize kidAvailSize;
|
nsSize kidAvailSize;
|
||||||
kidAvailSize.width = mReflowData.mAvailWidth;
|
kidAvailSize.width = mReflowData.mAvailWidth;
|
||||||
kidAvailSize.height = mAvailHeight;
|
kidAvailSize.height = mMaxHeight;
|
||||||
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
|
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
|
||||||
kidSC->GetData(kStyleSpacingSID);
|
kidSC->GetData(kStyleSpacingSID);
|
||||||
if (!mUnconstrainedWidth) {
|
if (!mUnconstrainedWidth) {
|
||||||
@ -328,6 +400,7 @@ nsLineLayout::ReflowChild()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reflow the child
|
// Reflow the child
|
||||||
|
nsRect kidRect;
|
||||||
nsSize maxElementSize;
|
nsSize maxElementSize;
|
||||||
nsReflowMetrics kidSize;
|
nsReflowMetrics kidSize;
|
||||||
nsSize* kidMaxElementSize = nsnull;
|
nsSize* kidMaxElementSize = nsnull;
|
||||||
@ -336,9 +409,29 @@ nsLineLayout::ReflowChild()
|
|||||||
kidMaxElementSize = &maxElementSize;
|
kidMaxElementSize = &maxElementSize;
|
||||||
}
|
}
|
||||||
mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE;
|
mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE;
|
||||||
rv = mBlock->ReflowLineChild(mKidFrame, mPresContext, kidSize,
|
nscoord dx = mReflowData.mX + kidSpacing->mMargin.left;
|
||||||
kidAvailSize, kidMaxElementSize,
|
if (isBlock) {
|
||||||
kidReflowStatus);
|
mSpaceManager->Translate(dx, 0);
|
||||||
|
rv = mBlock->ReflowBlockChild(mKidFrame, mPresContext,
|
||||||
|
mSpaceManager, kidAvailSize, kidRect,
|
||||||
|
kidMaxElementSize, kidReflowStatus);
|
||||||
|
mSpaceManager->Translate(-dx, 0);
|
||||||
|
kidRect.x = dx;
|
||||||
|
kidRect.y = mY;
|
||||||
|
kidSize.width = kidRect.width;
|
||||||
|
kidSize.height = kidRect.height;
|
||||||
|
kidSize.ascent = kidRect.height;
|
||||||
|
kidSize.descent = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rv = mBlock->ReflowInlineChild(mKidFrame, mPresContext,
|
||||||
|
kidSize, kidAvailSize, kidMaxElementSize,
|
||||||
|
kidReflowStatus);
|
||||||
|
kidRect.x = dx;
|
||||||
|
kidRect.y = mY;
|
||||||
|
kidRect.width = kidSize.width;
|
||||||
|
kidRect.height = kidSize.height;
|
||||||
|
}
|
||||||
if (NS_OK != rv) return rv;
|
if (NS_OK != rv) return rv;
|
||||||
|
|
||||||
// See if the child fit
|
// See if the child fit
|
||||||
@ -367,27 +460,14 @@ nsLineLayout::ReflowChild()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if XXX
|
// For non-aware children they act like words which means that space
|
||||||
// Now that the child fit, see where to go next
|
// immediately following them must not be skipped over.
|
||||||
switch (mReflowResult) {
|
if (NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE == mReflowResult) {
|
||||||
case NS_LINE_LAYOUT_NOT_AWARE:
|
|
||||||
// The child did not update our reflow state. This means that it's
|
|
||||||
// the kind of child that doesn't interact with us directly which
|
|
||||||
// means we have to treat it carefully. An example of such a child
|
|
||||||
// is an html image.
|
|
||||||
mSkipLeadingWhiteSpace = PR_FALSE;
|
mSkipLeadingWhiteSpace = PR_FALSE;
|
||||||
mWordStart = nsnull;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Place child
|
// Place child
|
||||||
nsRect pos;
|
mKidFrame->SetRect(kidRect);
|
||||||
pos.x = mReflowData.mX + kidSpacing->mMargin.left;
|
|
||||||
pos.y = mY;
|
|
||||||
pos.width = kidSize.width;
|
|
||||||
pos.height = kidSize.height;
|
|
||||||
mKidFrame->SetRect(pos);
|
|
||||||
|
|
||||||
// Advance
|
// Advance
|
||||||
// XXX RTL
|
// XXX RTL
|
||||||
@ -413,14 +493,17 @@ nsLineLayout::ReflowChild()
|
|||||||
if (kidSize.descent > mReflowData.mMaxDescent) {
|
if (kidSize.descent > mReflowData.mMaxDescent) {
|
||||||
mReflowData.mMaxDescent = kidSize.descent;
|
mReflowData.mMaxDescent = kidSize.descent;
|
||||||
}
|
}
|
||||||
|
AddAscent(isBlock ? 0 : kidSize.ascent);
|
||||||
|
mLine->mIsBlock = isBlock;
|
||||||
|
|
||||||
// Set completion status
|
// Set completion status
|
||||||
mLine->mLastContentOffset = mKidIndex;
|
mLine->mLastContentOffset = mKidIndex;
|
||||||
if (nsIFrame::frComplete == kidReflowStatus) {
|
if (nsIFrame::frComplete == kidReflowStatus) {
|
||||||
mLine->mLastContentIsComplete = PR_TRUE;
|
mLine->mLastContentIsComplete = PR_TRUE;
|
||||||
rv = isBlock
|
if (isBlock ||
|
||||||
? NS_LINE_LAYOUT_BREAK_AFTER
|
(NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER == mReflowResult)) {
|
||||||
: NS_LINE_LAYOUT_COMPLETE;
|
rv = NS_LINE_LAYOUT_BREAK_AFTER;
|
||||||
|
}
|
||||||
mKidPrevInFlow = nsnull;
|
mKidPrevInFlow = nsnull;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -509,7 +592,7 @@ nsLineLayout::SplitLine(PRInt32 aChildReflowStatus, PRInt32 aRemainingKids)
|
|||||||
// to compute them so don't bother.
|
// to compute them so don't bother.
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
to->mLastContentOffset = -1;
|
to->mLastContentOffset = -1;
|
||||||
to->mLastContentIsComplete = PRBool(-1);
|
to->mLastContentIsComplete = PRPackedBool(0x255);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
from->mChildCount -= aRemainingKids;
|
from->mChildCount -= aRemainingKids;
|
||||||
@ -948,7 +1031,12 @@ nsLineLayout::ReflowLine()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform alignment operations
|
// Perform alignment operations
|
||||||
AlignChildren();
|
if (mLine->mIsBlock) {
|
||||||
|
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
AlignChildren();
|
||||||
|
}
|
||||||
|
|
||||||
// Set final bounds of the line
|
// Set final bounds of the line
|
||||||
mLine->mBounds.height = mLineHeight;
|
mLine->mBounds.height = mLineHeight;
|
||||||
@ -967,9 +1055,37 @@ nsLineLayout::ReflowLine()
|
|||||||
nsresult
|
nsresult
|
||||||
nsLineLayout::AlignChildren()
|
nsLineLayout::AlignChildren()
|
||||||
{
|
{
|
||||||
|
NS_PRECONDITION(mLine->mChildCount == mAscentNum, "bad line reflow");
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;/* XXX */
|
nsIStyleContextPtr blockSC;
|
||||||
|
mBlock->GetStyleContext(mPresContext, blockSC.AssignRef());
|
||||||
|
nsStyleFont* blockFont = (nsStyleFont*)
|
||||||
|
blockSC->GetData(kStyleFontSID);
|
||||||
|
nsStyleText* blockText = (nsStyleText*)
|
||||||
|
blockSC->GetData(kStyleTextSID);
|
||||||
|
|
||||||
|
// First vertically align the children on the line; this will
|
||||||
|
// compute the actual line height for us.
|
||||||
|
mLineHeight =
|
||||||
|
nsCSSLayout::VerticallyAlignChildren(mPresContext, mBlock, blockFont,
|
||||||
|
mY,
|
||||||
|
mLine->mFirstChild,
|
||||||
|
mLine->mChildCount,
|
||||||
|
mAscents, mReflowData.mMaxAscent);
|
||||||
|
|
||||||
|
// Now horizontally place the children
|
||||||
|
nsCSSLayout::HorizontallyPlaceChildren(mPresContext, mBlock, blockText,
|
||||||
|
mLine->mFirstChild,
|
||||||
|
mLine->mChildCount,
|
||||||
|
mReflowData.mX - mX0,
|
||||||
|
mMaxWidth);
|
||||||
|
|
||||||
|
// Last, apply relative positioning
|
||||||
|
nsCSSLayout::RelativePositionChildren(mPresContext, mBlock,
|
||||||
|
mLine->mFirstChild,
|
||||||
|
mLine->mChildCount);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "nsSize.h"
|
#include "nsSize.h"
|
||||||
|
|
||||||
class nsIPresContext;
|
class nsIPresContext;
|
||||||
|
class nsISpaceManager;
|
||||||
class nsBlockFrame;
|
class nsBlockFrame;
|
||||||
struct nsBlockReflowState;
|
struct nsBlockReflowState;
|
||||||
|
|
||||||
@ -34,10 +35,11 @@ struct nsLineData {
|
|||||||
~nsLineData();
|
~nsLineData();
|
||||||
|
|
||||||
nsIFrame* GetLastChild();
|
nsIFrame* GetLastChild();
|
||||||
nsresult Verify() const;
|
nsresult Verify(PRBool aFinalCheck = PR_TRUE) const;
|
||||||
void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||||
void UnlinkLine();
|
void UnlinkLine();
|
||||||
PRIntn GetLineNumber() const;
|
PRIntn GetLineNumber() const;
|
||||||
|
void MoveLineBy(nscoord dx, nscoord dy);
|
||||||
|
|
||||||
nsLineData* mNextLine;
|
nsLineData* mNextLine;
|
||||||
nsLineData* mPrevLine;
|
nsLineData* mPrevLine;
|
||||||
@ -47,6 +49,8 @@ struct nsLineData {
|
|||||||
PRInt32 mLastContentOffset;
|
PRInt32 mLastContentOffset;
|
||||||
nsRect mBounds;
|
nsRect mBounds;
|
||||||
PRPackedBool mLastContentIsComplete;
|
PRPackedBool mLastContentIsComplete;
|
||||||
|
PRPackedBool mHasBullet;
|
||||||
|
PRPackedBool mIsBlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
@ -64,12 +68,12 @@ struct nsLineLayoutReflowData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct nsLineLayout {
|
struct nsLineLayout {
|
||||||
nsLineLayout();
|
nsLineLayout(nsBlockReflowState& aState);
|
||||||
~nsLineLayout();
|
~nsLineLayout();
|
||||||
|
|
||||||
nsresult Initialize(nsBlockReflowState& aState,
|
nsresult Initialize(nsBlockReflowState& aState, nsLineData* aLine);
|
||||||
nsLineData* aLine,
|
|
||||||
const nsRect& aAvailSpace);
|
void SetReflowSpace(nsRect& aAvailableSpaceRect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <h2>Rules of order</h2>
|
* <h2>Rules of order</h2>
|
||||||
@ -101,6 +105,7 @@ struct nsLineLayout {
|
|||||||
|
|
||||||
// The block behind the line
|
// The block behind the line
|
||||||
nsBlockFrame* mBlock;
|
nsBlockFrame* mBlock;
|
||||||
|
nsISpaceManager* mSpaceManager;
|
||||||
PRBool mBlockIsPseudo;
|
PRBool mBlockIsPseudo;
|
||||||
nsIContent* mBlockContent;
|
nsIContent* mBlockContent;
|
||||||
PRInt32 mKidIndex;
|
PRInt32 mKidIndex;
|
||||||
@ -116,17 +121,23 @@ struct nsLineLayout {
|
|||||||
// width remains and the maximum element size so far.
|
// width remains and the maximum element size so far.
|
||||||
nsLineLayoutReflowData mReflowData;
|
nsLineLayoutReflowData mReflowData;
|
||||||
|
|
||||||
|
// This is set by the block code when it updates the available
|
||||||
|
// reflow area when a floater is placed.
|
||||||
|
PRBool mReflowDataChanged;
|
||||||
|
|
||||||
PRPackedBool mUnconstrainedWidth;
|
PRPackedBool mUnconstrainedWidth;
|
||||||
PRPackedBool mUnconstrainedHeight;
|
PRPackedBool mUnconstrainedHeight;
|
||||||
nscoord mY;
|
nscoord mY;
|
||||||
nscoord mLineHeight;
|
nscoord mLineHeight;
|
||||||
nscoord mAvailHeight;
|
nscoord mMaxWidth;
|
||||||
|
nscoord mMaxHeight;
|
||||||
nsSize* mMaxElementSizePointer;
|
nsSize* mMaxElementSizePointer;
|
||||||
nscoord mX0;
|
nscoord mX0;
|
||||||
|
|
||||||
nscoord* mAscents;
|
nscoord* mAscents;
|
||||||
nscoord mAscentBuf[20];
|
nscoord mAscentBuf[20];
|
||||||
nscoord mMaxAscents;
|
nscoord mMaxAscents;
|
||||||
|
nscoord mAscentNum;
|
||||||
|
|
||||||
// The current type of reflow in progress. Normally, this value is
|
// The current type of reflow in progress. Normally, this value is
|
||||||
// set to NS_LINE_LAYOUT_NORMAL_REFLOW. However, in the special case
|
// set to NS_LINE_LAYOUT_NORMAL_REFLOW. However, in the special case
|
||||||
@ -158,9 +169,12 @@ struct nsLineLayout {
|
|||||||
nsLineLayoutReflowData mWordStartReflowData;
|
nsLineLayoutReflowData mWordStartReflowData;
|
||||||
|
|
||||||
PRBool mSkipLeadingWhiteSpace;
|
PRBool mSkipLeadingWhiteSpace;
|
||||||
|
PRInt32 mColumn;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
nsresult AddAscent(nscoord aAscent);
|
||||||
|
|
||||||
nsresult WordBreakReflow();
|
nsresult WordBreakReflow();
|
||||||
|
|
||||||
nsresult ReflowChild();
|
nsresult ReflowChild();
|
||||||
@ -189,7 +203,9 @@ protected:
|
|||||||
#define NS_LINE_LAYOUT_REFLOW_TYPE_WORD_WRAP 1
|
#define NS_LINE_LAYOUT_REFLOW_TYPE_WORD_WRAP 1
|
||||||
|
|
||||||
// Value's for nsLineLayout.mReflowResult
|
// Value's for nsLineLayout.mReflowResult
|
||||||
#define NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE 0
|
#define NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE 0
|
||||||
|
#define NS_LINE_LAYOUT_REFLOW_RESULT_AWARE 1
|
||||||
|
#define NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER 2
|
||||||
|
|
||||||
// Return value's from nsLineLayout reflow methods
|
// Return value's from nsLineLayout reflow methods
|
||||||
#define NS_LINE_LAYOUT_COMPLETE 0
|
#define NS_LINE_LAYOUT_COMPLETE 0
|
||||||
|
@ -22,15 +22,20 @@
|
|||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsIContentDelegate.h"
|
#include "nsIContentDelegate.h"
|
||||||
#include "nsIPresContext.h"
|
#include "nsIPresContext.h"
|
||||||
|
#include "nsISpaceManager.h"
|
||||||
#include "nsIPtr.h"
|
#include "nsIPtr.h"
|
||||||
#include "nsAbsoluteFrame.h"
|
#include "nsAbsoluteFrame.h"
|
||||||
#include "nsPlaceholderFrame.h"
|
#include "nsPlaceholderFrame.h"
|
||||||
|
#include "nsCSSLayout.h"
|
||||||
|
#include "nsCRT.h"
|
||||||
|
|
||||||
#undef NOISY_REFLOW
|
#undef NOISY_REFLOW
|
||||||
|
|
||||||
static NS_DEFINE_IID(kStyleDisplaySID, NS_STYLEDISPLAY_SID);
|
static NS_DEFINE_IID(kStyleDisplaySID, NS_STYLEDISPLAY_SID);
|
||||||
|
static NS_DEFINE_IID(kStyleFontSID, NS_STYLEFONT_SID);
|
||||||
static NS_DEFINE_IID(kStylePositionSID, NS_STYLEPOSITION_SID);
|
static NS_DEFINE_IID(kStylePositionSID, NS_STYLEPOSITION_SID);
|
||||||
static NS_DEFINE_IID(kStyleSpacingSID, NS_STYLESPACING_SID);
|
static NS_DEFINE_IID(kStyleSpacingSID, NS_STYLESPACING_SID);
|
||||||
|
static NS_DEFINE_IID(kStyleTextSID, NS_STYLETEXT_SID);
|
||||||
|
|
||||||
NS_DEF_PTR(nsIContent);
|
NS_DEF_PTR(nsIContent);
|
||||||
NS_DEF_PTR(nsIStyleContext);
|
NS_DEF_PTR(nsIStyleContext);
|
||||||
@ -44,6 +49,8 @@ nsLineData::nsLineData()
|
|||||||
mFirstContentOffset = 0;
|
mFirstContentOffset = 0;
|
||||||
mLastContentOffset = 0;
|
mLastContentOffset = 0;
|
||||||
mLastContentIsComplete = PR_TRUE;
|
mLastContentIsComplete = PR_TRUE;
|
||||||
|
mHasBullet = PR_FALSE;
|
||||||
|
mIsBlock = PR_FALSE;
|
||||||
mBounds.SetRect(0, 0, 0, 0);
|
mBounds.SetRect(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,34 +67,66 @@ nsLineData::UnlinkLine()
|
|||||||
if (nsnull != prevLine) prevLine->mNextLine = nextLine;
|
if (nsnull != prevLine) prevLine->mNextLine = nextLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
void
|
||||||
nsLineData::Verify() const
|
nsLineData::MoveLineBy(nscoord dx, nscoord dy)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(0 != mChildCount, "empty line");
|
nsIFrame* kid = mFirstChild;
|
||||||
NS_ASSERTION(nsnull != mFirstChild, "empty line");
|
nsPoint pt;
|
||||||
|
for (PRInt32 i = mChildCount; --i >= 0; ) {
|
||||||
|
kid->GetOrigin(pt);
|
||||||
|
pt.x += dx;
|
||||||
|
pt.y += dy;
|
||||||
|
kid->MoveTo(pt.x, pt.y);
|
||||||
|
kid->GetNextSibling(kid);
|
||||||
|
}
|
||||||
|
mBounds.MoveBy(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
nsIFrame* nextLinesFirstChild = nsnull;
|
nsresult
|
||||||
|
nsLineData::Verify(PRBool aFinalCheck) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(mNextLine != this, "bad line linkage");
|
||||||
|
NS_ASSERTION(mPrevLine != this, "bad line linkage");
|
||||||
|
if (nsnull != mPrevLine) {
|
||||||
|
NS_ASSERTION(mPrevLine->mNextLine == this, "bad line linkage");
|
||||||
|
}
|
||||||
if (nsnull != mNextLine) {
|
if (nsnull != mNextLine) {
|
||||||
nextLinesFirstChild = mNextLine->mFirstChild;
|
NS_ASSERTION(mNextLine->mPrevLine == this, "bad line linkage");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that number of children are ok and that the index in parent
|
if (aFinalCheck) {
|
||||||
// information agrees with the content offsets.
|
NS_ASSERTION(0 != mChildCount, "empty line");
|
||||||
PRInt32 offset = mFirstContentOffset;
|
NS_ASSERTION(nsnull != mFirstChild, "empty line");
|
||||||
PRInt32 len = 0;
|
|
||||||
nsIFrame* child = mFirstChild;
|
nsIFrame* nextLinesFirstChild = nsnull;
|
||||||
while ((nsnull != child) && (child != nextLinesFirstChild)) {
|
if (nsnull != mNextLine) {
|
||||||
PRInt32 indexInParent;
|
nextLinesFirstChild = mNextLine->mFirstChild;
|
||||||
child->GetIndexInParent(indexInParent);
|
|
||||||
NS_ASSERTION(indexInParent == offset, "bad line offsets");
|
|
||||||
len++;
|
|
||||||
if (len != mChildCount) {
|
|
||||||
offset++;
|
|
||||||
}
|
}
|
||||||
child->GetNextSibling(child);
|
|
||||||
|
|
||||||
|
// Check that number of children are ok and that the index in parent
|
||||||
|
// information agrees with the content offsets.
|
||||||
|
PRInt32 offset = mFirstContentOffset;
|
||||||
|
PRInt32 len = 0;
|
||||||
|
nsIFrame* child = mFirstChild;
|
||||||
|
if (mHasBullet) {
|
||||||
|
// Skip bullet
|
||||||
|
child->GetNextSibling(child);
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
while ((nsnull != child) && (child != nextLinesFirstChild)) {
|
||||||
|
PRInt32 indexInParent;
|
||||||
|
child->GetIndexInParent(indexInParent);
|
||||||
|
NS_ASSERTION(indexInParent == offset, "bad line offsets");
|
||||||
|
len++;
|
||||||
|
if (len != mChildCount) {
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
child->GetNextSibling(child);
|
||||||
|
}
|
||||||
|
NS_ASSERTION(offset == mLastContentOffset, "bad mLastContentOffset");
|
||||||
|
NS_ASSERTION(len == mChildCount, "bad child count");
|
||||||
}
|
}
|
||||||
NS_ASSERTION(offset == mLastContentOffset, "bad mLastContentOffset");
|
|
||||||
NS_ASSERTION(len == mChildCount, "bad child count");
|
|
||||||
|
|
||||||
// XXX verify content offsets and mLastContentIsComplete
|
// XXX verify content offsets and mLastContentIsComplete
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -155,49 +194,51 @@ nsLineData::List(FILE* out, PRInt32 aIndent) const
|
|||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
nsLineLayout::nsLineLayout()
|
nsLineLayout::nsLineLayout(nsBlockReflowState& aState)
|
||||||
{
|
{
|
||||||
mBlockContent = nsnull;
|
mBlock = aState.mBlock;
|
||||||
|
mSpaceManager = aState.mSpaceManager;
|
||||||
|
mBlock->GetContent(mBlockContent);
|
||||||
|
mPresContext = aState.mPresContext;
|
||||||
|
mBlockIsPseudo = aState.mBlockIsPseudo;
|
||||||
|
mUnconstrainedWidth = aState.mUnconstrainedWidth;
|
||||||
|
mUnconstrainedHeight = aState.mUnconstrainedHeight;
|
||||||
|
mMaxElementSizePointer = aState.mMaxElementSizePointer;
|
||||||
|
|
||||||
|
mAscents = mAscentBuf;
|
||||||
|
mMaxAscents = sizeof(mAscentBuf) / sizeof(mAscentBuf[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsLineLayout::~nsLineLayout()
|
nsLineLayout::~nsLineLayout()
|
||||||
{
|
{
|
||||||
NS_IF_RELEASE(mBlockContent);
|
NS_IF_RELEASE(mBlockContent);
|
||||||
|
if (mAscents != mAscentBuf) {
|
||||||
|
delete [] mAscents;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsLineLayout::Initialize(nsBlockReflowState& aState,
|
nsLineLayout::Initialize(nsBlockReflowState& aState, nsLineData* aLine)
|
||||||
nsLineData* aLine,
|
|
||||||
const nsRect& aAvailSpace)
|
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
mPresContext = aState.mPresContext;
|
|
||||||
mBlock = aState.mBlock;
|
|
||||||
mBlockIsPseudo = aState.mBlockIsPseudo;
|
|
||||||
mBlock->GetContent(mBlockContent);
|
|
||||||
mLine = aLine;
|
mLine = aLine;
|
||||||
mKidPrevInFlow = nsnull;
|
mKidPrevInFlow = nsnull;
|
||||||
mNewFrames = 0;
|
mNewFrames = 0;
|
||||||
mKidIndex = aLine->mFirstContentOffset;
|
mKidIndex = aLine->mFirstContentOffset;
|
||||||
|
|
||||||
mReflowData.mX = aAvailSpace.x;
|
|
||||||
mReflowData.mAvailWidth = aAvailSpace.width;
|
|
||||||
mReflowData.mMaxElementSize.width = 0;
|
mReflowData.mMaxElementSize.width = 0;
|
||||||
mReflowData.mMaxElementSize.height = 0;
|
mReflowData.mMaxElementSize.height = 0;
|
||||||
mReflowData.mMaxAscent = nsnull;
|
mReflowData.mMaxAscent = nsnull;
|
||||||
mReflowData.mMaxDescent = nsnull;
|
mReflowData.mMaxDescent = nsnull;
|
||||||
|
|
||||||
mUnconstrainedWidth = aState.mUnconstrainedWidth;
|
SetReflowSpace(aState.mCurrentBand.availSpace);
|
||||||
mUnconstrainedHeight = aState.mUnconstrainedHeight;
|
mY = aState.mY;
|
||||||
mY = aState.mY;/* XXX ??? */
|
mMaxHeight = aState.mAvailSize.height;
|
||||||
mLineHeight = 0;
|
mReflowDataChanged = PR_FALSE;
|
||||||
mAvailHeight = aState.mAvailHeight;
|
|
||||||
mMaxElementSizePointer = aState.mMaxElementSizePointer;
|
|
||||||
mX0 = aAvailSpace.x;
|
|
||||||
|
|
||||||
mAscents = mAscentBuf;
|
mLineHeight = 0;
|
||||||
mMaxAscents = sizeof(mAscentBuf) / sizeof(mAscentBuf[0]);
|
mAscentNum = 0;
|
||||||
|
|
||||||
mKidFrame = nsnull;
|
mKidFrame = nsnull;
|
||||||
mPrevKidFrame = nsnull;
|
mPrevKidFrame = nsnull;
|
||||||
@ -207,10 +248,41 @@ nsLineLayout::Initialize(nsBlockReflowState& aState,
|
|||||||
mWordStartOffset = 0;
|
mWordStartOffset = 0;
|
||||||
|
|
||||||
mSkipLeadingWhiteSpace = PR_TRUE;
|
mSkipLeadingWhiteSpace = PR_TRUE;
|
||||||
|
mColumn = 0;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsLineLayout::SetReflowSpace(nsRect& aAvailableSpaceRect)
|
||||||
|
{
|
||||||
|
mReflowData.mX = aAvailableSpaceRect.x;
|
||||||
|
mReflowData.mAvailWidth = aAvailableSpaceRect.width;
|
||||||
|
mX0 = mReflowData.mX;
|
||||||
|
mMaxWidth = mReflowData.mAvailWidth;
|
||||||
|
mReflowDataChanged = PR_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsLineLayout::AddAscent(nscoord aAscent)
|
||||||
|
{
|
||||||
|
if (mAscentNum == mMaxAscents) {
|
||||||
|
mMaxAscents *= 2;
|
||||||
|
nscoord* newAscents = new nscoord[mMaxAscents];
|
||||||
|
if (nsnull != newAscents) {
|
||||||
|
nsCRT::memcpy(newAscents, mAscents, sizeof(nscoord) * mAscentNum);
|
||||||
|
if (mAscents != mAscentBuf) {
|
||||||
|
delete [] mAscents;
|
||||||
|
}
|
||||||
|
mAscents = newAscents;
|
||||||
|
} else {
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mAscents[mAscentNum++] = aAscent;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsIFrame*
|
nsIFrame*
|
||||||
nsLineLayout::GetWordStartParent()
|
nsLineLayout::GetWordStartParent()
|
||||||
{
|
{
|
||||||
@ -248,7 +320,7 @@ nsLineLayout::WordBreakReflow()
|
|||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsSize kidAvailSize;
|
nsSize kidAvailSize;
|
||||||
kidAvailSize.width = mReflowData.mAvailWidth;
|
kidAvailSize.width = mReflowData.mAvailWidth;
|
||||||
kidAvailSize.height = mAvailHeight;
|
kidAvailSize.height = mMaxHeight;
|
||||||
if (!mUnconstrainedWidth) {
|
if (!mUnconstrainedWidth) {
|
||||||
nsIStyleContextPtr kidSC;
|
nsIStyleContextPtr kidSC;
|
||||||
rv = frame->GetStyleContext(mPresContext, kidSC.AssignRef());
|
rv = frame->GetStyleContext(mPresContext, kidSC.AssignRef());
|
||||||
@ -271,9 +343,9 @@ nsLineLayout::WordBreakReflow()
|
|||||||
if (nsnull != mMaxElementSizePointer) {
|
if (nsnull != mMaxElementSizePointer) {
|
||||||
kidMaxElementSize = &maxElementSize;
|
kidMaxElementSize = &maxElementSize;
|
||||||
}
|
}
|
||||||
rv = mBlock->ReflowLineChild(frame, mPresContext, kidSize,
|
rv = mBlock->ReflowInlineChild(frame, mPresContext, kidSize,
|
||||||
kidAvailSize, kidMaxElementSize,
|
kidAvailSize, kidMaxElementSize,
|
||||||
kidReflowStatus);
|
kidReflowStatus);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -316,7 +388,7 @@ nsLineLayout::ReflowChild()
|
|||||||
// Get the available size to reflow the child into
|
// Get the available size to reflow the child into
|
||||||
nsSize kidAvailSize;
|
nsSize kidAvailSize;
|
||||||
kidAvailSize.width = mReflowData.mAvailWidth;
|
kidAvailSize.width = mReflowData.mAvailWidth;
|
||||||
kidAvailSize.height = mAvailHeight;
|
kidAvailSize.height = mMaxHeight;
|
||||||
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
|
nsStyleSpacing* kidSpacing = (nsStyleSpacing*)
|
||||||
kidSC->GetData(kStyleSpacingSID);
|
kidSC->GetData(kStyleSpacingSID);
|
||||||
if (!mUnconstrainedWidth) {
|
if (!mUnconstrainedWidth) {
|
||||||
@ -328,6 +400,7 @@ nsLineLayout::ReflowChild()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reflow the child
|
// Reflow the child
|
||||||
|
nsRect kidRect;
|
||||||
nsSize maxElementSize;
|
nsSize maxElementSize;
|
||||||
nsReflowMetrics kidSize;
|
nsReflowMetrics kidSize;
|
||||||
nsSize* kidMaxElementSize = nsnull;
|
nsSize* kidMaxElementSize = nsnull;
|
||||||
@ -336,9 +409,29 @@ nsLineLayout::ReflowChild()
|
|||||||
kidMaxElementSize = &maxElementSize;
|
kidMaxElementSize = &maxElementSize;
|
||||||
}
|
}
|
||||||
mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE;
|
mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE;
|
||||||
rv = mBlock->ReflowLineChild(mKidFrame, mPresContext, kidSize,
|
nscoord dx = mReflowData.mX + kidSpacing->mMargin.left;
|
||||||
kidAvailSize, kidMaxElementSize,
|
if (isBlock) {
|
||||||
kidReflowStatus);
|
mSpaceManager->Translate(dx, 0);
|
||||||
|
rv = mBlock->ReflowBlockChild(mKidFrame, mPresContext,
|
||||||
|
mSpaceManager, kidAvailSize, kidRect,
|
||||||
|
kidMaxElementSize, kidReflowStatus);
|
||||||
|
mSpaceManager->Translate(-dx, 0);
|
||||||
|
kidRect.x = dx;
|
||||||
|
kidRect.y = mY;
|
||||||
|
kidSize.width = kidRect.width;
|
||||||
|
kidSize.height = kidRect.height;
|
||||||
|
kidSize.ascent = kidRect.height;
|
||||||
|
kidSize.descent = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rv = mBlock->ReflowInlineChild(mKidFrame, mPresContext,
|
||||||
|
kidSize, kidAvailSize, kidMaxElementSize,
|
||||||
|
kidReflowStatus);
|
||||||
|
kidRect.x = dx;
|
||||||
|
kidRect.y = mY;
|
||||||
|
kidRect.width = kidSize.width;
|
||||||
|
kidRect.height = kidSize.height;
|
||||||
|
}
|
||||||
if (NS_OK != rv) return rv;
|
if (NS_OK != rv) return rv;
|
||||||
|
|
||||||
// See if the child fit
|
// See if the child fit
|
||||||
@ -367,27 +460,14 @@ nsLineLayout::ReflowChild()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if XXX
|
// For non-aware children they act like words which means that space
|
||||||
// Now that the child fit, see where to go next
|
// immediately following them must not be skipped over.
|
||||||
switch (mReflowResult) {
|
if (NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE == mReflowResult) {
|
||||||
case NS_LINE_LAYOUT_NOT_AWARE:
|
|
||||||
// The child did not update our reflow state. This means that it's
|
|
||||||
// the kind of child that doesn't interact with us directly which
|
|
||||||
// means we have to treat it carefully. An example of such a child
|
|
||||||
// is an html image.
|
|
||||||
mSkipLeadingWhiteSpace = PR_FALSE;
|
mSkipLeadingWhiteSpace = PR_FALSE;
|
||||||
mWordStart = nsnull;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Place child
|
// Place child
|
||||||
nsRect pos;
|
mKidFrame->SetRect(kidRect);
|
||||||
pos.x = mReflowData.mX + kidSpacing->mMargin.left;
|
|
||||||
pos.y = mY;
|
|
||||||
pos.width = kidSize.width;
|
|
||||||
pos.height = kidSize.height;
|
|
||||||
mKidFrame->SetRect(pos);
|
|
||||||
|
|
||||||
// Advance
|
// Advance
|
||||||
// XXX RTL
|
// XXX RTL
|
||||||
@ -413,14 +493,17 @@ nsLineLayout::ReflowChild()
|
|||||||
if (kidSize.descent > mReflowData.mMaxDescent) {
|
if (kidSize.descent > mReflowData.mMaxDescent) {
|
||||||
mReflowData.mMaxDescent = kidSize.descent;
|
mReflowData.mMaxDescent = kidSize.descent;
|
||||||
}
|
}
|
||||||
|
AddAscent(isBlock ? 0 : kidSize.ascent);
|
||||||
|
mLine->mIsBlock = isBlock;
|
||||||
|
|
||||||
// Set completion status
|
// Set completion status
|
||||||
mLine->mLastContentOffset = mKidIndex;
|
mLine->mLastContentOffset = mKidIndex;
|
||||||
if (nsIFrame::frComplete == kidReflowStatus) {
|
if (nsIFrame::frComplete == kidReflowStatus) {
|
||||||
mLine->mLastContentIsComplete = PR_TRUE;
|
mLine->mLastContentIsComplete = PR_TRUE;
|
||||||
rv = isBlock
|
if (isBlock ||
|
||||||
? NS_LINE_LAYOUT_BREAK_AFTER
|
(NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER == mReflowResult)) {
|
||||||
: NS_LINE_LAYOUT_COMPLETE;
|
rv = NS_LINE_LAYOUT_BREAK_AFTER;
|
||||||
|
}
|
||||||
mKidPrevInFlow = nsnull;
|
mKidPrevInFlow = nsnull;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -509,7 +592,7 @@ nsLineLayout::SplitLine(PRInt32 aChildReflowStatus, PRInt32 aRemainingKids)
|
|||||||
// to compute them so don't bother.
|
// to compute them so don't bother.
|
||||||
#ifdef NS_DEBUG
|
#ifdef NS_DEBUG
|
||||||
to->mLastContentOffset = -1;
|
to->mLastContentOffset = -1;
|
||||||
to->mLastContentIsComplete = PRBool(-1);
|
to->mLastContentIsComplete = PRPackedBool(0x255);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
from->mChildCount -= aRemainingKids;
|
from->mChildCount -= aRemainingKids;
|
||||||
@ -948,7 +1031,12 @@ nsLineLayout::ReflowLine()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform alignment operations
|
// Perform alignment operations
|
||||||
AlignChildren();
|
if (mLine->mIsBlock) {
|
||||||
|
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
AlignChildren();
|
||||||
|
}
|
||||||
|
|
||||||
// Set final bounds of the line
|
// Set final bounds of the line
|
||||||
mLine->mBounds.height = mLineHeight;
|
mLine->mBounds.height = mLineHeight;
|
||||||
@ -967,9 +1055,37 @@ nsLineLayout::ReflowLine()
|
|||||||
nsresult
|
nsresult
|
||||||
nsLineLayout::AlignChildren()
|
nsLineLayout::AlignChildren()
|
||||||
{
|
{
|
||||||
|
NS_PRECONDITION(mLine->mChildCount == mAscentNum, "bad line reflow");
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
mLineHeight = mReflowData.mMaxAscent + mReflowData.mMaxDescent;/* XXX */
|
nsIStyleContextPtr blockSC;
|
||||||
|
mBlock->GetStyleContext(mPresContext, blockSC.AssignRef());
|
||||||
|
nsStyleFont* blockFont = (nsStyleFont*)
|
||||||
|
blockSC->GetData(kStyleFontSID);
|
||||||
|
nsStyleText* blockText = (nsStyleText*)
|
||||||
|
blockSC->GetData(kStyleTextSID);
|
||||||
|
|
||||||
|
// First vertically align the children on the line; this will
|
||||||
|
// compute the actual line height for us.
|
||||||
|
mLineHeight =
|
||||||
|
nsCSSLayout::VerticallyAlignChildren(mPresContext, mBlock, blockFont,
|
||||||
|
mY,
|
||||||
|
mLine->mFirstChild,
|
||||||
|
mLine->mChildCount,
|
||||||
|
mAscents, mReflowData.mMaxAscent);
|
||||||
|
|
||||||
|
// Now horizontally place the children
|
||||||
|
nsCSSLayout::HorizontallyPlaceChildren(mPresContext, mBlock, blockText,
|
||||||
|
mLine->mFirstChild,
|
||||||
|
mLine->mChildCount,
|
||||||
|
mReflowData.mX - mX0,
|
||||||
|
mMaxWidth);
|
||||||
|
|
||||||
|
// Last, apply relative positioning
|
||||||
|
nsCSSLayout::RelativePositionChildren(mPresContext, mBlock,
|
||||||
|
mLine->mFirstChild,
|
||||||
|
mLine->mChildCount);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "nsSize.h"
|
#include "nsSize.h"
|
||||||
|
|
||||||
class nsIPresContext;
|
class nsIPresContext;
|
||||||
|
class nsISpaceManager;
|
||||||
class nsBlockFrame;
|
class nsBlockFrame;
|
||||||
struct nsBlockReflowState;
|
struct nsBlockReflowState;
|
||||||
|
|
||||||
@ -34,10 +35,11 @@ struct nsLineData {
|
|||||||
~nsLineData();
|
~nsLineData();
|
||||||
|
|
||||||
nsIFrame* GetLastChild();
|
nsIFrame* GetLastChild();
|
||||||
nsresult Verify() const;
|
nsresult Verify(PRBool aFinalCheck = PR_TRUE) const;
|
||||||
void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
|
||||||
void UnlinkLine();
|
void UnlinkLine();
|
||||||
PRIntn GetLineNumber() const;
|
PRIntn GetLineNumber() const;
|
||||||
|
void MoveLineBy(nscoord dx, nscoord dy);
|
||||||
|
|
||||||
nsLineData* mNextLine;
|
nsLineData* mNextLine;
|
||||||
nsLineData* mPrevLine;
|
nsLineData* mPrevLine;
|
||||||
@ -47,6 +49,8 @@ struct nsLineData {
|
|||||||
PRInt32 mLastContentOffset;
|
PRInt32 mLastContentOffset;
|
||||||
nsRect mBounds;
|
nsRect mBounds;
|
||||||
PRPackedBool mLastContentIsComplete;
|
PRPackedBool mLastContentIsComplete;
|
||||||
|
PRPackedBool mHasBullet;
|
||||||
|
PRPackedBool mIsBlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
@ -64,12 +68,12 @@ struct nsLineLayoutReflowData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct nsLineLayout {
|
struct nsLineLayout {
|
||||||
nsLineLayout();
|
nsLineLayout(nsBlockReflowState& aState);
|
||||||
~nsLineLayout();
|
~nsLineLayout();
|
||||||
|
|
||||||
nsresult Initialize(nsBlockReflowState& aState,
|
nsresult Initialize(nsBlockReflowState& aState, nsLineData* aLine);
|
||||||
nsLineData* aLine,
|
|
||||||
const nsRect& aAvailSpace);
|
void SetReflowSpace(nsRect& aAvailableSpaceRect);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <h2>Rules of order</h2>
|
* <h2>Rules of order</h2>
|
||||||
@ -101,6 +105,7 @@ struct nsLineLayout {
|
|||||||
|
|
||||||
// The block behind the line
|
// The block behind the line
|
||||||
nsBlockFrame* mBlock;
|
nsBlockFrame* mBlock;
|
||||||
|
nsISpaceManager* mSpaceManager;
|
||||||
PRBool mBlockIsPseudo;
|
PRBool mBlockIsPseudo;
|
||||||
nsIContent* mBlockContent;
|
nsIContent* mBlockContent;
|
||||||
PRInt32 mKidIndex;
|
PRInt32 mKidIndex;
|
||||||
@ -116,17 +121,23 @@ struct nsLineLayout {
|
|||||||
// width remains and the maximum element size so far.
|
// width remains and the maximum element size so far.
|
||||||
nsLineLayoutReflowData mReflowData;
|
nsLineLayoutReflowData mReflowData;
|
||||||
|
|
||||||
|
// This is set by the block code when it updates the available
|
||||||
|
// reflow area when a floater is placed.
|
||||||
|
PRBool mReflowDataChanged;
|
||||||
|
|
||||||
PRPackedBool mUnconstrainedWidth;
|
PRPackedBool mUnconstrainedWidth;
|
||||||
PRPackedBool mUnconstrainedHeight;
|
PRPackedBool mUnconstrainedHeight;
|
||||||
nscoord mY;
|
nscoord mY;
|
||||||
nscoord mLineHeight;
|
nscoord mLineHeight;
|
||||||
nscoord mAvailHeight;
|
nscoord mMaxWidth;
|
||||||
|
nscoord mMaxHeight;
|
||||||
nsSize* mMaxElementSizePointer;
|
nsSize* mMaxElementSizePointer;
|
||||||
nscoord mX0;
|
nscoord mX0;
|
||||||
|
|
||||||
nscoord* mAscents;
|
nscoord* mAscents;
|
||||||
nscoord mAscentBuf[20];
|
nscoord mAscentBuf[20];
|
||||||
nscoord mMaxAscents;
|
nscoord mMaxAscents;
|
||||||
|
nscoord mAscentNum;
|
||||||
|
|
||||||
// The current type of reflow in progress. Normally, this value is
|
// The current type of reflow in progress. Normally, this value is
|
||||||
// set to NS_LINE_LAYOUT_NORMAL_REFLOW. However, in the special case
|
// set to NS_LINE_LAYOUT_NORMAL_REFLOW. However, in the special case
|
||||||
@ -158,9 +169,12 @@ struct nsLineLayout {
|
|||||||
nsLineLayoutReflowData mWordStartReflowData;
|
nsLineLayoutReflowData mWordStartReflowData;
|
||||||
|
|
||||||
PRBool mSkipLeadingWhiteSpace;
|
PRBool mSkipLeadingWhiteSpace;
|
||||||
|
PRInt32 mColumn;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
nsresult AddAscent(nscoord aAscent);
|
||||||
|
|
||||||
nsresult WordBreakReflow();
|
nsresult WordBreakReflow();
|
||||||
|
|
||||||
nsresult ReflowChild();
|
nsresult ReflowChild();
|
||||||
@ -189,7 +203,9 @@ protected:
|
|||||||
#define NS_LINE_LAYOUT_REFLOW_TYPE_WORD_WRAP 1
|
#define NS_LINE_LAYOUT_REFLOW_TYPE_WORD_WRAP 1
|
||||||
|
|
||||||
// Value's for nsLineLayout.mReflowResult
|
// Value's for nsLineLayout.mReflowResult
|
||||||
#define NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE 0
|
#define NS_LINE_LAYOUT_REFLOW_RESULT_NOT_AWARE 0
|
||||||
|
#define NS_LINE_LAYOUT_REFLOW_RESULT_AWARE 1
|
||||||
|
#define NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER 2
|
||||||
|
|
||||||
// Return value's from nsLineLayout reflow methods
|
// Return value's from nsLineLayout reflow methods
|
||||||
#define NS_LINE_LAYOUT_COMPLETE 0
|
#define NS_LINE_LAYOUT_COMPLETE 0
|
||||||
|
Loading…
Reference in New Issue
Block a user