Spanked nsBlockFrame: newly rewritten, broken into two pieces (see nsLineLayout.h,.cpp for the line layout code)

This commit is contained in:
kipp 1998-05-02 00:56:24 +00:00
Родитель ee76c81742
Коммит fa2e5e968b
23 изменённых файлов: 7195 добавлений и 11954 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -20,158 +20,101 @@
#include "nsHTMLContainerFrame.h"
#include "nsIFloaterContainer.h"
#include "nsIHTMLFrameType.h"
#include "nsIRunaround.h"
#include "nsISpaceManager.h"
#include "nsLineLayout.h"
#include "nsVoidArray.h"
struct BlockBandData;
struct nsMargin;
struct nsStyleDisplay;
struct nsStyleFont;
struct nsStyleText;
class nsBlockFrame;
struct nsBandData;
struct nsBlockBandData : public nsBandData {
// Trapezoid's used during band processing
nsBandTrapezoid data[12];
// Bounding rect of available space between any left and right floaters
nsRect availSpace;
nsBlockBandData() {
size = 12;
trapezoids = data;
}
/**
* Computes the bounding rect of the available space, i.e. space
* between any left and right floaters Uses the current trapezoid
* data, see nsISpaceManager::GetBandData(). Also updates member
* data "availSpace".
*/
void ComputeAvailSpaceRect();
};
/**
* Block frames have some state which needs to be made
* available to child frames for proper reflow. This structure
* describes that state.
*/
struct nsBlockReflowState {
// True if this is the first line of text in a block container
PRPackedBool firstLine;
// True if leading whitespace is allowed to show
PRPackedBool allowLeadingWhitespace;
// This is set when some child frame needs a break after it's placed
PRPackedBool breakAfterChild;
// This is set when a child needs a break before it's placed. Note
// that this value is set by a child AFTER we have called it's
// ResizeReflow method.
PRPackedBool breakBeforeChild;
// This is set when the first child should be treated specially
// because it's an inside list item bullet.
// XXX this can go away once we have a way for the bullet's style
// molecule to *not* be the same as it's parent's
PRPackedBool firstChildIsInsideBullet;
// For pre-formatted text, this is our current column
PRIntn column;
// The next list ordinal value
PRInt32 nextListOrdinal;
//----------------------------------------------------------------------
// State from here on down is not to be used by block child frames!
// Space manager to use
nsISpaceManager* spaceManager;
// Block's style context
nsIStyleContext* styleContext;
nsStyleText* styleText;
nsStyleFont* styleFont;
nsStyleDisplay* styleDisplay;
// Block's available size (computed from the block's parent)
nsSize availSize;
// Current band of available space. Used for doing runaround
BlockBandData* currentBand;
// Pointer to a max-element-size (nsnull if none required)
nsSize* maxElementSize;
// The maximum x-most of our lines and block-level elements. This is used to
// compute our desired size, and includes our left border/padding. For block-
// level elements this also includes the block's right margin.
nscoord kidXMost;
// Current reflow position
nscoord y;
// Current line state
nscoord x; // inline elements only. not include border/padding
PRBool isInline; // whether the current is inline or block
nsVoidArray lineLengths; // line length temporary storage
PRIntn currentLineNumber; // index into mLines
nsIFrame* lineStart; // frame starting the line
PRInt32 lineLength; // length of line
nscoord* ascents; // ascent information for each child
nscoord maxAscent; // max ascent for this line
nscoord maxDescent; // max descent for this line
nscoord lineWidth; // current width of line
#if 0
nscoord maxPosTopMargin; // maximum positive top margin
nscoord maxNegTopMargin; // maximum negative top margin
#else
nscoord topMargin; // current top margin
#endif
nscoord maxPosBottomMargin; // maximum positive bottom margin
nscoord maxNegBottomMargin; // maximum negative bottom margin
nsSize lineMaxElementSize; // max element size for current line
PRBool lastContentIsComplete; // reflow status of last child on line
nsVoidArray floaterToDo; // list of floaters to place below current line
PRInt32 maxAscents; // size of ascent buffer
nscoord ascentBuf[20];
PRPackedBool needRelativePos; // some kid in line needs relative pos
// Previous line state that we carry forward to the next line
nsIFrame* prevLineLastFrame;
nscoord prevLineHeight; // height of the previous line
nscoord prevMaxPosBottomMargin; // maximum posative bottom margin
nscoord prevMaxNegBottomMargin; // maximum negative bottom margin
PRBool prevLineLastContentIsComplete;
// Sanitized version of mol->borderPadding; if this block frame is a
// pseudo-frame then the margin will be zero'd.
nsMargin borderPadding;
PRPackedBool justifying; // we are justifying
// Status from last PlaceAndReflowChild
nsIFrame::ReflowStatus reflowStatus;
// Flags for whether the max size is unconstrained
PRBool unconstrainedWidth;
PRBool unconstrainedHeight;
nsBlockReflowState();
~nsBlockReflowState();
void Init(const nsSize& aMaxSize, nsSize* aMaxElementSize,
nsIStyleContext* aStyleContext, nsISpaceManager* aSpaceManager);
nsresult Initialize(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsSize* aMaxElementSize,
nsBlockFrame* aBlock);
void AddAscent(nscoord aAscent);
void AdvanceToNextLine(nsIFrame* aPrevLineLastFrame, nscoord aPrevLineHeight);
nsIPresContext* mPresContext;
#ifdef NS_DEBUG
void DumpLine();
void DumpList();
#endif
nsBlockFrame* mBlock;
PRBool mBlockIsPseudo;
// Current line being reflowed
nsLineLayout* mCurrentLine;
// Previous line's last child frame
nsIFrame* mPrevKidFrame;
// Layout position information
nscoord mX;
nscoord mY;
nsSize mAvailSize;
PRPackedBool mUnconstrainedWidth;
PRPackedBool mUnconstrainedHeight;
nsSize* mMaxElementSizePointer;
nscoord mKidXMost;
// Bottom margin information from the previous line
nscoord mPrevMaxNegBottomMargin;
nscoord mPrevMaxPosBottomMargin;
// Block frame border+padding information
nsMargin mBorderPadding;
// Space manager and current band information
nsISpaceManager* mSpaceManager;
nsBlockBandData mCurrentBand;
// Array of floaters to place below current line
nsVoidArray mPendingFloaters;
PRInt32 mNextListOrdinal;
PRPackedBool mFirstChildIsInsideBullet;
};
//----------------------------------------------------------------------
/* 94e8e410-de21-11d1-89bf-006008911b81 */
#define NS_BLOCKFRAME_CID \
{0x94e8e410, 0xde21, 0x11d1, {0x89, 0xbf, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81}}
/**
* <h2>Block Reflow</h2>
*
* The block frame reflow machinery performs "2D" layout. Inline
* elements are flowed into logical lines (left to right or right to
* left) and the lines are stacked vertically. Block elements are
* flowed onto their own line after flushing out any preceeding line.<p>
*
* After a line is ready to be flushed out, vertical alignment is
* performed. Vertical alignment may require the line to consume more
* vertical space than is available thus causing the entire line to
* be pushed. <p>
*
* After vertical alignment is done, horizontal alignment (including
* justification) is performed. Finally, relative positioning is done
* on any elements that require it. <p>
* left) and the lines are stacked vertically. nsLineLayout is used
* for this part of the process. Block elements are flowed directly by
* the block reflow logic after flushing out any preceeding line.<p>
*
* During reflow, the block frame will make available to child frames
* it's reflow state using the presentation shell's cached data
@ -186,144 +129,155 @@ struct nsBlockReflowState {
*
* <h3>Assertions</h3>
* <b>mLastContentIsComplete</b> always reflects the state of the last
* child frame on our chlid list.
* child frame on our chlid list.
*/
class nsBlockFrame : public nsHTMLContainerFrame, public nsIHTMLFrameType,
public nsIRunaround, public nsIFloaterContainer
// XXX we don't use nsContainerFrame mOverFlowList!!! wasted memory
class nsBlockFrame : public nsHTMLContainerFrame,
public nsIRunaround,
public nsIFloaterContainer
{
public:
/**
* Create a new block frame that maps the given piece of content.
*/
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
nsIContent* aContent,
PRInt32 aIndexInParent,
nsIFrame* aParent);
// nsISupports
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD ResizeReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsSize* aMaxElementSize,
ReflowStatus& aStatus);
NS_IMETHOD IncrementalReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsReflowCommand& aReflowCommand,
ReflowStatus& aStatus);
NS_IMETHOD ContentAppended(nsIPresShell* aShell,
// nsIFrame
NS_IMETHOD ContentAppended(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer);
nsIContent* aContainer);
NS_IMETHOD ContentInserted(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInParent);
NS_IMETHOD ContentReplaced(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInParent);
NS_IMETHOD ContentDeleted(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInParent);
NS_IMETHOD GetReflowMetrics(nsIPresContext* aPresContext,
nsReflowMetrics& aMetrics);
NS_IMETHOD IsSplittable(SplittableType& aIsSplittable) const;
NS_IMETHOD CreateContinuingFrame(nsIPresContext* aPresContext,
nsIFrame* aParent,
nsIFrame*& aContinuingFrame);
nsIFrame* aParent,
nsIFrame*& aContinuingFrame);
NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
NS_IMETHOD ListTag(FILE* out) const;
NS_IMETHOD VerifyTree() const;
virtual PRBool AddFloater(nsIPresContext* aCX,
nsIFrame* aFloater,
// nsIRunaround
NS_IMETHOD ResizeReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsSize* aMaxElementSize,
nsIFrame::ReflowStatus& aStatus);
NS_IMETHOD IncrementalReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsReflowCommand& aReflowCommand,
nsIFrame::ReflowStatus& aStatus);
// nsIFloaterContainer
virtual PRBool AddFloater(nsIPresContext* aPresContext,
nsIFrame* aFloater,
PlaceholderFrame* aPlaceholder);
virtual void PlaceFloater(nsIPresContext* aCX,
nsIFrame* aFloater,
virtual void PlaceFloater(nsIPresContext* aPresContext,
nsIFrame* aFloater,
PlaceholderFrame* aPlaceholder);
NS_IMETHOD ListTag(FILE* out = stdout) const;
// nsBlockFrame
nsresult ReflowInlineChild(nsIFrame* aKidFrame,
nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsSize* aMaxElementSize,
ReflowStatus& aStatus);
virtual nsHTMLFrameType GetFrameType() const;
nsresult ReflowBlockChild(nsIFrame* aKidFrame,
nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsSize* aMaxElementSize,
ReflowStatus& aStatus);
nsLineData* GetFirstLine();
static nsBlockReflowState* FindBlockReflowState(nsIPresContext* aPresContext,
nsIFrame* aFrame);
protected:
nsBlockFrame(nsIContent* aContent,
PRInt32 aIndexInParent,
nsIFrame* aParent);
PRInt32 aIndexInParent,
nsIFrame* aParent);
virtual ~nsBlockFrame();
virtual PRIntn GetSkipSides() const;
PRBool MoreToReflow(nsIPresContext* aCX);
virtual void WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow);
nscoord GetTopMarginFor(nsIPresContext* aCX,
nsBlockReflowState& aState,
nsIFrame* aKidFrame,
nsIStyleContext* aKidSC,
PRBool aIsInline);
PRBool AdvanceToNextLine(nsIPresContext* aPresContext,
nsresult InitializeState(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsSize* aMaxElementSize,
nsBlockReflowState& aState);
void AddInlineChildToLine(nsIPresContext* aCX,
nsBlockReflowState& aState,
nsIFrame* aKidFrame,
nsReflowMetrics& aKidSize,
nsSize* aKidMaxElementSize,
nsIStyleContext* aKidSC);
nsresult DoResizeReflow(nsBlockReflowState& aState,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
ReflowStatus& aStatus);
void AddBlockChild(nsIPresContext* aCX,
nsBlockReflowState& aState,
nsIFrame* aKidFrame,
nsRect& aKidRect,
nsSize* aKidMaxElementSize,
nsIStyleContext* aKidSC);
void DestroyLines();
void GetAvailSize(nsSize& aResult,
nsBlockReflowState& aState,
nsIStyleContext* aKidSC,
PRBool aIsInline);
void DrainOverflowList();
PRIntn PlaceAndReflowChild(nsIPresContext* aCX,
nsBlockReflowState& aState,
nsIFrame* kidFrame,
nsIStyleContext* aKidSC);
nsLineData* CreateLineForOverflowList(nsIFrame* aOverflowList);
void PushKids(nsBlockReflowState& aState);
nsresult VerifyLines(PRBool aFinalCheck) const;
void SetupState(nsIPresContext* aCX, nsBlockReflowState& aState,
const nsSize& aMaxSize, nsSize* aMaxElementSize,
nsISpaceManager* aSpaceManager);
nsresult DoResizeReflow(nsIPresContext* aPresContext,
nsBlockReflowState& aState,
nsRect& aDesiredRect,
ReflowStatus& aStatus);
PRBool ReflowMappedChildren(nsIPresContext* aPresContext,
nsBlockReflowState& aState);
PRBool PullUpChildren(nsIPresContext* aCX,
nsBlockReflowState& aState);
ReflowStatus ReflowAppendedChildren(nsIPresContext* aPresContext,
nsBlockReflowState& aState);
void JustifyLines(nsIPresContext* aPresContext, nsBlockReflowState& aState);
nsresult PlaceLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineData* aLine);
PRBool IsLeftMostChild(nsIFrame* aFrame);
void GetAvailableSpaceBand(nsBlockReflowState& aState, nscoord aY);
void PlaceBelowCurrentLineFloaters(nsIPresContext* aCX,
nsBlockReflowState& aState,
void PlaceFloater(nsIPresContext* aPresContext,
nsIFrame* aFloater,
PlaceholderFrame* aPlaceholder,
nsBlockReflowState& aState);
void PlaceBelowCurrentLineFloaters(nsBlockReflowState& aState,
nscoord aY);
void ClearFloaters(nsBlockReflowState& aState, PRUint32 aClear);
nsresult GetAvailableSpace(nsBlockReflowState& aState, nscoord aY);
#ifdef NS_DEBUG
void DumpFlow() const;
#endif
PRBool MoreToReflow(nsBlockReflowState& aState);
/**
* Array of lines lengths. For each logical line of children, this array
* contains a count of the number of children on the line.
*/
PRInt32* mLines;
PRInt32 mNumLines;
nsBlockReflowState* mCurrentState;
nsresult PushLines(nsBlockReflowState& aState,
nsLineData* aLine);
nsresult ReflowMapped(nsBlockReflowState& aState);
nsresult ReflowUnmapped(nsBlockReflowState& aState);
nsLineData* mLines;
};
#endif /* nsBlockFrame_h___ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -42,14 +42,6 @@ public:
nsIFrame** aFrame,
PRInt32& aCursor);
#if 0
virtual ReflowStatus IncrementalReflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsISpaceManager* aSpaceManager,
nsReflowCommand& aReflowCommand);
#endif
protected:
virtual ~nsHTMLContainerFrame();
@ -59,32 +51,6 @@ protected:
const nsString& aBase,
const nsString& aURLSpec,
const nsString& aTargetSpec);
#if 0
virtual ReflowStatus ReflowAppended(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsISpaceManager* aSpaceManager,
nsReflowCommand& aReflowCommand);
virtual ReflowStatus ReflowInserted(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsISpaceManager* aSpaceManager,
nsReflowCommand& aReflowCommand);
virtual ReflowStatus ReflowDeleted(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsISpaceManager* aSpaceManager,
nsReflowCommand& aReflowCommand);
virtual ReflowStatus ReflowChanged(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsISpaceManager* aSpaceManager,
nsReflowCommand& aReflowCommand);
#endif
};
#endif /* nsHTMLContainerFrame_h___ */

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

