This commit is contained in:
kipp%netscape.com 1998-09-23 02:29:03 +00:00
parent bfc5f6a627
commit c60547b531
5 changed files with 0 additions and 907 deletions

View File

@ -1,131 +0,0 @@
/* -*- 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 "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.
*/
#ifndef nsInlineFrame_h___
#define nsInlineFrame_h___
#include "nsHTMLContainerFrame.h"
#include "nsInlineLayout.h"
#include "nsLineLayout.h"
class nsInlineFrame;
class nsPlaceholderFrame;
/**
* Reflow state object for managing css inline layout. Most of the state
* is managed by the nsInlineLayout object.
*/
struct nsInlineReflowState : public nsReflowState {
nsInlineReflowState(nsLineLayout& aLineLayout,
nsInlineFrame* aInlineFrame,
nsIStyleContext* aInlineSC,
const nsReflowState& aReflowState,
PRBool aComputeMaxElementSize);
~nsInlineReflowState();
nsIPresContext* mPresContext;
nsInlineLayout mInlineLayout;
nsIFrame* mLastChild; // last child we have reflowed (so far)
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 nsInlineFrame : public nsHTMLContainerFrame,
public nsIInlineReflow
{
public:
// nsISupports
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
// nsIFrame
NS_IMETHOD Init(nsIPresContext& aPresContext, nsIFrame* aChildList);
NS_IMETHOD CreateContinuingFrame(nsIPresContext& aCX,
nsIFrame* aParent,
nsIStyleContext* aStyleContext,
nsIFrame*& aContinuingFrame);
#if XXX_not_yet
NS_IMETHOD Reflow(nsIPresContext& aPresContext,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState,
nsReflowStatus& aStatus);
#endif
// nsIInlineReflow
NS_IMETHOD FindTextRuns(nsLineLayout& aLineLayout,
nsIReflowCommand* aReflowCommand);
NS_IMETHOD InlineReflow(nsLineLayout& aLineLayout,
nsReflowMetrics& aDesiredSize,
const nsReflowState& aReflowState);
// nsContainerFrame
virtual PRBool DeleteNextInFlowsFor(nsIPresContext& aPresContext, nsIFrame* aChild);
protected:
nsInlineFrame(nsIContent* aContent, nsIFrame* aParent);
virtual ~nsInlineFrame();
virtual PRIntn GetSkipSides() const;
nsresult InitialReflow(nsInlineReflowState& aState);
nsresult FrameAppendedReflow(nsInlineReflowState& aState);
nsresult ChildIncrementalReflow(nsInlineReflowState& aState);
nsresult ResizeReflow(nsInlineReflowState& aState);
void ComputeFinalSize(nsInlineReflowState& aState,
nsReflowMetrics& aMetrics);
PRBool ReflowMapped(nsInlineReflowState& aState,
nsInlineReflowStatus& aReflowStatus);
PRBool PullUpChildren(nsInlineReflowState& aState,
nsInlineReflowStatus& aReflowStatus);
nsIFrame* PullOneChild(nsInlineFrame* aNextInFlow,
nsIFrame* aLastChild);
nsresult MaybeCreateNextInFlow(nsInlineReflowState& aState,
nsIFrame* aFrame);
void PushKids(nsInlineReflowState& aState,
nsIFrame* aPrevChild, nsIFrame* aPushedChild);
void DrainOverflowLists();
nsresult AppendNewFrames(nsIPresContext* aPresContext, nsIFrame*);
void InsertNewFrame(nsIFrame* aNewFrame, nsIFrame* aPrevSibling);
friend nsresult NS_NewInlineFrame(nsIContent* aContent, nsIFrame* aParentFrame,
nsIFrame*& aNewFrame);
};
#endif /* nsInlineFrame_h___ */

View File

@ -1,126 +0,0 @@
/* -*- 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 "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.
*/
#include "nsAbsoluteFrame.h"
#include "nsFrame.h"
#include "nsHTMLBase.h"
#include "nsPlaceholderFrame.h"
#include "nsScrollFrame.h"
#include "nsStyleConsts.h"
#include "nsViewsCID.h"
#include "nsIPresContext.h"
#include "nsIStyleContext.h"
#include "nsIView.h"
#include "nsIViewManager.h"
#include "nsHTMLAtoms.h"
nsresult
nsHTMLBase::CreateViewForFrame(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIStyleContext* aStyleContext,
PRBool aForce)
{
nsIView* view;
aFrame->GetView(view);
if (nsnull == view) {
// We don't yet have a view; see if we need a view
// See if the opacity is not the same as the geometric parent
// frames opacity.
if (!aForce) {
nsIFrame* parent;
aFrame->GetGeometricParent(parent);
if (nsnull != parent) {
// Get my nsStyleColor
const nsStyleColor* myColor = (const nsStyleColor*)
aStyleContext->GetStyleData(eStyleStruct_Color);
// Get parent's nsStyleColor
const nsStyleColor* parentColor;
parent->GetStyleData(eStyleStruct_Color, (const nsStyleStruct*&)parentColor);
// If the opacities are different then I need a view
if (myColor->mOpacity != parentColor->mOpacity) {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsHTMLBase::CreateViewForFrame: frame=%p opacity=%g parentOpacity=%g",
aFrame, myColor->mOpacity, parentColor->mOpacity));
aForce = PR_TRUE;
}
}
}
// See if the frame is being relatively positioned
if (!aForce) {
const nsStylePosition* position = (const nsStylePosition*)
aStyleContext->GetStyleData(eStyleStruct_Position);
if (NS_STYLE_POSITION_RELATIVE == position->mPosition) {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsHTMLBase::CreateViewForFrame: frame=%p relatively positioned",
aFrame));
aForce = PR_TRUE;
}
}
if (aForce) {
// Create a view
nsIFrame* parent;
nsIView* view;
aFrame->GetParentWithView(parent);
NS_ASSERTION(parent, "GetParentWithView failed");
nsIView* parView;
parent->GetView(parView);
NS_ASSERTION(parView, "no parent with view");
// Create a view
static NS_DEFINE_IID(kViewCID, NS_VIEW_CID);
static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID);
nsresult result = nsRepository::CreateInstance(kViewCID,
nsnull,
kIViewIID,
(void **)&view);
if (NS_OK == result) {
nsIView* rootView = parView;
nsIViewManager* viewManager;
rootView->GetViewManager(viewManager);
// Initialize the view
NS_ASSERTION(nsnull != viewManager, "null view manager");
nsRect bounds;
aFrame->GetRect(bounds);
view->Init(viewManager, bounds, rootView);
viewManager->InsertChild(rootView, view, 0);
NS_RELEASE(viewManager);
}
// Remember our view
aFrame->SetView(view);
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsHTMLBase::CreateViewForFrame: frame=%p view=%p",
aFrame));
return result;
}
}
return NS_OK;
}

