зеркало из https://github.com/mozilla/pjs.git
snapshot
This commit is contained in:
Родитель
3626bfa96d
Коммит
f7d5a13f2b
|
@ -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 "nsCSSLineLayout.h"
|
||||
#include "nsCSSInlineLayout.h"
|
||||
#include "nsCSSLayout.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsHTMLIIDs.h"
|
||||
|
||||
#include "nsIAnchoredItems.h"
|
||||
#include "nsIPresContext.h"
|
||||
|
@ -35,11 +37,6 @@
|
|||
#include "nsHTMLValue.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 inline span frames
|
||||
// XXX IsFirstChild
|
||||
|
@ -178,8 +175,6 @@ nsCSSBlockReflowState::nsCSSBlockReflowState(nsIPresContext* aPresContext,
|
|||
if (!mBlockIsPseudo) {
|
||||
const nsStyleSpacing* blockSpacing = (const nsStyleSpacing*)
|
||||
mBlockSC->GetStyleData(eStyleStruct_Spacing);
|
||||
const nsStylePosition* blockPosition = (const nsStylePosition*)
|
||||
mBlockSC->GetStyleData(eStyleStruct_Position);
|
||||
|
||||
blockSpacing->CalcBorderPaddingFor(mBlock, mBorderPadding);
|
||||
mY = mBorderPadding.top;
|
||||
|
@ -1145,8 +1140,8 @@ InlineFrameData::ReflowLine(nsCSSBlockReflowState& aState,
|
|||
|
||||
// Prepare for reflowing this line
|
||||
aLineLayout.Prepare(aState.mX);
|
||||
nsCSSInlineLayout inlineLayout(aLineLayout, aState.mBlock, aState.mBlockSC,
|
||||
aState);
|
||||
nsCSSInlineLayout inlineLayout(aLineLayout, aState.mBlock, aState.mBlockSC);
|
||||
inlineLayout.Init(&aState);
|
||||
inlineLayout.Prepare(aState.mUnconstrainedWidth, aState.mNoWrap,
|
||||
aState.mMaxElementSize);
|
||||
inlineLayout.SetReflowSpace(aState.mCurrentBand.availSpace.x,
|
||||
|
@ -1291,7 +1286,7 @@ InlineFrameData::ReflowLine(nsCSSBlockReflowState& aState,
|
|||
|
||||
// See if speculative application of the margin should stick
|
||||
if (ild == &mLines) {
|
||||
if (0 == inlineLayout.GetLineHeight()) {
|
||||
if (0 == inlineLayout.mMaxAscent + inlineLayout.mMaxDescent) {
|
||||
// No, undo margin application when we get a zero height child.
|
||||
aState.mY -= bottomMargin;
|
||||
if (aState.mY + bottomMargin >= aState.mCurrentBand.availSpace.YMost()) {
|
||||
|
@ -1351,7 +1346,7 @@ InlineFrameData::SplitLine(nsCSSBlockReflowState& aState,
|
|||
InlineLineData* ild,
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
PRInt32 pushCount = ild->mChildCount - aInlineLayout.GetFrameNum();
|
||||
PRInt32 pushCount = ild->mChildCount - aInlineLayout.mFrameNum;
|
||||
NS_FRAME_LOG(NS_FRAME_TRACE_CHILD_REFLOW,
|
||||
("LineLayout::SplitLine: pushing %d frames",
|
||||
pushCount));
|
||||
|
@ -1692,7 +1687,7 @@ nsCSSBlockFrame::Reflow(nsIPresContext* aPresContext,
|
|||
// Replace parent provided reflow state with our own significantly
|
||||
// more extensive version.
|
||||
nsCSSBlockReflowState state(aPresContext, aSpaceManager, this, aReflowState,
|
||||
aMetrics.maxElementSize);
|
||||
aMetrics.maxElementSize);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (eReflowReason_Initial == state.reason) {
|
||||
|
|
|
@ -171,6 +171,4 @@ protected:
|
|||
nsVoidArray* mRunInFloaters;
|
||||
};
|
||||
|
||||
#define IS_REFLOW_ERROR(_status) (PRInt32(_status) < 0)
|
||||
|
||||
#endif /* nsCSSBlockFrame_h___ */
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -15,28 +15,61 @@
|
|||
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||||
* Reserved.
|
||||
*/
|
||||
#ifndef nsInlineFrame_h___
|
||||
#define nsInlineFrame_h___
|
||||
#ifndef nsCSSInlineFrame_h___
|
||||
#define nsCSSInlineFrame_h___
|
||||
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
#include "nsCSSContainerFrame.h"
|
||||
#include "nsCSSInlineLayout.h"
|
||||
#include "nsCSSLineLayout.h"
|
||||
class nsInlineState;
|
||||
|
||||
// Inline container class. Does not support being used as a pseudo frame
|
||||
class nsInlineFrame : public nsHTMLContainerFrame, public nsIInlineReflow {
|
||||
class nsCSSInlineFrame;
|
||||
|
||||
/**
|
||||
* 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:
|
||||
static nsresult NewFrame(nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent);
|
||||
|
||||
// nsISupports
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
|
||||
|
||||
// nsIFrame
|
||||
#if XXX_not_yet
|
||||
NS_IMETHOD Reflow(nsIPresContext* aPresContext,
|
||||
nsReflowMetrics& aDesiredSize,
|
||||
const nsReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
#endif
|
||||
|
||||
// nsIInlineReflow
|
||||
NS_IMETHOD FindTextRuns(nsCSSLineLayout& aLineLayout);
|
||||
|
@ -45,70 +78,38 @@ public:
|
|||
const nsReflowState& aReflowState);
|
||||
|
||||
protected:
|
||||
nsInlineFrame(nsIContent* aContent, nsIFrame* aParent);
|
||||
nsCSSInlineFrame(nsIContent* aContent, nsIFrame* aParent);
|
||||
|
||||
virtual ~nsInlineFrame();
|
||||
virtual ~nsCSSInlineFrame();
|
||||
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
|
||||
void InitializeState(nsIPresContext* aPresContext,
|
||||
const nsReflowState& aReflowState,
|
||||
nsInlineState& aState);
|
||||
nsresult FrameAppendedReflow(nsCSSInlineReflowState& aState);
|
||||
|
||||
PRBool DidFitChild(nsIPresContext* aPresContext,
|
||||
nsInlineState& aState,
|
||||
nsIFrame* aChildFrame,
|
||||
nsReflowMetrics& aChildMetrics);
|
||||
nsresult ChildIncrementalReflow(nsCSSInlineReflowState& aState);
|
||||
|
||||
PRBool CanFitChild(nsIPresContext* aPresContext,
|
||||
nsInlineState& aState,
|
||||
nsIFrame* aChildFrame);
|
||||
nsresult ResizeReflow(nsCSSInlineReflowState& aState);
|
||||
|
||||
void ComputeFinalSize(nsIPresContext* aPresContext,
|
||||
nsInlineState& aState,
|
||||
nsReflowMetrics& aSize);
|
||||
void ComputeFinalSize(nsCSSInlineReflowState& aState,
|
||||
nsReflowMetrics& aMetrics);
|
||||
|
||||
PRBool ReflowMappedChildrenFrom(nsIPresContext* aPresContext,
|
||||
nsInlineState& aState,
|
||||
nsIFrame* aChildFrame,
|
||||
PRInt32 aChildIndex);
|
||||
nsInlineReflowStatus ReflowMapped(nsCSSInlineReflowState& aState);
|
||||
|
||||
PRBool PullUpChildren(nsIPresContext* aPresContext,
|
||||
nsInlineState& aState);
|
||||
nsInlineReflowStatus ReflowUnmapped(nsCSSInlineReflowState& aState);
|
||||
|
||||
nsReflowStatus ReflowUnmappedChildren(nsIPresContext* aPresContext,
|
||||
nsInlineState& aState);
|
||||
nsInlineReflowStatus PullUpChildren(nsCSSInlineReflowState& aState);
|
||||
|
||||
void PlaceChild(nsIFrame* aChild,
|
||||
PRInt32 aIndex, // in the child frame list
|
||||
nsInlineState& aState,
|
||||
const nsReflowMetrics& aChildSize,
|
||||
const nsSize* aChildMaxElementSize);
|
||||
void PushKids(nsCSSInlineReflowState& aState,
|
||||
nsIFrame* aPrevChild, nsIFrame* aPushedChild);
|
||||
|
||||
PRInt32 RecoverState(nsIPresContext* aCX,
|
||||
nsInlineState& aState,
|
||||
nsIFrame* aSkipChild);
|
||||
|
||||
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);
|
||||
friend nsresult NS_NewCSSInlineFrame(nsIFrame** aInstancePtrResult,
|
||||
nsIContent* aContent,
|
||||
nsIFrame* aParent);
|
||||
};
|
||||
|
||||
#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 "nsCSSLayout.h"
|
||||
|
||||
#if 0
|
||||
#include "nsIFontMetrics.h"
|
||||
#include "nsIPresContext.h"
|
||||
#include "nsIRunaround.h"
|
||||
|
@ -27,6 +28,7 @@
|
|||
// XXX nsCSSIIDs.[h,cpp]
|
||||
static NS_DEFINE_IID(kIInlineReflowIID, NS_IINLINE_REFLOW_IID);
|
||||
static NS_DEFINE_IID(kIRunaroundIID, NS_IRUNAROUND_IID);
|
||||
#endif
|
||||
|
||||
void
|
||||
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,
|
||||
nsISpaceManager* aSpaceManager)
|
||||
{
|
||||
|
@ -467,4 +93,3 @@ nsCSSLineLayout::AddText(nsIFrame* aTextFrame)
|
|||
mCurrentTextRun->mArray.AppendElement(aTextFrame);
|
||||
return NS_OK;/* XXX */
|
||||
}
|
||||
|
||||
|
|
|
@ -19,84 +19,8 @@
|
|||
#ifndef nsCSSLineLayout_h___
|
||||
#define nsCSSLineLayout_h___
|
||||
|
||||
#include "nsCSSBlockFrame.h"
|
||||
#include "nsIFrame.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
|
||||
// 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
|
||||
// 2) horizontal layout of frames for block
|
||||
// 3) horizontal layout of frames for inline
|
||||
|
|
Загрузка…
Ссылка в новой задаче