@ -592,42 +592,6 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
// FALLTHROUGH
case NS_STYLE_DISPLAY_INLINE:
// XXX temporary hack to make plain BR's in inlines "work"
// get style for break-before-after; get break-type (line, page, etc.)
{
nsIAtom* tag = kid->GetTag();
if (nsHTMLAtoms::br == tag) {
// Set break-after flag so we stop mapping children (we
// will end up being continued if there are more children)
breakAfter = PR_TRUE;
// Get cached state for containing block frame
// XXX how about QueryInterface(kIHTMLBlockFrameIID)? DOH!
nsBlockReflowState* state = nsnull;
nsIFrame* parent = mGeometricParent;
while (nsnull != parent) {
nsIHTMLFrameType* ft;
nsresult status =
parent->QueryInterface(kIHTMLFrameTypeIID, (void**) &ft);
if (NS_OK == status) {
nsHTMLFrameType type = ft->GetFrameType();
if (eHTMLFrame_Block == type) {
break;
}
}
parent->GetGeometricParent(parent);
}
if (nsnull != parent) {
nsIPresShell* shell = aPresContext->GetShell();
state = (nsBlockReflowState*) shell->GetCachedData(parent);
// XXX Of course this won't work if the inline span is nested
// in another inline span!
state->breakAfterChild = PR_TRUE;
NS_RELEASE(shell);
}
}
NS_IF_RELEASE(tag);
}
kidDel = kid->GetDelegate(aPresContext);
kidFrame = kidDel->CreateFrame(aPresContext, kid, kidIndex, this);
NS_RELEASE(kidDel);

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