View File

@ -1,38 +0,0 @@
/* -*- 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 "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.
*/
#ifndef nsHTMLBase_h___
#define nsHTMLBase_h___
#include "nsIFrame.h"
// This is a class whose purpose is to provide shared code that is
// common to all html frames, including containers and leaf frames.
class nsHTMLBase {
public:
/**
* Create a view for a frame if it needs one. A frame needs a view
* if it requires a scrollbar, is relatively positioned or has a
* non opaque opacity.
*/
static nsresult CreateViewForFrame(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIStyleContext* aStyleContext,
PRBool aForce);
};
#endif /* nsHTMLBase_h___ */

View File

@ -1,500 +0,0 @@
/* -*- 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 "nsInlineLayout.h"
#include "nsLineLayout.h"
#include "nsCSSLayout.h"
#include "nsHTMLIIDs.h"
#include "nsContainerFrame.h"
#include "nsIFontMetrics.h"
#include "nsIStyleContext.h"
#include "nsIPresContext.h"
#include "nsIReflowCommand.h"
#include "nsIRunaround.h"
#include "nsISpaceManager.h"
nsInlineLayout::nsInlineLayout(nsLineLayout& aLineLayout,
nsContainerFrame* aContainerFrame,
nsIStyleContext* aContainerStyle)
: mLineLayout(aLineLayout)
{
mContainerFrame = aContainerFrame;
mAscents = mAscentBuf;
mMaxAscents = sizeof(mAscentBuf) / sizeof(mAscentBuf[0]);
mContainerFont = (const nsStyleFont*)
aContainerStyle->GetStyleData(eStyleStruct_Font);
mContainerText = (const nsStyleText*)
aContainerStyle->GetStyleData(eStyleStruct_Text);
mContainerDisplay = (const nsStyleDisplay*)
aContainerStyle->GetStyleData(eStyleStruct_Display);
mDirection = mContainerDisplay->mDirection;
mIsBullet = PR_FALSE;
mHaveBullet = PR_FALSE;
mNextRCFrame = nsnull;
}
nsInlineLayout::~nsInlineLayout()
{
if (mAscents != mAscentBuf) {
delete [] mAscents;
}
}
void
nsInlineLayout::Init(const nsReflowState* aContainerReflowState)
{
mContainerReflowState = aContainerReflowState;
}
nsresult
nsInlineLayout::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
nsInlineLayout::Prepare(PRBool aUnconstrainedWidth,
PRBool aNoWrap,
PRBool aComputeMaxElementSize)
{
mIsBullet = PR_FALSE;
mHaveBullet = PR_FALSE;
mFrameNum = 0;
mUnconstrainedWidth = aUnconstrainedWidth;
mNoWrap = aNoWrap;
mComputeMaxElementSize = aComputeMaxElementSize;
if (aComputeMaxElementSize) {
mMaxElementSize.width = 0;
mMaxElementSize.height = 0;
}
mMaxAscent = 0;
mMaxDescent = 0;
}
void
nsInlineLayout::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
nsInlineLayout::ReflowAndPlaceFrame(nsIFrame* aFrame)
{
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsInlineLayout::ReflowAndPlaceFrame: frame=%p x=%d",
aFrame, mX));
// If the frame is a block frame and this is not the first frame on
// the line, we need to break before the block frame.
const nsStyleDisplay* kidDisplay;
aFrame->GetStyleData(eStyleStruct_Display,
(const nsStyleStruct*&) kidDisplay);
const nsStylePosition* kidPosition;
aFrame->GetStyleData(eStyleStruct_Position,
(const nsStyleStruct*&) kidPosition);
PRBool isBlock = nsLineLayout::TreatFrameAsBlock(kidDisplay, kidPosition);
if (isBlock && !IsFirstChild()) {
return NS_INLINE_LINE_BREAK_BEFORE(0);/* XXX indicate never-reflowed? */
}
// 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)) {
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsInlineLayout::ReflowAndPlaceFrame: break-before"));
return NS_INLINE_LINE_BREAK_BEFORE(0);/* XXX indicate never-reflowed? */
}
// 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;
nsFrameState state;
aFrame->GetFrameState(state);
if (NS_FRAME_FIRST_REFLOW & state) {
reason = eReflowReason_Initial;
}
else if (mNextRCFrame == aFrame) {
reason = eReflowReason_Incremental;
// Make sure we only incrementally reflow once
mNextRCFrame = nsnull;
}
// Setup reflow state for reflowing the frame
nsReflowState reflowState(aFrame, *mContainerReflowState, maxSize);
reflowState.reason = reason;
nsInlineReflowStatus rs;
nsSize frameMaxElementSize;
nsReflowMetrics metrics(mComputeMaxElementSize
? &frameMaxElementSize
: nsnull);
PRBool isAware;
aFrame->WillReflow(*mLineLayout.mPresContext);
rs = ReflowFrame(aFrame, metrics, reflowState, isAware);
if (NS_IS_REFLOW_ERROR(rs)) {
return rs;
}
if (NS_INLINE_IS_BREAK_BEFORE(rs)) {
return rs;
}
// XXX we need to do this because blocks depend on it; we shouldn't expect
// the child frame to deal with it.
if (eReflowReason_Initial == reason) {
aFrame->GetFrameState(state);
aFrame->SetFrameState(state & ~NS_FRAME_FIRST_REFLOW);
}
// XXX the 0,0 part of this is hack: get rid of it
if (!isAware && ((0 != metrics.width) || (0 != metrics.height))) {
mLineLayout.SetSkipLeadingWhiteSpace(PR_FALSE);
}
// 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,
("nsInlineLayout::ReflowAndPlaceFrame: !fit size=%d,%d",
metrics.width, metrics.height));
// XXX if the child requested a break and we need to break too...
return NS_INLINE_LINE_BREAK_BEFORE(0);
}
}
nsRect frameRect(mX, mY, metrics.width, metrics.height);
return PlaceFrame(aFrame, frameRect, metrics, margin, rs, isBlock);
}
// XXX RTL
PRBool
nsInlineLayout::IsFirstChild()
{
if (mHaveBullet) {
return mFrameNum < 2;
}
return mFrameNum < 1;
}
PRBool
nsInlineLayout::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;
// Note: We let zero sneak through here in case the next child is
// either something that gets compressed into zero or is a BR
// (which is zero width)
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,
("nsInlineLayout::ComputeMaxSize: !fit"));
return PR_FALSE;
}
}
// Give the child a limited height in case it's a block child and
// our height was limited.
aResult.height = mAvailHeight;
return PR_TRUE;
}
nsInlineReflowStatus
nsInlineLayout::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.
NS_ASSERTION(nsnull != mLineLayout.mSpaceManager, "yikes");
nsresult rv;
nsIRunaround* runAround;
nsIInlineReflow* inlineReflow;
// Make local copies of x,y in case what we are reflowing is a
// floater and the floater ends up being a left aligned
// current-line-floater (which means it will adjust our mX value)
nscoord x = mX;
nscoord y = mY;
if ((nsnull != mLineLayout.mSpaceManager) &&
(NS_OK == aKidFrame->QueryInterface(kIRunaroundIID,
(void**)&runAround))) {
nsRect r;
mLineLayout.mSpaceManager->Translate(x, y);
runAround->ReflowAround(*mLineLayout.mPresContext,
mLineLayout.mSpaceManager,
aMetrics, aReflowState, r, rv);
mLineLayout.mSpaceManager->Translate(-x, -y);
aMetrics.width = r.width;
aMetrics.height = r.height;
aMetrics.ascent = r.height;
aMetrics.descent = 0;
aInlineAware = PR_FALSE;
}
else if (NS_OK == aKidFrame->QueryInterface(kIInlineReflowIID,
(void**)&inlineReflow)) {
mLineLayout.mSpaceManager->Translate(x, y);
rv = inlineReflow->InlineReflow(mLineLayout, aMetrics, aReflowState);
mLineLayout.mSpaceManager->Translate(-x, -y);
aInlineAware = PR_TRUE;
}
else {
mLineLayout.mSpaceManager->Translate(x, y);
aKidFrame->Reflow(*mLineLayout.mPresContext, aMetrics, aReflowState, rv);
mLineLayout.mSpaceManager->Translate(-x, -y);
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)
nsIFrame* parent;
aKidFrame->GetGeometricParent(parent);
((nsHTMLContainerFrame*)parent)->DeleteNextInFlowsFor(*mLineLayout.mPresContext,
aKidFrame);
}
}
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsInlineLayout::ReflowFrame: frame=%p reflowStatus=%x %saware",
aKidFrame, rv, aInlineAware ? "" :"not "));
return rv;
}
nsInlineReflowStatus
nsInlineLayout::PlaceFrame(nsIFrame* aFrame,
nsRect& aFrameRect,
const nsReflowMetrics& aFrameMetrics,
const nsMargin& aFrameMargin,
nsInlineReflowStatus aFrameReflowStatus,
PRBool aIsBlock)
{
nscoord horizontalMargins = 0;
// XXX RTL
// Special case to position outside list bullets.
if (mIsBullet) {
// 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).
nsIFontMetrics* fm =
mLineLayout.mPresContext->GetMetricsFor(mContainerFont->mFont);
nscoord height;
fm->GetHeight(height);
nscoord dx = height / 2; // from old layout engine
NS_RELEASE(fm);
aFrameRect.x = mX - aFrameRect.width - dx;
if (aFrameRect.x < 0) aFrameRect.x = 0;
aFrame->SetRect(aFrameRect);
}
else {
// Place normal in-flow child
aFrame->SetRect(aFrameRect);
// 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, its margins are applied there
// not here.
break;
case NS_STYLE_FLOAT_NONE:
horizontalMargins = aFrameMargin.left + aFrameMargin.right;
break;
}
mX += aFrameMetrics.width + horizontalMargins;
}
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
("nsInlineLayout::PlaceFrame: frame=%p {%d, %d, %d, %d}",
aFrame,
aFrameRect.x, aFrameRect.y,
aFrameRect.width, aFrameRect.height));
// XXX this is not right; the max-element-size of a child depends on
// its margins which it doesn't know how to add in
// Fold in child's max-element-size information into our own
if (mComputeMaxElementSize) {
if (aFrameMetrics.maxElementSize->width > mMaxElementSize.width) {
mMaxElementSize.width = aFrameMetrics.maxElementSize->width;
}
if (aFrameMetrics.maxElementSize->height > mMaxElementSize.height) {
mMaxElementSize.height = aFrameMetrics.maxElementSize->height;
}
}
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 (aIsBlock) {
if (!NS_INLINE_IS_BREAK(aFrameReflowStatus)) {
aFrameReflowStatus =
NS_INLINE_LINE_BREAK_AFTER(aFrameReflowStatus & NS_FRAME_NOT_COMPLETE);
}
}
return aFrameReflowStatus;
}
void
nsInlineLayout::AlignFrames(nsIFrame* aFrame, PRInt32 aFrameCount,
nsRect& aBounds)
{
NS_PRECONDITION(aFrameCount == mFrameNum, "bogus reflow");
// Vertically align the children on the line; this will compute
// the actual line height for us.
// XXX Fold in vertical alignment code here and make it update the
// max ascent and max descent values properly. When line-height is
// involved, give half of it to ascent and half to descent
nscoord lineHeight =
nsCSSLayout::VerticallyAlignChildren(mLineLayout.mPresContext,
mContainerFrame, mContainerFont,
mY, aFrame, aFrameCount,
mAscents, mMaxAscent/* XXX maxDescent */);
nscoord lineWidth = mX - mLeftEdge;
// Save away line bounds before other adjustments
aBounds.x = mLeftEdge;
aBounds.y = mY;
aBounds.width = lineWidth;
aBounds.height = lineHeight;
// Now horizontally place the children
if (!mUnconstrainedWidth && (mAvailWidth > lineWidth)) {
nsCSSLayout::HorizontallyPlaceChildren(mLineLayout.mPresContext,
mContainerFrame,
mContainerText->mTextAlign,
mDirection,
aFrame, aFrameCount,
lineWidth,
mAvailWidth);
}
// Last, apply relative positioning
nsCSSLayout::RelativePositionChildren(mLineLayout.mPresContext,
mContainerFrame,
aFrame, aFrameCount);
}
nsresult
nsInlineLayout::MaybeCreateNextInFlow(nsIFrame* aFrame,
nsIFrame*& aNextInFlowResult)
{
aNextInFlowResult = nsnull;
nsIFrame* nextInFlow;
aFrame->GetNextInFlow(nextInFlow);
if (nsnull == nextInFlow) {
// Create a continuation frame for the child frame and insert it
// into our lines child list.
nsIFrame* nextFrame;
aFrame->GetNextSibling(nextFrame);
nsIStyleContext* kidSC;
aFrame->GetStyleContext(mLineLayout.mPresContext, kidSC);
aFrame->CreateContinuingFrame(*mLineLayout.mPresContext, mContainerFrame,
kidSC, nextInFlow);
NS_RELEASE(kidSC);
if (nsnull == nextInFlow) {
return NS_ERROR_OUT_OF_MEMORY;
}
aFrame->SetNextSibling(nextInFlow);
nextInFlow->SetNextSibling(nextFrame);
NS_FRAME_LOG(NS_FRAME_TRACE_NEW_FRAMES,
("nsInlineLayout::MaybeCreateNextInFlow: frame=%p nextInFlow=%p",
aFrame, nextInFlow));
aNextInFlowResult = nextInFlow;
}
return NS_OK;
}

