This commit is contained in:
troy 1998-05-11 18:38:10 +00:00
Родитель 3fe3d7ca6d
Коммит eaaa05815e
15 изменённых файлов: 462 добавлений и 104 удалений

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

@ -319,8 +319,7 @@ public:
/**
* This call is invoked when content is changed in the content tree.
* The first frame that maps that content is asked to deal with the
* change by generating an incremental reflow command which will be
* to reflow the frame tree.
* change by generating an incremental reflow command.
*
* @param aIndexInParent the index in the content container where
* the new content was deleted.

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

@ -958,13 +958,24 @@ NS_METHOD nsFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsReflowCommand& aReflowCommand,
ReflowStatus& aStatus)
{
NS_ERROR("not a reflow command handler");
aDesiredSize.width = 0;
aDesiredSize.height = 0;
aDesiredSize.ascent = 0;
aDesiredSize.descent = 0;
aStatus = frComplete;
return NS_ERROR_NOT_IMPLEMENTED;
NS_PRECONDITION(aReflowCommand.GetTarget() == this, "bad target");
// The only type of incremental reflow command we expect to get is a
// content changed reflow command
if (aReflowCommand.GetType() == nsReflowCommand.ContentChanged) {
// Generic response is to reflow the child
return ResizeReflow(aPresContext, aDesiredSize, aMaxSize, nsnull, aStatus);
} else {
NS_ERROR("not a container reflow command handler");
aDesiredSize.width = 0;
aDesiredSize.height = 0;
aDesiredSize.ascent = 0;
aDesiredSize.descent = 0;
aStatus = frComplete;
return NS_ERROR_NOT_IMPLEMENTED;
}
}
NS_METHOD nsFrame::ContentAppended(nsIPresShell* aShell,
@ -1007,10 +1018,9 @@ NS_METHOD nsFrame::ContentChanged(nsIPresShell* aShell,
nsIContent* aChild,
nsISupports* aSubContent)
{
// Generate a reflow command with our geometric parent as the target,
// and us as the child frame
nsReflowCommand* cmd = new nsReflowCommand(aPresContext, mGeometricParent,
nsReflowCommand::ContentChanged, this);
// Generate a reflow command with this frame as the target frame
nsReflowCommand* cmd = new nsReflowCommand(aPresContext, this,
nsReflowCommand::ContentChanged);
aShell->AppendReflowCommand(cmd);
return NS_OK;
}

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

@ -525,16 +525,12 @@ PresShell::ContentChanged(nsIContent* aContent,
{
NS_PRECONDITION(nsnull != mRootFrame, "null root frame");
#if XXX_enable_once_content_changed_is_limping
// Notify the first frame that maps the content. It will generate a reflow
// command
nsIFrame* frame = FindFrameWithContent(aContent);
NS_PRECONDITION(nsnull != frame, "null frame");
frame->ContentChanged(this, mPresContext, aContent, aSubContent);
ProcessReflowCommands();
#else
mResizeReflows++;
#endif
}
void

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

@ -29,13 +29,16 @@ class nsReflowCommand {
public:
enum ReflowType {
// Reflow commands generated in response to a content insert/delete/append
// notification
// notification. The target of the reflow command is the container frame
// itself
FrameAppended,
FrameInserted,
FrameDeleted,
// This reflow command is used when a leaf node's content changes
// (e.g. some text in a text run, an image's source, etc.)
// This reflow command is used when a leaf node's content changes (e.g. some
// text in a text run, an image's source, etc.). The target of the reflow
// command is the frame that changed (see nsIFrame#ContentChanged() for how
// the target frame is determined).
ContentChanged,
// When an incremental reflow operation affects a next-in-flow,

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

@ -1368,7 +1368,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
else {
rv = ReflowUnmapped(state);
}
#if 0
} else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
// Restore our state as if the child that changed is the next frame to reflow
nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
@ -1380,7 +1380,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
#endif
} else {
NS_NOTYETIMPLEMENTED("unexpected reflow command");
}

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

@ -1368,7 +1368,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
else {
rv = ReflowUnmapped(state);
}
#if 0
} else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
// Restore our state as if the child that changed is the next frame to reflow
nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
@ -1380,7 +1380,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
#endif
} else {
NS_NOTYETIMPLEMENTED("unexpected reflow command");
}

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

@ -1368,7 +1368,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
else {
rv = ReflowUnmapped(state);
}
#if 0
} else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
// Restore our state as if the child that changed is the next frame to reflow
nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
@ -1380,7 +1380,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
#endif
} else {
NS_NOTYETIMPLEMENTED("unexpected reflow command");
}

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

@ -319,8 +319,7 @@ public:
/**
* This call is invoked when content is changed in the content tree.
* The first frame that maps that content is asked to deal with the
* change by generating an incremental reflow command which will be
* to reflow the frame tree.
* change by generating an incremental reflow command.
*
* @param aIndexInParent the index in the content container where
* the new content was deleted.

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

@ -29,6 +29,7 @@
#include "nsHTMLAtoms.h"
#include "nsAbsoluteFrame.h"
#include "nsLeafFrame.h"
#include "nsIPtr.h"
// XXX To Do:
// 2. horizontal child margins
@ -49,6 +50,10 @@ static NS_DEFINE_IID(kStyleFontSID, NS_STYLEFONT_SID);
static NS_DEFINE_IID(kStyleDisplaySID, NS_STYLEDISPLAY_SID);
static NS_DEFINE_IID(kStyleSpacingSID, NS_STYLESPACING_SID);
NS_DEF_PTR(nsIStyleContext);
NS_DEF_PTR(nsIContent);
NS_DEF_PTR(nsIContentDelegate);
class nsInlineState
{
public:
@ -192,18 +197,22 @@ void nsInlineFrame::PlaceChild(nsIFrame* aChild,
*
* @param aPresContext presentation context to use
* @param aState current inline state
* @param aChildFrame the first child frame to reflow
* @param aChildIndex the first child frame's index in the frame list
* @return true if we successfully reflowed all the mapped children and false
* otherwise, e.g. we pushed children to the next in flow
*/
PRBool nsInlineFrame::ReflowMappedChildren(nsIPresContext* aPresContext,
nsInlineState& aState)
PRBool nsInlineFrame::ReflowMappedChildrenFrom(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex)
{
#ifdef NS_DEBUG
VerifyLastIsComplete();
#endif
NS_PRECONDITION(nsnull != mFirstChild, "no children");
NS_PRECONDITION(nsnull != aChildFrame, "no children");
PRInt32 childCount = 0;
PRInt32 childCount = aChildIndex;
nsIFrame* prevKidFrame = nsnull;
// Remember our original mLastContentIsComplete so that if we end up
@ -215,7 +224,7 @@ PRBool nsInlineFrame::ReflowMappedChildren(nsIPresContext* aPresContext,
nsSize* pKidMaxElementSize = (nsnull != aState.maxElementSize) ? &kidMaxElementSize : nsnull;
PRBool result = PR_TRUE;
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) {
for (nsIFrame* kidFrame = aChildFrame; nsnull != kidFrame; ) {
nsReflowMetrics kidSize;
ReflowStatus status;
@ -259,11 +268,10 @@ PRBool nsInlineFrame::ReflowMappedChildren(nsIPresContext* aPresContext,
// frame. This hooks the child into the flow
nsIFrame* continuingFrame;
nsIStyleContext* kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC);
nsIStyleContextPtr kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
continuingFrame);
NS_RELEASE(kidSC);
NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
// Add the continuing frame to the sibling list
@ -447,11 +455,10 @@ PRBool nsInlineFrame::PullUpChildren(nsIPresContext* aPresContext,
// prepares it for reflow.
nsIFrame* continuingFrame;
nsIStyleContext* kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC);
nsIStyleContextPtr kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
continuingFrame);
NS_RELEASE(kidSC);
NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
// Add the continuing frame to our sibling list and then push
@ -554,7 +561,7 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
LastChild(prevKidFrame);
for (;;) {
// Get the next content object
nsIContent* kid = mContent->ChildAt(kidIndex);
nsIContentPtr kid = mContent->ChildAt(kidIndex);
if (nsnull == kid) {
result = frComplete;
break;
@ -563,13 +570,11 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
// Make sure we still have room left
if (aState.availSize.width <= 0) {
// Note: return status was set to frNotComplete above...
NS_RELEASE(kid);
break;
}
// Resolve style for the child
nsIStyleContext* kidStyleContext =
aPresContext->ResolveStyleContextFor(kid, this);
nsIStyleContextPtr kidStyleContext = aPresContext->ResolveStyleContextFor(kid, this);
// Figure out how we should treat the child
nsIFrame* kidFrame;
@ -591,15 +596,13 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
kidFrame->SetStyleContext(aPresContext, kidStyleContext);
}
} else if (nsnull == kidPrevInFlow) {
nsIContentDelegate* kidDel;
nsIContentDelegatePtr kidDel;
switch (kidDisplay->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
if (kidIndex != mFirstContentOffset) {
// We don't allow block elements to be placed in us anywhere
// other than at our left margin.
NS_RELEASE(kidStyleContext);
NS_RELEASE(kid);
goto done;
}
// FALLTHROUGH
@ -608,7 +611,6 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
kidDel = kid->GetDelegate(aPresContext);
rv = kidDel->CreateFrame(aPresContext, kid, this,
kidStyleContext, kidFrame);
NS_RELEASE(kidDel);
break;
default:
@ -623,8 +625,6 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
rv = kidPrevInFlow->CreateContinuingFrame(aPresContext, this,
kidStyleContext, kidFrame);
}
NS_RELEASE(kid);
NS_RELEASE(kidStyleContext);
// Try to reflow the child into the available space. It might not
// fit or might need continuing.
@ -732,7 +732,7 @@ NS_METHOD nsInlineFrame::ResizeReflow(nsIPresContext* aPresContext,
// Reflow any existing frames
if (nsnull != mFirstChild) {
reflowMappedOK = ReflowMappedChildren(aPresContext, state);
reflowMappedOK = ReflowMappedChildrenFrom(aPresContext, state, mFirstChild, 0);
if (PR_FALSE == reflowMappedOK) {
aStatus = frNotComplete;
@ -854,14 +854,14 @@ NS_METHOD nsInlineFrame::GetReflowMetrics(nsIPresContext* aPresContext,
* of aSkipChild in our list of children.
* If aSkipChild is nsnull then resets the state for appended content.
*/
PRIntn nsInlineFrame::RecoverState(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aSkipChild)
PRInt32 nsInlineFrame::RecoverState(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aSkipChild)
{
// Get ascent & descent info for all the children up to but not
// including aSkipChild. Also compute the x coordinate for where
// aSkipChild will be place after it is reflowed.
PRIntn i = 0;
PRInt32 i = 0;
nsIFrame* kid = mFirstChild;
nscoord x = aState.x;
nscoord maxAscent = 0;
@ -885,6 +885,78 @@ PRIntn nsInlineFrame::RecoverState(nsIPresContext* aPresContext,
return i;
}
// XXX We need to return information about whether our next-in-flow is
// dirty...
nsIFrame::ReflowStatus
nsInlineFrame::IncrementalReflowFrom(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex)
{
ReflowStatus status = frComplete;
// Just reflow all the mapped children starting with childFrame.
// XXX This isn't the optimal thing to do...
if (ReflowMappedChildrenFrom(aPresContext, aState, aChildFrame, aChildIndex)) {
if (NextChildOffset() < mContent->ChildCount()) {
// Any space left?
if (aState.availSize.width <= 0) {
// No space left. Don't try to pull-up children
status = frNotComplete;
} else {
// Try and pull-up some children from a next-in-flow
if (!PullUpChildren(aPresContext, aState)) {
// We were not able to pull-up all the child frames from our
// next-in-flow
status = frNotComplete;
}
}
}
} else {
// We were unable to reflow all our mapped frames
status = frNotComplete;
}
return status;
}
nsIFrame::ReflowStatus
nsInlineFrame::IncrementalReflowAfter(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex)
{
ReflowStatus status = frComplete;
nsIFrame* nextFrame;
aChildFrame->GetNextSibling(nextFrame);
// Just reflow all the remaining mapped children
// XXX This isn't the optimal thing to do...
if ((nsnull == nextFrame) ||
ReflowMappedChildrenFrom(aPresContext, aState, nextFrame, aChildIndex + 1)) {
if (NextChildOffset() < mContent->ChildCount()) {
// Any space left?
if (aState.availSize.width <= 0) {
// No space left. Don't try to pull-up children
status = frNotComplete;
} else {
// Try and pull-up some children from a next-in-flow
if (!PullUpChildren(aPresContext, aState)) {
// We were not able to pull-up all the child frames from our
// next-in-flow
status = frNotComplete;
}
}
}
} else {
// We were unable to reflow all our mapped frames
status = frNotComplete;
}
return status;
}
NS_METHOD nsInlineFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
@ -899,7 +971,9 @@ NS_METHOD nsInlineFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsStyleSpacing* styleSpacing =
(nsStyleSpacing*)mStyleContext->GetData(kStyleSpacingSID);
nscoord lineHeight;
nscoord lineHeight;
nsIFrame* kidFrame;
PRInt32 kidIndex;
nsInlineState state(styleFont, styleSpacing, aMaxSize, nsnull);
InitializeState(aPresContext, state);
@ -913,22 +987,112 @@ NS_METHOD nsInlineFrame::IncrementalReflow(nsIPresContext* aPresContext,
aStatus = ReflowUnmappedChildren(aPresContext, state);
// Vertically align the children
lineHeight =
nsCSSLayout::VerticallyAlignChildren(aPresContext, this, styleFont,
styleSpacing->mBorderPadding.top,
mFirstChild, mChildCount,
state.ascents, state.maxAscent);
lineHeight = nsCSSLayout::VerticallyAlignChildren(aPresContext, this,
styleFont, styleSpacing->mBorderPadding.top, mFirstChild,
mChildCount, state.ascents, state.maxAscent);
ComputeFinalSize(aPresContext, state, aDesiredSize);
break;
#if 0
case nsReflowCommand::ContentChanged:
// Recover our state
kidFrame = aReflowCommand.GetChildFrame();
kidIndex = RecoverState(aPresContext, state, kidFrame);
aStatus = IncrementalReflowFrom(aPresContext, state, kidFrame, kidIndex);
// Vertically align the children
lineHeight = nsCSSLayout::VerticallyAlignChildren(aPresContext, this,
styleFont, styleSpacing->mBorderPadding.top, mFirstChild,
mChildCount, state.ascents, state.maxAscent);
ComputeFinalSize(aPresContext, state, aDesiredSize);
break;
#endif
default:
NS_NOTYETIMPLEMENTED("unexpected reflow command");
break;
}
} else {
NS_NOTYETIMPLEMENTED("unexpected reflow command");
// The command is passing through us. Get the next frame in the reflow chain
nsIFrame* kidFrame = aReflowCommand.GetNext();
nsReflowMetrics kidSize;
// Restore our state as if nextFrame is the next frame to reflow
kidIndex = RecoverState(aPresContext, state, kidFrame);
// Reflow the child into the available space
aStatus = aReflowCommand.Next(kidSize, state.availSize, kidFrame);
// Did the child fit?
if ((kidSize.width > state.availSize.width) && (kidFrame != mFirstChild)) {
nsIFrame* prevFrame;
// The child is too wide to fit in the available space, and it's not our
// first child
PrevChild(kidFrame, prevFrame);
PushChildren(kidFrame, prevFrame, mLastContentIsComplete);
SetLastContentOffset(prevFrame);
mChildCount = kidIndex - 1;
aStatus = frNotComplete;
} else {
// Place and size the child
PlaceChild(kidFrame, kidIndex, state, kidSize, nsnull);
nsIFrame* kidNextInFlow;
kidFrame->GetNextInFlow(kidNextInFlow);
// Is the child complete?
if (frComplete == aStatus) {
// Check whether the frame has next-in-flow(s) that are no longer needed
if (nsnull != kidNextInFlow) {
// Remove the next-in-flow(s)
DeleteChildsNextInFlow(kidFrame);
}
// Adjust the frames that follow
aStatus = IncrementalReflowAfter(aPresContext, state, kidFrame, kidIndex);
} else {
nsIFrame* nextSibling;
// No, the child isn't complete
if (nsnull == kidNextInFlow) {
// The child doesn't have a next-in-flow so create a continuing
// frame.
nsIFrame* continuingFrame;
nsIStyleContextPtr kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC, continuingFrame);
// Link the child into the sibling list
kidFrame->GetNextSibling(nextSibling);
continuingFrame->SetNextSibling(nextSibling);
kidFrame->SetNextSibling(continuingFrame);
}
// We've used up all of our available space, so push the remaining
// children to the next-in-flow
kidFrame->GetNextSibling(nextSibling);
if (nsnull != nextSibling) {
PushChildren(nextSibling, kidFrame, mLastContentIsComplete);
}
SetLastContentOffset(kidFrame);
mChildCount = kidIndex;
}
}
// Vertically align the children
lineHeight = nsCSSLayout::VerticallyAlignChildren(aPresContext, this,
styleFont, styleSpacing->mBorderPadding.top, mFirstChild,
mChildCount, state.ascents, state.maxAscent);
ComputeFinalSize(aPresContext, state, aDesiredSize);
}
return NS_OK;
}

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

@ -59,8 +59,10 @@ protected:
nsInlineState& aState,
nsReflowMetrics& aSize);
PRBool ReflowMappedChildren(nsIPresContext* aPresContext,
nsInlineState& aState);
PRBool ReflowMappedChildrenFrom(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex);
PRBool PullUpChildren(nsIPresContext* aPresContext,
nsInlineState& aState);
@ -74,8 +76,19 @@ protected:
const nsReflowMetrics& aChildSize,
const nsSize* aChildMaxElementSize);
PRIntn RecoverState(nsIPresContext* aCX, nsInlineState& aState,
nsIFrame* aSkipChild);
PRInt32 RecoverState(nsIPresContext* aCX,
nsInlineState& aState,
nsIFrame* aSkipChild);
ReflowStatus IncrementalReflowFrom(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex);
ReflowStatus IncrementalReflowAfter(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex);
ReflowStatus AdjustChildren(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,

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

@ -1368,7 +1368,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
else {
rv = ReflowUnmapped(state);
}
#if 0
} else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
// Restore our state as if the child that changed is the next frame to reflow
nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
@ -1380,7 +1380,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
#endif
} else {
NS_NOTYETIMPLEMENTED("unexpected reflow command");
}

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

@ -1368,7 +1368,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
else {
rv = ReflowUnmapped(state);
}
#if 0
} else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
// Restore our state as if the child that changed is the next frame to reflow
nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
@ -1380,7 +1380,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
#endif
} else {
NS_NOTYETIMPLEMENTED("unexpected reflow command");
}

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

@ -1368,7 +1368,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
else {
rv = ReflowUnmapped(state);
}
#if 0
} else if (aReflowCommand.GetType() == nsReflowCommand::ContentChanged) {
// Restore our state as if the child that changed is the next frame to reflow
nsLineData* line = FindLine(aReflowCommand.GetChildFrame());
@ -1380,7 +1380,7 @@ nsBlockFrame::IncrementalReflow(nsIPresContext* aPresContext,
// Reflow the affected line, and all the lines that follow...
// XXX Obviously this needs to be more efficient
rv = ReflowMappedFrom(state, line);
#endif
} else {
NS_NOTYETIMPLEMENTED("unexpected reflow command");
}

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

@ -251,6 +251,14 @@ NS_METHOD nsBodyFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsReflowCommand& aReflowCommand,
ReflowStatus& aStatus)
{
// XXX Currently there's a bug that when the body background image dimension
// is resolved we're treating that as a content change rather than just repainting
// the body...
if (aReflowCommand.GetTarget() == this) {
NS_ASSERTION(aReflowCommand.GetType() == nsReflowCommand::ContentChanged, "unexpected type");
return ResizeReflow(aPresContext, aDesiredSize, aMaxSize, nsnull, aStatus);
}
// Get our border/padding info
nsStyleSpacing* mySpacing =
(nsStyleSpacing*)mStyleContext->GetData(kStyleSpacingSID);
@ -265,8 +273,10 @@ NS_METHOD nsBodyFrame::IncrementalReflow(nsIPresContext* aPresContext,
mSpaceManager->Translate(leftInset, topInset);
#if 0
// The reflow command should never be target for us
NS_ASSERTION(aReflowCommand.GetTarget() != this, "bad reflow command target");
#endif
// Compute the child frame's max size
nsSize columnMaxSize = GetColumnAvailSpace(aPresContext, mySpacing,

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

@ -29,6 +29,7 @@
#include "nsHTMLAtoms.h"
#include "nsAbsoluteFrame.h"
#include "nsLeafFrame.h"
#include "nsIPtr.h"
// XXX To Do:
// 2. horizontal child margins
@ -49,6 +50,10 @@ static NS_DEFINE_IID(kStyleFontSID, NS_STYLEFONT_SID);
static NS_DEFINE_IID(kStyleDisplaySID, NS_STYLEDISPLAY_SID);
static NS_DEFINE_IID(kStyleSpacingSID, NS_STYLESPACING_SID);
NS_DEF_PTR(nsIStyleContext);
NS_DEF_PTR(nsIContent);
NS_DEF_PTR(nsIContentDelegate);
class nsInlineState
{
public:
@ -192,18 +197,22 @@ void nsInlineFrame::PlaceChild(nsIFrame* aChild,
*
* @param aPresContext presentation context to use
* @param aState current inline state
* @param aChildFrame the first child frame to reflow
* @param aChildIndex the first child frame's index in the frame list
* @return true if we successfully reflowed all the mapped children and false
* otherwise, e.g. we pushed children to the next in flow
*/
PRBool nsInlineFrame::ReflowMappedChildren(nsIPresContext* aPresContext,
nsInlineState& aState)
PRBool nsInlineFrame::ReflowMappedChildrenFrom(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex)
{
#ifdef NS_DEBUG
VerifyLastIsComplete();
#endif
NS_PRECONDITION(nsnull != mFirstChild, "no children");
NS_PRECONDITION(nsnull != aChildFrame, "no children");
PRInt32 childCount = 0;
PRInt32 childCount = aChildIndex;
nsIFrame* prevKidFrame = nsnull;
// Remember our original mLastContentIsComplete so that if we end up
@ -215,7 +224,7 @@ PRBool nsInlineFrame::ReflowMappedChildren(nsIPresContext* aPresContext,
nsSize* pKidMaxElementSize = (nsnull != aState.maxElementSize) ? &kidMaxElementSize : nsnull;
PRBool result = PR_TRUE;
for (nsIFrame* kidFrame = mFirstChild; nsnull != kidFrame; ) {
for (nsIFrame* kidFrame = aChildFrame; nsnull != kidFrame; ) {
nsReflowMetrics kidSize;
ReflowStatus status;
@ -259,11 +268,10 @@ PRBool nsInlineFrame::ReflowMappedChildren(nsIPresContext* aPresContext,
// frame. This hooks the child into the flow
nsIFrame* continuingFrame;
nsIStyleContext* kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC);
nsIStyleContextPtr kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
continuingFrame);
NS_RELEASE(kidSC);
NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
// Add the continuing frame to the sibling list
@ -447,11 +455,10 @@ PRBool nsInlineFrame::PullUpChildren(nsIPresContext* aPresContext,
// prepares it for reflow.
nsIFrame* continuingFrame;
nsIStyleContext* kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC);
nsIStyleContextPtr kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC,
continuingFrame);
NS_RELEASE(kidSC);
NS_ASSERTION(nsnull != continuingFrame, "frame creation failed");
// Add the continuing frame to our sibling list and then push
@ -554,7 +561,7 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
LastChild(prevKidFrame);
for (;;) {
// Get the next content object
nsIContent* kid = mContent->ChildAt(kidIndex);
nsIContentPtr kid = mContent->ChildAt(kidIndex);
if (nsnull == kid) {
result = frComplete;
break;
@ -563,13 +570,11 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
// Make sure we still have room left
if (aState.availSize.width <= 0) {
// Note: return status was set to frNotComplete above...
NS_RELEASE(kid);
break;
}
// Resolve style for the child
nsIStyleContext* kidStyleContext =
aPresContext->ResolveStyleContextFor(kid, this);
nsIStyleContextPtr kidStyleContext = aPresContext->ResolveStyleContextFor(kid, this);
// Figure out how we should treat the child
nsIFrame* kidFrame;
@ -591,15 +596,13 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
kidFrame->SetStyleContext(aPresContext, kidStyleContext);
}
} else if (nsnull == kidPrevInFlow) {
nsIContentDelegate* kidDel;
nsIContentDelegatePtr kidDel;
switch (kidDisplay->mDisplay) {
case NS_STYLE_DISPLAY_BLOCK:
case NS_STYLE_DISPLAY_LIST_ITEM:
if (kidIndex != mFirstContentOffset) {
// We don't allow block elements to be placed in us anywhere
// other than at our left margin.
NS_RELEASE(kidStyleContext);
NS_RELEASE(kid);
goto done;
}
// FALLTHROUGH
@ -608,7 +611,6 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
kidDel = kid->GetDelegate(aPresContext);
rv = kidDel->CreateFrame(aPresContext, kid, this,
kidStyleContext, kidFrame);
NS_RELEASE(kidDel);
break;
default:
@ -623,8 +625,6 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
rv = kidPrevInFlow->CreateContinuingFrame(aPresContext, this,
kidStyleContext, kidFrame);
}
NS_RELEASE(kid);
NS_RELEASE(kidStyleContext);
// Try to reflow the child into the available space. It might not
// fit or might need continuing.
@ -732,7 +732,7 @@ NS_METHOD nsInlineFrame::ResizeReflow(nsIPresContext* aPresContext,
// Reflow any existing frames
if (nsnull != mFirstChild) {
reflowMappedOK = ReflowMappedChildren(aPresContext, state);
reflowMappedOK = ReflowMappedChildrenFrom(aPresContext, state, mFirstChild, 0);
if (PR_FALSE == reflowMappedOK) {
aStatus = frNotComplete;
@ -854,14 +854,14 @@ NS_METHOD nsInlineFrame::GetReflowMetrics(nsIPresContext* aPresContext,
* of aSkipChild in our list of children.
* If aSkipChild is nsnull then resets the state for appended content.
*/
PRIntn nsInlineFrame::RecoverState(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aSkipChild)
PRInt32 nsInlineFrame::RecoverState(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aSkipChild)
{
// Get ascent & descent info for all the children up to but not
// including aSkipChild. Also compute the x coordinate for where
// aSkipChild will be place after it is reflowed.
PRIntn i = 0;
PRInt32 i = 0;
nsIFrame* kid = mFirstChild;
nscoord x = aState.x;
nscoord maxAscent = 0;
@ -885,6 +885,78 @@ PRIntn nsInlineFrame::RecoverState(nsIPresContext* aPresContext,
return i;
}
// XXX We need to return information about whether our next-in-flow is
// dirty...
nsIFrame::ReflowStatus
nsInlineFrame::IncrementalReflowFrom(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex)
{
ReflowStatus status = frComplete;
// Just reflow all the mapped children starting with childFrame.
// XXX This isn't the optimal thing to do...
if (ReflowMappedChildrenFrom(aPresContext, aState, aChildFrame, aChildIndex)) {
if (NextChildOffset() < mContent->ChildCount()) {
// Any space left?
if (aState.availSize.width <= 0) {
// No space left. Don't try to pull-up children
status = frNotComplete;
} else {
// Try and pull-up some children from a next-in-flow
if (!PullUpChildren(aPresContext, aState)) {
// We were not able to pull-up all the child frames from our
// next-in-flow
status = frNotComplete;
}
}
}
} else {
// We were unable to reflow all our mapped frames
status = frNotComplete;
}
return status;
}
nsIFrame::ReflowStatus
nsInlineFrame::IncrementalReflowAfter(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex)
{
ReflowStatus status = frComplete;
nsIFrame* nextFrame;
aChildFrame->GetNextSibling(nextFrame);
// Just reflow all the remaining mapped children
// XXX This isn't the optimal thing to do...
if ((nsnull == nextFrame) ||
ReflowMappedChildrenFrom(aPresContext, aState, nextFrame, aChildIndex + 1)) {
if (NextChildOffset() < mContent->ChildCount()) {
// Any space left?
if (aState.availSize.width <= 0) {
// No space left. Don't try to pull-up children
status = frNotComplete;
} else {
// Try and pull-up some children from a next-in-flow
if (!PullUpChildren(aPresContext, aState)) {
// We were not able to pull-up all the child frames from our
// next-in-flow
status = frNotComplete;
}
}
}
} else {
// We were unable to reflow all our mapped frames
status = frNotComplete;
}
return status;
}
NS_METHOD nsInlineFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
@ -899,7 +971,9 @@ NS_METHOD nsInlineFrame::IncrementalReflow(nsIPresContext* aPresContext,
nsStyleSpacing* styleSpacing =
(nsStyleSpacing*)mStyleContext->GetData(kStyleSpacingSID);
nscoord lineHeight;
nscoord lineHeight;
nsIFrame* kidFrame;
PRInt32 kidIndex;
nsInlineState state(styleFont, styleSpacing, aMaxSize, nsnull);
InitializeState(aPresContext, state);
@ -913,22 +987,112 @@ NS_METHOD nsInlineFrame::IncrementalReflow(nsIPresContext* aPresContext,
aStatus = ReflowUnmappedChildren(aPresContext, state);
// Vertically align the children
lineHeight =
nsCSSLayout::VerticallyAlignChildren(aPresContext, this, styleFont,
styleSpacing->mBorderPadding.top,
mFirstChild, mChildCount,
state.ascents, state.maxAscent);
lineHeight = nsCSSLayout::VerticallyAlignChildren(aPresContext, this,
styleFont, styleSpacing->mBorderPadding.top, mFirstChild,
mChildCount, state.ascents, state.maxAscent);
ComputeFinalSize(aPresContext, state, aDesiredSize);
break;
#if 0
case nsReflowCommand::ContentChanged:
// Recover our state
kidFrame = aReflowCommand.GetChildFrame();
kidIndex = RecoverState(aPresContext, state, kidFrame);
aStatus = IncrementalReflowFrom(aPresContext, state, kidFrame, kidIndex);
// Vertically align the children
lineHeight = nsCSSLayout::VerticallyAlignChildren(aPresContext, this,
styleFont, styleSpacing->mBorderPadding.top, mFirstChild,
mChildCount, state.ascents, state.maxAscent);
ComputeFinalSize(aPresContext, state, aDesiredSize);
break;
#endif
default:
NS_NOTYETIMPLEMENTED("unexpected reflow command");
break;
}
} else {
NS_NOTYETIMPLEMENTED("unexpected reflow command");
// The command is passing through us. Get the next frame in the reflow chain
nsIFrame* kidFrame = aReflowCommand.GetNext();
nsReflowMetrics kidSize;
// Restore our state as if nextFrame is the next frame to reflow
kidIndex = RecoverState(aPresContext, state, kidFrame);
// Reflow the child into the available space
aStatus = aReflowCommand.Next(kidSize, state.availSize, kidFrame);
// Did the child fit?
if ((kidSize.width > state.availSize.width) && (kidFrame != mFirstChild)) {
nsIFrame* prevFrame;
// The child is too wide to fit in the available space, and it's not our
// first child
PrevChild(kidFrame, prevFrame);
PushChildren(kidFrame, prevFrame, mLastContentIsComplete);
SetLastContentOffset(prevFrame);
mChildCount = kidIndex - 1;
aStatus = frNotComplete;
} else {
// Place and size the child
PlaceChild(kidFrame, kidIndex, state, kidSize, nsnull);
nsIFrame* kidNextInFlow;
kidFrame->GetNextInFlow(kidNextInFlow);
// Is the child complete?
if (frComplete == aStatus) {
// Check whether the frame has next-in-flow(s) that are no longer needed
if (nsnull != kidNextInFlow) {
// Remove the next-in-flow(s)
DeleteChildsNextInFlow(kidFrame);
}
// Adjust the frames that follow
aStatus = IncrementalReflowAfter(aPresContext, state, kidFrame, kidIndex);
} else {
nsIFrame* nextSibling;
// No, the child isn't complete
if (nsnull == kidNextInFlow) {
// The child doesn't have a next-in-flow so create a continuing
// frame.
nsIFrame* continuingFrame;
nsIStyleContextPtr kidSC;
kidFrame->GetStyleContext(aPresContext, kidSC.AssignRef());
kidFrame->CreateContinuingFrame(aPresContext, this, kidSC, continuingFrame);
// Link the child into the sibling list
kidFrame->GetNextSibling(nextSibling);
continuingFrame->SetNextSibling(nextSibling);
kidFrame->SetNextSibling(continuingFrame);
}
// We've used up all of our available space, so push the remaining
// children to the next-in-flow
kidFrame->GetNextSibling(nextSibling);
if (nsnull != nextSibling) {
PushChildren(nextSibling, kidFrame, mLastContentIsComplete);
}
SetLastContentOffset(kidFrame);
mChildCount = kidIndex;
}
}
// Vertically align the children
lineHeight = nsCSSLayout::VerticallyAlignChildren(aPresContext, this,
styleFont, styleSpacing->mBorderPadding.top, mFirstChild,
mChildCount, state.ascents, state.maxAscent);
ComputeFinalSize(aPresContext, state, aDesiredSize);
}
return NS_OK;
}