This commit is contained in:
kipp 1998-06-18 23:16:00 +00:00
Родитель 3626bfa96d
Коммит f7d5a13f2b
9 изменённых файлов: 1070 добавлений и 1902 удалений

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

@ -1,55 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..\..
LIBRARY_NAME=nglcsslay_s
MODULE=raptor
REQUIRES=xpcom raptor
DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN
CPPSRCS= \
nsCSSBlockFrame.cpp \
nsCSSContainerFrame.cpp \
nsCSSInlineFrame.cpp \
nsCSSLineLayout.cpp \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsCSSBlockFrame.obj \
.\$(OBJDIR)\nsCSSContainerFrame.obj \
.\$(OBJDIR)\nsCSSInlineFrame.obj \
.\$(OBJDIR)\nsCSSLineLayout.obj \
$(NULL)
LINCS = \
-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\dom -I$(PUBLIC)\netlib \
-I..\..\..\base\src \
-I..\..\..\html\style\src -I..\..\..\html\base\src
LCFLAGS = \
$(LCFLAGS) \
$(DEFINES) \
$(NULL)
include <$(DEPTH)\layout\config\rules.mak>
libs:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

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

@ -18,9 +18,11 @@
*/ */
#include "nsCSSBlockFrame.h" #include "nsCSSBlockFrame.h"
#include "nsCSSLineLayout.h" #include "nsCSSLineLayout.h"
#include "nsCSSInlineLayout.h"
#include "nsCSSLayout.h" #include "nsCSSLayout.h"
#include "nsPlaceholderFrame.h" #include "nsPlaceholderFrame.h"
#include "nsStyleConsts.h" #include "nsStyleConsts.h"
#include "nsHTMLIIDs.h"
#include "nsIAnchoredItems.h" #include "nsIAnchoredItems.h"
#include "nsIPresContext.h" #include "nsIPresContext.h"
@ -35,11 +37,6 @@
#include "nsHTMLValue.h"// XXX list ordinal hack #include "nsHTMLValue.h"// XXX list ordinal hack
#include "nsIHTMLContent.h"// XXX list ordinal hack #include "nsIHTMLContent.h"// XXX list ordinal hack
static NS_DEFINE_IID(kIAnchoredItemsIID, NS_IANCHOREDITEMS_IID);
static NS_DEFINE_IID(kIFloaterContainerIID, NS_IFLOATERCONTAINER_IID);
static NS_DEFINE_IID(kIInlineReflowIID, NS_IINLINE_REFLOW_IID);
static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
// XXX mLastContentOffset, mFirstContentOffset, mLastContentIsComplete // XXX mLastContentOffset, mFirstContentOffset, mLastContentIsComplete
// XXX inline span frames // XXX inline span frames
// XXX IsFirstChild // XXX IsFirstChild
@ -178,8 +175,6 @@ nsCSSBlockReflowState::nsCSSBlockReflowState(nsIPresContext* aPresContext,
if (!mBlockIsPseudo) { if (!mBlockIsPseudo) {
const nsStyleSpacing* blockSpacing = (const nsStyleSpacing*) const nsStyleSpacing* blockSpacing = (const nsStyleSpacing*)
mBlockSC->GetStyleData(eStyleStruct_Spacing); mBlockSC->GetStyleData(eStyleStruct_Spacing);
const nsStylePosition* blockPosition = (const nsStylePosition*)
mBlockSC->GetStyleData(eStyleStruct_Position);
blockSpacing->CalcBorderPaddingFor(mBlock, mBorderPadding); blockSpacing->CalcBorderPaddingFor(mBlock, mBorderPadding);
mY = mBorderPadding.top; mY = mBorderPadding.top;
@ -1145,8 +1140,8 @@ InlineFrameData::ReflowLine(nsCSSBlockReflowState& aState,
// Prepare for reflowing this line // Prepare for reflowing this line
aLineLayout.Prepare(aState.mX); aLineLayout.Prepare(aState.mX);
nsCSSInlineLayout inlineLayout(aLineLayout, aState.mBlock, aState.mBlockSC, nsCSSInlineLayout inlineLayout(aLineLayout, aState.mBlock, aState.mBlockSC);
aState); inlineLayout.Init(&aState);
inlineLayout.Prepare(aState.mUnconstrainedWidth, aState.mNoWrap, inlineLayout.Prepare(aState.mUnconstrainedWidth, aState.mNoWrap,
aState.mMaxElementSize); aState.mMaxElementSize);
inlineLayout.SetReflowSpace(aState.mCurrentBand.availSpace.x, inlineLayout.SetReflowSpace(aState.mCurrentBand.availSpace.x,
@ -1291,7 +1286,7 @@ InlineFrameData::ReflowLine(nsCSSBlockReflowState& aState,
// See if speculative application of the margin should stick // See if speculative application of the margin should stick
if (ild == &mLines) { if (ild == &mLines) {
if (0 == inlineLayout.GetLineHeight()) { if (0 == inlineLayout.mMaxAscent + inlineLayout.mMaxDescent) {
// No, undo margin application when we get a zero height child. // No, undo margin application when we get a zero height child.
aState.mY -= bottomMargin; aState.mY -= bottomMargin;
if (aState.mY + bottomMargin >= aState.mCurrentBand.availSpace.YMost()) { if (aState.mY + bottomMargin >= aState.mCurrentBand.availSpace.YMost()) {
@ -1351,7 +1346,7 @@ InlineFrameData::SplitLine(nsCSSBlockReflowState& aState,
InlineLineData* ild, InlineLineData* ild,
nsIFrame* aFrame) nsIFrame* aFrame)
{ {
PRInt32 pushCount = ild->mChildCount - aInlineLayout.GetFrameNum(); PRInt32 pushCount = ild->mChildCount - aInlineLayout.mFrameNum;
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW, NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("LineLayout::SplitLine: pushing %d frames", ("LineLayout::SplitLine: pushing %d frames",
pushCount)); pushCount));
@ -1692,7 +1687,7 @@ nsCSSBlockFrame::Reflow(nsIPresContext* aPresContext,
// Replace parent provided reflow state with our own significantly // Replace parent provided reflow state with our own significantly
// more extensive version. // more extensive version.
nsCSSBlockReflowState state(aPresContext, aSpaceManager, this, aReflowState, nsCSSBlockReflowState state(aPresContext, aSpaceManager, this, aReflowState,
aMetrics.maxElementSize); aMetrics.maxElementSize);
nsresult rv = NS_OK; nsresult rv = NS_OK;
if (eReflowReason_Initial == state.reason) { if (eReflowReason_Initial == state.reason) {

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

@ -171,6 +171,4 @@ protected:
nsVoidArray* mRunInFloaters; nsVoidArray* mRunInFloaters;
}; };
#define IS_REFLOW_ERROR(_status) (PRInt32(_status) < 0)
#endif /* nsCSSBlockFrame_h___ */ #endif /* nsCSSBlockFrame_h___ */

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

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

@ -15,28 +15,61 @@
* Copyright (C) 1998 Netscape Communications Corporation. All Rights * Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved. * Reserved.
*/ */
#ifndef nsInlineFrame_h___ #ifndef nsCSSInlineFrame_h___
#define nsInlineFrame_h___ #define nsCSSInlineFrame_h___
#include "nsHTMLContainerFrame.h" #include "nsCSSContainerFrame.h"
#include "nsCSSInlineLayout.h"
#include "nsCSSLineLayout.h" #include "nsCSSLineLayout.h"
class nsInlineState;
// Inline container class. Does not support being used as a pseudo frame class nsCSSInlineFrame;
class nsInlineFrame : public nsHTMLContainerFrame, public nsIInlineReflow {
/**
* Reflow state object for managing css inline layout. Most of the state
* is managed by the nsCSSInlineLayout object.
*/
struct nsCSSInlineReflowState : public nsReflowState {
nsCSSInlineReflowState(nsCSSLineLayout& aLineLayout,
nsCSSInlineFrame* aInlineFrame,
nsIStyleContext* aInlineSC,
const nsReflowState& aReflowState,
nsSize* aMaxElementSize);
~nsCSSInlineReflowState();
nsIPresContext* mPresContext;
nsCSSInlineLayout mInlineLayout;
nsIFrame* mLastChild; // last child we have reflowed (so far)
PRInt32 mKidContentIndex; // content index of last child reflowed
nsMargin mBorderPadding;
PRBool mNoWrap;
PRIntn mStyleSizeFlags;
nsSize mStyleSize;
};
//----------------------------------------------------------------------
/**
* CSS "inline" layout class.
*
* Note: This class does not support being used as a pseudo frame.
*/
class nsCSSInlineFrame : public nsCSSContainerFrame,
public nsIInlineReflow
{
public: public:
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
nsIContent* aContent,
nsIFrame* aParent);
// nsISupports // nsISupports
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
// nsIFrame // nsIFrame
#if XXX_not_yet
NS_IMETHOD Reflow(nsIPresContext* aPresContext, NS_IMETHOD Reflow(nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize, nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState, const nsReflowState& aReflowState,
nsReflowStatus& aStatus); nsReflowStatus& aStatus);
#endif
// nsIInlineReflow // nsIInlineReflow
NS_IMETHOD FindTextRuns(nsCSSLineLayout& aLineLayout); NS_IMETHOD FindTextRuns(nsCSSLineLayout& aLineLayout);
@ -45,70 +78,38 @@ public:
const nsReflowState& aReflowState); const nsReflowState& aReflowState);
protected: protected:
nsInlineFrame(nsIContent* aContent, nsIFrame* aParent); nsCSSInlineFrame(nsIContent* aContent, nsIFrame* aParent);
virtual ~nsInlineFrame(); virtual ~nsCSSInlineFrame();
virtual PRIntn GetSkipSides() const; virtual PRIntn GetSkipSides() const;
void InitializeState(nsIPresContext* aPresContext, nsresult FrameAppendedReflow(nsCSSInlineReflowState& aState);
const nsReflowState& aReflowState,
nsInlineState& aState);
PRBool DidFitChild(nsIPresContext* aPresContext, nsresult ChildIncrementalReflow(nsCSSInlineReflowState& aState);
nsInlineState& aState,
nsIFrame* aChildFrame,
nsReflowMetrics& aChildMetrics);
PRBool CanFitChild(nsIPresContext* aPresContext, nsresult ResizeReflow(nsCSSInlineReflowState& aState);
nsInlineState& aState,
nsIFrame* aChildFrame);
void ComputeFinalSize(nsIPresContext* aPresContext, void ComputeFinalSize(nsCSSInlineReflowState& aState,
nsInlineState& aState, nsReflowMetrics& aMetrics);
nsReflowMetrics& aSize);
PRBool ReflowMappedChildrenFrom(nsIPresContext* aPresContext, nsInlineReflowStatus ReflowMapped(nsCSSInlineReflowState& aState);
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex);
PRBool PullUpChildren(nsIPresContext* aPresContext, nsInlineReflowStatus ReflowUnmapped(nsCSSInlineReflowState& aState);
nsInlineState& aState);
nsReflowStatus ReflowUnmappedChildren(nsIPresContext* aPresContext, nsInlineReflowStatus PullUpChildren(nsCSSInlineReflowState& aState);
nsInlineState& aState);
void PlaceChild(nsIFrame* aChild, void PushKids(nsCSSInlineReflowState& aState,
PRInt32 aIndex, // in the child frame list nsIFrame* aPrevChild, nsIFrame* aPushedChild);
nsInlineState& aState,
const nsReflowMetrics& aChildSize,
const nsSize* aChildMaxElementSize);
PRInt32 RecoverState(nsIPresContext* aCX, friend nsresult NS_NewCSSInlineFrame(nsIFrame** aInstancePtrResult,
nsInlineState& aState, nsIContent* aContent,
nsIFrame* aSkipChild); nsIFrame* aParent);
nsresult Reflow2(nsIPresContext* aPresContext,
nsCSSLineLayout* aLineLayout,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState);
nsReflowStatus IncrementalReflowFrom(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex);
nsReflowStatus IncrementalReflowAfter(nsIPresContext* aPresContext,
nsInlineState& aState,
nsIFrame* aChildFrame,
PRInt32 aChildIndex);
nsInlineReflowStatus ReflowChild(nsInlineState& aState,
nsIFrame* aKidFrame,
nsIPresContext* aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState);
}; };
#endif /* nsInlineFrame_h___ */ extern nsresult NS_NewCSSInlineFrame(nsIFrame** aInstancePtrResult,
nsIContent* aContent,
nsIFrame* aParent);
#endif /* nsCSSInlineFrame_h___ */

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

@ -0,0 +1,422 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#include "nsCSSInlineLayout.h"
#include "nsCSSLineLayout.h"
#include "nsCSSLayout.h"
#include "nsHTMLIIDs.h"
#include "nsCSSContainerFrame.h"
#include "nsIFontMetrics.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
#include "nsIRunaround.h"
nsCSSInlineLayout::nsCSSInlineLayout(nsCSSLineLayout& aLineLayout,
nsIFrame* aContainerFrame,
nsIStyleContext* aContainerStyle)
: mLineLayout(aLineLayout)
{
mContainerFrame = aContainerFrame;
mAscents = mAscentBuf;
mMaxAscents = sizeof(mAscentBuf) / sizeof(mAscentBuf[0]);
mMaxElementSize = nsnull;
mContainerFont = (const nsStyleFont*)
aContainerStyle->GetStyleData(eStyleStruct_Font);
mContainerText = (const nsStyleText*)
aContainerStyle->GetStyleData(eStyleStruct_Text);
mContainerDisplay = (const nsStyleDisplay*)
aContainerStyle->GetStyleData(eStyleStruct_Display);
mDirection = mContainerDisplay->mDirection;
}
nsCSSInlineLayout::~nsCSSInlineLayout()
{
if (mAscents != mAscentBuf) {
delete [] mAscents;
}
}
void
nsCSSInlineLayout::Init(const nsReflowState* aContainerReflowState)
{
mContainerReflowState = aContainerReflowState;
}
nsresult
nsCSSInlineLayout::SetAscent(nscoord aAscent)
{
PRInt32 frameNum = mFrameNum;
if (frameNum == mMaxAscents) {
mMaxAscents *= 2;
nscoord* newAscents = new nscoord[mMaxAscents];
if (nsnull == newAscents) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCRT::memcpy(newAscents, mAscents, sizeof(nscoord) * frameNum);
if (mAscents != mAscentBuf) {
delete [] mAscents;
}
mAscents = newAscents;
}
mAscents[frameNum] = aAscent;
return NS_OK;
}
void
nsCSSInlineLayout::Prepare(PRBool aUnconstrainedWidth, PRBool aNoWrap,
nsSize* aMaxElementSize)
{
mFrameNum = 0;
mUnconstrainedWidth = aUnconstrainedWidth;
mNoWrap = aNoWrap;
mMaxElementSize = aMaxElementSize;
mMaxAscent = 0;
mMaxDescent = 0;
}
void
nsCSSInlineLayout::SetReflowSpace(nscoord aX, nscoord aY,
nscoord aAvailWidth, nscoord aAvailHeight)
{
mAvailWidth = aAvailWidth;
mAvailHeight = aAvailHeight;
mX = aX;
mY = aY;
mLeftEdge = aX;
mRightEdge = aX + aAvailWidth;
}
//XXX block children of inline frames needs handling *here*
nsInlineReflowStatus
nsCSSInlineLayout::ReflowAndPlaceFrame(nsIFrame* aFrame)
{
// Compute the maximum size of the frame. If there is no room at all
// for it, then trigger a line-break before the frame.
nsSize maxSize;
nsMargin margin;
if (!ComputeMaxSize(aFrame, margin, maxSize)) {
return NS_INLINE_REFLOW_LINE_BREAK_BEFORE;
}
// Get reflow reason set correctly. It's possible that we created a
// child and then decided that we cannot reflow it (for example, a
// block frame that isn't at the start of a line). In this case the
// reason will be wrong so we need to check the frame state.
nsReflowReason reason = eReflowReason_Resize;
if (nsnull != mContainerReflowState->reflowCommand) {
reason = eReflowReason_Incremental;
}
else {
nsFrameState state;
aFrame->GetFrameState(state);
if (NS_FRAME_FIRST_REFLOW & state) {
reason = eReflowReason_Initial;
}
}
// Setup reflow state for reflowing the frame
nsReflowState reflowState(aFrame, *mContainerReflowState, maxSize, reason);
nsInlineReflowStatus rs;
nsReflowMetrics metrics(mMaxElementSize);
PRBool isAware;
aFrame->WillReflow(*mLineLayout.mPresContext);
rs = ReflowFrame(aFrame, metrics, reflowState, isAware);
if (IS_REFLOW_ERROR(rs)) {
return rs;
}
if (NS_INLINE_REFLOW_BREAK_BEFORE == (rs & NS_INLINE_REFLOW_REFLOW_MASK)) {
return rs;
}
// It's possible the frame didn't fit
if (metrics.width > maxSize.width) {
if (!IsFirstChild()) {
// We are out of room.
// XXX mKidPrevInFlow
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("LineLayout::ReflowChild: !fit size=%d,%d",
metrics.width, metrics.height));
return NS_INLINE_REFLOW_LINE_BREAK_BEFORE;
}
}
nsRect frameRect(mX, mY, metrics.width, metrics.height);
return PlaceFrame(aFrame, frameRect, metrics, margin, rs);
}
// XXX RTL
PRBool
nsCSSInlineLayout::IsFirstChild()
{
return 0 == mFrameNum;
}
PRBool
nsCSSInlineLayout::ComputeMaxSize(nsIFrame* aFrame,
nsMargin& aKidMargin,
nsSize& aResult)
{
const nsStyleSpacing* kidSpacing;
aFrame->GetStyleData(eStyleStruct_Spacing,
(const nsStyleStruct*&)kidSpacing);
kidSpacing->CalcMarginFor(aFrame, aKidMargin);
if (mUnconstrainedWidth || mNoWrap) {
aResult.width = NS_UNCONSTRAINEDSIZE;
}
else {
aResult.width = mRightEdge - mX;
aResult.width -= aKidMargin.left + aKidMargin.right;
if (!IsFirstChild() && (aResult.width <= 0)) {
// XXX Make sure child is dirty for next time
aFrame->WillReflow(*mLineLayout.mPresContext);
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("CSSLineLayout::ComputeMaxSize: !fit"));
return PR_FALSE;
}
}
aResult.height = mAvailHeight;
return PR_TRUE;
}
nsInlineReflowStatus
nsCSSInlineLayout::ReflowFrame(nsIFrame* aKidFrame,
nsReflowMetrics& aMetrics,
const nsReflowState& aReflowState,
PRBool& aInlineAware)
{
// There are 3 ways to reflow the child frame: using the nsIRunaround
// interface, using the nsIInlineReflow interface or using the default
// Reflow method in nsIFrame. The order of precedence is nsIRunaround,
// nsIInlineReflow, nsIFrame. For all three API's we map the reflow status
// into an nsInlineReflowStatus.
nsresult rv;
nsIRunaround* runAround;
nsIInlineReflow* inlineReflow;
if ((nsnull != mLineLayout.mSpaceManager) &&
(NS_OK == aKidFrame->QueryInterface(kIRunaroundIID,
(void**)&runAround))) {
nsRect r;
runAround->Reflow(mLineLayout.mPresContext, mLineLayout.mSpaceManager,
aMetrics, aReflowState, r, rv);
aMetrics.width = r.width;
aMetrics.height = r.height;
aMetrics.ascent = r.height;
aMetrics.descent = 0;
rv = NS_FRAME_REFLOW_STATUS_2_INLINE_REFLOW_STATUS(rv);
aInlineAware = PR_FALSE;
}
else if (NS_OK == aKidFrame->QueryInterface(kIInlineReflowIID,
(void**)&inlineReflow)) {
rv = inlineReflow->InlineReflow(mLineLayout, aMetrics, aReflowState);
aInlineAware = PR_TRUE;
}
else {
aKidFrame->Reflow(mLineLayout.mPresContext, aMetrics, aReflowState, rv);
rv = NS_FRAME_REFLOW_STATUS_2_INLINE_REFLOW_STATUS(rv);
aInlineAware = PR_FALSE;
}
if (NS_FRAME_IS_COMPLETE(rv)) {
nsIFrame* kidNextInFlow;
aKidFrame->GetNextInFlow(kidNextInFlow);
if (nsnull != kidNextInFlow) {
// Remove all of the childs next-in-flows. Make sure that we ask
// the right parent to do the removal (it's possible that the
// parent is not this because we are executing pullup code)
nsCSSContainerFrame* parent;
aKidFrame->GetGeometricParent((nsIFrame*&)parent);
parent->DeleteChildsNextInFlow(aKidFrame);
}
}
return rv;
}
nsInlineReflowStatus
nsCSSInlineLayout::PlaceFrame(nsIFrame* aFrame,
nsRect& aFrameRect,
const nsReflowMetrics& aFrameMetrics,
const nsMargin& aFrameMargin,
nsInlineReflowStatus aFrameReflowStatus)
{
nscoord horizontalMargins = 0;
// Special case to position outside list bullets.
// XXX RTL bullets
PRBool isBullet = PR_FALSE;
if (mLineLayout.mListPositionOutside) {
PRBool isFirstChild = IsFirstChild();
if (isFirstChild && (0 == mLineLayout.mLineNumber)) {
nsIFrame* containerPrevInFlow;
mContainerFrame->GetPrevInFlow(containerPrevInFlow);
if (nsnull == containerPrevInFlow) {
isBullet = PR_TRUE;
// We are placing the first child of the container and we have
// list-style-position of "outside" therefore this is the
// bullet that is being reflowed. The bullet is placed in the
// padding area of this block. Don't worry about getting the Y
// coordinate of the bullet right (vertical alignment will
// take care of that).
// Compute gap between bullet and inner rect left edge
nsIFontMetrics* fm =
mLineLayout.mPresContext->GetMetricsFor(mContainerFont->mFont);
nscoord kidAscent = fm->GetMaxAscent();
nscoord dx = fm->GetHeight() / 2; // from old layout engine
NS_RELEASE(fm);
// XXX RTL bullets
aFrameRect.x = mX - aFrameRect.width - dx;
aFrame->SetRect(aFrameRect);
}
}
}
if (!isBullet) {
// Place normal in-flow child
aFrame->SetRect(aFrameRect);
// XXX RTL
// Advance
const nsStyleDisplay* frameDisplay;
aFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) frameDisplay);
switch (frameDisplay->mFloats) {
default:
NS_NOTYETIMPLEMENTED("Unsupported floater type");
// FALL THROUGH
case NS_STYLE_FLOAT_LEFT:
case NS_STYLE_FLOAT_RIGHT:
// When something is floated, it's margin's are applied there
// not here.
break;
case NS_STYLE_FLOAT_NONE:
horizontalMargins = aFrameMargin.left + aFrameMargin.right;
break;
}
nscoord totalWidth = aFrameMetrics.width + horizontalMargins;
mX += totalWidth;
}
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("CSSLineLayout::PlaceChild: frame=%p {%d, %d, %d, %d}",
aFrame,
aFrameRect.x, aFrameRect.y,
aFrameRect.width, aFrameRect.height));
#if XXX_fix_me
// XXX this is not right; the max-element-size of a child depends on
// it's margins which it doesn't know how to add in
if (nsnull != mMaxElementSize) {
// XXX I'm not certain that this is doing the right thing; rethink this
nscoord elementWidth = kidMaxElementSize->width + horizontalMargins;
if (elementWidth > mMaxElementSize->width) {
mMaxElementSize->width = elementWidth;
}
if (aFrameMetrics.height > mMaxElementSize->height) {
mMaxElementSize->height = aFrameMetrics.height;
}
}
#endif
if (aFrameMetrics.ascent > mMaxAscent) {
mMaxAscent = aFrameMetrics.ascent;
}
if (aFrameMetrics.descent > mMaxDescent) {
mMaxDescent = aFrameMetrics.descent;
}
nsresult rv = SetAscent(aFrameMetrics.ascent);
if (NS_OK != rv) {
return nsInlineReflowStatus(rv);
}
mFrameNum++;
#if XXX_fix_me
mLine->mLastContentOffset = mKidContentIndex;
switch (aFrameReflowStatus & NS_INLINE_REFLOW_REFLOW_MASK) {
case NS_INLINE_REFLOW_COMPLETE:
case NS_INLINE_REFLOW_BREAK_AFTER:
mLine->mLastContentIsComplete = PR_TRUE;
mKidPrevInFlow = nsnull;
break;
case NS_INLINE_REFLOW_NOT_COMPLETE:
mLine->mLastContentIsComplete = PR_FALSE;
mKidPrevInFlow = mKidFrame;
break;
}
#endif
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("CSSLineLayout::PlaceChild: aFrameReflowStatus=%x",
aFrameReflowStatus));
return aFrameReflowStatus;
}
nscoord
nsCSSInlineLayout::AlignFrames(nsIFrame* aFrame, PRInt32 aFrameCount,
nsRect& aBounds)
{
NS_PRECONDITION(aFrameCount == mFrameNum, "bogus reflow");
nscoord lineHeight;
if (PR_TRUE /*XXX !mLine->mIsBlock*/) {
// Vertically align the children on the line; this will compute
// the actual line height for us.
lineHeight =
nsCSSLayout::VerticallyAlignChildren(mLineLayout.mPresContext,
mContainerFrame, mContainerFont,
mY, aFrame, aFrameCount,
mAscents, mMaxAscent);
}
else {
// The line height of a block is just the block's height
lineHeight = mMaxAscent;
}
// Save away line bounds before other adjustments
aBounds.x = mLeftEdge;
aBounds.y = mY;
aBounds.width = mX - mLeftEdge;
aBounds.height = lineHeight;
// Now horizontally place the children
if (!mUnconstrainedWidth) {
nsCSSLayout::HorizontallyPlaceChildren(mLineLayout.mPresContext,
mContainerFrame,
mContainerText->mTextAlign,
mDirection,
aFrame, aFrameCount,
mX - mLeftEdge,
mAvailWidth);
}
// Last, apply relative positioning
nsCSSLayout::RelativePositionChildren(mLineLayout.mPresContext,
mContainerFrame,
aFrame, aFrameCount);
return lineHeight;
}

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

@ -0,0 +1,97 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are Copyright (C) 1998
* Netscape Communications Corporation. All Rights Reserved.
*/
#ifndef nsCSSInlineLayout_h___
#define nsCSSInlineLayout_h___
#include "nsIFrame.h"
#include "nsIInlineReflow.h"
class nsCSSLineLayout;
struct nsStyleDisplay;
struct nsStyleFont;
struct nsStyleText;
/**
* This structure contains the horizontal layout state for line
* layout frame placement. This is factored out of nsCSSLineLayout so
* that the block layout code and the inline layout code can use
* nsCSSLineLayout to reflow and place frames.
*/
struct nsCSSInlineLayout {
nsCSSInlineLayout(nsCSSLineLayout& aLineLayout,
nsIFrame* aContainerFrame,
nsIStyleContext* aContainerStyle);
~nsCSSInlineLayout();
void Init(const nsReflowState* aContainerReflowState);
void Prepare(PRBool aUnconstrainedWidth,
PRBool aNoWrap,
nsSize* aMaxElementSize);
void SetReflowSpace(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
nsInlineReflowStatus ReflowAndPlaceFrame(nsIFrame* aFrame);
nscoord AlignFrames(nsIFrame* aFrame, PRInt32 aFrameCount, nsRect& aBounds);
PRBool IsFirstChild();
nsresult SetAscent(nscoord aAscent);
PRBool ComputeMaxSize(nsIFrame* aFrame,
nsMargin& aKidMargin,
nsSize& aResult);
nsInlineReflowStatus ReflowFrame(nsIFrame* aFrame,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
PRBool& aInlineAware);
nsInlineReflowStatus PlaceFrame(nsIFrame* aFrame,
nsRect& kidRect,
const nsReflowMetrics& kidMetrics,
const nsMargin& kidMargin,
nsInlineReflowStatus kidReflowStatus);
nsCSSLineLayout& mLineLayout;
nsIFrame* mContainerFrame;
const nsStyleFont* mContainerFont;
const nsStyleText* mContainerText;
const nsStyleDisplay* mContainerDisplay;
const nsReflowState* mContainerReflowState;
PRUint8 mDirection;
PRPackedBool mUnconstrainedWidth;
PRPackedBool mNoWrap;
nscoord mAvailWidth;
nscoord mAvailHeight;
nscoord mX, mY;
nscoord mLeftEdge, mRightEdge;
PRInt32 mFrameNum;
nscoord* mAscents;
nscoord mAscentBuf[20];
nscoord mMaxAscents;
nscoord mMaxAscent;
nscoord mMaxDescent;
nsSize* mMaxElementSize;
};
#endif /* nsCSSInlineLayout_h___ */

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

@ -19,6 +19,7 @@
#include "nsCSSLineLayout.h" #include "nsCSSLineLayout.h"
#include "nsCSSLayout.h" #include "nsCSSLayout.h"
#if 0
#include "nsIFontMetrics.h" #include "nsIFontMetrics.h"
#include "nsIPresContext.h" #include "nsIPresContext.h"
#include "nsIRunaround.h" #include "nsIRunaround.h"
@ -27,6 +28,7 @@
// XXX nsCSSIIDs.[h,cpp] // XXX nsCSSIIDs.[h,cpp]
static NS_DEFINE_IID(kIInlineReflowIID, NS_IINLINE_REFLOW_IID); static NS_DEFINE_IID(kIInlineReflowIID, NS_IINLINE_REFLOW_IID);
static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID); static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
#endif
void void
nsCSSTextRun::List(FILE* out, PRInt32 aIndent) nsCSSTextRun::List(FILE* out, PRInt32 aIndent)
@ -45,382 +47,6 @@ nsCSSTextRun::List(FILE* out, PRInt32 aIndent)
//---------------------------------------------------------------------- //----------------------------------------------------------------------
nsCSSInlineLayout::nsCSSInlineLayout(nsCSSLineLayout& aLineLayout,
nsIFrame* aContainerFrame,
nsIStyleContext* aContainerStyle,
const nsReflowState& aContainerRS)
: mLineLayout(aLineLayout),
mContainerReflowState(aContainerRS)
{
mContainerFrame = aContainerFrame;
mAscents = mAscentBuf;
mMaxAscents = sizeof(mAscentBuf) / sizeof(mAscentBuf[0]);
mMaxElementSize = nsnull;
mContainerFont = (const nsStyleFont*)
aContainerStyle->GetStyleData(eStyleStruct_Font);
mContainerText = (const nsStyleText*)
aContainerStyle->GetStyleData(eStyleStruct_Text);
mContainerDisplay = (const nsStyleDisplay*)
aContainerStyle->GetStyleData(eStyleStruct_Display);
mDirection = mContainerDisplay->mDirection;
}
nsCSSInlineLayout::~nsCSSInlineLayout()
{
if (mAscents != mAscentBuf) {
delete [] mAscents;
}
}
nsresult
nsCSSInlineLayout::SetAscent(nscoord aAscent)
{
PRInt32 frameNum = mFrameNum;
if (frameNum == mMaxAscents) {
mMaxAscents *= 2;
nscoord* newAscents = new nscoord[mMaxAscents];
if (nsnull == newAscents) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCRT::memcpy(newAscents, mAscents, sizeof(nscoord) * frameNum);
if (mAscents != mAscentBuf) {
delete [] mAscents;
}
mAscents = newAscents;
}
mAscents[frameNum] = aAscent;
return NS_OK;
}
void
nsCSSInlineLayout::Prepare(PRBool aUnconstrainedWidth, PRBool aNoWrap,
nsSize* aMaxElementSize)
{
mFrameNum = 0;
mUnconstrainedWidth = aUnconstrainedWidth;
mNoWrap = aNoWrap;
mMaxElementSize = aMaxElementSize;
// mKidPrevInFlow = ???;
}
void
nsCSSInlineLayout::SetReflowSpace(nscoord aX, nscoord aY,
nscoord aAvailWidth, nscoord aAvailHeight)
{
mAvailWidth = aAvailWidth;
mAvailHeight = aAvailHeight;
mX = aX;
mY = aY;
mLeftEdge = aX;
mRightEdge = aX + aAvailWidth;
}
//XXX block children of inline frames needs handling *here*
nsInlineReflowStatus
nsCSSInlineLayout::ReflowAndPlaceFrame(nsIFrame* aFrame)
{
// Compute the maximum size of the frame. If there is no room at all
// for it, then trigger a line-break before the frame.
nsSize maxSize;
nsMargin margin;
if (!ComputeMaxSize(aFrame, margin, maxSize)) {
return NS_INLINE_REFLOW_LINE_BREAK_BEFORE;
}
// Setup reflow state for reflowing the frame
nsReflowState reflowState(aFrame, mContainerReflowState, maxSize);
nsInlineReflowStatus rs;
nsReflowMetrics metrics(mMaxElementSize);
PRBool isAware;
aFrame->WillReflow(*mLineLayout.mPresContext);
rs = ReflowFrame(aFrame, metrics, reflowState, isAware);
if (IS_REFLOW_ERROR(rs)) {
return rs;
}
if (NS_INLINE_REFLOW_BREAK_BEFORE == (rs & NS_INLINE_REFLOW_REFLOW_MASK)) {
return rs;
}
// It's possible the frame didn't fit
if (metrics.width > maxSize.width) {
if (!IsFirstChild()) {
// We are out of room.
// XXX mKidPrevInFlow
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("LineLayout::ReflowChild: !fit size=%d,%d",
metrics.width, metrics.height));
return NS_INLINE_REFLOW_LINE_BREAK_BEFORE;
}
}
nsRect frameRect(mX, mY, metrics.width, metrics.height);
return PlaceFrame(aFrame, frameRect, metrics, margin, rs);
}
// XXX RTL
PRBool
nsCSSInlineLayout::IsFirstChild()
{
return 0 == mFrameNum;
}
PRBool
nsCSSInlineLayout::ComputeMaxSize(nsIFrame* aFrame,
nsMargin& aKidMargin,
nsSize& aResult)
{
const nsStyleSpacing* kidSpacing;
aFrame->GetStyleData(eStyleStruct_Spacing,
(const nsStyleStruct*&)kidSpacing);
kidSpacing->CalcMarginFor(aFrame, aKidMargin);
if (mUnconstrainedWidth || mNoWrap) {
aResult.width = NS_UNCONSTRAINEDSIZE;
}
else {
aResult.width = mRightEdge - mX;
aResult.width -= aKidMargin.left + aKidMargin.right;
if (!IsFirstChild() && (aResult.width <= 0)) {
// XXX Make sure child is dirty for next time
aFrame->WillReflow(*mLineLayout.mPresContext);
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("CSSLineLayout::ComputeMaxSize: !fit"));
return PR_FALSE;
}
}
aResult.height = mAvailHeight;
return PR_TRUE;
}
nsInlineReflowStatus
nsCSSInlineLayout::ReflowFrame(nsIFrame* aKidFrame,
nsReflowMetrics& aMetrics,
const nsReflowState& aReflowState,
PRBool& aInlineAware)
{
// There are 3 ways to reflow the child frame: using the nsIRunaround
// interface, using the nsIInlineReflow interface or using the default
// Reflow method in nsIFrame. The order of precedence is nsIRunaround,
// nsIInlineReflow, nsIFrame. For all three API's we map the reflow status
// into an nsInlineReflowStatus.
nsresult rv;
nsIRunaround* runAround;
nsIInlineReflow* inlineReflow;
if ((nsnull != mLineLayout.mSpaceManager) &&
(NS_OK == aKidFrame->QueryInterface(kIRunaroundIID,
(void**)&runAround))) {
nsRect r;
runAround->Reflow(mLineLayout.mPresContext, mLineLayout.mSpaceManager,
aMetrics, aReflowState, r, rv);
aMetrics.width = r.width;
aMetrics.height = r.height;
aMetrics.ascent = r.height;
aMetrics.descent = 0;
rv = NS_FRAME_REFLOW_STATUS_2_INLINE_REFLOW_STATUS(rv);
aInlineAware = PR_FALSE;
}
else if (NS_OK == aKidFrame->QueryInterface(kIInlineReflowIID,
(void**)&inlineReflow)) {
rv = inlineReflow->InlineReflow(mLineLayout, aMetrics, aReflowState);
aInlineAware = PR_TRUE;
}
else {
aKidFrame->Reflow(mLineLayout.mPresContext, aMetrics, aReflowState, rv);
rv = NS_FRAME_REFLOW_STATUS_2_INLINE_REFLOW_STATUS(rv);
aInlineAware = PR_FALSE;
}
if (NS_FRAME_IS_COMPLETE(rv)) {
nsIFrame* kidNextInFlow;
aKidFrame->GetNextInFlow(kidNextInFlow);
if (nsnull != kidNextInFlow) {
// Remove all of the childs next-in-flows. Make sure that we ask
// the right parent to do the removal (it's possible that the
// parent is not this because we are executing pullup code)
nsCSSContainerFrame* parent;
aKidFrame->GetGeometricParent((nsIFrame*&)parent);
parent->DeleteChildsNextInFlow(aKidFrame);
}
}
return rv;
}
nsInlineReflowStatus
nsCSSInlineLayout::PlaceFrame(nsIFrame* aFrame,
nsRect& aFrameRect,
const nsReflowMetrics& aFrameMetrics,
const nsMargin& aFrameMargin,
nsInlineReflowStatus aFrameReflowStatus)
{
nscoord horizontalMargins = 0;
// Special case to position outside list bullets.
// XXX RTL bullets
PRBool isBullet = PR_FALSE;
if (mLineLayout.mListPositionOutside) {
PRBool isFirstChild = IsFirstChild();
if (isFirstChild && (0 == mLineLayout.mLineNumber)) {
nsIFrame* containerPrevInFlow;
mContainerFrame->GetPrevInFlow(containerPrevInFlow);
if (nsnull == containerPrevInFlow) {
isBullet = PR_TRUE;
// We are placing the first child of the container and we have
// list-style-position of "outside" therefore this is the
// bullet that is being reflowed. The bullet is placed in the
// padding area of this block. Don't worry about getting the Y
// coordinate of the bullet right (vertical alignment will
// take care of that).
// Compute gap between bullet and inner rect left edge
nsIFontMetrics* fm =
mLineLayout.mPresContext->GetMetricsFor(mContainerFont->mFont);
nscoord kidAscent = fm->GetMaxAscent();
nscoord dx = fm->GetHeight() / 2; // from old layout engine
NS_RELEASE(fm);
// XXX RTL bullets
aFrameRect.x = mX - aFrameRect.width - dx;
aFrame->SetRect(aFrameRect);
}
}
}
if (!isBullet) {
// Place normal in-flow child
aFrame->SetRect(aFrameRect);
// XXX RTL
// Advance
const nsStyleDisplay* frameDisplay;
aFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) frameDisplay);
switch (frameDisplay->mFloats) {
default:
NS_NOTYETIMPLEMENTED("Unsupported floater type");
// FALL THROUGH
case NS_STYLE_FLOAT_LEFT:
case NS_STYLE_FLOAT_RIGHT:
// When something is floated, it's margin's are applied there
// not here.
break;
case NS_STYLE_FLOAT_NONE:
horizontalMargins = aFrameMargin.left + aFrameMargin.right;
break;
}
nscoord totalWidth = aFrameMetrics.width + horizontalMargins;
mX += totalWidth;
}
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("CSSLineLayout::PlaceChild: frame=%p {%d, %d, %d, %d}",
aFrame,
aFrameRect.x, aFrameRect.y,
aFrameRect.width, aFrameRect.height));
#if XXX_fix_me
// XXX this is not right; the max-element-size of a child depends on
// it's margins which it doesn't know how to add in
if (nsnull != mMaxElementSize) {
// XXX I'm not certain that this is doing the right thing; rethink this
nscoord elementWidth = kidMaxElementSize->width + horizontalMargins;
if (elementWidth > mMaxElementSize->width) {
mMaxElementSize->width = elementWidth;
}
if (aFrameMetrics.height > mMaxElementSize->height) {
mMaxElementSize->height = aFrameMetrics.height;
}
}
#endif
if (aFrameMetrics.ascent > mMaxAscent) {
mMaxAscent = aFrameMetrics.ascent;
}
if (aFrameMetrics.descent > mMaxDescent) {
mMaxDescent = aFrameMetrics.descent;
}
nsresult rv = SetAscent(aFrameMetrics.ascent);
if (NS_OK != rv) {
return nsInlineReflowStatus(rv);
}
mFrameNum++;
#if XXX_fix_me
mLine->mLastContentOffset = mKidContentIndex;
switch (aFrameReflowStatus & NS_INLINE_REFLOW_REFLOW_MASK) {
case NS_INLINE_REFLOW_COMPLETE:
case NS_INLINE_REFLOW_BREAK_AFTER:
mLine->mLastContentIsComplete = PR_TRUE;
mKidPrevInFlow = nsnull;
break;
case NS_INLINE_REFLOW_NOT_COMPLETE:
mLine->mLastContentIsComplete = PR_FALSE;
mKidPrevInFlow = mKidFrame;
break;
}
#endif
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("CSSLineLayout::PlaceChild: aFrameReflowStatus=%x",
aFrameReflowStatus));
return aFrameReflowStatus;
}
nscoord
nsCSSInlineLayout::AlignFrames(nsIFrame* aFrame, PRInt32 aFrameCount,
nsRect& aBounds)
{
NS_PRECONDITION(aFrameCount == mFrameNum, "bogus reflow");
nscoord lineHeight;
if (PR_TRUE /*XXX !mLine->mIsBlock*/) {
// Vertically align the children on the line; this will compute
// the actual line height for us.
lineHeight =
nsCSSLayout::VerticallyAlignChildren(mLineLayout.mPresContext,
mContainerFrame, mContainerFont,
mY, aFrame, aFrameCount,
mAscents, mMaxAscent);
}
else {
// The line height of a block is just the block's height
lineHeight = mMaxAscent;
}
// Save away line bounds before other adjustments
aBounds.x = mLeftEdge;
aBounds.y = mY;
aBounds.width = mX - mLeftEdge;
aBounds.height = lineHeight;
// Now horizontally place the children
if (!mUnconstrainedWidth) {
nsCSSLayout::HorizontallyPlaceChildren(mLineLayout.mPresContext,
mContainerFrame,
mContainerText->mTextAlign,
mDirection,
aFrame, aFrameCount,
mX - mLeftEdge,
mAvailWidth);
}
// Last, apply relative positioning
nsCSSLayout::RelativePositionChildren(mLineLayout.mPresContext,
mContainerFrame,
aFrame, aFrameCount);
return lineHeight;
}
//----------------------------------------------------------------------
nsCSSLineLayout::nsCSSLineLayout(nsIPresContext* aPresContext, nsCSSLineLayout::nsCSSLineLayout(nsIPresContext* aPresContext,
nsISpaceManager* aSpaceManager) nsISpaceManager* aSpaceManager)
{ {
@ -467,4 +93,3 @@ nsCSSLineLayout::AddText(nsIFrame* aTextFrame)
mCurrentTextRun->mArray.AppendElement(aTextFrame); mCurrentTextRun->mArray.AppendElement(aTextFrame);
return NS_OK;/* XXX */ return NS_OK;/* XXX */
} }

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