View File

@ -1,112 +0,0 @@
/* -*- 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 nsInlineLayout_h___
#define nsInlineLayout_h___
#include "nsHTMLContainerFrame.h"
#include "nsIInlineReflow.h"
class nsLineLayout;
struct nsStyleDisplay;
struct nsStyleFont;
struct nsStyleText;
/**
* This structure contains the horizontal layout state for line
* layout frame placement. This is factored out of nsLineLayout so
* that the block layout code and the inline layout code can use
* nsLineLayout to reflow and place frames.
*/
struct nsInlineLayout {
nsInlineLayout(nsLineLayout& aLineLayout,
nsContainerFrame* aContainerFrame,
nsIStyleContext* aContainerStyle);
~nsInlineLayout();
void Init(const nsReflowState* aContainerReflowState);
void Prepare(PRBool aUnconstrainedWidth,
PRBool aNoWrap,
PRBool aComputeMaxElementSize);
void SetReflowSpace(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight);
nsInlineReflowStatus ReflowAndPlaceFrame(nsIFrame* aFrame);
/**
* Align the frames that have been reflowed by this object.
* aBounds is filled in with the size of the "line" before any
* horziontal alignment or relative positioning. aBounds.width will
* be the line width, aBounds.height will be the line height.
*/
void 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,
PRBool aIsBlock);
nsresult MaybeCreateNextInFlow(nsIFrame* aFrame,
nsIFrame*& aNextInFlowResult);
nsLineLayout& mLineLayout;
nsContainerFrame* mContainerFrame;
const nsStyleFont* mContainerFont;
const nsStyleText* mContainerText;
const nsStyleDisplay* mContainerDisplay;
const nsReflowState* mContainerReflowState;
PRUint8 mDirection;
PRPackedBool mUnconstrainedWidth;
PRPackedBool mNoWrap;
PRPackedBool mComputeMaxElementSize;
PRPackedBool mIsBullet;
PRPackedBool mHaveBullet;
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;
nsIFrame* mNextRCFrame;
};
#endif /* nsInlineLayout_h___ */