@ -841,10 +841,10 @@ nsLineLayout::CreateFrameFor(nsIContent* aKid)
nsIFrame* kidFrame;
if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) {
AbsoluteFrame::NewFrame(&kidFrame, aKid, mKidIndex, mBlock);
kidFrame->SetStyleContext(kidSC);
kidFrame->SetStyleContext(mPresContext, kidSC);
} else if (kidDisplay->mFloats != NS_STYLE_FLOAT_NONE) {
PlaceholderFrame::NewFrame(&kidFrame, aKid, mKidIndex, mBlock);
kidFrame->SetStyleContext(kidSC);
kidFrame->SetStyleContext(mPresContext, kidSC);
} else if (nsnull == mKidPrevInFlow) {
// Create initial frame for the child
@ -882,7 +882,7 @@ nsLineLayout::CreateFrameFor(nsIContent* aKid)
nsFrame::NewFrame(&kidFrame, aKid, mKidIndex, mBlock);
break;
}
kidFrame->SetStyleContext(kidSC);
kidFrame->SetStyleContext(mPresContext, kidSC);
} else {
// Since kid has a prev-in-flow, use that to create the next
// frame.

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

@ -42,6 +42,7 @@ CPPSRCS= \
nsImageMap.cpp \
nsInlineFrame.cpp \
nsLeafFrame.cpp \
nsLineLayout.cpp \
nsListItemFrame.cpp \
nsPageFrame.cpp \
nsPlaceholderFrame.cpp \
@ -73,6 +74,7 @@ CPP_OBJS= \
.\$(OBJDIR)\nsImageMap.obj \
.\$(OBJDIR)\nsInlineFrame.obj \
.\$(OBJDIR)\nsLeafFrame.obj \
.\$(OBJDIR)\nsLineLayout.obj \
.\$(OBJDIR)\nsListItemFrame.obj \
.\$(OBJDIR)\nsPageFrame.obj \
.\$(OBJDIR)\nsPlaceholderFrame.obj \

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

@ -28,8 +28,10 @@
#include "nsIHTMLAttributes.h"
#include "nsIStyleContext.h"
#include "nsIFontMetrics.h"
#include "nsIRenderingContext.h"
static NS_DEFINE_IID(kStyleFontSID, NS_STYLEFONT_SID);
static NS_DEFINE_IID(kStyleColorSID, NS_STYLECOLOR_SID);
class BRFrame : public nsFrame
{
@ -37,6 +39,10 @@ public:
BRFrame(nsIContent* aContent,
PRInt32 aIndexInParent,
nsIFrame* aParentFrame);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
NS_IMETHOD ResizeReflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
@ -60,13 +66,34 @@ BRFrame::~BRFrame()
{
}
NS_METHOD BRFrame::Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect)
{
if (nsIFrame::GetShowFrameBorders()) {
nsStyleColor* color = (nsStyleColor*)
mStyleContext->GetData(kStyleColorSID);
float p2t = aPresContext.GetPixelsToTwips();
aRenderingContext.SetColor(color->mColor);
aRenderingContext.FillRect(0, 0, nscoord(5 * p2t), mRect.height);
}
return NS_OK;
}
NS_METHOD BRFrame::GetReflowMetrics(nsIPresContext* aPresContext, nsReflowMetrics& aMetrics)
{
// We have no width, but we're the height of the default font
nsStyleFont* font =
(nsStyleFont*)mStyleContext->GetData(kStyleFontSID);
nsIFontMetrics* fm = aPresContext->GetMetricsFor(font->mFont);
aMetrics.width = 0;
if (nsIFrame::GetShowFrameBorders()) {
// Reserve a tiny bit of space so that our frame won't be zero
// sized so we get a chance to paint.
aMetrics.width = 1;
}
aMetrics.height = fm->GetHeight();
aMetrics.ascent = fm->GetMaxAscent();
aMetrics.descent = fm->GetMaxDescent();
@ -81,27 +108,15 @@ NS_METHOD BRFrame::ResizeReflow(nsIPresContext* aPresContext,
ReflowStatus& aStatus)
{
// Get cached state for containing block frame
nsBlockReflowState* state = nsnull;
nsIFrame* parent = mGeometricParent;
while (nsnull != parent) {
nsIHTMLFrameType* ft;
nsresult status = parent->QueryInterface(kIHTMLFrameTypeIID, (void**) &ft);
if (NS_OK == status) {
nsHTMLFrameType type = ft->GetFrameType();
if (eHTMLFrame_Block == type) {
break;
}
}
parent->GetGeometricParent(parent);
}
if (nsnull != parent) {
nsIPresShell* shell = aPresContext->GetShell();
state = (nsBlockReflowState*) shell->GetCachedData(parent);
NS_RELEASE(shell);
}
nsLineLayout* lineLayoutState = nsnull;
nsBlockReflowState* state =
nsBlockFrame::FindBlockReflowState(aPresContext, this);
if (nsnull != state) {
// XXX <BR clear=...>
state->breakAfterChild = PR_TRUE;
lineLayoutState = state->mCurrentLine;
if (nsnull != lineLayoutState) {
lineLayoutState->mReflowResult =
NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER;
}
}
GetReflowMetrics(aPresContext, aDesiredSize);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -20,158 +20,101 @@
#include "nsHTMLContainerFrame.h"
#include "nsIFloaterContainer.h"
#include "nsIHTMLFrameType.h"
#include "nsIRunaround.h"
#include "nsISpaceManager.h"
#include "nsLineLayout.h"
#include "nsVoidArray.h"
struct BlockBandData;
struct nsMargin;
struct nsStyleDisplay;
struct nsStyleFont;
struct nsStyleText;
class nsBlockFrame;
struct nsBandData;
struct nsBlockBandData : public nsBandData {
// Trapezoid's used during band processing
nsBandTrapezoid data[12];
// Bounding rect of available space between any left and right floaters
nsRect availSpace;
nsBlockBandData() {
size = 12;
trapezoids = data;
}
/**
* Computes the bounding rect of the available space, i.e. space
* between any left and right floaters Uses the current trapezoid
* data, see nsISpaceManager::GetBandData(). Also updates member
* data "availSpace".
*/
void ComputeAvailSpaceRect();
};
/**
* Block frames have some state which needs to be made
* available to child frames for proper reflow. This structure
* describes that state.
*/
struct nsBlockReflowState {
// True if this is the first line of text in a block container
PRPackedBool firstLine;
// True if leading whitespace is allowed to show
PRPackedBool allowLeadingWhitespace;
// This is set when some child frame needs a break after it's placed
PRPackedBool breakAfterChild;
// This is set when a child needs a break before it's placed. Note
// that this value is set by a child AFTER we have called it's
// ResizeReflow method.
PRPackedBool breakBeforeChild;
// This is set when the first child should be treated specially
// because it's an inside list item bullet.
// XXX this can go away once we have a way for the bullet's style
// molecule to *not* be the same as it's parent's
PRPackedBool firstChildIsInsideBullet;
// For pre-formatted text, this is our current column
PRIntn column;
// The next list ordinal value
PRInt32 nextListOrdinal;
//----------------------------------------------------------------------
// State from here on down is not to be used by block child frames!
// Space manager to use
nsISpaceManager* spaceManager;
// Block's style context
nsIStyleContext* styleContext;
nsStyleText* styleText;
nsStyleFont* styleFont;
nsStyleDisplay* styleDisplay;
// Block's available size (computed from the block's parent)
nsSize availSize;
// Current band of available space. Used for doing runaround
BlockBandData* currentBand;
// Pointer to a max-element-size (nsnull if none required)
nsSize* maxElementSize;
// The maximum x-most of our lines and block-level elements. This is used to
// compute our desired size, and includes our left border/padding. For block-
// level elements this also includes the block's right margin.
nscoord kidXMost;
// Current reflow position
nscoord y;
// Current line state
nscoord x; // inline elements only. not include border/padding
PRBool isInline; // whether the current is inline or block
nsVoidArray lineLengths; // line length temporary storage
PRIntn currentLineNumber; // index into mLines
nsIFrame* lineStart; // frame starting the line
PRInt32 lineLength; // length of line
nscoord* ascents; // ascent information for each child
nscoord maxAscent; // max ascent for this line
nscoord maxDescent; // max descent for this line
nscoord lineWidth; // current width of line
#if 0
nscoord maxPosTopMargin; // maximum positive top margin
nscoord maxNegTopMargin; // maximum negative top margin
#else
nscoord topMargin; // current top margin
#endif
nscoord maxPosBottomMargin; // maximum positive bottom margin
nscoord maxNegBottomMargin; // maximum negative bottom margin
nsSize lineMaxElementSize; // max element size for current line
PRBool lastContentIsComplete; // reflow status of last child on line
nsVoidArray floaterToDo; // list of floaters to place below current line
PRInt32 maxAscents; // size of ascent buffer
nscoord ascentBuf[20];
PRPackedBool needRelativePos; // some kid in line needs relative pos
// Previous line state that we carry forward to the next line
nsIFrame* prevLineLastFrame;
nscoord prevLineHeight; // height of the previous line
nscoord prevMaxPosBottomMargin; // maximum posative bottom margin
nscoord prevMaxNegBottomMargin; // maximum negative bottom margin
PRBool prevLineLastContentIsComplete;
// Sanitized version of mol->borderPadding; if this block frame is a
// pseudo-frame then the margin will be zero'd.
nsMargin borderPadding;
PRPackedBool justifying; // we are justifying
// Status from last PlaceAndReflowChild
nsIFrame::ReflowStatus reflowStatus;
// Flags for whether the max size is unconstrained
PRBool unconstrainedWidth;
PRBool unconstrainedHeight;
nsBlockReflowState();
~nsBlockReflowState();
void Init(const nsSize& aMaxSize, nsSize* aMaxElementSize,
nsIStyleContext* aStyleContext, nsISpaceManager* aSpaceManager);
nsresult Initialize(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsSize* aMaxElementSize,
nsBlockFrame* aBlock);
void AddAscent(nscoord aAscent);
void AdvanceToNextLine(nsIFrame* aPrevLineLastFrame, nscoord aPrevLineHeight);
nsIPresContext* mPresContext;
#ifdef NS_DEBUG
void DumpLine();
void DumpList();
#endif
nsBlockFrame* mBlock;
PRBool mBlockIsPseudo;
// Current line being reflowed
nsLineLayout* mCurrentLine;
// Previous line's last child frame
nsIFrame* mPrevKidFrame;
// Layout position information
nscoord mX;
nscoord mY;
nsSize mAvailSize;
PRPackedBool mUnconstrainedWidth;
PRPackedBool mUnconstrainedHeight;
nsSize* mMaxElementSizePointer;
nscoord mKidXMost;
// Bottom margin information from the previous line
nscoord mPrevMaxNegBottomMargin;
nscoord mPrevMaxPosBottomMargin;
// Block frame border+padding information
nsMargin mBorderPadding;
// Space manager and current band information
nsISpaceManager* mSpaceManager;
nsBlockBandData mCurrentBand;
// Array of floaters to place below current line
nsVoidArray mPendingFloaters;
PRInt32 mNextListOrdinal;
PRPackedBool mFirstChildIsInsideBullet;
};
//----------------------------------------------------------------------
/* 94e8e410-de21-11d1-89bf-006008911b81 */
#define NS_BLOCKFRAME_CID \
{0x94e8e410, 0xde21, 0x11d1, {0x89, 0xbf, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81}}
/**
* <h2>Block Reflow</h2>
*
* The block frame reflow machinery performs "2D" layout. Inline
* elements are flowed into logical lines (left to right or right to
* left) and the lines are stacked vertically. Block elements are
* flowed onto their own line after flushing out any preceeding line.<p>
*
* After a line is ready to be flushed out, vertical alignment is
* performed. Vertical alignment may require the line to consume more
* vertical space than is available thus causing the entire line to
* be pushed. <p>
*
* After vertical alignment is done, horizontal alignment (including
* justification) is performed. Finally, relative positioning is done
* on any elements that require it. <p>
* left) and the lines are stacked vertically. nsLineLayout is used
* for this part of the process. Block elements are flowed directly by
* the block reflow logic after flushing out any preceeding line.<p>
*
* During reflow, the block frame will make available to child frames
* it's reflow state using the presentation shell's cached data
@ -186,144 +129,155 @@ struct nsBlockReflowState {
*
* <h3>Assertions</h3>
* <b>mLastContentIsComplete</b> always reflects the state of the last
* child frame on our chlid list.
* child frame on our chlid list.
*/
class nsBlockFrame : public nsHTMLContainerFrame, public nsIHTMLFrameType,
public nsIRunaround, public nsIFloaterContainer
// XXX we don't use nsContainerFrame mOverFlowList!!! wasted memory
class nsBlockFrame : public nsHTMLContainerFrame,
public nsIRunaround,
public nsIFloaterContainer
{
public:
/**
* Create a new block frame that maps the given piece of content.
*/
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
nsIContent* aContent,
PRInt32 aIndexInParent,
nsIFrame* aParent);
// nsISupports
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD ResizeReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsSize* aMaxElementSize,
ReflowStatus& aStatus);
NS_IMETHOD IncrementalReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsReflowCommand& aReflowCommand,
ReflowStatus& aStatus);
NS_IMETHOD ContentAppended(nsIPresShell* aShell,
// nsIFrame
NS_IMETHOD ContentAppended(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer);
nsIContent* aContainer);
NS_IMETHOD ContentInserted(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInParent);
NS_IMETHOD ContentReplaced(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aOldChild,
nsIContent* aNewChild,
PRInt32 aIndexInParent);
NS_IMETHOD ContentDeleted(nsIPresShell* aShell,
nsIPresContext* aPresContext,
nsIContent* aContainer,
nsIContent* aChild,
PRInt32 aIndexInParent);
NS_IMETHOD GetReflowMetrics(nsIPresContext* aPresContext,
nsReflowMetrics& aMetrics);
NS_IMETHOD IsSplittable(SplittableType& aIsSplittable) const;
NS_IMETHOD CreateContinuingFrame(nsIPresContext* aPresContext,
nsIFrame* aParent,
nsIFrame*& aContinuingFrame);
nsIFrame* aParent,
nsIFrame*& aContinuingFrame);
NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
NS_IMETHOD ListTag(FILE* out) const;
NS_IMETHOD VerifyTree() const;
virtual PRBool AddFloater(nsIPresContext* aCX,
nsIFrame* aFloater,
// nsIRunaround
NS_IMETHOD ResizeReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsSize* aMaxElementSize,
nsIFrame::ReflowStatus& aStatus);
NS_IMETHOD IncrementalReflow(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsReflowCommand& aReflowCommand,
nsIFrame::ReflowStatus& aStatus);
// nsIFloaterContainer
virtual PRBool AddFloater(nsIPresContext* aPresContext,
nsIFrame* aFloater,
PlaceholderFrame* aPlaceholder);
virtual void PlaceFloater(nsIPresContext* aCX,
nsIFrame* aFloater,
virtual void PlaceFloater(nsIPresContext* aPresContext,
nsIFrame* aFloater,
PlaceholderFrame* aPlaceholder);
NS_IMETHOD ListTag(FILE* out = stdout) const;
// nsBlockFrame
nsresult ReflowInlineChild(nsIFrame* aKidFrame,
nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsSize* aMaxElementSize,
ReflowStatus& aStatus);
virtual nsHTMLFrameType GetFrameType() const;
nsresult ReflowBlockChild(nsIFrame* aKidFrame,
nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsSize* aMaxElementSize,
ReflowStatus& aStatus);
nsLineData* GetFirstLine();
static nsBlockReflowState* FindBlockReflowState(nsIPresContext* aPresContext,
nsIFrame* aFrame);
protected:
nsBlockFrame(nsIContent* aContent,
PRInt32 aIndexInParent,
nsIFrame* aParent);
PRInt32 aIndexInParent,
nsIFrame* aParent);
virtual ~nsBlockFrame();
virtual PRIntn GetSkipSides() const;
PRBool MoreToReflow(nsIPresContext* aCX);
virtual void WillDeleteNextInFlowFrame(nsIFrame* aNextInFlow);
nscoord GetTopMarginFor(nsIPresContext* aCX,
nsBlockReflowState& aState,
nsIFrame* aKidFrame,
nsIStyleContext* aKidSC,
PRBool aIsInline);
PRBool AdvanceToNextLine(nsIPresContext* aPresContext,
nsresult InitializeState(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsSize* aMaxElementSize,
nsBlockReflowState& aState);
void AddInlineChildToLine(nsIPresContext* aCX,
nsBlockReflowState& aState,
nsIFrame* aKidFrame,
nsReflowMetrics& aKidSize,
nsSize* aKidMaxElementSize,
nsIStyleContext* aKidSC);
nsresult DoResizeReflow(nsBlockReflowState& aState,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
ReflowStatus& aStatus);
void AddBlockChild(nsIPresContext* aCX,
nsBlockReflowState& aState,
nsIFrame* aKidFrame,
nsRect& aKidRect,
nsSize* aKidMaxElementSize,
nsIStyleContext* aKidSC);
void DestroyLines();
void GetAvailSize(nsSize& aResult,
nsBlockReflowState& aState,
nsIStyleContext* aKidSC,
PRBool aIsInline);
void DrainOverflowList();
PRIntn PlaceAndReflowChild(nsIPresContext* aCX,
nsBlockReflowState& aState,
nsIFrame* kidFrame,
nsIStyleContext* aKidSC);
nsLineData* CreateLineForOverflowList(nsIFrame* aOverflowList);
void PushKids(nsBlockReflowState& aState);
nsresult VerifyLines(PRBool aFinalCheck) const;
void SetupState(nsIPresContext* aCX, nsBlockReflowState& aState,
const nsSize& aMaxSize, nsSize* aMaxElementSize,
nsISpaceManager* aSpaceManager);
nsresult DoResizeReflow(nsIPresContext* aPresContext,
nsBlockReflowState& aState,
nsRect& aDesiredRect,
ReflowStatus& aStatus);
PRBool ReflowMappedChildren(nsIPresContext* aPresContext,
nsBlockReflowState& aState);
PRBool PullUpChildren(nsIPresContext* aCX,
nsBlockReflowState& aState);
ReflowStatus ReflowAppendedChildren(nsIPresContext* aPresContext,
nsBlockReflowState& aState);
void JustifyLines(nsIPresContext* aPresContext, nsBlockReflowState& aState);
nsresult PlaceLine(nsBlockReflowState& aState,
nsLineLayout& aLineLayout,
nsLineData* aLine);
PRBool IsLeftMostChild(nsIFrame* aFrame);
void GetAvailableSpaceBand(nsBlockReflowState& aState, nscoord aY);
void PlaceBelowCurrentLineFloaters(nsIPresContext* aCX,
nsBlockReflowState& aState,
void PlaceFloater(nsIPresContext* aPresContext,
nsIFrame* aFloater,
PlaceholderFrame* aPlaceholder,
nsBlockReflowState& aState);
void PlaceBelowCurrentLineFloaters(nsBlockReflowState& aState,
nscoord aY);
void ClearFloaters(nsBlockReflowState& aState, PRUint32 aClear);
nsresult GetAvailableSpace(nsBlockReflowState& aState, nscoord aY);
#ifdef NS_DEBUG
void DumpFlow() const;
#endif
PRBool MoreToReflow(nsBlockReflowState& aState);
/**
* Array of lines lengths. For each logical line of children, this array
* contains a count of the number of children on the line.
*/
PRInt32* mLines;
PRInt32 mNumLines;
nsBlockReflowState* mCurrentState;
nsresult PushLines(nsBlockReflowState& aState,
nsLineData* aLine);
nsresult ReflowMapped(nsBlockReflowState& aState);
nsresult ReflowUnmapped(nsBlockReflowState& aState);
nsLineData* mLines;
};
#endif /* nsBlockFrame_h___ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -73,9 +73,9 @@ public:
PRInt32 aIndexInParent,
nsIFrame* aParentFrame);
NS_METHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
NS_IMETHOD Paint(nsIPresContext& aPresContext,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);
protected:
virtual ~HRuleFrame();

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

@ -42,14 +42,6 @@ public:
nsIFrame** aFrame,
PRInt32& aCursor);
#if 0
virtual ReflowStatus IncrementalReflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsISpaceManager* aSpaceManager,
nsReflowCommand& aReflowCommand);
#endif
protected:
virtual ~nsHTMLContainerFrame();
@ -59,32 +51,6 @@ protected:
const nsString& aBase,
const nsString& aURLSpec,
const nsString& aTargetSpec);
#if 0
virtual ReflowStatus ReflowAppended(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsISpaceManager* aSpaceManager,
nsReflowCommand& aReflowCommand);
virtual ReflowStatus ReflowInserted(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsISpaceManager* aSpaceManager,
nsReflowCommand& aReflowCommand);
virtual ReflowStatus ReflowDeleted(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsISpaceManager* aSpaceManager,
nsReflowCommand& aReflowCommand);
virtual ReflowStatus ReflowChanged(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsSize& aMaxSize,
nsISpaceManager* aSpaceManager,
nsReflowCommand& aReflowCommand);
#endif
};
#endif /* nsHTMLContainerFrame_h___ */

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

@ -17,7 +17,7 @@
*/
#include "nsHTMLIIDs.h"
#include "nsIHTMLContent.h"
#include "nsIHTMLFrameType.h"
#include "nsBlockFrame.h"
const nsIID kIHTMLContentIID = NS_IHTMLCONTENT_IID;
const nsIID kIHTMLFrameTypeIID = NS_IHTMLFRAMETYPE_IID;
const nsIID kBlockFrameCID = NS_BLOCKFRAME_CID;

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

@ -21,6 +21,6 @@
#include "nsISupports.h"
extern const nsIID kIHTMLContentIID;
extern const nsIID kIHTMLFrameTypeIID;
extern const nsIID kBlockFrameCID;
#endif /* nsHTMLIIDs_h___ */

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

@ -592,42 +592,6 @@ nsInlineFrame::ReflowUnmappedChildren(nsIPresContext* aPresContext,
// FALLTHROUGH
case NS_STYLE_DISPLAY_INLINE:
// XXX temporary hack to make plain BR's in inlines "work"
// get style for break-before-after; get break-type (line, page, etc.)
{
nsIAtom* tag = kid->GetTag();
if (nsHTMLAtoms::br == tag) {
// Set break-after flag so we stop mapping children (we
// will end up being continued if there are more children)
breakAfter = PR_TRUE;
// Get cached state for containing block frame
// XXX how about QueryInterface(kIHTMLBlockFrameIID)? DOH!
nsBlockReflowState* state = nsnull;
nsIFrame* parent = mGeometricParent;
while (nsnull != parent) {
nsIHTMLFrameType* ft;
nsresult status =
parent->QueryInterface(kIHTMLFrameTypeIID, (void**) &ft);
if (NS_OK == status) {
nsHTMLFrameType type = ft->GetFrameType();
if (eHTMLFrame_Block == type) {
break;
}
}
parent->GetGeometricParent(parent);
}
if (nsnull != parent) {
nsIPresShell* shell = aPresContext->GetShell();
state = (nsBlockReflowState*) shell->GetCachedData(parent);
// XXX Of course this won't work if the inline span is nested
// in another inline span!
state->breakAfterChild = PR_TRUE;
NS_RELEASE(shell);
}
}
NS_IF_RELEASE(tag);
}
kidDel = kid->GetDelegate(aPresContext);
kidFrame = kidDel->CreateFrame(aPresContext, kid, kidIndex, this);
NS_RELEASE(kidDel);

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

@ -841,10 +841,10 @@ nsLineLayout::CreateFrameFor(nsIContent* aKid)
nsIFrame* kidFrame;
if (NS_STYLE_POSITION_ABSOLUTE == kidPosition->mPosition) {
AbsoluteFrame::NewFrame(&kidFrame, aKid, mKidIndex, mBlock);
kidFrame->SetStyleContext(kidSC);
kidFrame->SetStyleContext(mPresContext, kidSC);
} else if (kidDisplay->mFloats != NS_STYLE_FLOAT_NONE) {
PlaceholderFrame::NewFrame(&kidFrame, aKid, mKidIndex, mBlock);
kidFrame->SetStyleContext(kidSC);
kidFrame->SetStyleContext(mPresContext, kidSC);
} else if (nsnull == mKidPrevInFlow) {
// Create initial frame for the child
@ -882,7 +882,7 @@ nsLineLayout::CreateFrameFor(nsIContent* aKid)
nsFrame::NewFrame(&kidFrame, aKid, mKidIndex, mBlock);
break;
}
kidFrame->SetStyleContext(kidSC);
kidFrame->SetStyleContext(mPresContext, kidSC);
} else {
// Since kid has a prev-in-flow, use that to create the next
// frame.

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

@ -197,7 +197,7 @@ PRInt32 BulletFrame::GetListItemOrdinal(nsIPresContext* aCX,
if (eHTMLUnit_Integer == value.GetUnit()) {
ordinal = value.GetIntValue();
if (nsnull != state) {
state->nextListOrdinal = ordinal + 1;
state->mNextListOrdinal = ordinal + 1;
}
goto done;
}
@ -205,7 +205,7 @@ PRInt32 BulletFrame::GetListItemOrdinal(nsIPresContext* aCX,
// Get ordinal from block reflow state
if (nsnull != state) {
ordinal = state->nextListOrdinal;
ordinal = state->mNextListOrdinal;
if (ordinal < 0) {
// This is the first list item and the list container doesn't
// have a "start" attribute. Get the starting ordinal value
@ -219,7 +219,7 @@ PRInt32 BulletFrame::GetListItemOrdinal(nsIPresContext* aCX,
break;
}
}
state->nextListOrdinal = ordinal + 1;
state->mNextListOrdinal = ordinal + 1;
}
done:
@ -518,26 +518,23 @@ nsListItemFrame::GetListContainerReflowState(nsIPresContext* aCX)
nsBlockReflowState* state = nsnull;
nsIFrame* parent = mGeometricParent;
while (nsnull != parent) {
nsIHTMLFrameType* ft;
nsresult status = parent->QueryInterface(kIHTMLFrameTypeIID, (void**) &ft);
void* ft;
nsresult status = parent->QueryInterface(kBlockFrameCID, &ft);
if (NS_OK == status) {
nsHTMLFrameType type = ft->GetFrameType();
if (eHTMLFrame_Block == type) {
// The parent is a block. See if its content object is a list
// container. Only UL, OL, MENU or DIR can be list containers.
// XXX need something more flexible, say style?
nsIContent* parentContent;
// The parent is a block. See if its content object is a list
// container. Only UL, OL, MENU or DIR can be list containers.
// XXX need something more flexible, say style?
nsIContent* parentContent;
parent->GetContent(parentContent);
nsIAtom* tag = parentContent->GetTag();
NS_RELEASE(parentContent);
if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
(tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
NS_RELEASE(tag);
break;
}
parent->GetContent(parentContent);
nsIAtom* tag = parentContent->GetTag();
NS_RELEASE(parentContent);
if ((tag == nsHTMLAtoms::ul) || (tag == nsHTMLAtoms::ol) ||
(tag == nsHTMLAtoms::menu) || (tag == nsHTMLAtoms::dir)) {
NS_RELEASE(tag);
break;
}
NS_RELEASE(tag);
}
parent->GetGeometricParent(parent);
}
@ -549,6 +546,29 @@ nsListItemFrame::GetListContainerReflowState(nsIPresContext* aCX)
return state;
}
void
nsListItemFrame::InsertBullet(nsIFrame* aBullet)
{
mFirstChild = aBullet;
mChildCount++;
if (nsnull == mLines) {
mLines = new nsLineData();
mLines->mFirstChild = aBullet;
mLines->mChildCount = 1;
mLines->mFirstContentOffset = 0;
mLines->mLastContentOffset = 0;
mLines->mLastContentIsComplete = PR_TRUE;
}
else {
mLines->mChildCount++;
mLines->mFirstChild = aBullet;
}
mLines->mHasBullet = PR_TRUE;
#ifdef NS_DEBUG
mLines->Verify();
#endif
}
/**
* The basic approach here is pretty simple: let our base class do all
* the hard work, and after it's done, get the bullet placed. We only
@ -579,8 +599,7 @@ NS_METHOD nsListItemFrame::ResizeReflow(nsIPresContext* aCX,
// Inside bullets get placed on the list immediately so that
// the regular reflow logic can place them.
bullet = CreateBullet(aCX);
mFirstChild = bullet;
mChildCount++;
InsertBullet(bullet);
} else {
// We already have a first child. It's the bullet (check?)
// so we don't need to do anything here
@ -593,6 +612,9 @@ NS_METHOD nsListItemFrame::ResizeReflow(nsIPresContext* aCX,
// Pull bullet off list (we'll put it back later)
bullet = mFirstChild;
bullet->GetNextSibling(mFirstChild);
mLines->mFirstChild = mFirstChild;
mLines->mChildCount--;
mLines->mHasBullet = PR_FALSE;
mChildCount--;
}
}
@ -600,9 +622,9 @@ NS_METHOD nsListItemFrame::ResizeReflow(nsIPresContext* aCX,
// Let base class do things first
nsBlockReflowState state;
SetupState(aCX, state, aMaxSize, aMaxElementSize, aSpaceManager);
state.firstChildIsInsideBullet = insideBullet;
DoResizeReflow(aCX, state, aDesiredRect, aStatus);
InitializeState(aCX, aSpaceManager, aMaxSize, aMaxElementSize, state);
state.mFirstChildIsInsideBullet = insideBullet;
DoResizeReflow(state, aMaxSize, aDesiredRect, aStatus);
// Now place the bullet and put it at the head of the list of children
if (!insideBullet && (nsnull != bullet)) {
@ -612,19 +634,12 @@ NS_METHOD nsListItemFrame::ResizeReflow(nsIPresContext* aCX,
// information for the first line.
PlaceOutsideBullet(bullet, aCX);
bullet->SetNextSibling(mFirstChild);
mFirstChild = bullet;
mChildCount++;
if (nsnull == mLines) {
mLines = new PRInt32[1];
mLines[0] = 1;
mNumLines = 1;
} else {
mLines[0]++;
}
InsertBullet(bullet);
}
return NS_OK;
}
#if XXX
// XXX we may need to grow to accomodate the bullet
NS_METHOD nsListItemFrame::IncrementalReflow(nsIPresContext* aCX,
nsISpaceManager* aSpaceManager,
@ -634,8 +649,10 @@ NS_METHOD nsListItemFrame::IncrementalReflow(nsIPresContext* aCX,
ReflowStatus& aStatus)
{
aStatus = frComplete;
// XXX
return NS_OK;
}
#endif
NS_METHOD nsListItemFrame::CreateContinuingFrame(nsIPresContext* aCX,
nsIFrame* aParent,

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

@ -28,20 +28,13 @@ public:
PRInt32 aIndexInParent,
nsIFrame* aParent);
// nsIFrame
NS_IMETHOD ResizeReflow(nsIPresContext* aCX,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsSize* aMaxElementSize,
ReflowStatus& aStatus);
NS_IMETHOD IncrementalReflow(nsIPresContext* aCX,
nsISpaceManager* aSpaceManager,
const nsSize& aMaxSize,
nsRect& aDesiredRect,
nsReflowCommand& aReflowCommand,
ReflowStatus& aStatus);
NS_IMETHOD CreateContinuingFrame(nsIPresContext* aCX,
nsIFrame* aParent,
nsIFrame*& aContinuingFrame);
@ -62,6 +55,8 @@ protected:
nsIFrame* CreateBullet(nsIPresContext* aCX);
void InsertBullet(nsIFrame* aBullet);
virtual void PaintChildren(nsIPresContext& aCX,
nsIRenderingContext& aRenderingContext,
const nsRect& aDirtyRect);

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

@ -91,9 +91,9 @@ SpacerFrame::ResizeReflow(nsIPresContext* aPresContext,
{
// Get cached state for containing block frame
nsBlockReflowState* state = nsnull;
#if XXX
nsIFrame* parent = mGeometricParent;
while (nsnull != parent) {
nsIHTMLFrameType* ft;
nsresult status = parent->QueryInterface(kIHTMLFrameTypeIID, (void**) &ft);
if (NS_OK == status) {
nsHTMLFrameType type = ft->GetFrameType();
@ -108,6 +108,7 @@ SpacerFrame::ResizeReflow(nsIPresContext* aPresContext,
state = (nsBlockReflowState*) shell->GetCachedData(parent);
NS_RELEASE(shell);
}
#endif
// By default, we have no area
aDesiredSize.width = 0;
@ -170,8 +171,10 @@ SpacerFrame::ResizeReflow(nsIPresContext* aPresContext,
case TYPE_LINE:
if (0 != width) {
#if XXX
state->breakBeforeChild = PR_TRUE;
state->breakAfterChild = PR_TRUE;
#endif
aDesiredSize.height = nscoord(width * p2t);
aDesiredSize.ascent = aDesiredSize.height;
}

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

@ -34,6 +34,7 @@
#include "nsITimer.h"
#include "nsBlockFrame.h"
#include "prtime.h"
#include "nsVoidArray.h"
#include "prprf.h"
#include "nsIDOMText.h"
@ -151,7 +152,7 @@ protected:
nsSize* aMaxElementSize,
nsStyleFont& aFont,
PRInt32 aStartingOffset,
nsBlockReflowState* aState);
nsLineLayout* aLineState);
ReflowStatus ReflowNormal(nsIPresContext* aCX,
nsReflowMetrics& aDesiredSize,
@ -160,7 +161,7 @@ protected:
nsStyleFont& aFont,
nsStyleText& aTextStyle,
PRInt32 aStartingOffset,
nsBlockReflowState* aState);
nsLineLayout* aLineState);
public:
PRInt32 mContentOffset;
@ -665,23 +666,13 @@ NS_METHOD TextFrame::ResizeReflow(nsIPresContext* aCX,
}
// Get cached state for containing block frame
nsBlockReflowState* state = nsnull;
nsIFrame* parent = mGeometricParent;
while (nsnull != parent) {
nsIHTMLFrameType* ft;
nsresult status = parent->QueryInterface(kIHTMLFrameTypeIID, (void**) &ft);
if (NS_OK == status) {
nsHTMLFrameType type = ft->GetFrameType();
if (eHTMLFrame_Block == type) {
break;
}
nsLineLayout* lineLayoutState = nsnull;
nsBlockReflowState* state = nsBlockFrame::FindBlockReflowState(aCX, this);
if (nsnull != state) {
lineLayoutState = state->mCurrentLine;
if (nsnull != lineLayoutState) {
lineLayoutState->mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_AWARE;
}
parent->GetGeometricParent(parent);
}
if (nsnull != parent) {
nsIPresShell* shell = aCX->GetShell();
state = (nsBlockReflowState*) shell->GetCachedData(parent);
NS_RELEASE(shell);
}
nsStyleFont* font =
@ -703,13 +694,14 @@ NS_METHOD TextFrame::ResizeReflow(nsIPresContext* aCX,
if (NS_STYLE_WHITESPACE_PRE == text->mWhiteSpace) {
// Use a specialized routine for pre-formatted text
aStatus = ReflowPre(aCX, aDesiredSize, aMaxSize,
aMaxElementSize, *font, startingOffset, state);
aMaxElementSize, *font, startingOffset,
lineLayoutState);
} else {
// Use normal wrapping routine for non-pre text (this includes
// text that is not wrapping)
aStatus = ReflowNormal(aCX, aDesiredSize, aMaxSize,
aMaxElementSize, *font, *text,
startingOffset, state);
startingOffset, lineLayoutState);
}
#ifdef NOISY
@ -731,7 +723,7 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
nsStyleFont& aFont,
nsStyleText& aTextStyle,
PRInt32 aStartingOffset,
nsBlockReflowState* aState)
nsLineLayout* aLineState)
{
Text* txt = (Text*) mContent;
const PRUnichar* cp = txt->mText + aStartingOffset;
@ -749,8 +741,8 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
// Set whitespace skip flag
PRBool skipWhitespace = PR_FALSE;
if (nsnull != aState) {
if (!aState->allowLeadingWhitespace) {
if (nsnull != aLineState) {
if (aLineState->mSkipLeadingWhiteSpace) {
skipWhitespace = PR_TRUE;
mFlags |= TEXT_SKIP_LEADING_WS;
}
@ -769,6 +761,7 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
nscoord maxWidth = aMaxSize.width;
nscoord maxWordWidth = 0;
const PRUnichar* lastWordEnd = cpStart;
const PRUnichar* lastWordStart = cpStart;
PRBool hasMultibyte = PR_FALSE;
PRBool endsInWhitespace = PR_FALSE;
while (cp < end) {
@ -798,6 +791,7 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
hasMultibyte = PR_TRUE;
}
const PRUnichar* wordStart = cp - 1;
lastWordStart = wordStart;
while (cp < end) {
ch = *cp;
if (ch >= 256) {
@ -840,13 +834,14 @@ TextFrame::ReflowNormal(nsIPresContext* aCX,
mFlags |= TEXT_HAS_MULTIBYTE;
}
if (nsnull != aState) {
if (nsnull != aLineState) {
if (0 == x) {
// Since we collapsed into nothingness (all our whitespace
// is ignored) leave the aState->allowLeadingWhitespace
// is ignored) leave the aState->mSkipLeadingWhiteSpace
// flag alone since it doesn't want leading whitespace
} else {
aState->allowLeadingWhitespace = !endsInWhitespace;
}
else {
aLineState->mSkipLeadingWhiteSpace = endsInWhitespace;
}
}
@ -889,7 +884,7 @@ TextFrame::ReflowPre(nsIPresContext* aCX,
nsSize* aMaxElementSize,
nsStyleFont& aFont,
PRInt32 aStartingOffset,
nsBlockReflowState* aState)
nsLineLayout* aLineState)
{
Text* txt = (Text*) mContent;
const PRUnichar* cp = txt->mText + aStartingOffset;
@ -903,16 +898,16 @@ TextFrame::ReflowPre(nsIPresContext* aCX,
PRBool hasMultibyte = PR_FALSE;
PRUint16 tabs = 0;
PRIntn col = 0;
if (nsnull != aState) {
col = aState->column;
if (nsnull != aLineState) {
col = aLineState->mColumn;
}
mColumn = (PRUint16) col;
nscoord spaceWidth = widths[' '];
while (cp < end) {
PRUnichar ch = *cp++;
if (ch == '\n') {
if (nsnull != aState) {
aState->breakAfterChild = PR_TRUE;
if (nsnull != aLineState) {
aLineState->mReflowResult = NS_LINE_LAYOUT_REFLOW_RESULT_BREAK_AFTER;
}
break;
}
@ -937,8 +932,8 @@ TextFrame::ReflowPre(nsIPresContext* aCX,
}
col++;
}
if (nsnull != aState) {
aState->column = col;
if (nsnull != aLineState) {
aLineState->mColumn = col;
}
if (hasMultibyte) {
mFlags |= TEXT_HAS_MULTIBYTE;