@ -19,84 +19,8 @@
#ifndef nsCSSLineLayout_h___ #ifndef nsCSSLineLayout_h___
#define nsCSSLineLayout_h___ #define nsCSSLineLayout_h___
#include "nsCSSBlockFrame.h" #include "nsIFrame.h"
#include "nsVoidArray.h" #include "nsVoidArray.h"
#include "nsStyleConsts.h"
class nsCSSLineLayout;
struct nsStyleDisplay;
struct nsStyleFont;
struct nsStyleText;
/* d76e29b0-ff56-11d1-89e7-006008911b81 */
#define NS_IINLINE_REFLOW_IID \
{0xd76e29b0, 0xff56, 0x11d1, {0x89, 0xe7, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81}}
class nsIInlineReflow {
public:
/**
* Recursively find all of the text runs contained in an outer
* block container. Inline frames implement this by recursing over
* their children; note that inlines frames may need to create
* missing child frames before proceeding (e.g. when a tree
* containing inlines is appended/inserted into a block container
*/
NS_IMETHOD FindTextRuns(nsCSSLineLayout& aLineLayout) = 0;
/**
* InlineReflow method. See below for how to interpret the return value.
*/
NS_IMETHOD InlineReflow(nsCSSLineLayout& aLineLayout,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState) = 0;
};
/**
* For InlineReflow the return value (an nsresult) indicates the
* status of the reflow operation. If the return value is negative
* then some sort of catastrophic error has occured (e.g. out of memory).
* If the return value is non-negative then the macros below can be
* used to interpret it.
*/
typedef nsresult nsInlineReflowStatus;
// The low 3 bits of the nsInlineReflowStatus indicate what happened
// to the child during it's reflow.
#define NS_INLINE_REFLOW_COMPLETE 0 // note: not a bit!
#define NS_INLINE_REFLOW_NOT_COMPLETE 1
#define NS_INLINE_REFLOW_BREAK_BEFORE 2
#define NS_INLINE_REFLOW_BREAK_AFTER 3
#define NS_INLINE_REFLOW_REFLOW_MASK 0x3
// The inline reflow status may need to indicate that the next-in-flow
// must be reflowed. This bit is or'd in in that case.
#define NS_INLINE_REFLOW_NEXT_IN_FLOW 0x4
// When a break is indicated (break-before/break-after) the type of
// break requested is indicate in bits 4-7.
#define NS_INLINE_REFLOW_BREAK_MASK 0xF0
#define NS_INLINE_REFLOW_GET_BREAK_TYPE(_status) (((_status) >> 4) & 0xF)
#define NS_INLINE_REFLOW_MAKE_BREAK_TYPE(_type) ((_type) << 4)
// This macro maps an nsIFrame nsReflowStatus value into an
// nsInlineReflowStatus value.
#define NS_FRAME_REFLOW_STATUS_2_INLINE_REFLOW_STATUS(_status) \
(((_status) & 0x1) | (((_status) & NS_FRAME_REFLOW_NEXTINFLOW) << 2))
// Convenience macro's
#define NS_INLINE_REFLOW_LINE_BREAK_BEFORE \
(NS_INLINE_REFLOW_BREAK_BEFORE | \
NS_INLINE_REFLOW_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE))
#define NS_INLINE_REFLOW_LINE_BREAK_AFTER \
(NS_INLINE_REFLOW_BREAK_AFTER | \
NS_INLINE_REFLOW_MAKE_BREAK_TYPE(NS_STYLE_CLEAR_LINE))
// This macro tests to see if an nsInlineReflowStatus is an error value
// or just a regular return value
#define NS_INLINE_REFLOW_ERROR(_status) (PRInt32(_status) < 0)
//----------------------------------------------------------------------
// This structure represents a run of text. In mText are the // This structure represents a run of text. In mText are the
// nsIFrame's that are considered text frames. // nsIFrame's that are considered text frames.
@ -122,87 +46,6 @@ struct nsCSSTextRun {
//---------------------------------------------------------------------- //----------------------------------------------------------------------
/**
* This structure contains the horizontal layout state for line
* layout frame placement. This is factored out of nsCSSLineLayout so
* that the block layout code and the inline layout code can use
* nsCSSLineLayout to reflow and place frames.
*/
struct nsCSSInlineLayout {
nsCSSInlineLayout(nsCSSLineLayout& aLineLayout,
nsIFrame* aContainerFrame,
nsIStyleContext* aContainerStyle,
const nsReflowState& aContainerReflowState);
~nsCSSInlineLayout();
void Prepare(PRBool aUnconstrainedWidth,
PRBool aNoWrap,
nsSize* aMaxElementSize);
void SetReflowSpace(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
nsInlineReflowStatus ReflowAndPlaceFrame(nsIFrame* aFrame);
nscoord AlignFrames(nsIFrame* aFrame, PRInt32 aFrameCount,
nsRect& aBounds);
PRInt32 GetFrameNum() { return mFrameNum; }
/**
* Return an approximation of the line height for the line as
* reflowed so far. Note that this value doesn't take into account
* any vertical alignment properties on the frames in the line so
* it may be smaller than it should be.
*/
nscoord GetLineHeight() { return mMaxAscent + mMaxDescent; }
protected:
PRBool IsFirstChild();
nsresult SetAscent(nscoord aAscent);
PRBool ComputeMaxSize(nsIFrame* aFrame,
nsMargin& aKidMargin,
nsSize& aResult);
nsInlineReflowStatus ReflowFrame(nsIFrame* aFrame,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
PRBool& aInlineAware);
nsInlineReflowStatus PlaceFrame(nsIFrame* aFrame,
nsRect& kidRect,
const nsReflowMetrics& kidMetrics,
const nsMargin& kidMargin,
nsInlineReflowStatus kidReflowStatus);
nsCSSLineLayout& mLineLayout;
nsIFrame* mContainerFrame;
const nsStyleFont* mContainerFont;
const nsStyleText* mContainerText;
const nsStyleDisplay* mContainerDisplay;
const nsReflowState& mContainerReflowState;
PRUint8 mDirection;
PRPackedBool mUnconstrainedWidth;
PRPackedBool mNoWrap;
nscoord mAvailWidth;
nscoord mAvailHeight;
nscoord mX, mY;
nscoord mLeftEdge, mRightEdge;
PRInt32 mFrameNum;
nscoord* mAscents;
nscoord mAscentBuf[20];
nscoord mMaxAscents;
nscoord mMaxAscent;
nscoord mMaxDescent;
nsSize* mMaxElementSize;
};
//----------------------------------------------------------------------
// 1) collecting frames for text-runs // 1) collecting frames for text-runs
// 2) horizontal layout of frames for block // 2) horizontal layout of frames for block
// 3) horizontal layout of frames for inline // 3) horizontal layout of frames for inline