зеркало из https://github.com/mozilla/pjs.git
Added nsFirstLineFrame subclass; move class decl out to header file
This commit is contained in:
Родитель
f5675f8348
Коммит
15a1e2f34d
|
@ -16,10 +16,9 @@
|
|||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
#include "nsInlineFrame.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsFrameList.h"
|
||||
#include "nsBlockReflowContext.h"
|
||||
#include "nsLineLayout.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLParts.h"
|
||||
|
@ -47,178 +46,9 @@
|
|||
#define INLINE_FRAME_CID \
|
||||
{ 0xa6cf90e0, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
|
||||
|
||||
static NS_DEFINE_IID(kInlineFrameCID, INLINE_FRAME_CID);
|
||||
|
||||
#define nsInlineFrameSuper nsHTMLContainerFrame
|
||||
|
||||
class nsInlineFrame : public nsInlineFrameSuper
|
||||
{
|
||||
public:
|
||||
friend nsresult NS_NewInlineFrame(nsIFrame*& aNewFrame);
|
||||
|
||||
// nsISupports overrides
|
||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||
|
||||
// nsIFrame overrides
|
||||
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aChildList);
|
||||
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame);
|
||||
NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext);
|
||||
NS_IMETHOD GetFrameName(nsString& aResult) const;
|
||||
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
|
||||
|
||||
// nsIHTMLReflow overrides
|
||||
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
NS_IMETHOD FindTextRuns(nsLineLayout& aLineLayout);
|
||||
#if XXX_fix_me
|
||||
NS_IMETHOD AdjustFrameSize(nscoord aExtraSpace, nscoord& aUsedSpace);
|
||||
NS_IMETHOD TrimTrailingWhiteSpace(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRC,
|
||||
nscoord& aDeltaWidth);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Additional reflow state used during our reflow methods
|
||||
struct InlineReflowState {
|
||||
nsIFrame* mNextRCFrame;
|
||||
nsIFrame* mPrevFrame;
|
||||
nsInlineFrame* mNextInFlow;
|
||||
};
|
||||
|
||||
// A helper class that knows how to take a list of frames and chop
|
||||
// it up into 3 sections.
|
||||
struct SectionData {
|
||||
SectionData(nsIFrame* aFrameList);
|
||||
|
||||
PRBool SplitFrameList(nsFrameList& aSection1,
|
||||
nsFrameList& aSection2,
|
||||
nsFrameList& aSection3);
|
||||
|
||||
PRBool HasABlock() const {
|
||||
return nsnull != firstBlock;
|
||||
}
|
||||
|
||||
nsIFrame* firstBlock;
|
||||
nsIFrame* prevFirstBlock;
|
||||
nsIFrame* lastBlock;
|
||||
nsIFrame* firstFrame;
|
||||
nsIFrame* lastFrame;
|
||||
};
|
||||
|
||||
nsInlineFrame();
|
||||
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
|
||||
PRBool HaveAnonymousBlock() const {
|
||||
return mFrames.NotEmpty()
|
||||
? nsLineLayout::TreatFrameAsBlock(mFrames.FirstChild())
|
||||
: PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool ParentIsInlineFrame(nsIFrame* aFrame, nsIFrame** aParent) {
|
||||
void* tmp;
|
||||
nsIFrame* parent;
|
||||
aFrame->GetParent(&parent);
|
||||
*aParent = parent;
|
||||
if (NS_SUCCEEDED(parent->QueryInterface(kInlineFrameCID, &tmp))) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsAnonymousBlockFrame* FindPrevAnonymousBlock(nsInlineFrame** aBlockParent);
|
||||
|
||||
nsAnonymousBlockFrame* FindAnonymousBlock(nsInlineFrame** aBlockParent);
|
||||
|
||||
nsresult CreateAnonymousBlock(nsIPresContext& aPresContext,
|
||||
nsIFrame* aFrameList,
|
||||
nsIFrame** aResult);
|
||||
|
||||
nsresult AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aFrameList,
|
||||
PRBool aGenerateReflowCommands);
|
||||
|
||||
nsresult InsertBlockFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
|
||||
nsresult InsertInlineFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
|
||||
nsresult ReflowInlineFrames(nsIPresContext& aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& rs,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
nsresult ReflowInlineFrame(nsIPresContext& aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& rs,
|
||||
nsIFrame* aFrame,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
nsIFrame* PullInlineFrame(InlineReflowState& rs, PRBool* aIsComplete);
|
||||
|
||||
nsIFrame* PullAnyFrame(InlineReflowState& rs);
|
||||
|
||||
void PushFrames(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
|
||||
|
||||
void DrainOverflow();
|
||||
|
||||
nsresult ReflowBlockFrame(nsIPresContext& aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& rs,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
nsReflowStatus& aStatus);
|
||||
};
|
||||
nsIID nsInlineFrame::kInlineFrameCID = INLINE_FRAME_CID;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Derived class created for relatively positioned inline-level elements
|
||||
// that acts as a containing block for child absolutely positioned
|
||||
// elements
|
||||
|
||||
class nsPositionedInlineFrame : public nsInlineFrame
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext);
|
||||
|
||||
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aChildList);
|
||||
|
||||
NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex,
|
||||
nsIAtom** aListName) const;
|
||||
|
||||
NS_IMETHOD FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const;
|
||||
|
||||
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
protected:
|
||||
nsAbsoluteContainingBlock mAbsoluteContainer;
|
||||
};
|
||||
|
||||
nsresult
|
||||
NS_NewPositionedInlineFrame(nsIFrame*& aNewFrame)
|
||||
|
@ -322,6 +152,7 @@ nsPositionedInlineFrame::Reflow(nsIPresContext& aPresContext,
|
|||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SectionData implementation
|
||||
|
||||
nsInlineFrame::SectionData::SectionData(nsIFrame* aFrameList)
|
||||
|
@ -489,7 +320,7 @@ nsInlineFrame::CreateAnonymousBlock(nsIPresContext& aPresContext,
|
|||
nsIFrame** aResult)
|
||||
{
|
||||
nsIFrame* bf;
|
||||
nsresult rv = NS_NewAnonymousBlockFrame(bf);
|
||||
nsresult rv = NS_NewAnonymousBlockFrame(&bf);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIStyleContext> newSC;
|
||||
aPresContext.ResolvePseudoStyleContextFor(mContent,
|
||||
|
@ -617,7 +448,7 @@ nsInlineFrame::AppendFrames(nsIPresContext& aPresContext,
|
|||
|
||||
// Now we can append the frames to the anonymous block and it
|
||||
// can generate a reflow command.
|
||||
rv = anonymousBlock->AppendFrames2(aPresContext, aPresShell, nsnull,
|
||||
rv = anonymousBlock->AppendFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
newBlockFrames.FirstChild());
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("AppendFrames: case 1\n");
|
||||
|
@ -776,7 +607,7 @@ nsInlineFrame::InsertBlockFrames(nsIPresContext& aPresContext,
|
|||
frames.AppendFrames(anonymousBlock, start->mFrames);
|
||||
start->GetNextInFlow((nsIFrame**) &start);
|
||||
}
|
||||
anonymousBlock->InsertFrames2(aPresContext, aPresShell, nsnull,
|
||||
anonymousBlock->InsertFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
nsnull, frames.FirstChild());
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("InsertBlockFrames: case 2\n");
|
||||
|
@ -797,7 +628,7 @@ nsInlineFrame::InsertBlockFrames(nsIPresContext& aPresContext,
|
|||
}
|
||||
nsAnonymousBlockFrame* anonymousBlock;
|
||||
anonymousBlock = (nsAnonymousBlockFrame*) prevFrameParent;
|
||||
anonymousBlock->InsertFrames2(aPresContext, aPresShell, nsnull,
|
||||
anonymousBlock->InsertFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
aPrevFrame, aFrameList);
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("InsertBlockFrames: case 3\n");
|
||||
|
@ -835,7 +666,7 @@ nsInlineFrame::InsertBlockFrames(nsIPresContext& aPresContext,
|
|||
// Finally, append the block frames to "frames" and then
|
||||
// append the list of frames to the anonymous block.
|
||||
frames.AppendFrames(anonymousBlock, aFrameList);
|
||||
anonymousBlock->AppendFrames2(aPresContext, aPresShell, nsnull,
|
||||
anonymousBlock->AppendFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
frames.FirstChild());
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("InsertBlockFrames: case 4\n");
|
||||
|
@ -873,7 +704,7 @@ nsInlineFrame::InsertBlockFrames(nsIPresContext& aPresContext,
|
|||
}
|
||||
|
||||
// Now update the anonymous block
|
||||
anonymousBlock->InsertFrames2(aPresContext, aPresShell, nsnull,
|
||||
anonymousBlock->InsertFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
nsnull, frames.FirstChild());
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("InsertBlockFrames: case 5\n");
|
||||
|
@ -961,7 +792,7 @@ nsInlineFrame::InsertInlineFrames(nsIPresContext& aPresContext,
|
|||
frame->SetParent(anonymousBlock);
|
||||
frame->GetNextSibling(&frame);
|
||||
}
|
||||
anonymousBlock->InsertFrames2(aPresContext, aPresShell, nsnull,
|
||||
anonymousBlock->InsertFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
aPrevFrame, aFrameList);
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("InsertInlineFrames: case 2\n");
|
||||
|
@ -1122,7 +953,7 @@ nsInlineFrame::RemoveFrame(nsIPresContext& aPresContext,
|
|||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("RemoveFrame: case 3\n");
|
||||
#endif
|
||||
anonymousBlock->RemoveFrame2(aPresContext, aPresShell, aListName,
|
||||
anonymousBlock->RemoveFrame2(&aPresContext, &aPresShell, aListName,
|
||||
aOldFrame);
|
||||
}
|
||||
else {
|
||||
|
@ -1276,7 +1107,7 @@ nsInlineFrame::RemoveFrame(nsIPresContext& aPresContext,
|
|||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("RemoveFrame: case 6\n");
|
||||
#endif
|
||||
anonymousBlock->RemoveFrame2(aPresContext, aPresShell, aListName,
|
||||
anonymousBlock->RemoveFrame2(&aPresContext, &aPresShell, aListName,
|
||||
aOldFrame);
|
||||
}
|
||||
}
|
||||
|
@ -1308,7 +1139,7 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
|
|||
if (nsnull == aReflowState.lineLayout) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
DrainOverflow();
|
||||
DrainOverflow(&aPresContext);
|
||||
|
||||
// Set our own reflow state (additional state above and beyond
|
||||
// aReflowState)
|
||||
|
@ -1328,25 +1159,9 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
|
|||
|
||||
nsresult rv;
|
||||
if (mFrames.IsEmpty()) {
|
||||
// Try to pull over one frame before starting so that we know what
|
||||
// state we should be in.
|
||||
nsIFrame* frame = PullAnyFrame(irs);
|
||||
if (nsnull == frame) {
|
||||
// Nothing to pull, nothing to do...
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
aMetrics.width = 0;
|
||||
aMetrics.height = 0;
|
||||
aMetrics.ascent = 0;
|
||||
aMetrics.descent = 0;
|
||||
//XXX aMetrics.mCarriedOutTopMargin = 0;
|
||||
aMetrics.mCarriedOutBottomMargin = 0;
|
||||
aMetrics.mCombinedArea.SetRect(0, 0, 0, 0);
|
||||
if (nsnull != aMetrics.maxElementSize) {
|
||||
aMetrics.maxElementSize->SizeTo(0, 0);
|
||||
}
|
||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
||||
return NS_OK;
|
||||
}
|
||||
// Try to pull over one frame before starting so that we know
|
||||
// whether we have an anonymous block or not.
|
||||
(void) PullAnyFrame(&aPresContext, irs);
|
||||
}
|
||||
|
||||
if (HaveAnonymousBlock()) {
|
||||
|
@ -1358,7 +1173,7 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
|
|||
rv = NS_OK;
|
||||
}
|
||||
else {
|
||||
rv = ReflowBlockFrame(aPresContext, aReflowState, irs,
|
||||
rv = ReflowBlockFrame(&aPresContext, aReflowState, irs,
|
||||
aMetrics, aStatus);
|
||||
|
||||
// If the combined area of our children exceeds our bounding box
|
||||
|
@ -1376,7 +1191,7 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
|
|||
}
|
||||
}
|
||||
else {
|
||||
rv = ReflowInlineFrames(aPresContext, aReflowState, irs,
|
||||
rv = ReflowInlineFrames(&aPresContext, aReflowState, irs,
|
||||
aMetrics, aStatus);
|
||||
// Note: when we are reflowing inline frames the line layout code
|
||||
// will properly compute our NS_FRAME_OUTSIDE_CHILDREN state for
|
||||
|
@ -1407,10 +1222,8 @@ nsInlineFrame::FindTextRuns(nsLineLayout& aLineLayout)
|
|||
}
|
||||
|
||||
void
|
||||
nsInlineFrame::DrainOverflow()
|
||||
nsInlineFrame::DrainOverflow(nsIPresContext* aPresContext)
|
||||
{
|
||||
PRBool changedFirstFrame = PR_FALSE;
|
||||
|
||||
// Check for an overflow list with our prev-in-flow
|
||||
nsInlineFrame* prevInFlow = (nsInlineFrame*)mPrevInFlow;
|
||||
if (nsnull != prevInFlow) {
|
||||
|
@ -1424,7 +1237,6 @@ nsInlineFrame::DrainOverflow()
|
|||
nsHTMLContainerFrame::ReparentFrameView(f, prevInFlow, this);
|
||||
}
|
||||
mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames);
|
||||
changedFirstFrame = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1436,7 +1248,7 @@ nsInlineFrame::DrainOverflow()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
||||
nsInlineFrame::ReflowInlineFrames(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& irs,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
|
@ -1476,7 +1288,7 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
if (!done && (nsnull != mNextInFlow)) {
|
||||
while (!done) {
|
||||
PRBool isComplete;
|
||||
frame = PullInlineFrame(irs, &isComplete);
|
||||
frame = PullInlineFrame(aPresContext, irs, &isComplete);
|
||||
if (nsnull == frame) {
|
||||
if (!isComplete) {
|
||||
aStatus = NS_FRAME_NOT_COMPLETE;
|
||||
|
@ -1500,9 +1312,17 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
|
||||
// If after reflowing our children they take up no area then make
|
||||
// sure that we don't either.
|
||||
//
|
||||
// Note: CSS demands that empty inline elements still affect the
|
||||
// line-height calculations. However, continuations of an inline
|
||||
// that are empty we force to empty so that things like collapsed
|
||||
// whitespace in an inline element don't affect the line-height.
|
||||
nsSize size;
|
||||
lineLayout->EndSpan(this, size, aMetrics.maxElementSize);
|
||||
if ((0 == size.height) && (0 == size.width)) {
|
||||
if ((0 == size.height) && (0 == size.width) &&
|
||||
((nsnull != mPrevInFlow) || (nsnull != mNextInFlow))) {
|
||||
// This is a continuation of a previous inline. Therefore make
|
||||
// sure we don't affect the line-height.
|
||||
aMetrics.width = 0;
|
||||
aMetrics.height = 0;
|
||||
aMetrics.ascent = 0;
|
||||
|
@ -1522,18 +1342,15 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
aMetrics.width += aReflowState.mComputedBorderPadding.right;
|
||||
}
|
||||
|
||||
// Compute final height. The height of our box is the sum of our
|
||||
// font size plus the top and bottom border and padding. The height
|
||||
// of children do not affect our height.
|
||||
//
|
||||
// Note 2: we use the actual font height for sizing our selves instead
|
||||
// of the computed font height. On systems where they disagree the
|
||||
// actual font height is more appropriate.
|
||||
const nsStyleFont* font;
|
||||
GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&)font);
|
||||
aReflowState.rendContext->SetFont(font->mFont);
|
||||
nsIFontMetrics* fm;
|
||||
aReflowState.rendContext->GetFontMetrics(fm);
|
||||
|
||||
// Compute final height. The height of our box is the sum of our
|
||||
// font size plus the top and bottom border and padding. The height
|
||||
// of children do not affect our height.
|
||||
fm->GetMaxAscent(aMetrics.ascent);
|
||||
fm->GetMaxDescent(aMetrics.descent);
|
||||
fm->GetHeight(aMetrics.height);
|
||||
|
@ -1542,6 +1359,11 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
aMetrics.height += aReflowState.mComputedBorderPadding.top +
|
||||
aReflowState.mComputedBorderPadding.bottom;
|
||||
|
||||
// Note: we use the actual font height for sizing our selves
|
||||
// instead of the computed font height. On systems where they
|
||||
// disagree the actual font height is more appropriate. This
|
||||
// little hack lets us override that behavior to allow for more
|
||||
// precise layout in the face of imprecise fonts.
|
||||
#if defined(XP_UNIX) || defined(XP_PC)
|
||||
static PRBool useComputedHeight = PR_FALSE;
|
||||
static PRBool firstTime = 1;
|
||||
|
@ -1550,25 +1372,26 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
useComputedHeight = PR_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (useComputedHeight) {
|
||||
// Special debug code that violates the above CSS2 spec
|
||||
// clarification. Why? So that we can predictably compute the values
|
||||
// for testing layout.
|
||||
// clarification. Why? So that we can predictably compute the
|
||||
// values for testing layout.
|
||||
nscoord computedHeight = aReflowState.mComputedBorderPadding.top +
|
||||
aReflowState.mComputedBorderPadding.bottom +
|
||||
font->mFont.size;
|
||||
if (computedHeight != aMetrics.height) {
|
||||
#ifdef DEBUG
|
||||
if (0 == (mState & 0x80000000)) {
|
||||
nsFrame::ListTag(stdout, this);
|
||||
printf(": using computedHeight %d instead of actual height %d\n",
|
||||
computedHeight, aMetrics.height);
|
||||
mState |= 0x80000000;
|
||||
}
|
||||
#endif
|
||||
aMetrics.height = computedHeight;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_RELEASE(fm);
|
||||
}
|
||||
|
||||
|
@ -1589,7 +1412,7 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
||||
nsInlineFrame::ReflowInlineFrame(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& irs,
|
||||
nsIFrame* aFrame,
|
||||
|
@ -1602,7 +1425,7 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
|||
// across a block frame its an anonymous block).
|
||||
if (nsLineLayout::TreatFrameAsBlock(aFrame)) {
|
||||
NS_ASSERTION(aFrame != mFrames.FirstChild(), "bad anon-block status");
|
||||
PushFrames(aFrame, irs.mPrevFrame);
|
||||
PushFrames(aPresContext, aFrame, irs.mPrevFrame);
|
||||
aStatus = NS_INLINE_LINE_BREAK_AFTER(NS_FRAME_NOT_COMPLETE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1621,7 +1444,7 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
|||
aStatus = NS_FRAME_NOT_COMPLETE |
|
||||
NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |
|
||||
(aStatus & NS_INLINE_BREAK_TYPE_MASK);
|
||||
PushFrames(aFrame, irs.mPrevFrame);
|
||||
PushFrames(aPresContext, aFrame, irs.mPrevFrame);
|
||||
}
|
||||
else {
|
||||
// Preserve reflow status when breaking-before our first child
|
||||
|
@ -1632,7 +1455,7 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
|||
// Break-after
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
nsIFrame* newFrame;
|
||||
rv = CreateNextInFlow(aPresContext, this, aFrame, newFrame);
|
||||
rv = CreateNextInFlow(*aPresContext, this, aFrame, newFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1641,7 +1464,7 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
|||
aFrame->GetNextSibling(&nextFrame);
|
||||
if (nsnull != nextFrame) {
|
||||
aStatus |= NS_FRAME_NOT_COMPLETE;
|
||||
PushFrames(nextFrame, aFrame);
|
||||
PushFrames(aPresContext, nextFrame, aFrame);
|
||||
}
|
||||
else if (nsnull != mNextInFlow) {
|
||||
// We must return an incomplete status if there are more child
|
||||
|
@ -1659,21 +1482,23 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
|||
}
|
||||
else if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
nsIFrame* newFrame;
|
||||
rv = CreateNextInFlow(aPresContext, this, aFrame, newFrame);
|
||||
rv = CreateNextInFlow(*aPresContext, this, aFrame, newFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsIFrame* nextFrame;
|
||||
aFrame->GetNextSibling(&nextFrame);
|
||||
if (nsnull != nextFrame) {
|
||||
PushFrames(nextFrame, aFrame);
|
||||
PushFrames(aPresContext, nextFrame, aFrame);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsInlineFrame::PullInlineFrame(InlineReflowState& irs, PRBool* aIsComplete)
|
||||
nsInlineFrame::PullInlineFrame(nsIPresContext* aPresContext,
|
||||
InlineReflowState& irs,
|
||||
PRBool* aIsComplete)
|
||||
{
|
||||
PRBool isComplete = PR_TRUE;
|
||||
|
||||
|
@ -1687,6 +1512,7 @@ nsInlineFrame::PullInlineFrame(InlineReflowState& irs, PRBool* aIsComplete)
|
|||
frame = mFrames.PullFrame(this, irs.mPrevFrame, nextInFlow->mFrames);
|
||||
if (nsnull != frame) {
|
||||
isComplete = PR_FALSE;
|
||||
nsHTMLContainerFrame::ReparentFrameView(frame, nextInFlow, this);
|
||||
break;
|
||||
}
|
||||
nextInFlow = (nsInlineFrame*) nextInFlow->mNextInFlow;
|
||||
|
@ -1698,13 +1524,15 @@ nsInlineFrame::PullInlineFrame(InlineReflowState& irs, PRBool* aIsComplete)
|
|||
}
|
||||
|
||||
nsIFrame*
|
||||
nsInlineFrame::PullAnyFrame(InlineReflowState& irs)
|
||||
nsInlineFrame::PullAnyFrame(nsIPresContext* aPresContext,
|
||||
InlineReflowState& irs)
|
||||
{
|
||||
nsIFrame* frame = nsnull;
|
||||
nsInlineFrame* nextInFlow = irs.mNextInFlow;
|
||||
while (nsnull != nextInFlow) {
|
||||
frame = mFrames.PullFrame(this, irs.mPrevFrame, nextInFlow->mFrames);
|
||||
if (nsnull != frame) {
|
||||
nsHTMLContainerFrame::ReparentFrameView(frame, nextInFlow, this);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1716,7 +1544,9 @@ nsInlineFrame::PullAnyFrame(InlineReflowState& irs)
|
|||
}
|
||||
|
||||
void
|
||||
nsInlineFrame::PushFrames(nsIFrame* aFromChild, nsIFrame* aPrevSibling)
|
||||
nsInlineFrame::PushFrames(nsIPresContext* aPresContext,
|
||||
nsIFrame* aFromChild,
|
||||
nsIFrame* aPrevSibling)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aFromChild, "null pointer");
|
||||
NS_PRECONDITION(nsnull != aPrevSibling, "pushing first child");
|
||||
|
@ -1736,7 +1566,7 @@ nsInlineFrame::PushFrames(nsIFrame* aFromChild, nsIFrame* aPrevSibling)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsInlineFrame::ReflowBlockFrame(nsIPresContext& aPresContext,
|
||||
nsInlineFrame::ReflowBlockFrame(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& irs,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
|
@ -1772,7 +1602,7 @@ nsInlineFrame::ReflowBlockFrame(nsIPresContext& aPresContext,
|
|||
#endif
|
||||
|
||||
// XXX_ib write me...
|
||||
nscoord collapsedTopMargin = 0;
|
||||
//XXX nscoord collapsedTopMargin = 0;
|
||||
nscoord collapsedBottomMargin = 0;
|
||||
|
||||
// Reflow the block frame
|
||||
|
@ -1807,7 +1637,7 @@ nsInlineFrame::ReflowBlockFrame(nsIPresContext& aPresContext,
|
|||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
// When the block isn't complete create a continuation for it
|
||||
nsIFrame* newFrame;
|
||||
rv = CreateNextInFlow(aPresContext, this, blockFrame, newFrame);
|
||||
rv = CreateNextInFlow(*aPresContext, this, blockFrame, newFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1819,7 +1649,7 @@ nsInlineFrame::ReflowBlockFrame(nsIPresContext& aPresContext,
|
|||
nsIFrame* nextFrame;
|
||||
blockFrame->GetNextSibling(&nextFrame);
|
||||
if (nsnull != nextFrame) {
|
||||
PushFrames(nextFrame, blockFrame);
|
||||
PushFrames(aPresContext, nextFrame, blockFrame);
|
||||
aStatus |= NS_FRAME_NOT_COMPLETE;
|
||||
}
|
||||
else if (NS_FRAME_IS_COMPLETE(aStatus)) {
|
||||
|
@ -1845,7 +1675,6 @@ nsInlineFrame::ReflowBlockFrame(nsIPresContext& aPresContext,
|
|||
aMetrics.height = bounds.height;
|
||||
aMetrics.ascent = bounds.height;
|
||||
aMetrics.descent = 0;
|
||||
//XXX aMetrics.mCarriedOutTopMargin = bc.GetCollapsedTopMargin();
|
||||
aMetrics.mCarriedOutBottomMargin = bc.GetCarriedOutBottomMargin();
|
||||
if (nsnull != aMetrics.maxElementSize) {
|
||||
*aMetrics.maxElementSize = bc.GetMaxElementSize();
|
||||
|
@ -1863,10 +1692,332 @@ nsInlineFrame::GetSkipSides() const
|
|||
{
|
||||
PRIntn skip = 0;
|
||||
if (nsnull != mPrevInFlow) {
|
||||
skip |= 1 << NS_SIDE_LEFT;
|
||||
nsInlineFrame* prev = (nsInlineFrame*) mPrevInFlow;
|
||||
if (prev->mRect.height || prev->mRect.width) {
|
||||
// Prev-in-flow is not empty therefore we don't render our left
|
||||
// border edge.
|
||||
skip |= 1 << NS_SIDE_LEFT;
|
||||
}
|
||||
else {
|
||||
// If the prev-in-flow is empty, then go ahead and let our right
|
||||
// edge border render.
|
||||
}
|
||||
}
|
||||
if (nsnull != mNextInFlow) {
|
||||
skip |= 1 << NS_SIDE_RIGHT;
|
||||
nsInlineFrame* next = (nsInlineFrame*) mNextInFlow;
|
||||
if (next->mRect.height || next->mRect.width) {
|
||||
// Next-in-flow is not empty therefore we don't render our right
|
||||
// border edge.
|
||||
skip |= 1 << NS_SIDE_RIGHT;
|
||||
}
|
||||
else {
|
||||
// If the next-in-flow is empty, then go ahead and let our right
|
||||
// edge border render.
|
||||
}
|
||||
}
|
||||
return skip;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// nsLineFrame implementation
|
||||
|
||||
static void
|
||||
ReResolveChildList(nsIPresContext* aPresContext,
|
||||
nsIStyleContext* aParentStyleContext,
|
||||
nsFrameList& aFrameList)
|
||||
{
|
||||
nsIFrame* kid = aFrameList.FirstChild();
|
||||
while (nsnull != kid) {
|
||||
kid->ReResolveStyleContext(aPresContext, aParentStyleContext,
|
||||
NS_STYLE_HINT_REFLOW,
|
||||
nsnull, nsnull);
|
||||
kid->GetNextSibling(&kid);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewFirstLineFrame(nsIFrame** aNewFrame)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aNewFrame, "null ptr");
|
||||
if (nsnull == aNewFrame) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsInlineFrame* it = new nsFirstLineFrame;
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*aNewFrame = it;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsFirstLineFrame::nsFirstLineFrame()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::GetFrameName(nsString& aResult) const
|
||||
{
|
||||
return MakeFrameName("Line", aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::GetFrameType(nsIAtom** aType) const
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
|
||||
*aType = nsHTMLAtoms::lineFrame;
|
||||
NS_ADDREF(*aType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
return mParent->AppendFrames(aPresContext, aPresShell, aListName,
|
||||
aFrameList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
return mParent->InsertFrames(aPresContext, aPresShell, aListName,
|
||||
aPrevFrame, aFrameList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
return mParent->RemoveFrame(aPresContext, aPresShell, aListName,
|
||||
aOldFrame);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFirstLineFrame::AppendFrames2(nsIPresContext* aPresContext,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
nsFrameList frames(aFrameList);
|
||||
ReResolveChildList(aPresContext, mStyleContext, frames);
|
||||
// XXX ReparentFrameView
|
||||
mFrames.AppendFrames(this, aFrameList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFirstLineFrame::InsertFrames2(nsIPresContext* aPresContext,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
nsFrameList frames(aFrameList);
|
||||
ReResolveChildList(aPresContext, mStyleContext, frames);
|
||||
// XXX ReparentFrameView
|
||||
mFrames.InsertFrames(this, aPrevFrame, aFrameList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFirstLineFrame::RemoveFrame2(nsIPresContext* aPresContext,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
nsIFrame* nextInFlow;
|
||||
aOldFrame->GetNextInFlow(&nextInFlow);
|
||||
if (nextInFlow) {
|
||||
DeleteChildsNextInFlow(*aPresContext, aOldFrame);
|
||||
}
|
||||
mFrames.RemoveFrame(aOldFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFirstLineFrame::RemoveFramesFrom(nsIFrame* aFrame)
|
||||
{
|
||||
nsIFrame* prevFrame = mFrames.GetPrevSiblingFor(aFrame);
|
||||
if (prevFrame) {
|
||||
prevFrame->SetNextSibling(nsnull);
|
||||
}
|
||||
else {
|
||||
mFrames.SetFrames(nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsFirstLineFrame::PullInlineFrame(nsIPresContext* aPresContext,
|
||||
InlineReflowState& irs,
|
||||
PRBool* aIsComplete)
|
||||
{
|
||||
nsIFrame* frame =
|
||||
nsInlineFrame::PullInlineFrame(aPresContext, irs, aIsComplete);
|
||||
if (frame && !mPrevInFlow) {
|
||||
// We are a first-line frame. Fixup the child frames
|
||||
// style-context that we just pulled.
|
||||
frame->ReResolveStyleContext(aPresContext, mStyleContext,
|
||||
NS_STYLE_HINT_REFLOW, nsnull, nsnull);
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
void
|
||||
nsFirstLineFrame::DrainOverflow(nsIPresContext* aPresContext)
|
||||
{
|
||||
// Check for an overflow list with our prev-in-flow
|
||||
nsFirstLineFrame* prevInFlow = (nsFirstLineFrame*)mPrevInFlow;
|
||||
if (nsnull != prevInFlow) {
|
||||
if (prevInFlow->mOverflowFrames.NotEmpty()) {
|
||||
ReResolveChildList(aPresContext, mStyleContext,
|
||||
prevInFlow->mOverflowFrames);
|
||||
mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames);
|
||||
}
|
||||
}
|
||||
|
||||
// It's also possible that we have an overflow list for ourselves
|
||||
if (mOverflowFrames.NotEmpty()) {
|
||||
NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
|
||||
ReResolveChildList(aPresContext, mStyleContext, mOverflowFrames);
|
||||
mFrames.AppendFrames(nsnull, mOverflowFrames);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
if (nsnull == aReflowState.lineLayout) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
DrainOverflow(&aPresContext);
|
||||
|
||||
// Set our own reflow state (additional state above and beyond
|
||||
// aReflowState)
|
||||
InlineReflowState irs;
|
||||
irs.mPrevFrame = nsnull;
|
||||
irs.mNextInFlow = (nsInlineFrame*) mNextInFlow;
|
||||
irs.mNextRCFrame = nsnull;
|
||||
if (eReflowReason_Incremental == aReflowState.reason) {
|
||||
// Peel off the next frame in the path if this is an incremental
|
||||
// reflow aimed at one of the children.
|
||||
nsIFrame* target;
|
||||
aReflowState.reflowCommand->GetTarget(target);
|
||||
if (this != target) {
|
||||
aReflowState.reflowCommand->GetNext(irs.mNextRCFrame);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
PRBool wasEmpty = mFrames.IsEmpty();
|
||||
if (wasEmpty) {
|
||||
// Try to pull over one frame before starting so that we know
|
||||
// whether we have an anonymous block or not.
|
||||
PullAnyFrame(&aPresContext, irs);
|
||||
}
|
||||
|
||||
if (HaveAnonymousBlock()) {
|
||||
if (!aReflowState.lineLayout->LineIsEmpty()) {
|
||||
// This inline frame cannot be placed on the current line
|
||||
// because there already is an inline frame on this line (and we
|
||||
// contain an anonymous block).
|
||||
aStatus = NS_INLINE_LINE_BREAK_BEFORE();
|
||||
rv = NS_OK;
|
||||
}
|
||||
else {
|
||||
rv = ReflowBlockFrame(&aPresContext, aReflowState, irs,
|
||||
aMetrics, aStatus);
|
||||
|
||||
// If the combined area of our children exceeds our bounding box
|
||||
// then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear
|
||||
// it.
|
||||
if ((aMetrics.mCombinedArea.x < 0) ||
|
||||
(aMetrics.mCombinedArea.y < 0) ||
|
||||
(aMetrics.mCombinedArea.XMost() > aMetrics.width) ||
|
||||
(aMetrics.mCombinedArea.YMost() > aMetrics.height)) {
|
||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
||||
}
|
||||
else {
|
||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (wasEmpty) {
|
||||
// Fixup style of frame just pulled up
|
||||
nsIFrame* firstFrame = mFrames.FirstChild();
|
||||
if (firstFrame) {
|
||||
firstFrame->ReResolveStyleContext(&aPresContext, mStyleContext,
|
||||
NS_STYLE_HINT_REFLOW, nsnull,
|
||||
nsnull);
|
||||
}
|
||||
}
|
||||
if (nsnull == mPrevInFlow) {
|
||||
// XXX This is pretty sick, but what we do here is to pull-up, in
|
||||
// advance, all of the next-in-flows children. We re-resolve their
|
||||
// style while we are at at it so that when we reflow they have
|
||||
// the right style.
|
||||
//
|
||||
// All of this is so that text-runs reflow properly.
|
||||
irs.mPrevFrame = mFrames.LastChild();
|
||||
for (;;) {
|
||||
PRBool complete;
|
||||
nsIFrame* frame = PullInlineFrame(&aPresContext, irs, &complete);
|
||||
if (!frame) {
|
||||
break;
|
||||
}
|
||||
irs.mPrevFrame = frame;
|
||||
}
|
||||
irs.mPrevFrame = nsnull;
|
||||
}
|
||||
else {
|
||||
// For continuations, we need to check and see if our style
|
||||
// context is right. If its the same as the first-in-flow, then
|
||||
// we need to fix it up (that way :first-line style doesn't leak
|
||||
// into this continuation since we aren't the first line).
|
||||
nsFirstLineFrame* first = (nsFirstLineFrame*) GetFirstInFlow();
|
||||
if (mStyleContext == first->mStyleContext) {
|
||||
// Fixup our style context and our children. First get the
|
||||
// proper parent context.
|
||||
nsIFrame* parentFrame;
|
||||
first->GetParent(&parentFrame);
|
||||
nsIStyleContext* parentContext;
|
||||
parentFrame->GetStyleContext(&parentContext);
|
||||
if (parentContext) {
|
||||
// Create a new style context that is a child of the parent
|
||||
// style context thus removing the :first-line style. This way
|
||||
// we behave as if an anonymous (unstyled) span was the child
|
||||
// of the parent frame.
|
||||
nsIStyleContext* newSC;
|
||||
aPresContext.ResolvePseudoStyleContextFor(mContent,
|
||||
nsHTMLAtoms::mozLineFrame,
|
||||
parentContext,
|
||||
PR_FALSE, &newSC);
|
||||
if (newSC) {
|
||||
// Switch to the new style context.
|
||||
SetStyleContext(&aPresContext, newSC);
|
||||
|
||||
// Re-resolve all children
|
||||
ReResolveChildList(&aPresContext, mStyleContext, mFrames);
|
||||
|
||||
NS_RELEASE(newSC);
|
||||
}
|
||||
NS_RELEASE(parentContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = ReflowInlineFrames(&aPresContext, aReflowState, irs,
|
||||
aMetrics, aStatus);
|
||||
// Note: when we are reflowing inline frames the line layout code
|
||||
// will properly compute our NS_FRAME_OUTSIDE_CHILDREN state for
|
||||
// us.
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -16,10 +16,9 @@
|
|||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
#include "nsInlineFrame.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsFrameList.h"
|
||||
#include "nsBlockReflowContext.h"
|
||||
#include "nsLineLayout.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHTMLParts.h"
|
||||
|
@ -47,178 +46,9 @@
|
|||
#define INLINE_FRAME_CID \
|
||||
{ 0xa6cf90e0, 0x15b3, 0x11d2,{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
|
||||
|
||||
static NS_DEFINE_IID(kInlineFrameCID, INLINE_FRAME_CID);
|
||||
|
||||
#define nsInlineFrameSuper nsHTMLContainerFrame
|
||||
|
||||
class nsInlineFrame : public nsInlineFrameSuper
|
||||
{
|
||||
public:
|
||||
friend nsresult NS_NewInlineFrame(nsIFrame*& aNewFrame);
|
||||
|
||||
// nsISupports overrides
|
||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||
|
||||
// nsIFrame overrides
|
||||
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aChildList);
|
||||
NS_IMETHOD AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
NS_IMETHOD RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame);
|
||||
NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext);
|
||||
NS_IMETHOD GetFrameName(nsString& aResult) const;
|
||||
NS_IMETHOD GetFrameType(nsIAtom** aType) const;
|
||||
|
||||
// nsIHTMLReflow overrides
|
||||
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
NS_IMETHOD FindTextRuns(nsLineLayout& aLineLayout);
|
||||
#if XXX_fix_me
|
||||
NS_IMETHOD AdjustFrameSize(nscoord aExtraSpace, nscoord& aUsedSpace);
|
||||
NS_IMETHOD TrimTrailingWhiteSpace(nsIPresContext& aPresContext,
|
||||
nsIRenderingContext& aRC,
|
||||
nscoord& aDeltaWidth);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Additional reflow state used during our reflow methods
|
||||
struct InlineReflowState {
|
||||
nsIFrame* mNextRCFrame;
|
||||
nsIFrame* mPrevFrame;
|
||||
nsInlineFrame* mNextInFlow;
|
||||
};
|
||||
|
||||
// A helper class that knows how to take a list of frames and chop
|
||||
// it up into 3 sections.
|
||||
struct SectionData {
|
||||
SectionData(nsIFrame* aFrameList);
|
||||
|
||||
PRBool SplitFrameList(nsFrameList& aSection1,
|
||||
nsFrameList& aSection2,
|
||||
nsFrameList& aSection3);
|
||||
|
||||
PRBool HasABlock() const {
|
||||
return nsnull != firstBlock;
|
||||
}
|
||||
|
||||
nsIFrame* firstBlock;
|
||||
nsIFrame* prevFirstBlock;
|
||||
nsIFrame* lastBlock;
|
||||
nsIFrame* firstFrame;
|
||||
nsIFrame* lastFrame;
|
||||
};
|
||||
|
||||
nsInlineFrame();
|
||||
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
|
||||
PRBool HaveAnonymousBlock() const {
|
||||
return mFrames.NotEmpty()
|
||||
? nsLineLayout::TreatFrameAsBlock(mFrames.FirstChild())
|
||||
: PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool ParentIsInlineFrame(nsIFrame* aFrame, nsIFrame** aParent) {
|
||||
void* tmp;
|
||||
nsIFrame* parent;
|
||||
aFrame->GetParent(&parent);
|
||||
*aParent = parent;
|
||||
if (NS_SUCCEEDED(parent->QueryInterface(kInlineFrameCID, &tmp))) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsAnonymousBlockFrame* FindPrevAnonymousBlock(nsInlineFrame** aBlockParent);
|
||||
|
||||
nsAnonymousBlockFrame* FindAnonymousBlock(nsInlineFrame** aBlockParent);
|
||||
|
||||
nsresult CreateAnonymousBlock(nsIPresContext& aPresContext,
|
||||
nsIFrame* aFrameList,
|
||||
nsIFrame** aResult);
|
||||
|
||||
nsresult AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aFrameList,
|
||||
PRBool aGenerateReflowCommands);
|
||||
|
||||
nsresult InsertBlockFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
|
||||
nsresult InsertInlineFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList);
|
||||
|
||||
nsresult ReflowInlineFrames(nsIPresContext& aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& rs,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
nsresult ReflowInlineFrame(nsIPresContext& aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& rs,
|
||||
nsIFrame* aFrame,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
nsIFrame* PullInlineFrame(InlineReflowState& rs, PRBool* aIsComplete);
|
||||
|
||||
nsIFrame* PullAnyFrame(InlineReflowState& rs);
|
||||
|
||||
void PushFrames(nsIFrame* aFromChild, nsIFrame* aPrevSibling);
|
||||
|
||||
void DrainOverflow();
|
||||
|
||||
nsresult ReflowBlockFrame(nsIPresContext& aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& rs,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
nsReflowStatus& aStatus);
|
||||
};
|
||||
nsIID nsInlineFrame::kInlineFrameCID = INLINE_FRAME_CID;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Derived class created for relatively positioned inline-level elements
|
||||
// that acts as a containing block for child absolutely positioned
|
||||
// elements
|
||||
|
||||
class nsPositionedInlineFrame : public nsInlineFrame
|
||||
{
|
||||
public:
|
||||
NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext);
|
||||
|
||||
NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aChildList);
|
||||
|
||||
NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex,
|
||||
nsIAtom** aListName) const;
|
||||
|
||||
NS_IMETHOD FirstChild(nsIAtom* aListName, nsIFrame** aFirstChild) const;
|
||||
|
||||
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
protected:
|
||||
nsAbsoluteContainingBlock mAbsoluteContainer;
|
||||
};
|
||||
|
||||
nsresult
|
||||
NS_NewPositionedInlineFrame(nsIFrame*& aNewFrame)
|
||||
|
@ -322,6 +152,7 @@ nsPositionedInlineFrame::Reflow(nsIPresContext& aPresContext,
|
|||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// SectionData implementation
|
||||
|
||||
nsInlineFrame::SectionData::SectionData(nsIFrame* aFrameList)
|
||||
|
@ -489,7 +320,7 @@ nsInlineFrame::CreateAnonymousBlock(nsIPresContext& aPresContext,
|
|||
nsIFrame** aResult)
|
||||
{
|
||||
nsIFrame* bf;
|
||||
nsresult rv = NS_NewAnonymousBlockFrame(bf);
|
||||
nsresult rv = NS_NewAnonymousBlockFrame(&bf);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIStyleContext> newSC;
|
||||
aPresContext.ResolvePseudoStyleContextFor(mContent,
|
||||
|
@ -617,7 +448,7 @@ nsInlineFrame::AppendFrames(nsIPresContext& aPresContext,
|
|||
|
||||
// Now we can append the frames to the anonymous block and it
|
||||
// can generate a reflow command.
|
||||
rv = anonymousBlock->AppendFrames2(aPresContext, aPresShell, nsnull,
|
||||
rv = anonymousBlock->AppendFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
newBlockFrames.FirstChild());
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("AppendFrames: case 1\n");
|
||||
|
@ -776,7 +607,7 @@ nsInlineFrame::InsertBlockFrames(nsIPresContext& aPresContext,
|
|||
frames.AppendFrames(anonymousBlock, start->mFrames);
|
||||
start->GetNextInFlow((nsIFrame**) &start);
|
||||
}
|
||||
anonymousBlock->InsertFrames2(aPresContext, aPresShell, nsnull,
|
||||
anonymousBlock->InsertFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
nsnull, frames.FirstChild());
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("InsertBlockFrames: case 2\n");
|
||||
|
@ -797,7 +628,7 @@ nsInlineFrame::InsertBlockFrames(nsIPresContext& aPresContext,
|
|||
}
|
||||
nsAnonymousBlockFrame* anonymousBlock;
|
||||
anonymousBlock = (nsAnonymousBlockFrame*) prevFrameParent;
|
||||
anonymousBlock->InsertFrames2(aPresContext, aPresShell, nsnull,
|
||||
anonymousBlock->InsertFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
aPrevFrame, aFrameList);
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("InsertBlockFrames: case 3\n");
|
||||
|
@ -835,7 +666,7 @@ nsInlineFrame::InsertBlockFrames(nsIPresContext& aPresContext,
|
|||
// Finally, append the block frames to "frames" and then
|
||||
// append the list of frames to the anonymous block.
|
||||
frames.AppendFrames(anonymousBlock, aFrameList);
|
||||
anonymousBlock->AppendFrames2(aPresContext, aPresShell, nsnull,
|
||||
anonymousBlock->AppendFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
frames.FirstChild());
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("InsertBlockFrames: case 4\n");
|
||||
|
@ -873,7 +704,7 @@ nsInlineFrame::InsertBlockFrames(nsIPresContext& aPresContext,
|
|||
}
|
||||
|
||||
// Now update the anonymous block
|
||||
anonymousBlock->InsertFrames2(aPresContext, aPresShell, nsnull,
|
||||
anonymousBlock->InsertFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
nsnull, frames.FirstChild());
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("InsertBlockFrames: case 5\n");
|
||||
|
@ -961,7 +792,7 @@ nsInlineFrame::InsertInlineFrames(nsIPresContext& aPresContext,
|
|||
frame->SetParent(anonymousBlock);
|
||||
frame->GetNextSibling(&frame);
|
||||
}
|
||||
anonymousBlock->InsertFrames2(aPresContext, aPresShell, nsnull,
|
||||
anonymousBlock->InsertFrames2(&aPresContext, &aPresShell, nsnull,
|
||||
aPrevFrame, aFrameList);
|
||||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("InsertInlineFrames: case 2\n");
|
||||
|
@ -1122,7 +953,7 @@ nsInlineFrame::RemoveFrame(nsIPresContext& aPresContext,
|
|||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("RemoveFrame: case 3\n");
|
||||
#endif
|
||||
anonymousBlock->RemoveFrame2(aPresContext, aPresShell, aListName,
|
||||
anonymousBlock->RemoveFrame2(&aPresContext, &aPresShell, aListName,
|
||||
aOldFrame);
|
||||
}
|
||||
else {
|
||||
|
@ -1276,7 +1107,7 @@ nsInlineFrame::RemoveFrame(nsIPresContext& aPresContext,
|
|||
#ifdef NOISY_ANON_BLOCK
|
||||
printf("RemoveFrame: case 6\n");
|
||||
#endif
|
||||
anonymousBlock->RemoveFrame2(aPresContext, aPresShell, aListName,
|
||||
anonymousBlock->RemoveFrame2(&aPresContext, &aPresShell, aListName,
|
||||
aOldFrame);
|
||||
}
|
||||
}
|
||||
|
@ -1308,7 +1139,7 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
|
|||
if (nsnull == aReflowState.lineLayout) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
DrainOverflow();
|
||||
DrainOverflow(&aPresContext);
|
||||
|
||||
// Set our own reflow state (additional state above and beyond
|
||||
// aReflowState)
|
||||
|
@ -1328,25 +1159,9 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
|
|||
|
||||
nsresult rv;
|
||||
if (mFrames.IsEmpty()) {
|
||||
// Try to pull over one frame before starting so that we know what
|
||||
// state we should be in.
|
||||
nsIFrame* frame = PullAnyFrame(irs);
|
||||
if (nsnull == frame) {
|
||||
// Nothing to pull, nothing to do...
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
aMetrics.width = 0;
|
||||
aMetrics.height = 0;
|
||||
aMetrics.ascent = 0;
|
||||
aMetrics.descent = 0;
|
||||
//XXX aMetrics.mCarriedOutTopMargin = 0;
|
||||
aMetrics.mCarriedOutBottomMargin = 0;
|
||||
aMetrics.mCombinedArea.SetRect(0, 0, 0, 0);
|
||||
if (nsnull != aMetrics.maxElementSize) {
|
||||
aMetrics.maxElementSize->SizeTo(0, 0);
|
||||
}
|
||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
||||
return NS_OK;
|
||||
}
|
||||
// Try to pull over one frame before starting so that we know
|
||||
// whether we have an anonymous block or not.
|
||||
(void) PullAnyFrame(&aPresContext, irs);
|
||||
}
|
||||
|
||||
if (HaveAnonymousBlock()) {
|
||||
|
@ -1358,7 +1173,7 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
|
|||
rv = NS_OK;
|
||||
}
|
||||
else {
|
||||
rv = ReflowBlockFrame(aPresContext, aReflowState, irs,
|
||||
rv = ReflowBlockFrame(&aPresContext, aReflowState, irs,
|
||||
aMetrics, aStatus);
|
||||
|
||||
// If the combined area of our children exceeds our bounding box
|
||||
|
@ -1376,7 +1191,7 @@ nsInlineFrame::Reflow(nsIPresContext& aPresContext,
|
|||
}
|
||||
}
|
||||
else {
|
||||
rv = ReflowInlineFrames(aPresContext, aReflowState, irs,
|
||||
rv = ReflowInlineFrames(&aPresContext, aReflowState, irs,
|
||||
aMetrics, aStatus);
|
||||
// Note: when we are reflowing inline frames the line layout code
|
||||
// will properly compute our NS_FRAME_OUTSIDE_CHILDREN state for
|
||||
|
@ -1407,10 +1222,8 @@ nsInlineFrame::FindTextRuns(nsLineLayout& aLineLayout)
|
|||
}
|
||||
|
||||
void
|
||||
nsInlineFrame::DrainOverflow()
|
||||
nsInlineFrame::DrainOverflow(nsIPresContext* aPresContext)
|
||||
{
|
||||
PRBool changedFirstFrame = PR_FALSE;
|
||||
|
||||
// Check for an overflow list with our prev-in-flow
|
||||
nsInlineFrame* prevInFlow = (nsInlineFrame*)mPrevInFlow;
|
||||
if (nsnull != prevInFlow) {
|
||||
|
@ -1424,7 +1237,6 @@ nsInlineFrame::DrainOverflow()
|
|||
nsHTMLContainerFrame::ReparentFrameView(f, prevInFlow, this);
|
||||
}
|
||||
mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames);
|
||||
changedFirstFrame = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1436,7 +1248,7 @@ nsInlineFrame::DrainOverflow()
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
||||
nsInlineFrame::ReflowInlineFrames(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& irs,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
|
@ -1476,7 +1288,7 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
if (!done && (nsnull != mNextInFlow)) {
|
||||
while (!done) {
|
||||
PRBool isComplete;
|
||||
frame = PullInlineFrame(irs, &isComplete);
|
||||
frame = PullInlineFrame(aPresContext, irs, &isComplete);
|
||||
if (nsnull == frame) {
|
||||
if (!isComplete) {
|
||||
aStatus = NS_FRAME_NOT_COMPLETE;
|
||||
|
@ -1500,9 +1312,17 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
|
||||
// If after reflowing our children they take up no area then make
|
||||
// sure that we don't either.
|
||||
//
|
||||
// Note: CSS demands that empty inline elements still affect the
|
||||
// line-height calculations. However, continuations of an inline
|
||||
// that are empty we force to empty so that things like collapsed
|
||||
// whitespace in an inline element don't affect the line-height.
|
||||
nsSize size;
|
||||
lineLayout->EndSpan(this, size, aMetrics.maxElementSize);
|
||||
if ((0 == size.height) && (0 == size.width)) {
|
||||
if ((0 == size.height) && (0 == size.width) &&
|
||||
((nsnull != mPrevInFlow) || (nsnull != mNextInFlow))) {
|
||||
// This is a continuation of a previous inline. Therefore make
|
||||
// sure we don't affect the line-height.
|
||||
aMetrics.width = 0;
|
||||
aMetrics.height = 0;
|
||||
aMetrics.ascent = 0;
|
||||
|
@ -1522,18 +1342,15 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
aMetrics.width += aReflowState.mComputedBorderPadding.right;
|
||||
}
|
||||
|
||||
// Compute final height. The height of our box is the sum of our
|
||||
// font size plus the top and bottom border and padding. The height
|
||||
// of children do not affect our height.
|
||||
//
|
||||
// Note 2: we use the actual font height for sizing our selves instead
|
||||
// of the computed font height. On systems where they disagree the
|
||||
// actual font height is more appropriate.
|
||||
const nsStyleFont* font;
|
||||
GetStyleData(eStyleStruct_Font, (const nsStyleStruct*&)font);
|
||||
aReflowState.rendContext->SetFont(font->mFont);
|
||||
nsIFontMetrics* fm;
|
||||
aReflowState.rendContext->GetFontMetrics(fm);
|
||||
|
||||
// Compute final height. The height of our box is the sum of our
|
||||
// font size plus the top and bottom border and padding. The height
|
||||
// of children do not affect our height.
|
||||
fm->GetMaxAscent(aMetrics.ascent);
|
||||
fm->GetMaxDescent(aMetrics.descent);
|
||||
fm->GetHeight(aMetrics.height);
|
||||
|
@ -1542,6 +1359,11 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
aMetrics.height += aReflowState.mComputedBorderPadding.top +
|
||||
aReflowState.mComputedBorderPadding.bottom;
|
||||
|
||||
// Note: we use the actual font height for sizing our selves
|
||||
// instead of the computed font height. On systems where they
|
||||
// disagree the actual font height is more appropriate. This
|
||||
// little hack lets us override that behavior to allow for more
|
||||
// precise layout in the face of imprecise fonts.
|
||||
#if defined(XP_UNIX) || defined(XP_PC)
|
||||
static PRBool useComputedHeight = PR_FALSE;
|
||||
static PRBool firstTime = 1;
|
||||
|
@ -1550,25 +1372,26 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
useComputedHeight = PR_TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (useComputedHeight) {
|
||||
// Special debug code that violates the above CSS2 spec
|
||||
// clarification. Why? So that we can predictably compute the values
|
||||
// for testing layout.
|
||||
// clarification. Why? So that we can predictably compute the
|
||||
// values for testing layout.
|
||||
nscoord computedHeight = aReflowState.mComputedBorderPadding.top +
|
||||
aReflowState.mComputedBorderPadding.bottom +
|
||||
font->mFont.size;
|
||||
if (computedHeight != aMetrics.height) {
|
||||
#ifdef DEBUG
|
||||
if (0 == (mState & 0x80000000)) {
|
||||
nsFrame::ListTag(stdout, this);
|
||||
printf(": using computedHeight %d instead of actual height %d\n",
|
||||
computedHeight, aMetrics.height);
|
||||
mState |= 0x80000000;
|
||||
}
|
||||
#endif
|
||||
aMetrics.height = computedHeight;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_RELEASE(fm);
|
||||
}
|
||||
|
||||
|
@ -1589,7 +1412,7 @@ nsInlineFrame::ReflowInlineFrames(nsIPresContext& aPresContext,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
||||
nsInlineFrame::ReflowInlineFrame(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& irs,
|
||||
nsIFrame* aFrame,
|
||||
|
@ -1602,7 +1425,7 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
|||
// across a block frame its an anonymous block).
|
||||
if (nsLineLayout::TreatFrameAsBlock(aFrame)) {
|
||||
NS_ASSERTION(aFrame != mFrames.FirstChild(), "bad anon-block status");
|
||||
PushFrames(aFrame, irs.mPrevFrame);
|
||||
PushFrames(aPresContext, aFrame, irs.mPrevFrame);
|
||||
aStatus = NS_INLINE_LINE_BREAK_AFTER(NS_FRAME_NOT_COMPLETE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1621,7 +1444,7 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
|||
aStatus = NS_FRAME_NOT_COMPLETE |
|
||||
NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |
|
||||
(aStatus & NS_INLINE_BREAK_TYPE_MASK);
|
||||
PushFrames(aFrame, irs.mPrevFrame);
|
||||
PushFrames(aPresContext, aFrame, irs.mPrevFrame);
|
||||
}
|
||||
else {
|
||||
// Preserve reflow status when breaking-before our first child
|
||||
|
@ -1632,7 +1455,7 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
|||
// Break-after
|
||||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
nsIFrame* newFrame;
|
||||
rv = CreateNextInFlow(aPresContext, this, aFrame, newFrame);
|
||||
rv = CreateNextInFlow(*aPresContext, this, aFrame, newFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1641,7 +1464,7 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
|||
aFrame->GetNextSibling(&nextFrame);
|
||||
if (nsnull != nextFrame) {
|
||||
aStatus |= NS_FRAME_NOT_COMPLETE;
|
||||
PushFrames(nextFrame, aFrame);
|
||||
PushFrames(aPresContext, nextFrame, aFrame);
|
||||
}
|
||||
else if (nsnull != mNextInFlow) {
|
||||
// We must return an incomplete status if there are more child
|
||||
|
@ -1659,21 +1482,23 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext& aPresContext,
|
|||
}
|
||||
else if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
nsIFrame* newFrame;
|
||||
rv = CreateNextInFlow(aPresContext, this, aFrame, newFrame);
|
||||
rv = CreateNextInFlow(*aPresContext, this, aFrame, newFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsIFrame* nextFrame;
|
||||
aFrame->GetNextSibling(&nextFrame);
|
||||
if (nsnull != nextFrame) {
|
||||
PushFrames(nextFrame, aFrame);
|
||||
PushFrames(aPresContext, nextFrame, aFrame);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsInlineFrame::PullInlineFrame(InlineReflowState& irs, PRBool* aIsComplete)
|
||||
nsInlineFrame::PullInlineFrame(nsIPresContext* aPresContext,
|
||||
InlineReflowState& irs,
|
||||
PRBool* aIsComplete)
|
||||
{
|
||||
PRBool isComplete = PR_TRUE;
|
||||
|
||||
|
@ -1687,6 +1512,7 @@ nsInlineFrame::PullInlineFrame(InlineReflowState& irs, PRBool* aIsComplete)
|
|||
frame = mFrames.PullFrame(this, irs.mPrevFrame, nextInFlow->mFrames);
|
||||
if (nsnull != frame) {
|
||||
isComplete = PR_FALSE;
|
||||
nsHTMLContainerFrame::ReparentFrameView(frame, nextInFlow, this);
|
||||
break;
|
||||
}
|
||||
nextInFlow = (nsInlineFrame*) nextInFlow->mNextInFlow;
|
||||
|
@ -1698,13 +1524,15 @@ nsInlineFrame::PullInlineFrame(InlineReflowState& irs, PRBool* aIsComplete)
|
|||
}
|
||||
|
||||
nsIFrame*
|
||||
nsInlineFrame::PullAnyFrame(InlineReflowState& irs)
|
||||
nsInlineFrame::PullAnyFrame(nsIPresContext* aPresContext,
|
||||
InlineReflowState& irs)
|
||||
{
|
||||
nsIFrame* frame = nsnull;
|
||||
nsInlineFrame* nextInFlow = irs.mNextInFlow;
|
||||
while (nsnull != nextInFlow) {
|
||||
frame = mFrames.PullFrame(this, irs.mPrevFrame, nextInFlow->mFrames);
|
||||
if (nsnull != frame) {
|
||||
nsHTMLContainerFrame::ReparentFrameView(frame, nextInFlow, this);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1716,7 +1544,9 @@ nsInlineFrame::PullAnyFrame(InlineReflowState& irs)
|
|||
}
|
||||
|
||||
void
|
||||
nsInlineFrame::PushFrames(nsIFrame* aFromChild, nsIFrame* aPrevSibling)
|
||||
nsInlineFrame::PushFrames(nsIPresContext* aPresContext,
|
||||
nsIFrame* aFromChild,
|
||||
nsIFrame* aPrevSibling)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aFromChild, "null pointer");
|
||||
NS_PRECONDITION(nsnull != aPrevSibling, "pushing first child");
|
||||
|
@ -1736,7 +1566,7 @@ nsInlineFrame::PushFrames(nsIFrame* aFromChild, nsIFrame* aPrevSibling)
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsInlineFrame::ReflowBlockFrame(nsIPresContext& aPresContext,
|
||||
nsInlineFrame::ReflowBlockFrame(nsIPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
InlineReflowState& irs,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
|
@ -1772,7 +1602,7 @@ nsInlineFrame::ReflowBlockFrame(nsIPresContext& aPresContext,
|
|||
#endif
|
||||
|
||||
// XXX_ib write me...
|
||||
nscoord collapsedTopMargin = 0;
|
||||
//XXX nscoord collapsedTopMargin = 0;
|
||||
nscoord collapsedBottomMargin = 0;
|
||||
|
||||
// Reflow the block frame
|
||||
|
@ -1807,7 +1637,7 @@ nsInlineFrame::ReflowBlockFrame(nsIPresContext& aPresContext,
|
|||
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
||||
// When the block isn't complete create a continuation for it
|
||||
nsIFrame* newFrame;
|
||||
rv = CreateNextInFlow(aPresContext, this, blockFrame, newFrame);
|
||||
rv = CreateNextInFlow(*aPresContext, this, blockFrame, newFrame);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1819,7 +1649,7 @@ nsInlineFrame::ReflowBlockFrame(nsIPresContext& aPresContext,
|
|||
nsIFrame* nextFrame;
|
||||
blockFrame->GetNextSibling(&nextFrame);
|
||||
if (nsnull != nextFrame) {
|
||||
PushFrames(nextFrame, blockFrame);
|
||||
PushFrames(aPresContext, nextFrame, blockFrame);
|
||||
aStatus |= NS_FRAME_NOT_COMPLETE;
|
||||
}
|
||||
else if (NS_FRAME_IS_COMPLETE(aStatus)) {
|
||||
|
@ -1845,7 +1675,6 @@ nsInlineFrame::ReflowBlockFrame(nsIPresContext& aPresContext,
|
|||
aMetrics.height = bounds.height;
|
||||
aMetrics.ascent = bounds.height;
|
||||
aMetrics.descent = 0;
|
||||
//XXX aMetrics.mCarriedOutTopMargin = bc.GetCollapsedTopMargin();
|
||||
aMetrics.mCarriedOutBottomMargin = bc.GetCarriedOutBottomMargin();
|
||||
if (nsnull != aMetrics.maxElementSize) {
|
||||
*aMetrics.maxElementSize = bc.GetMaxElementSize();
|
||||
|
@ -1863,10 +1692,332 @@ nsInlineFrame::GetSkipSides() const
|
|||
{
|
||||
PRIntn skip = 0;
|
||||
if (nsnull != mPrevInFlow) {
|
||||
skip |= 1 << NS_SIDE_LEFT;
|
||||
nsInlineFrame* prev = (nsInlineFrame*) mPrevInFlow;
|
||||
if (prev->mRect.height || prev->mRect.width) {
|
||||
// Prev-in-flow is not empty therefore we don't render our left
|
||||
// border edge.
|
||||
skip |= 1 << NS_SIDE_LEFT;
|
||||
}
|
||||
else {
|
||||
// If the prev-in-flow is empty, then go ahead and let our right
|
||||
// edge border render.
|
||||
}
|
||||
}
|
||||
if (nsnull != mNextInFlow) {
|
||||
skip |= 1 << NS_SIDE_RIGHT;
|
||||
nsInlineFrame* next = (nsInlineFrame*) mNextInFlow;
|
||||
if (next->mRect.height || next->mRect.width) {
|
||||
// Next-in-flow is not empty therefore we don't render our right
|
||||
// border edge.
|
||||
skip |= 1 << NS_SIDE_RIGHT;
|
||||
}
|
||||
else {
|
||||
// If the next-in-flow is empty, then go ahead and let our right
|
||||
// edge border render.
|
||||
}
|
||||
}
|
||||
return skip;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// nsLineFrame implementation
|
||||
|
||||
static void
|
||||
ReResolveChildList(nsIPresContext* aPresContext,
|
||||
nsIStyleContext* aParentStyleContext,
|
||||
nsFrameList& aFrameList)
|
||||
{
|
||||
nsIFrame* kid = aFrameList.FirstChild();
|
||||
while (nsnull != kid) {
|
||||
kid->ReResolveStyleContext(aPresContext, aParentStyleContext,
|
||||
NS_STYLE_HINT_REFLOW,
|
||||
nsnull, nsnull);
|
||||
kid->GetNextSibling(&kid);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewFirstLineFrame(nsIFrame** aNewFrame)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aNewFrame, "null ptr");
|
||||
if (nsnull == aNewFrame) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
nsInlineFrame* it = new nsFirstLineFrame;
|
||||
if (nsnull == it) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
*aNewFrame = it;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsFirstLineFrame::nsFirstLineFrame()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::GetFrameName(nsString& aResult) const
|
||||
{
|
||||
return MakeFrameName("Line", aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::GetFrameType(nsIAtom** aType) const
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer");
|
||||
*aType = nsHTMLAtoms::lineFrame;
|
||||
NS_ADDREF(*aType);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::AppendFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
return mParent->AppendFrames(aPresContext, aPresShell, aListName,
|
||||
aFrameList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::InsertFrames(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
return mParent->InsertFrames(aPresContext, aPresShell, aListName,
|
||||
aPrevFrame, aFrameList);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::RemoveFrame(nsIPresContext& aPresContext,
|
||||
nsIPresShell& aPresShell,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
return mParent->RemoveFrame(aPresContext, aPresShell, aListName,
|
||||
aOldFrame);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFirstLineFrame::AppendFrames2(nsIPresContext* aPresContext,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
nsFrameList frames(aFrameList);
|
||||
ReResolveChildList(aPresContext, mStyleContext, frames);
|
||||
// XXX ReparentFrameView
|
||||
mFrames.AppendFrames(this, aFrameList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFirstLineFrame::InsertFrames2(nsIPresContext* aPresContext,
|
||||
nsIFrame* aPrevFrame,
|
||||
nsIFrame* aFrameList)
|
||||
{
|
||||
nsFrameList frames(aFrameList);
|
||||
ReResolveChildList(aPresContext, mStyleContext, frames);
|
||||
// XXX ReparentFrameView
|
||||
mFrames.InsertFrames(this, aPrevFrame, aFrameList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFirstLineFrame::RemoveFrame2(nsIPresContext* aPresContext,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
nsIFrame* nextInFlow;
|
||||
aOldFrame->GetNextInFlow(&nextInFlow);
|
||||
if (nextInFlow) {
|
||||
DeleteChildsNextInFlow(*aPresContext, aOldFrame);
|
||||
}
|
||||
mFrames.RemoveFrame(aOldFrame);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFirstLineFrame::RemoveFramesFrom(nsIFrame* aFrame)
|
||||
{
|
||||
nsIFrame* prevFrame = mFrames.GetPrevSiblingFor(aFrame);
|
||||
if (prevFrame) {
|
||||
prevFrame->SetNextSibling(nsnull);
|
||||
}
|
||||
else {
|
||||
mFrames.SetFrames(nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
nsFirstLineFrame::PullInlineFrame(nsIPresContext* aPresContext,
|
||||
InlineReflowState& irs,
|
||||
PRBool* aIsComplete)
|
||||
{
|
||||
nsIFrame* frame =
|
||||
nsInlineFrame::PullInlineFrame(aPresContext, irs, aIsComplete);
|
||||
if (frame && !mPrevInFlow) {
|
||||
// We are a first-line frame. Fixup the child frames
|
||||
// style-context that we just pulled.
|
||||
frame->ReResolveStyleContext(aPresContext, mStyleContext,
|
||||
NS_STYLE_HINT_REFLOW, nsnull, nsnull);
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
void
|
||||
nsFirstLineFrame::DrainOverflow(nsIPresContext* aPresContext)
|
||||
{
|
||||
// Check for an overflow list with our prev-in-flow
|
||||
nsFirstLineFrame* prevInFlow = (nsFirstLineFrame*)mPrevInFlow;
|
||||
if (nsnull != prevInFlow) {
|
||||
if (prevInFlow->mOverflowFrames.NotEmpty()) {
|
||||
ReResolveChildList(aPresContext, mStyleContext,
|
||||
prevInFlow->mOverflowFrames);
|
||||
mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames);
|
||||
}
|
||||
}
|
||||
|
||||
// It's also possible that we have an overflow list for ourselves
|
||||
if (mOverflowFrames.NotEmpty()) {
|
||||
NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
|
||||
ReResolveChildList(aPresContext, mStyleContext, mOverflowFrames);
|
||||
mFrames.AppendFrames(nsnull, mOverflowFrames);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLineFrame::Reflow(nsIPresContext& aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
if (nsnull == aReflowState.lineLayout) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
DrainOverflow(&aPresContext);
|
||||
|
||||
// Set our own reflow state (additional state above and beyond
|
||||
// aReflowState)
|
||||
InlineReflowState irs;
|
||||
irs.mPrevFrame = nsnull;
|
||||
irs.mNextInFlow = (nsInlineFrame*) mNextInFlow;
|
||||
irs.mNextRCFrame = nsnull;
|
||||
if (eReflowReason_Incremental == aReflowState.reason) {
|
||||
// Peel off the next frame in the path if this is an incremental
|
||||
// reflow aimed at one of the children.
|
||||
nsIFrame* target;
|
||||
aReflowState.reflowCommand->GetTarget(target);
|
||||
if (this != target) {
|
||||
aReflowState.reflowCommand->GetNext(irs.mNextRCFrame);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
PRBool wasEmpty = mFrames.IsEmpty();
|
||||
if (wasEmpty) {
|
||||
// Try to pull over one frame before starting so that we know
|
||||
// whether we have an anonymous block or not.
|
||||
PullAnyFrame(&aPresContext, irs);
|
||||
}
|
||||
|
||||
if (HaveAnonymousBlock()) {
|
||||
if (!aReflowState.lineLayout->LineIsEmpty()) {
|
||||
// This inline frame cannot be placed on the current line
|
||||
// because there already is an inline frame on this line (and we
|
||||
// contain an anonymous block).
|
||||
aStatus = NS_INLINE_LINE_BREAK_BEFORE();
|
||||
rv = NS_OK;
|
||||
}
|
||||
else {
|
||||
rv = ReflowBlockFrame(&aPresContext, aReflowState, irs,
|
||||
aMetrics, aStatus);
|
||||
|
||||
// If the combined area of our children exceeds our bounding box
|
||||
// then set the NS_FRAME_OUTSIDE_CHILDREN flag, otherwise clear
|
||||
// it.
|
||||
if ((aMetrics.mCombinedArea.x < 0) ||
|
||||
(aMetrics.mCombinedArea.y < 0) ||
|
||||
(aMetrics.mCombinedArea.XMost() > aMetrics.width) ||
|
||||
(aMetrics.mCombinedArea.YMost() > aMetrics.height)) {
|
||||
mState |= NS_FRAME_OUTSIDE_CHILDREN;
|
||||
}
|
||||
else {
|
||||
mState &= ~NS_FRAME_OUTSIDE_CHILDREN;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (wasEmpty) {
|
||||
// Fixup style of frame just pulled up
|
||||
nsIFrame* firstFrame = mFrames.FirstChild();
|
||||
if (firstFrame) {
|
||||
firstFrame->ReResolveStyleContext(&aPresContext, mStyleContext,
|
||||
NS_STYLE_HINT_REFLOW, nsnull,
|
||||
nsnull);
|
||||
}
|
||||
}
|
||||
if (nsnull == mPrevInFlow) {
|
||||
// XXX This is pretty sick, but what we do here is to pull-up, in
|
||||
// advance, all of the next-in-flows children. We re-resolve their
|
||||
// style while we are at at it so that when we reflow they have
|
||||
// the right style.
|
||||
//
|
||||
// All of this is so that text-runs reflow properly.
|
||||
irs.mPrevFrame = mFrames.LastChild();
|
||||
for (;;) {
|
||||
PRBool complete;
|
||||
nsIFrame* frame = PullInlineFrame(&aPresContext, irs, &complete);
|
||||
if (!frame) {
|
||||
break;
|
||||
}
|
||||
irs.mPrevFrame = frame;
|
||||
}
|
||||
irs.mPrevFrame = nsnull;
|
||||
}
|
||||
else {
|
||||
// For continuations, we need to check and see if our style
|
||||
// context is right. If its the same as the first-in-flow, then
|
||||
// we need to fix it up (that way :first-line style doesn't leak
|
||||
// into this continuation since we aren't the first line).
|
||||
nsFirstLineFrame* first = (nsFirstLineFrame*) GetFirstInFlow();
|
||||
if (mStyleContext == first->mStyleContext) {
|
||||
// Fixup our style context and our children. First get the
|
||||
// proper parent context.
|
||||
nsIFrame* parentFrame;
|
||||
first->GetParent(&parentFrame);
|
||||
nsIStyleContext* parentContext;
|
||||
parentFrame->GetStyleContext(&parentContext);
|
||||
if (parentContext) {
|
||||
// Create a new style context that is a child of the parent
|
||||
// style context thus removing the :first-line style. This way
|
||||
// we behave as if an anonymous (unstyled) span was the child
|
||||
// of the parent frame.
|
||||
nsIStyleContext* newSC;
|
||||
aPresContext.ResolvePseudoStyleContextFor(mContent,
|
||||
nsHTMLAtoms::mozLineFrame,
|
||||
parentContext,
|
||||
PR_FALSE, &newSC);
|
||||
if (newSC) {
|
||||
// Switch to the new style context.
|
||||
SetStyleContext(&aPresContext, newSC);
|
||||
|
||||
// Re-resolve all children
|
||||
ReResolveChildList(&aPresContext, mStyleContext, mFrames);
|
||||
|
||||
NS_RELEASE(newSC);
|
||||
}
|
||||
NS_RELEASE(parentContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = ReflowInlineFrames(&aPresContext, aReflowState, irs,
|
||||
aMetrics, aStatus);
|
||||
// Note: when we are reflowing inline frames the line layout code
|
||||
// will properly compute our NS_FRAME_OUTSIDE_CHILDREN state for
|
||||
// us.
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче