зеркало из https://github.com/mozilla/pjs.git
bug 588 (text justification) for Robert O'Callahan <roc+moz@cs.cmu.edu>
r=buster bug 18545 ([FLOAT] Problem Centering <TABLE> with <DIV> tag) r=troy bugs 18827, 19579, 22327 24782, 26512, 30124, 31849, 32846 (floater behavior wrong) The primary change here is to determine if a block is impacted by a floater, and if so mark the block's lines dirty when appropriate. r=troy no bug number. performance work. reduced the size of some reflow data structures by collapsing multiple fields into a single bit field. r=troy
This commit is contained in:
Родитель
134ac7603e
Коммит
2fd6bc2c33
|
@ -3874,6 +3874,9 @@ FindTopFrame(nsIFrame* aRoot)
|
||||||
PRBool
|
PRBool
|
||||||
PresShell::VerifyIncrementalReflow()
|
PresShell::VerifyIncrementalReflow()
|
||||||
{
|
{
|
||||||
|
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
|
||||||
|
printf("Building Verification Tree...\n");
|
||||||
|
}
|
||||||
// All the stuff we are creating that needs releasing
|
// All the stuff we are creating that needs releasing
|
||||||
nsIPresContext* cx;
|
nsIPresContext* cx;
|
||||||
nsIViewManager* vm;
|
nsIViewManager* vm;
|
||||||
|
@ -3976,6 +3979,9 @@ PresShell::VerifyIncrementalReflow()
|
||||||
vm->SetViewObserver((nsIViewObserver *)((PresShell*)sh));
|
vm->SetViewObserver((nsIViewObserver *)((PresShell*)sh));
|
||||||
sh->InitialReflow(r.width, r.height);
|
sh->InitialReflow(r.width, r.height);
|
||||||
sh->SetVerifyReflowEnable(PR_TRUE); // turn on verify reflow again now that we're done reflowing the test frame tree
|
sh->SetVerifyReflowEnable(PR_TRUE); // turn on verify reflow again now that we're done reflowing the test frame tree
|
||||||
|
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
|
||||||
|
printf("Verification Tree built, comparing...\n");
|
||||||
|
}
|
||||||
|
|
||||||
// Now that the document has been reflowed, use its frame tree to
|
// Now that the document has been reflowed, use its frame tree to
|
||||||
// compare against our frame tree.
|
// compare against our frame tree.
|
||||||
|
@ -3999,15 +4005,15 @@ PresShell::VerifyIncrementalReflow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("Incremental reflow doomed view tree:\n");
|
|
||||||
// view->List(stdout, 1);
|
|
||||||
// view->SetVisibility(nsViewVisibility_kHide);
|
|
||||||
cx->Stop();
|
cx->Stop();
|
||||||
cx->SetContainer(nsnull);
|
cx->SetContainer(nsnull);
|
||||||
NS_RELEASE(cx);
|
NS_RELEASE(cx);
|
||||||
sh->EndObservingDocument();
|
sh->EndObservingDocument();
|
||||||
NS_RELEASE(sh);
|
NS_RELEASE(sh);
|
||||||
NS_RELEASE(vm);
|
NS_RELEASE(vm);
|
||||||
|
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
|
||||||
|
printf("Finished Verifying Reflow...\n");
|
||||||
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,10 @@ nsBlockBandData::GetAvailableSpace(nscoord aY, nsRect& aResult)
|
||||||
// between any left and right floaters.
|
// between any left and right floaters.
|
||||||
ComputeAvailSpaceRect();
|
ComputeAvailSpaceRect();
|
||||||
aResult = mAvailSpace;
|
aResult = mAvailSpace;
|
||||||
|
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||||
|
printf("nsBBD %p GetAvailableSpace(%d) returing (%d, %d, %d, %d)\n",
|
||||||
|
this, aY, aResult.x, aResult.y, aResult.width, aResult.height);
|
||||||
|
#endif
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +138,7 @@ void
|
||||||
nsBlockBandData::ComputeAvailSpaceRect()
|
nsBlockBandData::ComputeAvailSpaceRect()
|
||||||
{
|
{
|
||||||
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||||
printf("nsBlockBandData::ComputeAvailSpaceRect %p \n", this);
|
printf("nsBlockBandData::ComputeAvailSpaceRect %p with count %d\n", this, mCount);
|
||||||
#endif
|
#endif
|
||||||
if (0 == mCount) {
|
if (0 == mCount) {
|
||||||
mAvailSpace.x = 0;
|
mAvailSpace.x = 0;
|
||||||
|
@ -248,6 +252,11 @@ nsBlockBandData::ComputeAvailSpaceRect()
|
||||||
if (NS_UNCONSTRAINEDSIZE == mSpace.width) {
|
if (NS_UNCONSTRAINEDSIZE == mSpace.width) {
|
||||||
mAvailSpace.width = NS_UNCONSTRAINEDSIZE;
|
mAvailSpace.width = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||||
|
printf(" ComputeAvailSpaceRect settting state mAvailSpace (%d,%d,%d,%d)\n",
|
||||||
|
mAvailSpace.x, mAvailSpace.y, mAvailSpace.width, mAvailSpace.height);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -471,3 +480,15 @@ nsBlockBandData::GetMaxElementSize(nsIPresContext* aPresContext,
|
||||||
*aWidthResult = maxWidth;
|
*aWidthResult = maxWidth;
|
||||||
*aHeightResult = maxHeight;
|
*aHeightResult = maxHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void nsBlockBandData::List()
|
||||||
|
{
|
||||||
|
printf("nsBlockBandData %p sm=%p, sm coord = (%d,%d), mSpace = (%d,%d)\n",
|
||||||
|
this, mSpaceManager, mSpaceManagerX, mSpaceManagerY,
|
||||||
|
mSpace.width, mSpace.height);
|
||||||
|
printf(" availSpace=(%d, %d, %d, %d), floaters l=%d r=%d\n",
|
||||||
|
mAvailSpace.x, mAvailSpace.y, mAvailSpace.width, mAvailSpace.height,
|
||||||
|
mLeftFloaters, mRightFloaters);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -89,6 +89,10 @@ public:
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
nsSize* aResult);
|
nsSize* aResult);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void List();
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** utility method to calculate the band data at aY.
|
/** utility method to calculate the band data at aY.
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Steve Clark <buster@netscape.com>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
*/
|
*/
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
@ -61,6 +63,8 @@
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
//#define NOISY_BLOCK_INVALIDATE // DO NOT CHECK THIS IN TURNED ON!
|
||||||
|
|
||||||
static PRBool gLamePaintMetrics;
|
static PRBool gLamePaintMetrics;
|
||||||
static PRBool gLameReflowMetrics;
|
static PRBool gLameReflowMetrics;
|
||||||
static PRBool gNoisy;
|
static PRBool gNoisy;
|
||||||
|
@ -451,12 +455,6 @@ public:
|
||||||
|
|
||||||
nscoord mBottomEdge;
|
nscoord mBottomEdge;
|
||||||
|
|
||||||
PRPackedBool mUnconstrainedWidth;
|
|
||||||
PRPackedBool mUnconstrainedHeight;
|
|
||||||
PRPackedBool mShrinkWrapWidth;
|
|
||||||
PRPackedBool mNeedResizeReflow;
|
|
||||||
PRPackedBool mIsInlineIncrReflow;
|
|
||||||
|
|
||||||
// The content area to reflow child frames within. The x/y
|
// The content area to reflow child frames within. The x/y
|
||||||
// coordinates are known to be mBorderPadding.left and
|
// coordinates are known to be mBorderPadding.left and
|
||||||
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
||||||
|
@ -464,15 +462,6 @@ public:
|
||||||
// unconstrained area.
|
// unconstrained area.
|
||||||
nsSize mContentArea;
|
nsSize mContentArea;
|
||||||
|
|
||||||
// Our wrapping behavior
|
|
||||||
PRPackedBool mNoWrap;
|
|
||||||
|
|
||||||
// Is this frame a root for top/bottom margin collapsing?
|
|
||||||
PRPackedBool mIsTopMarginRoot, mIsBottomMarginRoot;
|
|
||||||
|
|
||||||
// See ShouldApplyTopMargin
|
|
||||||
PRPackedBool mApplyTopMargin;
|
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
// This state is "running" state updated by the reflow of each line
|
// This state is "running" state updated by the reflow of each line
|
||||||
|
@ -541,15 +530,48 @@ public:
|
||||||
// being N^2.
|
// being N^2.
|
||||||
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
||||||
|
|
||||||
PRPackedBool mComputeMaxElementSize;
|
|
||||||
PRPackedBool mComputeMaximumWidth;
|
|
||||||
|
|
||||||
nsSize mMaxElementSize;
|
nsSize mMaxElementSize;
|
||||||
nscoord mMaximumWidth;
|
nscoord mMaximumWidth;
|
||||||
|
|
||||||
nscoord mMinLineHeight;
|
nscoord mMinLineHeight;
|
||||||
|
|
||||||
PRInt32 mLineNumber;
|
PRInt32 mLineNumber;
|
||||||
|
|
||||||
|
// block reflow state flags
|
||||||
|
#define BRS_UNCONSTRAINEDWIDTH 0x00000001
|
||||||
|
#define BRS_UNCONSTRAINEDHEIGHT 0x00000002
|
||||||
|
#define BRS_SHRINKWRAPWIDTH 0x00000004
|
||||||
|
#define BRS_NEEDRESIZEREFLOW 0x00000008
|
||||||
|
#define BRS_ISINLINEINCRREFLOW 0x00000010
|
||||||
|
#define BRS_NOWRAP 0x00000020
|
||||||
|
#define BRS_ISTOPMARGINROOT 0x00000040 // Is this frame a root for top/bottom margin collapsing?
|
||||||
|
#define BRS_ISBOTTOMMARGINROOT 0x00000080
|
||||||
|
#define BRS_APPLYTOPMARGIN 0x00000100 // See ShouldApplyTopMargin
|
||||||
|
#define BRS_COMPUTEMAXELEMENTSIZE 0x00000200
|
||||||
|
#define BRS_COMPUTEMAXWIDTH 0x00000400
|
||||||
|
#define BRS_LASTFLAG BRS_COMPUTEMAXWIDTH
|
||||||
|
|
||||||
|
PRInt16 mFlags;
|
||||||
|
|
||||||
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
|
||||||
|
if (aValue) { // set flag
|
||||||
|
mFlags |= aFlag;
|
||||||
|
}
|
||||||
|
else { // unset flag
|
||||||
|
mFlags &= ~aFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GetFlag(PRUint32 aFlag) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
PRBool result = (mFlags & aFlag);
|
||||||
|
if (result) return PR_TRUE;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX This is vile. Make it go away
|
// XXX This is vile. Make it go away
|
||||||
|
@ -574,29 +596,25 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
: mBlock(aFrame),
|
: mBlock(aFrame),
|
||||||
mPresContext(aPresContext),
|
mPresContext(aPresContext),
|
||||||
mReflowState(aReflowState),
|
mReflowState(aReflowState),
|
||||||
mNeedResizeReflow(PR_FALSE),
|
|
||||||
mIsInlineIncrReflow(PR_FALSE),
|
|
||||||
mIsTopMarginRoot(PR_FALSE),
|
|
||||||
mIsBottomMarginRoot(PR_FALSE),
|
|
||||||
mApplyTopMargin(PR_FALSE),
|
|
||||||
mNextRCFrame(nsnull),
|
mNextRCFrame(nsnull),
|
||||||
mPrevBottomMargin(0),
|
mPrevBottomMargin(0),
|
||||||
mLineNumber(0)
|
mLineNumber(0),
|
||||||
|
mFlags(0)
|
||||||
{
|
{
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
|
||||||
if (aBlockMarginRoot) {
|
if (aBlockMarginRoot) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.top) {
|
if (0 != aReflowState.mComputedBorderPadding.top) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (mIsTopMarginRoot) {
|
if (GetFlag(BRS_ISTOPMARGINROOT)) {
|
||||||
mApplyTopMargin = PR_TRUE;
|
SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSpaceManager = aReflowState.mSpaceManager;
|
mSpaceManager = aReflowState.mSpaceManager;
|
||||||
|
@ -617,21 +635,19 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Compute content area width (the content area is inside the border
|
// Compute content area width (the content area is inside the border
|
||||||
// and padding)
|
// and padding)
|
||||||
mUnconstrainedWidth = PR_FALSE;
|
|
||||||
mShrinkWrapWidth = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
||||||
mContentArea.width = aReflowState.mComputedWidth;
|
mContentArea.width = aReflowState.mComputedWidth;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
||||||
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
||||||
mUnconstrainedWidth = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
||||||
// Choose a width based on the content (shrink wrap width) up
|
// Choose a width based on the content (shrink wrap width) up
|
||||||
// to the maximum width
|
// to the maximum width
|
||||||
mContentArea.width = aReflowState.mComputedMaxWidth;
|
mContentArea.width = aReflowState.mComputedMaxWidth;
|
||||||
mShrinkWrapWidth = PR_TRUE;
|
SetFlag(BRS_SHRINKWRAPWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nscoord lr = borderPadding.left + borderPadding.right;
|
nscoord lr = borderPadding.left + borderPadding.right;
|
||||||
|
@ -646,7 +662,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
// specified style height then we may end up limiting our height if
|
// specified style height then we may end up limiting our height if
|
||||||
// the availableHeight is constrained (this situation occurs when we
|
// the availableHeight is constrained (this situation occurs when we
|
||||||
// are paginated).
|
// are paginated).
|
||||||
mUnconstrainedHeight = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
||||||
// We are in a paginated situation. The bottom edge is just inside
|
// We are in a paginated situation. The bottom edge is just inside
|
||||||
// the bottom border and padding. The content area height doesn't
|
// the bottom border and padding. The content area height doesn't
|
||||||
|
@ -657,7 +672,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
else {
|
else {
|
||||||
// When we are not in a paginated situation then we always use
|
// When we are not in a paginated situation then we always use
|
||||||
// an constrained height.
|
// an constrained height.
|
||||||
mUnconstrainedHeight = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE);
|
||||||
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,16 +689,17 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
switch (styleText->mWhiteSpace) {
|
switch (styleText->mWhiteSpace) {
|
||||||
case NS_STYLE_WHITESPACE_PRE:
|
case NS_STYLE_WHITESPACE_PRE:
|
||||||
case NS_STYLE_WHITESPACE_NOWRAP:
|
case NS_STYLE_WHITESPACE_NOWRAP:
|
||||||
mNoWrap = PR_TRUE;
|
SetFlag(BRS_NOWRAP, PR_TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mNoWrap = PR_FALSE;
|
SetFlag(BRS_NOWRAP, PR_FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mComputeMaxElementSize = nsnull != aMetrics.maxElementSize;
|
SetFlag(BRS_COMPUTEMAXELEMENTSIZE, (nsnull != aMetrics.maxElementSize));
|
||||||
mMaxElementSize.SizeTo(0, 0);
|
mMaxElementSize.SizeTo(0, 0);
|
||||||
mComputeMaximumWidth = NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH);
|
SetFlag(BRS_COMPUTEMAXWIDTH,
|
||||||
|
(NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH)));
|
||||||
mMaximumWidth = 0;
|
mMaximumWidth = 0;
|
||||||
|
|
||||||
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
||||||
|
@ -729,8 +745,12 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
const nsStyleDisplay* aDisplay,
|
const nsStyleDisplay* aDisplay,
|
||||||
nsRect& aResult)
|
nsRect& aResult)
|
||||||
{
|
{
|
||||||
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
|
printf("CBAS frame=%p has floater count %d\n", aFrame, mBand.GetFloaterCount());
|
||||||
|
mBand.List();
|
||||||
|
#endif
|
||||||
aResult.y = mY;
|
aResult.y = mY;
|
||||||
aResult.height = mUnconstrainedHeight
|
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mBottomEdge - mY;
|
: mBottomEdge - mY;
|
||||||
|
|
||||||
|
@ -749,7 +769,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// The child block will flow around the floater. Therefore
|
// The child block will flow around the floater. Therefore
|
||||||
// give it all of the available space.
|
// give it all of the available space.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
break;
|
break;
|
||||||
|
@ -776,7 +796,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine width
|
// determine width
|
||||||
if (mUnconstrainedWidth) {
|
if (GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -810,7 +830,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// doesn't matter therefore give the block element all of the
|
// doesn't matter therefore give the block element all of the
|
||||||
// available space since it will flow around the floater itself.
|
// available space since it will flow around the floater itself.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
}
|
}
|
||||||
|
@ -957,12 +977,12 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
|
||||||
#endif
|
#endif
|
||||||
mKidXMost = xmost;
|
mKidXMost = xmost;
|
||||||
}
|
}
|
||||||
if (mComputeMaxElementSize) {
|
if (GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If computing the maximum width, then update mMaximumWidth
|
// If computing the maximum width, then update mMaximumWidth
|
||||||
if (mComputeMaximumWidth) {
|
if (GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
UpdateMaximumWidth(aLine->mMaximumWidth);
|
UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,6 +1474,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
||||||
NS_BLOCK_MARGIN_ROOT & mState);
|
NS_BLOCK_MARGIN_ROOT & mState);
|
||||||
|
PRInt32 sizeofBRS = sizeof nsBlockReflowState;
|
||||||
|
|
||||||
if (eReflowReason_Resize != aReflowState.reason) {
|
if (eReflowReason_Resize != aReflowState.reason) {
|
||||||
RenumberLists(aPresContext);
|
RenumberLists(aPresContext);
|
||||||
|
@ -1462,7 +1483,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
PRBool isStyleChange = PR_FALSE;
|
PRBool isStyleChange = PR_FALSE;
|
||||||
state.mIsInlineIncrReflow = PR_FALSE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_FALSE);
|
||||||
nsIFrame* target;
|
nsIFrame* target;
|
||||||
switch (aReflowState.reason) {
|
switch (aReflowState.reason) {
|
||||||
case eReflowReason_Initial:
|
case eReflowReason_Initial:
|
||||||
|
@ -1535,7 +1556,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// reflow the line containing the target of the incr. reflow
|
// reflow the line containing the target of the incr. reflow
|
||||||
// first mark the line dirty and set up the state object
|
// first mark the line dirty and set up the state object
|
||||||
rv = PrepareChildIncrementalReflow(state);
|
rv = PrepareChildIncrementalReflow(state);
|
||||||
state.mIsInlineIncrReflow = PR_TRUE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_TRUE);
|
||||||
state.mPrevLine = prevLine;
|
state.mPrevLine = prevLine;
|
||||||
state.mCurrentLine = line;
|
state.mCurrentLine = line;
|
||||||
state.mNextRCFrame = state.mNextRCFrame;
|
state.mNextRCFrame = state.mNextRCFrame;
|
||||||
|
@ -1681,6 +1702,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
if (isStyleChange) {
|
if (isStyleChange) {
|
||||||
// Lots of things could have changed so damage our entire
|
// Lots of things could have changed so damage our entire
|
||||||
// bounds
|
// bounds
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 1 (%d, %d, %d, %d)\n",
|
||||||
|
this, 0, 0, mRect.width, mRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -1707,6 +1732,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = 0;
|
damageRect.y = 0;
|
||||||
damageRect.height = mRect.height;
|
damageRect.height = mRect.height;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 2 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1730,6 +1759,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = mRect.height - border.bottom;
|
damageRect.y = mRect.height - border.bottom;
|
||||||
damageRect.height = border.bottom;
|
damageRect.height = border.bottom;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 3 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1868,7 +1901,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
||||||
aState.mY, aState.mIsBottomMarginRoot ? "yes" : "no",
|
aState.mY, aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? "yes" : "no",
|
||||||
aState.mPrevBottomMargin,
|
aState.mPrevBottomMargin,
|
||||||
borderPadding.top, borderPadding.bottom);
|
borderPadding.top, borderPadding.bottom);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1946,7 +1979,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// contents or we fluff out to the maximum block width. Note:
|
// contents or we fluff out to the maximum block width. Note:
|
||||||
// We always shrink wrap when given an unconstrained width.
|
// We always shrink wrap when given an unconstrained width.
|
||||||
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
||||||
!aState.mUnconstrainedWidth && !aState.mShrinkWrapWidth &&
|
!aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) &&
|
||||||
!compact) {
|
!compact) {
|
||||||
// Set our width to the max width if we aren't already that
|
// Set our width to the max width if we aren't already that
|
||||||
// wide. Note that the max-width has nothing to do with our
|
// wide. Note that the max-width has nothing to do with our
|
||||||
|
@ -1956,9 +1989,9 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we should compute our max element size
|
// See if we should compute our max element size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Adjust the computedWidth
|
// Adjust the computedWidth
|
||||||
if (aState.mNoWrap) {
|
if (aState.GetFlag(BRS_NOWRAP)) {
|
||||||
// When no-wrap is true the max-element-size.width is the
|
// When no-wrap is true the max-element-size.width is the
|
||||||
// width of the widest line plus the right border. Note that
|
// width of the widest line plus the right border. Note that
|
||||||
// aState.mKidXMost already has the left border factored in
|
// aState.mKidXMost already has the left border factored in
|
||||||
|
@ -1996,7 +2029,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// need to do horizontal alignment of the inline lines and make sure
|
// need to do horizontal alignment of the inline lines and make sure
|
||||||
// blocks are correctly sized and positioned. Any lines that need
|
// blocks are correctly sized and positioned. Any lines that need
|
||||||
// final adjustment will have been marked as dirty
|
// final adjustment will have been marked as dirty
|
||||||
if (aState.mShrinkWrapWidth && aState.mNeedResizeReflow) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) {
|
||||||
// If the parent reflow state is also shrink wrap width, then
|
// If the parent reflow state is also shrink wrap width, then
|
||||||
// we don't need to do this, because it will reflow us after it
|
// we don't need to do this, because it will reflow us after it
|
||||||
// calculates the final width
|
// calculates the final width
|
||||||
|
@ -2025,7 +2058,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
||||||
if (aReflowState.parentReflowState) {
|
if (aReflowState.parentReflowState) {
|
||||||
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
||||||
|
@ -2047,7 +2080,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// Don't carry out a bottom margin when our height is fixed
|
// Don't carry out a bottom margin when our height is fixed
|
||||||
// unless the bottom of the last line adjoins the bottom of our
|
// unless the bottom of the last line adjoins the bottom of our
|
||||||
// content area.
|
// content area.
|
||||||
if (!aState.mIsBottomMarginRoot) {
|
if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
||||||
aState.mPrevBottomMargin = 0;
|
aState.mPrevBottomMargin = 0;
|
||||||
}
|
}
|
||||||
|
@ -2057,7 +2090,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
nscoord autoHeight = aState.mY;
|
nscoord autoHeight = aState.mY;
|
||||||
|
|
||||||
// Shrink wrap our height around our contents.
|
// Shrink wrap our height around our contents.
|
||||||
if (aState.mIsBottomMarginRoot) {
|
if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
// When we are a bottom-margin root make sure that our last
|
// When we are a bottom-margin root make sure that our last
|
||||||
// childs bottom margin is fully applied.
|
// childs bottom margin is fully applied.
|
||||||
// XXX check for a fit
|
// XXX check for a fit
|
||||||
|
@ -2082,7 +2115,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
aMetrics.height = autoHeight;
|
aMetrics.height = autoHeight;
|
||||||
|
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxHeight = aState.mMaxElementSize.height +
|
maxHeight = aState.mMaxElementSize.height +
|
||||||
borderPadding.top + borderPadding.bottom;
|
borderPadding.top + borderPadding.bottom;
|
||||||
}
|
}
|
||||||
|
@ -2090,7 +2123,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
aMetrics.ascent = aMetrics.height;
|
aMetrics.ascent = aMetrics.height;
|
||||||
aMetrics.descent = 0;
|
aMetrics.descent = 0;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Store away the final value
|
// Store away the final value
|
||||||
aMetrics.maxElementSize->width = maxWidth;
|
aMetrics.maxElementSize->width = maxWidth;
|
||||||
aMetrics.maxElementSize->height = maxHeight;
|
aMetrics.maxElementSize->height = maxHeight;
|
||||||
|
@ -2098,14 +2131,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Return bottom margin information
|
// Return bottom margin information
|
||||||
aMetrics.mCarriedOutBottomMargin =
|
aMetrics.mCarriedOutBottomMargin =
|
||||||
aState.mIsBottomMarginRoot ? 0 : aState.mPrevBottomMargin;
|
aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
||||||
}
|
}
|
||||||
if (aState.mComputeMaxElementSize &&
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) &&
|
||||||
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
||||||
|
@ -2115,7 +2148,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
printf("PASS1 ");
|
printf("PASS1 ");
|
||||||
|
@ -2130,7 +2163,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're requested to update our maximum width, then compute it
|
// If we're requested to update our maximum width, then compute it
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
// We need to add in for the right border/padding
|
// We need to add in for the right border/padding
|
||||||
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
||||||
}
|
}
|
||||||
|
@ -2337,8 +2370,13 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
// See if we can try and avoid marking all the lines as dirty
|
// See if we can try and avoid marking all the lines as dirty
|
||||||
PRBool tryAndSkipLines = PR_FALSE;
|
PRBool tryAndSkipLines = PR_FALSE;
|
||||||
|
|
||||||
// See if this is this a constrained resize reflow
|
// we need to calculate if any part of then block itself
|
||||||
if ((aState.mReflowState.reason == eReflowReason_Resize) &&
|
// is impacted by a floater (bug 19579)
|
||||||
|
aState.GetAvailableSpace();
|
||||||
|
|
||||||
|
// See if this is this a constrained resize reflow that is not impacted by floaters
|
||||||
|
if ((PR_FALSE==aState.IsImpactedByFloater()) &&
|
||||||
|
(aState.mReflowState.reason == eReflowReason_Resize) &&
|
||||||
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
||||||
|
|
||||||
// If the text is left-aligned, then we try and avoid reflowing the lines
|
// If the text is left-aligned, then we try and avoid reflowing the lines
|
||||||
|
@ -2389,7 +2427,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRBool notWrapping = aState.mNoWrap;
|
PRBool notWrapping = aState.GetFlag(BRS_NOWRAP);
|
||||||
while (nsnull != line) {
|
while (nsnull != line) {
|
||||||
|
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
|
@ -2402,8 +2440,6 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
||||||
line, line->IsImpactedByFloater() ? "" : "not ");
|
line, line->IsImpactedByFloater() ? "" : "not ");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (notWrapping) {
|
if (notWrapping) {
|
||||||
// When no-wrap is set then the only line-breaking that
|
// When no-wrap is set then the only line-breaking that
|
||||||
// occurs for inline lines is triggered by BR elements or by
|
// occurs for inline lines is triggered by BR elements or by
|
||||||
|
@ -2430,7 +2466,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
||||||
line, line->mNext,
|
line, line->mNext,
|
||||||
line->IsBlock() ? "block" : "inline",
|
line->IsBlock() ? "block" : "inline",
|
||||||
aState.mNoWrap ? "no-wrap" : "wrapping",
|
aState.GetFlag(BRS_NOWRAP) ? "no-wrap" : "wrapping",
|
||||||
line->HasBreak() ? "has-break " : "",
|
line->HasBreak() ? "has-break " : "",
|
||||||
line->HasFloaters() ? "has-floaters " : "",
|
line->HasFloaters() ? "has-floaters " : "",
|
||||||
line->IsImpactedByFloater() ? "impacted " : "",
|
line->IsImpactedByFloater() ? "impacted " : "",
|
||||||
|
@ -2628,7 +2664,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
||||||
kReflowCommandType[type], type,
|
kReflowCommandType[type], type,
|
||||||
aState.mIsInlineIncrReflow ? "true" : "false");
|
aState.GetFlag(BRS_ISINLINEINCRREFLOW) ? "true" : "false");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
IndentBy(stdout, gNoiseIndent);
|
IndentBy(stdout, gNoiseIndent);
|
||||||
|
@ -2651,7 +2687,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// Reflow the lines that are already ours
|
// Reflow the lines that are already ours
|
||||||
aState.mPrevLine = nsnull;
|
aState.mPrevLine = nsnull;
|
||||||
nsLineBox* line = mLines;
|
nsLineBox* line = mLines;
|
||||||
if (aState.mIsInlineIncrReflow && aState.mNextRCFrame)
|
if (aState.GetFlag(BRS_ISINLINEINCRREFLOW) && aState.mNextRCFrame)
|
||||||
{
|
{
|
||||||
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
||||||
aState.mCurrentLine = line;
|
aState.mCurrentLine = line;
|
||||||
|
@ -2662,6 +2698,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 4 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
aState.mPrevLine = line;
|
aState.mPrevLine = line;
|
||||||
|
@ -2689,7 +2729,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// If we're supposed to update our maximum width, then we'll also need to
|
// If we're supposed to update our maximum width, then we'll also need to
|
||||||
// reflow this line if it's line wrapped and any of the continuing lines
|
// reflow this line if it's line wrapped and any of the continuing lines
|
||||||
// are dirty
|
// are dirty
|
||||||
if (line->IsDirty() || (aState.mComputeMaximumWidth && ::WrappedLinesAreDirty(line))) {
|
if (line->IsDirty() || (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && ::WrappedLinesAreDirty(line))) {
|
||||||
// Compute the dirty lines "before" YMost, after factoring in
|
// Compute the dirty lines "before" YMost, after factoring in
|
||||||
// the running deltaY value - the running value is implicit in
|
// the running deltaY value - the running value is implicit in
|
||||||
// aState.mY.
|
// aState.mY.
|
||||||
|
@ -2729,6 +2769,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 5 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2902,6 +2946,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// XXX We need to improve on this...
|
// XXX We need to improve on this...
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 6 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -2918,6 +2966,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.x;
|
dirtyRect.x;
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
||||||
lineCombinedArea.height);
|
lineCombinedArea.height);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 7 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
if (oldCombinedArea.height != lineCombinedArea.height) {
|
if (oldCombinedArea.height != lineCombinedArea.height) {
|
||||||
|
@ -2933,6 +2985,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
||||||
lineCombinedArea.YMost()) -
|
lineCombinedArea.YMost()) -
|
||||||
dirtyRect.y;
|
dirtyRect.y;
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 8 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2951,21 +3007,21 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// we'll either need to recover the floater state that applies to the
|
// we'll either need to recover the floater state that applies to the
|
||||||
// unconstrained reflow or keep it around in a separate space manager...
|
// unconstrained reflow or keep it around in a separate space manager...
|
||||||
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
||||||
if (aState.mComputeMaximumWidth && isBeginningLine) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && isBeginningLine) {
|
||||||
nscoord oldY = aState.mY;
|
nscoord oldY = aState.mY;
|
||||||
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
||||||
PRBool oldUnconstrainedWidth = aState.mUnconstrainedWidth;
|
PRBool oldUnconstrainedWidth = aState.GetFlag(BRS_UNCONSTRAINEDWIDTH);
|
||||||
|
|
||||||
// First reflow the line with an unconstrained width. When doing this
|
// First reflow the line with an unconstrained width. When doing this
|
||||||
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
||||||
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
||||||
// associated floater we don't end up resetting the line's right edge and
|
// associated floater we don't end up resetting the line's right edge and
|
||||||
// have it think the width is unconstrained...
|
// have it think the width is unconstrained...
|
||||||
aState.mUnconstrainedWidth = PR_TRUE;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
||||||
aState.mY = oldY;
|
aState.mY = oldY;
|
||||||
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
||||||
aState.mUnconstrainedWidth = oldUnconstrainedWidth;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, oldUnconstrainedWidth);
|
||||||
|
|
||||||
// Update the line's maximum width
|
// Update the line's maximum width
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
|
@ -2980,14 +3036,14 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// Note: we need to reset both member variables, because the inline
|
// Note: we need to reset both member variables, because the inline
|
||||||
// code examines mComputeMaxElementSize and if there is a placeholder
|
// code examines mComputeMaxElementSize and if there is a placeholder
|
||||||
// on this line the code to reflow the floater looks at both...
|
// on this line the code to reflow the floater looks at both...
|
||||||
nscoord oldComputeMaxElementSize = aState.mComputeMaxElementSize;
|
nscoord oldComputeMaxElementSize = aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE);
|
||||||
nscoord oldComputeMaximumWidth = aState.mComputeMaximumWidth;
|
nscoord oldComputeMaximumWidth = aState.GetFlag(BRS_COMPUTEMAXWIDTH);
|
||||||
|
|
||||||
aState.mComputeMaxElementSize = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, PR_FALSE);
|
||||||
aState.mComputeMaximumWidth = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, PR_FALSE);
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
aState.mComputeMaxElementSize = oldComputeMaxElementSize;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, oldComputeMaxElementSize);
|
||||||
aState.mComputeMaximumWidth = oldComputeMaximumWidth;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, oldComputeMaximumWidth);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
|
@ -3001,6 +3057,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
|
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 9 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3368,7 +3428,7 @@ PRBool
|
||||||
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
nsLineBox* aLine)
|
nsLineBox* aLine)
|
||||||
{
|
{
|
||||||
if (aState.mApplyTopMargin) {
|
if (aState.GetFlag(BRS_APPLYTOPMARGIN)) {
|
||||||
// Apply short-circuit check to avoid searching the line list
|
// Apply short-circuit check to avoid searching the line list
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -3377,7 +3437,7 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
// If we aren't at the top Y coordinate then something of non-zero
|
// If we aren't at the top Y coordinate then something of non-zero
|
||||||
// height must have been placed. Therefore the childs top-margin
|
// height must have been placed. Therefore the childs top-margin
|
||||||
// applies.
|
// applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3387,13 +3447,13 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
// A line which preceeds aLine contains a block; therefore the
|
// A line which preceeds aLine contains a block; therefore the
|
||||||
// top margin applies.
|
// top margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else if (line->HasFloaters()) {
|
else if (line->HasFloaters()) {
|
||||||
// A line which preceeds aLine is not empty therefore the top
|
// A line which preceeds aLine is not empty therefore the top
|
||||||
// margin applies.
|
// margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
line = line->mNext;
|
line = line->mNext;
|
||||||
|
@ -3486,8 +3546,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
frame->GetStyleData(eStyleStruct_Display,
|
frame->GetStyleData(eStyleStruct_Display,
|
||||||
(const nsStyleStruct*&) display);
|
(const nsStyleStruct*&) display);
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// See if we should apply the top margin. If the block frame being
|
// See if we should apply the top margin. If the block frame being
|
||||||
|
@ -3611,14 +3671,14 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
&collapsedBottomMargin,
|
&collapsedBottomMargin,
|
||||||
aLine->mBounds, combinedArea);
|
aLine->mBounds, combinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line as block so once we known the final shrink wrap width
|
// Mark the line as block so once we known the final shrink wrap width
|
||||||
// we can reflow the block to the correct size
|
// we can reflow the block to the correct size
|
||||||
// XXX We don't always need to do this...
|
// XXX We don't always need to do this...
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (aState.mUnconstrainedWidth || aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Add the right margin to the line's bounnds. That way it will be taken into
|
// Add the right margin to the line's bounnds. That way it will be taken into
|
||||||
// account when we compute our shrink wrap size
|
// account when we compute our shrink wrap size
|
||||||
nscoord marginRight = brc.GetMargin().right;
|
nscoord marginRight = brc.GetMargin().right;
|
||||||
|
@ -3709,7 +3769,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Post-process the "line"
|
// Post-process the "line"
|
||||||
nsSize maxElementSize(0, 0);
|
nsSize maxElementSize(0, 0);
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxElementSize = brc.GetMaxElementSize();
|
maxElementSize = brc.GetMaxElementSize();
|
||||||
if (aState.IsImpactedByFloater() &&
|
if (aState.IsImpactedByFloater() &&
|
||||||
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
||||||
|
@ -3721,7 +3781,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
// If we asked the block to update its maximum width, then record the
|
// If we asked the block to update its maximum width, then record the
|
||||||
// updated value in the line, and update the current maximum width
|
// updated value in the line, and update the current maximum width
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
||||||
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
|
|
||||||
|
@ -3849,7 +3909,7 @@ nsBlockFrame::DoReflowInlineFramesMalloc(nsBlockReflowState& aState,
|
||||||
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -3872,7 +3932,7 @@ nsBlockFrame::DoReflowInlineFramesAuto(nsBlockReflowState& aState,
|
||||||
nsLineLayout lineLayout(aState.mPresContext,
|
nsLineLayout lineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
||||||
lineLayout.SetReflowTextRuns(mTextRuns);
|
lineLayout.SetReflowTextRuns(mTextRuns);
|
||||||
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
||||||
|
@ -3910,7 +3970,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
||||||
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
||||||
nscoord availWidth = aState.mAvailSpaceRect.width;
|
nscoord availWidth = aState.mAvailSpaceRect.width;
|
||||||
nscoord availHeight;
|
nscoord availHeight;
|
||||||
if (aState.mUnconstrainedHeight) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
|
||||||
availHeight = NS_UNCONSTRAINEDSIZE;
|
availHeight = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4359,7 +4419,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
nsSize maxElementSize;
|
nsSize maxElementSize;
|
||||||
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
||||||
// See if we're shrink wrapping the width
|
// See if we're shrink wrapping the width
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// When determining the line's width we also need to include any
|
// When determining the line's width we also need to include any
|
||||||
// right floaters that impact us. This represents the shrink wrap
|
// right floaters that impact us. This represents the shrink wrap
|
||||||
// width of the line
|
// width of the line
|
||||||
|
@ -4388,25 +4448,20 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// Only block frames horizontally align their children because
|
// Only block frames horizontally align their children because
|
||||||
// inline frames "shrink-wrap" around their children (therefore
|
// inline frames "shrink-wrap" around their children (therefore
|
||||||
// there is no extra horizontal space).
|
// there is no extra horizontal space).
|
||||||
#if XXX_fix_me
|
const nsStyleText* styleText = (const nsStyleText*)
|
||||||
PRBool allowJustify = PR_TRUE;
|
mStyleContext->GetStyleData(eStyleStruct_Text);
|
||||||
if (NS_STYLE_TEXT_ALIGN_JUSTIFY == aState.mStyleText->mTextAlign) {
|
PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign
|
||||||
allowJustify = ShouldJustifyLine(aState, aLine);
|
&& !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine);
|
||||||
}
|
PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
||||||
#else
|
aState.GetFlag(BRS_SHRINKWRAPWIDTH));
|
||||||
PRBool allowJustify = PR_FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PRBool successful;
|
|
||||||
nsRect combinedArea;
|
|
||||||
successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
|
||||||
aState.mShrinkWrapWidth);
|
|
||||||
if (!successful) {
|
if (!successful) {
|
||||||
// Mark the line dirty and then later once we've determined the width
|
// Mark the line dirty and then later once we've determined the width
|
||||||
// we can do the horizontal alignment
|
// we can do the horizontal alignment
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsRect combinedArea;
|
||||||
aLineLayout.RelativePositionFrames(combinedArea);
|
aLineLayout.RelativePositionFrames(combinedArea);
|
||||||
aLine->SetCombinedArea(combinedArea);
|
aLine->SetCombinedArea(combinedArea);
|
||||||
if (addedBullet) {
|
if (addedBullet) {
|
||||||
|
@ -4454,7 +4509,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
aState.mY = newY;
|
aState.mY = newY;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
|
@ -4478,7 +4533,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// we don't want updated...
|
// we don't want updated...
|
||||||
if (aUpdateMaximumWidth) {
|
if (aUpdateMaximumWidth) {
|
||||||
// However, we do need to update the max-element-size if requested
|
// However, we do need to update the max-element-size if requested
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(maxElementSize);
|
aState.UpdateMaxElementSize(maxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4519,7 +4574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mHaveRightFloaters &&
|
if (aState.mHaveRightFloaters &&
|
||||||
(aState.mUnconstrainedWidth || aState.mShrinkWrapWidth)) {
|
(aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// We are reflowing in an unconstrained situation or shrink wrapping and
|
// We are reflowing in an unconstrained situation or shrink wrapping and
|
||||||
// have some right floaters. They were placed at the infinite right edge
|
// have some right floaters. They were placed at the infinite right edge
|
||||||
// which will cause the combined area to be unusable.
|
// which will cause the combined area to be unusable.
|
||||||
|
@ -4540,11 +4595,11 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
||||||
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line dirty so we come back and re-place the floater once
|
// Mark the line dirty so we come back and re-place the floater once
|
||||||
// the shrink wrap width is determined
|
// the shrink wrap width is determined
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aLine->SetCombinedArea(lineCombinedArea);
|
aLine->SetCombinedArea(lineCombinedArea);
|
||||||
|
@ -4629,7 +4684,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update max-element-size
|
// Update max-element-size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(aMaxElementSize);
|
aState.UpdateMaxElementSize(aMaxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4639,7 +4694,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
// If this is an unconstrained reflow, then cache the line width in the
|
// If this is an unconstrained reflow, then cache the line width in the
|
||||||
// line. We'll need this during incremental reflow if we're asked to
|
// line. We'll need this during incremental reflow if we're asked to
|
||||||
// calculate the maximum width
|
// calculate the maximum width
|
||||||
if (aState.mUnconstrainedWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4653,7 +4708,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
#endif
|
#endif
|
||||||
// If we're shrink wrapping our width and the line was wrapped,
|
// If we're shrink wrapping our width and the line was wrapped,
|
||||||
// then make sure we take up all of the available width
|
// then make sure we take up all of the available width
|
||||||
if (aState.mShrinkWrapWidth && aLine->IsLineWrapped()) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aLine->IsLineWrapped()) {
|
||||||
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5187,6 +5242,10 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
||||||
// cases...
|
// cases...
|
||||||
nsRect lineCombinedArea;
|
nsRect lineCombinedArea;
|
||||||
line->GetCombinedArea(&lineCombinedArea);
|
line->GetCombinedArea(&lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 10 (%d, %d, %d, %d)\n",
|
||||||
|
this, lineCombinedArea.x, lineCombinedArea.y, lineCombinedArea.width, lineCombinedArea.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, lineCombinedArea);
|
Invalidate(aPresContext, lineCombinedArea);
|
||||||
line->Destroy(presShell);
|
line->Destroy(presShell);
|
||||||
line = next;
|
line = next;
|
||||||
|
@ -5282,8 +5341,8 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Setup block reflow state to reflow the floater
|
// Setup block reflow state to reflow the floater
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// Reflow the floater
|
// Reflow the floater
|
||||||
|
@ -5324,7 +5383,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||||
|
|
||||||
// If we computed it, then stash away the max-element-size for later
|
// If we computed it, then stash away the max-element-size for later
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5389,7 +5448,7 @@ nsBlockReflowState::AddFloater(nsLineLayout& aLineLayout,
|
||||||
// Pass on updated available space to the current inline reflow engine
|
// Pass on updated available space to the current inline reflow engine
|
||||||
GetAvailableSpace();
|
GetAvailableSpace();
|
||||||
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
||||||
mUnconstrainedWidth ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
GetFlag(BRS_UNCONSTRAINEDWIDTH) ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
||||||
mAvailSpaceRect.height,
|
mAvailSpaceRect.height,
|
||||||
isLeftFloater,
|
isLeftFloater,
|
||||||
aPlaceholder->GetOutOfFlowFrame());
|
aPlaceholder->GetOutOfFlowFrame());
|
||||||
|
@ -5615,7 +5674,12 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isLeftFloater = PR_FALSE;
|
isLeftFloater = PR_FALSE;
|
||||||
region.x = mAvailSpaceRect.XMost() - region.width;
|
if (NS_UNCONSTRAINEDSIZE != mAvailSpaceRect.XMost())
|
||||||
|
region.x = mAvailSpaceRect.XMost() - region.width;
|
||||||
|
else {
|
||||||
|
okToAddRectRegion = PR_FALSE;
|
||||||
|
region.x = mAvailSpaceRect.x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*aIsLeftFloater = isLeftFloater;
|
*aIsLeftFloater = isLeftFloater;
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
@ -5682,7 +5746,8 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
||||||
combinedArea.x += x;
|
combinedArea.x += x;
|
||||||
combinedArea.y += y;
|
combinedArea.y += y;
|
||||||
if (!isLeftFloater && (mUnconstrainedWidth || mShrinkWrapWidth)) {
|
if (!isLeftFloater &&
|
||||||
|
(GetFlag(BRS_UNCONSTRAINEDWIDTH) || GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// When we are placing a right floater in an unconstrained situation or
|
// When we are placing a right floater in an unconstrained situation or
|
||||||
// when shrink wrapping, we don't apply it to the floater combined area
|
// when shrink wrapping, we don't apply it to the floater combined area
|
||||||
// immediately. Otherwise we end up with an infinitely wide combined
|
// immediately. Otherwise we end up with an infinitely wide combined
|
||||||
|
|
|
@ -197,10 +197,12 @@ nsBlockReflowContext::AlignBlockHorizontally(nscoord aWidth,
|
||||||
// compatability cases.
|
// compatability cases.
|
||||||
switch (styleText->mTextAlign) {
|
switch (styleText->mTextAlign) {
|
||||||
case NS_STYLE_TEXT_ALIGN_MOZ_RIGHT:
|
case NS_STYLE_TEXT_ALIGN_MOZ_RIGHT:
|
||||||
|
case NS_STYLE_TEXT_ALIGN_RIGHT:
|
||||||
aAlign.mXOffset += remainingSpace;
|
aAlign.mXOffset += remainingSpace;
|
||||||
doCSS = PR_FALSE;
|
doCSS = PR_FALSE;
|
||||||
break;
|
break;
|
||||||
case NS_STYLE_TEXT_ALIGN_MOZ_CENTER:
|
case NS_STYLE_TEXT_ALIGN_MOZ_CENTER:
|
||||||
|
case NS_STYLE_TEXT_ALIGN_CENTER:
|
||||||
aAlign.mXOffset += remainingSpace / 2;
|
aAlign.mXOffset += remainingSpace / 2;
|
||||||
doCSS = PR_FALSE;
|
doCSS = PR_FALSE;
|
||||||
break;
|
break;
|
||||||
|
@ -359,7 +361,11 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||||
reflowState.mComputedBorderPadding.right;
|
reflowState.mComputedBorderPadding.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
x = aSpace.XMost() - mMargin.right - frameWidth;
|
// if this is an unconstrained width reflow, then just place the floater at the left margin
|
||||||
|
if (NS_UNCONSTRAINEDSIZE == aSpace.width)
|
||||||
|
x = aSpace.x;
|
||||||
|
else
|
||||||
|
x = aSpace.XMost() - mMargin.right - frameWidth;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
x = aSpace.x + mMargin.left;
|
x = aSpace.x + mMargin.left;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Steve Clark <buster@netscape.com>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
*/
|
*/
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
@ -61,6 +63,8 @@
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
//#define NOISY_BLOCK_INVALIDATE // DO NOT CHECK THIS IN TURNED ON!
|
||||||
|
|
||||||
static PRBool gLamePaintMetrics;
|
static PRBool gLamePaintMetrics;
|
||||||
static PRBool gLameReflowMetrics;
|
static PRBool gLameReflowMetrics;
|
||||||
static PRBool gNoisy;
|
static PRBool gNoisy;
|
||||||
|
@ -451,12 +455,6 @@ public:
|
||||||
|
|
||||||
nscoord mBottomEdge;
|
nscoord mBottomEdge;
|
||||||
|
|
||||||
PRPackedBool mUnconstrainedWidth;
|
|
||||||
PRPackedBool mUnconstrainedHeight;
|
|
||||||
PRPackedBool mShrinkWrapWidth;
|
|
||||||
PRPackedBool mNeedResizeReflow;
|
|
||||||
PRPackedBool mIsInlineIncrReflow;
|
|
||||||
|
|
||||||
// The content area to reflow child frames within. The x/y
|
// The content area to reflow child frames within. The x/y
|
||||||
// coordinates are known to be mBorderPadding.left and
|
// coordinates are known to be mBorderPadding.left and
|
||||||
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
||||||
|
@ -464,15 +462,6 @@ public:
|
||||||
// unconstrained area.
|
// unconstrained area.
|
||||||
nsSize mContentArea;
|
nsSize mContentArea;
|
||||||
|
|
||||||
// Our wrapping behavior
|
|
||||||
PRPackedBool mNoWrap;
|
|
||||||
|
|
||||||
// Is this frame a root for top/bottom margin collapsing?
|
|
||||||
PRPackedBool mIsTopMarginRoot, mIsBottomMarginRoot;
|
|
||||||
|
|
||||||
// See ShouldApplyTopMargin
|
|
||||||
PRPackedBool mApplyTopMargin;
|
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
// This state is "running" state updated by the reflow of each line
|
// This state is "running" state updated by the reflow of each line
|
||||||
|
@ -541,15 +530,48 @@ public:
|
||||||
// being N^2.
|
// being N^2.
|
||||||
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
||||||
|
|
||||||
PRPackedBool mComputeMaxElementSize;
|
|
||||||
PRPackedBool mComputeMaximumWidth;
|
|
||||||
|
|
||||||
nsSize mMaxElementSize;
|
nsSize mMaxElementSize;
|
||||||
nscoord mMaximumWidth;
|
nscoord mMaximumWidth;
|
||||||
|
|
||||||
nscoord mMinLineHeight;
|
nscoord mMinLineHeight;
|
||||||
|
|
||||||
PRInt32 mLineNumber;
|
PRInt32 mLineNumber;
|
||||||
|
|
||||||
|
// block reflow state flags
|
||||||
|
#define BRS_UNCONSTRAINEDWIDTH 0x00000001
|
||||||
|
#define BRS_UNCONSTRAINEDHEIGHT 0x00000002
|
||||||
|
#define BRS_SHRINKWRAPWIDTH 0x00000004
|
||||||
|
#define BRS_NEEDRESIZEREFLOW 0x00000008
|
||||||
|
#define BRS_ISINLINEINCRREFLOW 0x00000010
|
||||||
|
#define BRS_NOWRAP 0x00000020
|
||||||
|
#define BRS_ISTOPMARGINROOT 0x00000040 // Is this frame a root for top/bottom margin collapsing?
|
||||||
|
#define BRS_ISBOTTOMMARGINROOT 0x00000080
|
||||||
|
#define BRS_APPLYTOPMARGIN 0x00000100 // See ShouldApplyTopMargin
|
||||||
|
#define BRS_COMPUTEMAXELEMENTSIZE 0x00000200
|
||||||
|
#define BRS_COMPUTEMAXWIDTH 0x00000400
|
||||||
|
#define BRS_LASTFLAG BRS_COMPUTEMAXWIDTH
|
||||||
|
|
||||||
|
PRInt16 mFlags;
|
||||||
|
|
||||||
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
|
||||||
|
if (aValue) { // set flag
|
||||||
|
mFlags |= aFlag;
|
||||||
|
}
|
||||||
|
else { // unset flag
|
||||||
|
mFlags &= ~aFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GetFlag(PRUint32 aFlag) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
PRBool result = (mFlags & aFlag);
|
||||||
|
if (result) return PR_TRUE;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX This is vile. Make it go away
|
// XXX This is vile. Make it go away
|
||||||
|
@ -574,29 +596,25 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
: mBlock(aFrame),
|
: mBlock(aFrame),
|
||||||
mPresContext(aPresContext),
|
mPresContext(aPresContext),
|
||||||
mReflowState(aReflowState),
|
mReflowState(aReflowState),
|
||||||
mNeedResizeReflow(PR_FALSE),
|
|
||||||
mIsInlineIncrReflow(PR_FALSE),
|
|
||||||
mIsTopMarginRoot(PR_FALSE),
|
|
||||||
mIsBottomMarginRoot(PR_FALSE),
|
|
||||||
mApplyTopMargin(PR_FALSE),
|
|
||||||
mNextRCFrame(nsnull),
|
mNextRCFrame(nsnull),
|
||||||
mPrevBottomMargin(0),
|
mPrevBottomMargin(0),
|
||||||
mLineNumber(0)
|
mLineNumber(0),
|
||||||
|
mFlags(0)
|
||||||
{
|
{
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
|
||||||
if (aBlockMarginRoot) {
|
if (aBlockMarginRoot) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.top) {
|
if (0 != aReflowState.mComputedBorderPadding.top) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (mIsTopMarginRoot) {
|
if (GetFlag(BRS_ISTOPMARGINROOT)) {
|
||||||
mApplyTopMargin = PR_TRUE;
|
SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSpaceManager = aReflowState.mSpaceManager;
|
mSpaceManager = aReflowState.mSpaceManager;
|
||||||
|
@ -617,21 +635,19 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Compute content area width (the content area is inside the border
|
// Compute content area width (the content area is inside the border
|
||||||
// and padding)
|
// and padding)
|
||||||
mUnconstrainedWidth = PR_FALSE;
|
|
||||||
mShrinkWrapWidth = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
||||||
mContentArea.width = aReflowState.mComputedWidth;
|
mContentArea.width = aReflowState.mComputedWidth;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
||||||
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
||||||
mUnconstrainedWidth = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
||||||
// Choose a width based on the content (shrink wrap width) up
|
// Choose a width based on the content (shrink wrap width) up
|
||||||
// to the maximum width
|
// to the maximum width
|
||||||
mContentArea.width = aReflowState.mComputedMaxWidth;
|
mContentArea.width = aReflowState.mComputedMaxWidth;
|
||||||
mShrinkWrapWidth = PR_TRUE;
|
SetFlag(BRS_SHRINKWRAPWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nscoord lr = borderPadding.left + borderPadding.right;
|
nscoord lr = borderPadding.left + borderPadding.right;
|
||||||
|
@ -646,7 +662,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
// specified style height then we may end up limiting our height if
|
// specified style height then we may end up limiting our height if
|
||||||
// the availableHeight is constrained (this situation occurs when we
|
// the availableHeight is constrained (this situation occurs when we
|
||||||
// are paginated).
|
// are paginated).
|
||||||
mUnconstrainedHeight = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
||||||
// We are in a paginated situation. The bottom edge is just inside
|
// We are in a paginated situation. The bottom edge is just inside
|
||||||
// the bottom border and padding. The content area height doesn't
|
// the bottom border and padding. The content area height doesn't
|
||||||
|
@ -657,7 +672,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
else {
|
else {
|
||||||
// When we are not in a paginated situation then we always use
|
// When we are not in a paginated situation then we always use
|
||||||
// an constrained height.
|
// an constrained height.
|
||||||
mUnconstrainedHeight = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE);
|
||||||
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,16 +689,17 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
switch (styleText->mWhiteSpace) {
|
switch (styleText->mWhiteSpace) {
|
||||||
case NS_STYLE_WHITESPACE_PRE:
|
case NS_STYLE_WHITESPACE_PRE:
|
||||||
case NS_STYLE_WHITESPACE_NOWRAP:
|
case NS_STYLE_WHITESPACE_NOWRAP:
|
||||||
mNoWrap = PR_TRUE;
|
SetFlag(BRS_NOWRAP, PR_TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mNoWrap = PR_FALSE;
|
SetFlag(BRS_NOWRAP, PR_FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mComputeMaxElementSize = nsnull != aMetrics.maxElementSize;
|
SetFlag(BRS_COMPUTEMAXELEMENTSIZE, (nsnull != aMetrics.maxElementSize));
|
||||||
mMaxElementSize.SizeTo(0, 0);
|
mMaxElementSize.SizeTo(0, 0);
|
||||||
mComputeMaximumWidth = NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH);
|
SetFlag(BRS_COMPUTEMAXWIDTH,
|
||||||
|
(NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH)));
|
||||||
mMaximumWidth = 0;
|
mMaximumWidth = 0;
|
||||||
|
|
||||||
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
||||||
|
@ -729,8 +745,12 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
const nsStyleDisplay* aDisplay,
|
const nsStyleDisplay* aDisplay,
|
||||||
nsRect& aResult)
|
nsRect& aResult)
|
||||||
{
|
{
|
||||||
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
|
printf("CBAS frame=%p has floater count %d\n", aFrame, mBand.GetFloaterCount());
|
||||||
|
mBand.List();
|
||||||
|
#endif
|
||||||
aResult.y = mY;
|
aResult.y = mY;
|
||||||
aResult.height = mUnconstrainedHeight
|
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mBottomEdge - mY;
|
: mBottomEdge - mY;
|
||||||
|
|
||||||
|
@ -749,7 +769,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// The child block will flow around the floater. Therefore
|
// The child block will flow around the floater. Therefore
|
||||||
// give it all of the available space.
|
// give it all of the available space.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
break;
|
break;
|
||||||
|
@ -776,7 +796,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine width
|
// determine width
|
||||||
if (mUnconstrainedWidth) {
|
if (GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -810,7 +830,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// doesn't matter therefore give the block element all of the
|
// doesn't matter therefore give the block element all of the
|
||||||
// available space since it will flow around the floater itself.
|
// available space since it will flow around the floater itself.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
}
|
}
|
||||||
|
@ -957,12 +977,12 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
|
||||||
#endif
|
#endif
|
||||||
mKidXMost = xmost;
|
mKidXMost = xmost;
|
||||||
}
|
}
|
||||||
if (mComputeMaxElementSize) {
|
if (GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If computing the maximum width, then update mMaximumWidth
|
// If computing the maximum width, then update mMaximumWidth
|
||||||
if (mComputeMaximumWidth) {
|
if (GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
UpdateMaximumWidth(aLine->mMaximumWidth);
|
UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,6 +1474,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
||||||
NS_BLOCK_MARGIN_ROOT & mState);
|
NS_BLOCK_MARGIN_ROOT & mState);
|
||||||
|
PRInt32 sizeofBRS = sizeof nsBlockReflowState;
|
||||||
|
|
||||||
if (eReflowReason_Resize != aReflowState.reason) {
|
if (eReflowReason_Resize != aReflowState.reason) {
|
||||||
RenumberLists(aPresContext);
|
RenumberLists(aPresContext);
|
||||||
|
@ -1462,7 +1483,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
PRBool isStyleChange = PR_FALSE;
|
PRBool isStyleChange = PR_FALSE;
|
||||||
state.mIsInlineIncrReflow = PR_FALSE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_FALSE);
|
||||||
nsIFrame* target;
|
nsIFrame* target;
|
||||||
switch (aReflowState.reason) {
|
switch (aReflowState.reason) {
|
||||||
case eReflowReason_Initial:
|
case eReflowReason_Initial:
|
||||||
|
@ -1535,7 +1556,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// reflow the line containing the target of the incr. reflow
|
// reflow the line containing the target of the incr. reflow
|
||||||
// first mark the line dirty and set up the state object
|
// first mark the line dirty and set up the state object
|
||||||
rv = PrepareChildIncrementalReflow(state);
|
rv = PrepareChildIncrementalReflow(state);
|
||||||
state.mIsInlineIncrReflow = PR_TRUE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_TRUE);
|
||||||
state.mPrevLine = prevLine;
|
state.mPrevLine = prevLine;
|
||||||
state.mCurrentLine = line;
|
state.mCurrentLine = line;
|
||||||
state.mNextRCFrame = state.mNextRCFrame;
|
state.mNextRCFrame = state.mNextRCFrame;
|
||||||
|
@ -1681,6 +1702,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
if (isStyleChange) {
|
if (isStyleChange) {
|
||||||
// Lots of things could have changed so damage our entire
|
// Lots of things could have changed so damage our entire
|
||||||
// bounds
|
// bounds
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 1 (%d, %d, %d, %d)\n",
|
||||||
|
this, 0, 0, mRect.width, mRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -1707,6 +1732,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = 0;
|
damageRect.y = 0;
|
||||||
damageRect.height = mRect.height;
|
damageRect.height = mRect.height;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 2 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1730,6 +1759,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = mRect.height - border.bottom;
|
damageRect.y = mRect.height - border.bottom;
|
||||||
damageRect.height = border.bottom;
|
damageRect.height = border.bottom;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 3 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1868,7 +1901,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
||||||
aState.mY, aState.mIsBottomMarginRoot ? "yes" : "no",
|
aState.mY, aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? "yes" : "no",
|
||||||
aState.mPrevBottomMargin,
|
aState.mPrevBottomMargin,
|
||||||
borderPadding.top, borderPadding.bottom);
|
borderPadding.top, borderPadding.bottom);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1946,7 +1979,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// contents or we fluff out to the maximum block width. Note:
|
// contents or we fluff out to the maximum block width. Note:
|
||||||
// We always shrink wrap when given an unconstrained width.
|
// We always shrink wrap when given an unconstrained width.
|
||||||
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
||||||
!aState.mUnconstrainedWidth && !aState.mShrinkWrapWidth &&
|
!aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) &&
|
||||||
!compact) {
|
!compact) {
|
||||||
// Set our width to the max width if we aren't already that
|
// Set our width to the max width if we aren't already that
|
||||||
// wide. Note that the max-width has nothing to do with our
|
// wide. Note that the max-width has nothing to do with our
|
||||||
|
@ -1956,9 +1989,9 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we should compute our max element size
|
// See if we should compute our max element size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Adjust the computedWidth
|
// Adjust the computedWidth
|
||||||
if (aState.mNoWrap) {
|
if (aState.GetFlag(BRS_NOWRAP)) {
|
||||||
// When no-wrap is true the max-element-size.width is the
|
// When no-wrap is true the max-element-size.width is the
|
||||||
// width of the widest line plus the right border. Note that
|
// width of the widest line plus the right border. Note that
|
||||||
// aState.mKidXMost already has the left border factored in
|
// aState.mKidXMost already has the left border factored in
|
||||||
|
@ -1996,7 +2029,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// need to do horizontal alignment of the inline lines and make sure
|
// need to do horizontal alignment of the inline lines and make sure
|
||||||
// blocks are correctly sized and positioned. Any lines that need
|
// blocks are correctly sized and positioned. Any lines that need
|
||||||
// final adjustment will have been marked as dirty
|
// final adjustment will have been marked as dirty
|
||||||
if (aState.mShrinkWrapWidth && aState.mNeedResizeReflow) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) {
|
||||||
// If the parent reflow state is also shrink wrap width, then
|
// If the parent reflow state is also shrink wrap width, then
|
||||||
// we don't need to do this, because it will reflow us after it
|
// we don't need to do this, because it will reflow us after it
|
||||||
// calculates the final width
|
// calculates the final width
|
||||||
|
@ -2025,7 +2058,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
||||||
if (aReflowState.parentReflowState) {
|
if (aReflowState.parentReflowState) {
|
||||||
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
||||||
|
@ -2047,7 +2080,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// Don't carry out a bottom margin when our height is fixed
|
// Don't carry out a bottom margin when our height is fixed
|
||||||
// unless the bottom of the last line adjoins the bottom of our
|
// unless the bottom of the last line adjoins the bottom of our
|
||||||
// content area.
|
// content area.
|
||||||
if (!aState.mIsBottomMarginRoot) {
|
if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
||||||
aState.mPrevBottomMargin = 0;
|
aState.mPrevBottomMargin = 0;
|
||||||
}
|
}
|
||||||
|
@ -2057,7 +2090,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
nscoord autoHeight = aState.mY;
|
nscoord autoHeight = aState.mY;
|
||||||
|
|
||||||
// Shrink wrap our height around our contents.
|
// Shrink wrap our height around our contents.
|
||||||
if (aState.mIsBottomMarginRoot) {
|
if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
// When we are a bottom-margin root make sure that our last
|
// When we are a bottom-margin root make sure that our last
|
||||||
// childs bottom margin is fully applied.
|
// childs bottom margin is fully applied.
|
||||||
// XXX check for a fit
|
// XXX check for a fit
|
||||||
|
@ -2082,7 +2115,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
aMetrics.height = autoHeight;
|
aMetrics.height = autoHeight;
|
||||||
|
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxHeight = aState.mMaxElementSize.height +
|
maxHeight = aState.mMaxElementSize.height +
|
||||||
borderPadding.top + borderPadding.bottom;
|
borderPadding.top + borderPadding.bottom;
|
||||||
}
|
}
|
||||||
|
@ -2090,7 +2123,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
aMetrics.ascent = aMetrics.height;
|
aMetrics.ascent = aMetrics.height;
|
||||||
aMetrics.descent = 0;
|
aMetrics.descent = 0;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Store away the final value
|
// Store away the final value
|
||||||
aMetrics.maxElementSize->width = maxWidth;
|
aMetrics.maxElementSize->width = maxWidth;
|
||||||
aMetrics.maxElementSize->height = maxHeight;
|
aMetrics.maxElementSize->height = maxHeight;
|
||||||
|
@ -2098,14 +2131,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Return bottom margin information
|
// Return bottom margin information
|
||||||
aMetrics.mCarriedOutBottomMargin =
|
aMetrics.mCarriedOutBottomMargin =
|
||||||
aState.mIsBottomMarginRoot ? 0 : aState.mPrevBottomMargin;
|
aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
||||||
}
|
}
|
||||||
if (aState.mComputeMaxElementSize &&
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) &&
|
||||||
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
||||||
|
@ -2115,7 +2148,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
printf("PASS1 ");
|
printf("PASS1 ");
|
||||||
|
@ -2130,7 +2163,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're requested to update our maximum width, then compute it
|
// If we're requested to update our maximum width, then compute it
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
// We need to add in for the right border/padding
|
// We need to add in for the right border/padding
|
||||||
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
||||||
}
|
}
|
||||||
|
@ -2337,8 +2370,13 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
// See if we can try and avoid marking all the lines as dirty
|
// See if we can try and avoid marking all the lines as dirty
|
||||||
PRBool tryAndSkipLines = PR_FALSE;
|
PRBool tryAndSkipLines = PR_FALSE;
|
||||||
|
|
||||||
// See if this is this a constrained resize reflow
|
// we need to calculate if any part of then block itself
|
||||||
if ((aState.mReflowState.reason == eReflowReason_Resize) &&
|
// is impacted by a floater (bug 19579)
|
||||||
|
aState.GetAvailableSpace();
|
||||||
|
|
||||||
|
// See if this is this a constrained resize reflow that is not impacted by floaters
|
||||||
|
if ((PR_FALSE==aState.IsImpactedByFloater()) &&
|
||||||
|
(aState.mReflowState.reason == eReflowReason_Resize) &&
|
||||||
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
||||||
|
|
||||||
// If the text is left-aligned, then we try and avoid reflowing the lines
|
// If the text is left-aligned, then we try and avoid reflowing the lines
|
||||||
|
@ -2389,7 +2427,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRBool notWrapping = aState.mNoWrap;
|
PRBool notWrapping = aState.GetFlag(BRS_NOWRAP);
|
||||||
while (nsnull != line) {
|
while (nsnull != line) {
|
||||||
|
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
|
@ -2402,8 +2440,6 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
||||||
line, line->IsImpactedByFloater() ? "" : "not ");
|
line, line->IsImpactedByFloater() ? "" : "not ");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (notWrapping) {
|
if (notWrapping) {
|
||||||
// When no-wrap is set then the only line-breaking that
|
// When no-wrap is set then the only line-breaking that
|
||||||
// occurs for inline lines is triggered by BR elements or by
|
// occurs for inline lines is triggered by BR elements or by
|
||||||
|
@ -2430,7 +2466,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
||||||
line, line->mNext,
|
line, line->mNext,
|
||||||
line->IsBlock() ? "block" : "inline",
|
line->IsBlock() ? "block" : "inline",
|
||||||
aState.mNoWrap ? "no-wrap" : "wrapping",
|
aState.GetFlag(BRS_NOWRAP) ? "no-wrap" : "wrapping",
|
||||||
line->HasBreak() ? "has-break " : "",
|
line->HasBreak() ? "has-break " : "",
|
||||||
line->HasFloaters() ? "has-floaters " : "",
|
line->HasFloaters() ? "has-floaters " : "",
|
||||||
line->IsImpactedByFloater() ? "impacted " : "",
|
line->IsImpactedByFloater() ? "impacted " : "",
|
||||||
|
@ -2628,7 +2664,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
||||||
kReflowCommandType[type], type,
|
kReflowCommandType[type], type,
|
||||||
aState.mIsInlineIncrReflow ? "true" : "false");
|
aState.GetFlag(BRS_ISINLINEINCRREFLOW) ? "true" : "false");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
IndentBy(stdout, gNoiseIndent);
|
IndentBy(stdout, gNoiseIndent);
|
||||||
|
@ -2651,7 +2687,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// Reflow the lines that are already ours
|
// Reflow the lines that are already ours
|
||||||
aState.mPrevLine = nsnull;
|
aState.mPrevLine = nsnull;
|
||||||
nsLineBox* line = mLines;
|
nsLineBox* line = mLines;
|
||||||
if (aState.mIsInlineIncrReflow && aState.mNextRCFrame)
|
if (aState.GetFlag(BRS_ISINLINEINCRREFLOW) && aState.mNextRCFrame)
|
||||||
{
|
{
|
||||||
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
||||||
aState.mCurrentLine = line;
|
aState.mCurrentLine = line;
|
||||||
|
@ -2662,6 +2698,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 4 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
aState.mPrevLine = line;
|
aState.mPrevLine = line;
|
||||||
|
@ -2689,7 +2729,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// If we're supposed to update our maximum width, then we'll also need to
|
// If we're supposed to update our maximum width, then we'll also need to
|
||||||
// reflow this line if it's line wrapped and any of the continuing lines
|
// reflow this line if it's line wrapped and any of the continuing lines
|
||||||
// are dirty
|
// are dirty
|
||||||
if (line->IsDirty() || (aState.mComputeMaximumWidth && ::WrappedLinesAreDirty(line))) {
|
if (line->IsDirty() || (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && ::WrappedLinesAreDirty(line))) {
|
||||||
// Compute the dirty lines "before" YMost, after factoring in
|
// Compute the dirty lines "before" YMost, after factoring in
|
||||||
// the running deltaY value - the running value is implicit in
|
// the running deltaY value - the running value is implicit in
|
||||||
// aState.mY.
|
// aState.mY.
|
||||||
|
@ -2729,6 +2769,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 5 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2902,6 +2946,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// XXX We need to improve on this...
|
// XXX We need to improve on this...
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 6 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -2918,6 +2966,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.x;
|
dirtyRect.x;
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
||||||
lineCombinedArea.height);
|
lineCombinedArea.height);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 7 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
if (oldCombinedArea.height != lineCombinedArea.height) {
|
if (oldCombinedArea.height != lineCombinedArea.height) {
|
||||||
|
@ -2933,6 +2985,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
||||||
lineCombinedArea.YMost()) -
|
lineCombinedArea.YMost()) -
|
||||||
dirtyRect.y;
|
dirtyRect.y;
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 8 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2951,21 +3007,21 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// we'll either need to recover the floater state that applies to the
|
// we'll either need to recover the floater state that applies to the
|
||||||
// unconstrained reflow or keep it around in a separate space manager...
|
// unconstrained reflow or keep it around in a separate space manager...
|
||||||
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
||||||
if (aState.mComputeMaximumWidth && isBeginningLine) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && isBeginningLine) {
|
||||||
nscoord oldY = aState.mY;
|
nscoord oldY = aState.mY;
|
||||||
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
||||||
PRBool oldUnconstrainedWidth = aState.mUnconstrainedWidth;
|
PRBool oldUnconstrainedWidth = aState.GetFlag(BRS_UNCONSTRAINEDWIDTH);
|
||||||
|
|
||||||
// First reflow the line with an unconstrained width. When doing this
|
// First reflow the line with an unconstrained width. When doing this
|
||||||
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
||||||
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
||||||
// associated floater we don't end up resetting the line's right edge and
|
// associated floater we don't end up resetting the line's right edge and
|
||||||
// have it think the width is unconstrained...
|
// have it think the width is unconstrained...
|
||||||
aState.mUnconstrainedWidth = PR_TRUE;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
||||||
aState.mY = oldY;
|
aState.mY = oldY;
|
||||||
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
||||||
aState.mUnconstrainedWidth = oldUnconstrainedWidth;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, oldUnconstrainedWidth);
|
||||||
|
|
||||||
// Update the line's maximum width
|
// Update the line's maximum width
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
|
@ -2980,14 +3036,14 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// Note: we need to reset both member variables, because the inline
|
// Note: we need to reset both member variables, because the inline
|
||||||
// code examines mComputeMaxElementSize and if there is a placeholder
|
// code examines mComputeMaxElementSize and if there is a placeholder
|
||||||
// on this line the code to reflow the floater looks at both...
|
// on this line the code to reflow the floater looks at both...
|
||||||
nscoord oldComputeMaxElementSize = aState.mComputeMaxElementSize;
|
nscoord oldComputeMaxElementSize = aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE);
|
||||||
nscoord oldComputeMaximumWidth = aState.mComputeMaximumWidth;
|
nscoord oldComputeMaximumWidth = aState.GetFlag(BRS_COMPUTEMAXWIDTH);
|
||||||
|
|
||||||
aState.mComputeMaxElementSize = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, PR_FALSE);
|
||||||
aState.mComputeMaximumWidth = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, PR_FALSE);
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
aState.mComputeMaxElementSize = oldComputeMaxElementSize;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, oldComputeMaxElementSize);
|
||||||
aState.mComputeMaximumWidth = oldComputeMaximumWidth;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, oldComputeMaximumWidth);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
|
@ -3001,6 +3057,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
|
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 9 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3368,7 +3428,7 @@ PRBool
|
||||||
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
nsLineBox* aLine)
|
nsLineBox* aLine)
|
||||||
{
|
{
|
||||||
if (aState.mApplyTopMargin) {
|
if (aState.GetFlag(BRS_APPLYTOPMARGIN)) {
|
||||||
// Apply short-circuit check to avoid searching the line list
|
// Apply short-circuit check to avoid searching the line list
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -3377,7 +3437,7 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
// If we aren't at the top Y coordinate then something of non-zero
|
// If we aren't at the top Y coordinate then something of non-zero
|
||||||
// height must have been placed. Therefore the childs top-margin
|
// height must have been placed. Therefore the childs top-margin
|
||||||
// applies.
|
// applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3387,13 +3447,13 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
// A line which preceeds aLine contains a block; therefore the
|
// A line which preceeds aLine contains a block; therefore the
|
||||||
// top margin applies.
|
// top margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else if (line->HasFloaters()) {
|
else if (line->HasFloaters()) {
|
||||||
// A line which preceeds aLine is not empty therefore the top
|
// A line which preceeds aLine is not empty therefore the top
|
||||||
// margin applies.
|
// margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
line = line->mNext;
|
line = line->mNext;
|
||||||
|
@ -3486,8 +3546,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
frame->GetStyleData(eStyleStruct_Display,
|
frame->GetStyleData(eStyleStruct_Display,
|
||||||
(const nsStyleStruct*&) display);
|
(const nsStyleStruct*&) display);
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// See if we should apply the top margin. If the block frame being
|
// See if we should apply the top margin. If the block frame being
|
||||||
|
@ -3611,14 +3671,14 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
&collapsedBottomMargin,
|
&collapsedBottomMargin,
|
||||||
aLine->mBounds, combinedArea);
|
aLine->mBounds, combinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line as block so once we known the final shrink wrap width
|
// Mark the line as block so once we known the final shrink wrap width
|
||||||
// we can reflow the block to the correct size
|
// we can reflow the block to the correct size
|
||||||
// XXX We don't always need to do this...
|
// XXX We don't always need to do this...
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (aState.mUnconstrainedWidth || aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Add the right margin to the line's bounnds. That way it will be taken into
|
// Add the right margin to the line's bounnds. That way it will be taken into
|
||||||
// account when we compute our shrink wrap size
|
// account when we compute our shrink wrap size
|
||||||
nscoord marginRight = brc.GetMargin().right;
|
nscoord marginRight = brc.GetMargin().right;
|
||||||
|
@ -3709,7 +3769,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Post-process the "line"
|
// Post-process the "line"
|
||||||
nsSize maxElementSize(0, 0);
|
nsSize maxElementSize(0, 0);
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxElementSize = brc.GetMaxElementSize();
|
maxElementSize = brc.GetMaxElementSize();
|
||||||
if (aState.IsImpactedByFloater() &&
|
if (aState.IsImpactedByFloater() &&
|
||||||
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
||||||
|
@ -3721,7 +3781,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
// If we asked the block to update its maximum width, then record the
|
// If we asked the block to update its maximum width, then record the
|
||||||
// updated value in the line, and update the current maximum width
|
// updated value in the line, and update the current maximum width
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
||||||
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
|
|
||||||
|
@ -3849,7 +3909,7 @@ nsBlockFrame::DoReflowInlineFramesMalloc(nsBlockReflowState& aState,
|
||||||
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -3872,7 +3932,7 @@ nsBlockFrame::DoReflowInlineFramesAuto(nsBlockReflowState& aState,
|
||||||
nsLineLayout lineLayout(aState.mPresContext,
|
nsLineLayout lineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
||||||
lineLayout.SetReflowTextRuns(mTextRuns);
|
lineLayout.SetReflowTextRuns(mTextRuns);
|
||||||
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
||||||
|
@ -3910,7 +3970,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
||||||
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
||||||
nscoord availWidth = aState.mAvailSpaceRect.width;
|
nscoord availWidth = aState.mAvailSpaceRect.width;
|
||||||
nscoord availHeight;
|
nscoord availHeight;
|
||||||
if (aState.mUnconstrainedHeight) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
|
||||||
availHeight = NS_UNCONSTRAINEDSIZE;
|
availHeight = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4359,7 +4419,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
nsSize maxElementSize;
|
nsSize maxElementSize;
|
||||||
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
||||||
// See if we're shrink wrapping the width
|
// See if we're shrink wrapping the width
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// When determining the line's width we also need to include any
|
// When determining the line's width we also need to include any
|
||||||
// right floaters that impact us. This represents the shrink wrap
|
// right floaters that impact us. This represents the shrink wrap
|
||||||
// width of the line
|
// width of the line
|
||||||
|
@ -4388,25 +4448,20 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// Only block frames horizontally align their children because
|
// Only block frames horizontally align their children because
|
||||||
// inline frames "shrink-wrap" around their children (therefore
|
// inline frames "shrink-wrap" around their children (therefore
|
||||||
// there is no extra horizontal space).
|
// there is no extra horizontal space).
|
||||||
#if XXX_fix_me
|
const nsStyleText* styleText = (const nsStyleText*)
|
||||||
PRBool allowJustify = PR_TRUE;
|
mStyleContext->GetStyleData(eStyleStruct_Text);
|
||||||
if (NS_STYLE_TEXT_ALIGN_JUSTIFY == aState.mStyleText->mTextAlign) {
|
PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign
|
||||||
allowJustify = ShouldJustifyLine(aState, aLine);
|
&& !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine);
|
||||||
}
|
PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
||||||
#else
|
aState.GetFlag(BRS_SHRINKWRAPWIDTH));
|
||||||
PRBool allowJustify = PR_FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PRBool successful;
|
|
||||||
nsRect combinedArea;
|
|
||||||
successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
|
||||||
aState.mShrinkWrapWidth);
|
|
||||||
if (!successful) {
|
if (!successful) {
|
||||||
// Mark the line dirty and then later once we've determined the width
|
// Mark the line dirty and then later once we've determined the width
|
||||||
// we can do the horizontal alignment
|
// we can do the horizontal alignment
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsRect combinedArea;
|
||||||
aLineLayout.RelativePositionFrames(combinedArea);
|
aLineLayout.RelativePositionFrames(combinedArea);
|
||||||
aLine->SetCombinedArea(combinedArea);
|
aLine->SetCombinedArea(combinedArea);
|
||||||
if (addedBullet) {
|
if (addedBullet) {
|
||||||
|
@ -4454,7 +4509,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
aState.mY = newY;
|
aState.mY = newY;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
|
@ -4478,7 +4533,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// we don't want updated...
|
// we don't want updated...
|
||||||
if (aUpdateMaximumWidth) {
|
if (aUpdateMaximumWidth) {
|
||||||
// However, we do need to update the max-element-size if requested
|
// However, we do need to update the max-element-size if requested
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(maxElementSize);
|
aState.UpdateMaxElementSize(maxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4519,7 +4574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mHaveRightFloaters &&
|
if (aState.mHaveRightFloaters &&
|
||||||
(aState.mUnconstrainedWidth || aState.mShrinkWrapWidth)) {
|
(aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// We are reflowing in an unconstrained situation or shrink wrapping and
|
// We are reflowing in an unconstrained situation or shrink wrapping and
|
||||||
// have some right floaters. They were placed at the infinite right edge
|
// have some right floaters. They were placed at the infinite right edge
|
||||||
// which will cause the combined area to be unusable.
|
// which will cause the combined area to be unusable.
|
||||||
|
@ -4540,11 +4595,11 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
||||||
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line dirty so we come back and re-place the floater once
|
// Mark the line dirty so we come back and re-place the floater once
|
||||||
// the shrink wrap width is determined
|
// the shrink wrap width is determined
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aLine->SetCombinedArea(lineCombinedArea);
|
aLine->SetCombinedArea(lineCombinedArea);
|
||||||
|
@ -4629,7 +4684,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update max-element-size
|
// Update max-element-size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(aMaxElementSize);
|
aState.UpdateMaxElementSize(aMaxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4639,7 +4694,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
// If this is an unconstrained reflow, then cache the line width in the
|
// If this is an unconstrained reflow, then cache the line width in the
|
||||||
// line. We'll need this during incremental reflow if we're asked to
|
// line. We'll need this during incremental reflow if we're asked to
|
||||||
// calculate the maximum width
|
// calculate the maximum width
|
||||||
if (aState.mUnconstrainedWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4653,7 +4708,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
#endif
|
#endif
|
||||||
// If we're shrink wrapping our width and the line was wrapped,
|
// If we're shrink wrapping our width and the line was wrapped,
|
||||||
// then make sure we take up all of the available width
|
// then make sure we take up all of the available width
|
||||||
if (aState.mShrinkWrapWidth && aLine->IsLineWrapped()) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aLine->IsLineWrapped()) {
|
||||||
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5187,6 +5242,10 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
||||||
// cases...
|
// cases...
|
||||||
nsRect lineCombinedArea;
|
nsRect lineCombinedArea;
|
||||||
line->GetCombinedArea(&lineCombinedArea);
|
line->GetCombinedArea(&lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 10 (%d, %d, %d, %d)\n",
|
||||||
|
this, lineCombinedArea.x, lineCombinedArea.y, lineCombinedArea.width, lineCombinedArea.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, lineCombinedArea);
|
Invalidate(aPresContext, lineCombinedArea);
|
||||||
line->Destroy(presShell);
|
line->Destroy(presShell);
|
||||||
line = next;
|
line = next;
|
||||||
|
@ -5282,8 +5341,8 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Setup block reflow state to reflow the floater
|
// Setup block reflow state to reflow the floater
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// Reflow the floater
|
// Reflow the floater
|
||||||
|
@ -5324,7 +5383,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||||
|
|
||||||
// If we computed it, then stash away the max-element-size for later
|
// If we computed it, then stash away the max-element-size for later
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5389,7 +5448,7 @@ nsBlockReflowState::AddFloater(nsLineLayout& aLineLayout,
|
||||||
// Pass on updated available space to the current inline reflow engine
|
// Pass on updated available space to the current inline reflow engine
|
||||||
GetAvailableSpace();
|
GetAvailableSpace();
|
||||||
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
||||||
mUnconstrainedWidth ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
GetFlag(BRS_UNCONSTRAINEDWIDTH) ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
||||||
mAvailSpaceRect.height,
|
mAvailSpaceRect.height,
|
||||||
isLeftFloater,
|
isLeftFloater,
|
||||||
aPlaceholder->GetOutOfFlowFrame());
|
aPlaceholder->GetOutOfFlowFrame());
|
||||||
|
@ -5615,7 +5674,12 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isLeftFloater = PR_FALSE;
|
isLeftFloater = PR_FALSE;
|
||||||
region.x = mAvailSpaceRect.XMost() - region.width;
|
if (NS_UNCONSTRAINEDSIZE != mAvailSpaceRect.XMost())
|
||||||
|
region.x = mAvailSpaceRect.XMost() - region.width;
|
||||||
|
else {
|
||||||
|
okToAddRectRegion = PR_FALSE;
|
||||||
|
region.x = mAvailSpaceRect.x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*aIsLeftFloater = isLeftFloater;
|
*aIsLeftFloater = isLeftFloater;
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
@ -5682,7 +5746,8 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
||||||
combinedArea.x += x;
|
combinedArea.x += x;
|
||||||
combinedArea.y += y;
|
combinedArea.y += y;
|
||||||
if (!isLeftFloater && (mUnconstrainedWidth || mShrinkWrapWidth)) {
|
if (!isLeftFloater &&
|
||||||
|
(GetFlag(BRS_UNCONSTRAINEDWIDTH) || GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// When we are placing a right floater in an unconstrained situation or
|
// When we are placing a right floater in an unconstrained situation or
|
||||||
// when shrink wrapping, we don't apply it to the floater combined area
|
// when shrink wrapping, we don't apply it to the floater combined area
|
||||||
// immediately. Otherwise we end up with an infinitely wide combined
|
// immediately. Otherwise we end up with an infinitely wide combined
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Steve Clark <buster@netscape.com>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
*/
|
*/
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
@ -61,6 +63,8 @@
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
//#define NOISY_BLOCK_INVALIDATE // DO NOT CHECK THIS IN TURNED ON!
|
||||||
|
|
||||||
static PRBool gLamePaintMetrics;
|
static PRBool gLamePaintMetrics;
|
||||||
static PRBool gLameReflowMetrics;
|
static PRBool gLameReflowMetrics;
|
||||||
static PRBool gNoisy;
|
static PRBool gNoisy;
|
||||||
|
@ -451,12 +455,6 @@ public:
|
||||||
|
|
||||||
nscoord mBottomEdge;
|
nscoord mBottomEdge;
|
||||||
|
|
||||||
PRPackedBool mUnconstrainedWidth;
|
|
||||||
PRPackedBool mUnconstrainedHeight;
|
|
||||||
PRPackedBool mShrinkWrapWidth;
|
|
||||||
PRPackedBool mNeedResizeReflow;
|
|
||||||
PRPackedBool mIsInlineIncrReflow;
|
|
||||||
|
|
||||||
// The content area to reflow child frames within. The x/y
|
// The content area to reflow child frames within. The x/y
|
||||||
// coordinates are known to be mBorderPadding.left and
|
// coordinates are known to be mBorderPadding.left and
|
||||||
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
||||||
|
@ -464,15 +462,6 @@ public:
|
||||||
// unconstrained area.
|
// unconstrained area.
|
||||||
nsSize mContentArea;
|
nsSize mContentArea;
|
||||||
|
|
||||||
// Our wrapping behavior
|
|
||||||
PRPackedBool mNoWrap;
|
|
||||||
|
|
||||||
// Is this frame a root for top/bottom margin collapsing?
|
|
||||||
PRPackedBool mIsTopMarginRoot, mIsBottomMarginRoot;
|
|
||||||
|
|
||||||
// See ShouldApplyTopMargin
|
|
||||||
PRPackedBool mApplyTopMargin;
|
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
// This state is "running" state updated by the reflow of each line
|
// This state is "running" state updated by the reflow of each line
|
||||||
|
@ -541,15 +530,48 @@ public:
|
||||||
// being N^2.
|
// being N^2.
|
||||||
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
||||||
|
|
||||||
PRPackedBool mComputeMaxElementSize;
|
|
||||||
PRPackedBool mComputeMaximumWidth;
|
|
||||||
|
|
||||||
nsSize mMaxElementSize;
|
nsSize mMaxElementSize;
|
||||||
nscoord mMaximumWidth;
|
nscoord mMaximumWidth;
|
||||||
|
|
||||||
nscoord mMinLineHeight;
|
nscoord mMinLineHeight;
|
||||||
|
|
||||||
PRInt32 mLineNumber;
|
PRInt32 mLineNumber;
|
||||||
|
|
||||||
|
// block reflow state flags
|
||||||
|
#define BRS_UNCONSTRAINEDWIDTH 0x00000001
|
||||||
|
#define BRS_UNCONSTRAINEDHEIGHT 0x00000002
|
||||||
|
#define BRS_SHRINKWRAPWIDTH 0x00000004
|
||||||
|
#define BRS_NEEDRESIZEREFLOW 0x00000008
|
||||||
|
#define BRS_ISINLINEINCRREFLOW 0x00000010
|
||||||
|
#define BRS_NOWRAP 0x00000020
|
||||||
|
#define BRS_ISTOPMARGINROOT 0x00000040 // Is this frame a root for top/bottom margin collapsing?
|
||||||
|
#define BRS_ISBOTTOMMARGINROOT 0x00000080
|
||||||
|
#define BRS_APPLYTOPMARGIN 0x00000100 // See ShouldApplyTopMargin
|
||||||
|
#define BRS_COMPUTEMAXELEMENTSIZE 0x00000200
|
||||||
|
#define BRS_COMPUTEMAXWIDTH 0x00000400
|
||||||
|
#define BRS_LASTFLAG BRS_COMPUTEMAXWIDTH
|
||||||
|
|
||||||
|
PRInt16 mFlags;
|
||||||
|
|
||||||
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
|
||||||
|
if (aValue) { // set flag
|
||||||
|
mFlags |= aFlag;
|
||||||
|
}
|
||||||
|
else { // unset flag
|
||||||
|
mFlags &= ~aFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GetFlag(PRUint32 aFlag) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
PRBool result = (mFlags & aFlag);
|
||||||
|
if (result) return PR_TRUE;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX This is vile. Make it go away
|
// XXX This is vile. Make it go away
|
||||||
|
@ -574,29 +596,25 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
: mBlock(aFrame),
|
: mBlock(aFrame),
|
||||||
mPresContext(aPresContext),
|
mPresContext(aPresContext),
|
||||||
mReflowState(aReflowState),
|
mReflowState(aReflowState),
|
||||||
mNeedResizeReflow(PR_FALSE),
|
|
||||||
mIsInlineIncrReflow(PR_FALSE),
|
|
||||||
mIsTopMarginRoot(PR_FALSE),
|
|
||||||
mIsBottomMarginRoot(PR_FALSE),
|
|
||||||
mApplyTopMargin(PR_FALSE),
|
|
||||||
mNextRCFrame(nsnull),
|
mNextRCFrame(nsnull),
|
||||||
mPrevBottomMargin(0),
|
mPrevBottomMargin(0),
|
||||||
mLineNumber(0)
|
mLineNumber(0),
|
||||||
|
mFlags(0)
|
||||||
{
|
{
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
|
||||||
if (aBlockMarginRoot) {
|
if (aBlockMarginRoot) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.top) {
|
if (0 != aReflowState.mComputedBorderPadding.top) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (mIsTopMarginRoot) {
|
if (GetFlag(BRS_ISTOPMARGINROOT)) {
|
||||||
mApplyTopMargin = PR_TRUE;
|
SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSpaceManager = aReflowState.mSpaceManager;
|
mSpaceManager = aReflowState.mSpaceManager;
|
||||||
|
@ -617,21 +635,19 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Compute content area width (the content area is inside the border
|
// Compute content area width (the content area is inside the border
|
||||||
// and padding)
|
// and padding)
|
||||||
mUnconstrainedWidth = PR_FALSE;
|
|
||||||
mShrinkWrapWidth = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
||||||
mContentArea.width = aReflowState.mComputedWidth;
|
mContentArea.width = aReflowState.mComputedWidth;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
||||||
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
||||||
mUnconstrainedWidth = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
||||||
// Choose a width based on the content (shrink wrap width) up
|
// Choose a width based on the content (shrink wrap width) up
|
||||||
// to the maximum width
|
// to the maximum width
|
||||||
mContentArea.width = aReflowState.mComputedMaxWidth;
|
mContentArea.width = aReflowState.mComputedMaxWidth;
|
||||||
mShrinkWrapWidth = PR_TRUE;
|
SetFlag(BRS_SHRINKWRAPWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nscoord lr = borderPadding.left + borderPadding.right;
|
nscoord lr = borderPadding.left + borderPadding.right;
|
||||||
|
@ -646,7 +662,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
// specified style height then we may end up limiting our height if
|
// specified style height then we may end up limiting our height if
|
||||||
// the availableHeight is constrained (this situation occurs when we
|
// the availableHeight is constrained (this situation occurs when we
|
||||||
// are paginated).
|
// are paginated).
|
||||||
mUnconstrainedHeight = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
||||||
// We are in a paginated situation. The bottom edge is just inside
|
// We are in a paginated situation. The bottom edge is just inside
|
||||||
// the bottom border and padding. The content area height doesn't
|
// the bottom border and padding. The content area height doesn't
|
||||||
|
@ -657,7 +672,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
else {
|
else {
|
||||||
// When we are not in a paginated situation then we always use
|
// When we are not in a paginated situation then we always use
|
||||||
// an constrained height.
|
// an constrained height.
|
||||||
mUnconstrainedHeight = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE);
|
||||||
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,16 +689,17 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
switch (styleText->mWhiteSpace) {
|
switch (styleText->mWhiteSpace) {
|
||||||
case NS_STYLE_WHITESPACE_PRE:
|
case NS_STYLE_WHITESPACE_PRE:
|
||||||
case NS_STYLE_WHITESPACE_NOWRAP:
|
case NS_STYLE_WHITESPACE_NOWRAP:
|
||||||
mNoWrap = PR_TRUE;
|
SetFlag(BRS_NOWRAP, PR_TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mNoWrap = PR_FALSE;
|
SetFlag(BRS_NOWRAP, PR_FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mComputeMaxElementSize = nsnull != aMetrics.maxElementSize;
|
SetFlag(BRS_COMPUTEMAXELEMENTSIZE, (nsnull != aMetrics.maxElementSize));
|
||||||
mMaxElementSize.SizeTo(0, 0);
|
mMaxElementSize.SizeTo(0, 0);
|
||||||
mComputeMaximumWidth = NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH);
|
SetFlag(BRS_COMPUTEMAXWIDTH,
|
||||||
|
(NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH)));
|
||||||
mMaximumWidth = 0;
|
mMaximumWidth = 0;
|
||||||
|
|
||||||
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
||||||
|
@ -729,8 +745,12 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
const nsStyleDisplay* aDisplay,
|
const nsStyleDisplay* aDisplay,
|
||||||
nsRect& aResult)
|
nsRect& aResult)
|
||||||
{
|
{
|
||||||
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
|
printf("CBAS frame=%p has floater count %d\n", aFrame, mBand.GetFloaterCount());
|
||||||
|
mBand.List();
|
||||||
|
#endif
|
||||||
aResult.y = mY;
|
aResult.y = mY;
|
||||||
aResult.height = mUnconstrainedHeight
|
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mBottomEdge - mY;
|
: mBottomEdge - mY;
|
||||||
|
|
||||||
|
@ -749,7 +769,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// The child block will flow around the floater. Therefore
|
// The child block will flow around the floater. Therefore
|
||||||
// give it all of the available space.
|
// give it all of the available space.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
break;
|
break;
|
||||||
|
@ -776,7 +796,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine width
|
// determine width
|
||||||
if (mUnconstrainedWidth) {
|
if (GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -810,7 +830,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// doesn't matter therefore give the block element all of the
|
// doesn't matter therefore give the block element all of the
|
||||||
// available space since it will flow around the floater itself.
|
// available space since it will flow around the floater itself.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
}
|
}
|
||||||
|
@ -957,12 +977,12 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
|
||||||
#endif
|
#endif
|
||||||
mKidXMost = xmost;
|
mKidXMost = xmost;
|
||||||
}
|
}
|
||||||
if (mComputeMaxElementSize) {
|
if (GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If computing the maximum width, then update mMaximumWidth
|
// If computing the maximum width, then update mMaximumWidth
|
||||||
if (mComputeMaximumWidth) {
|
if (GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
UpdateMaximumWidth(aLine->mMaximumWidth);
|
UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,6 +1474,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
||||||
NS_BLOCK_MARGIN_ROOT & mState);
|
NS_BLOCK_MARGIN_ROOT & mState);
|
||||||
|
PRInt32 sizeofBRS = sizeof nsBlockReflowState;
|
||||||
|
|
||||||
if (eReflowReason_Resize != aReflowState.reason) {
|
if (eReflowReason_Resize != aReflowState.reason) {
|
||||||
RenumberLists(aPresContext);
|
RenumberLists(aPresContext);
|
||||||
|
@ -1462,7 +1483,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
PRBool isStyleChange = PR_FALSE;
|
PRBool isStyleChange = PR_FALSE;
|
||||||
state.mIsInlineIncrReflow = PR_FALSE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_FALSE);
|
||||||
nsIFrame* target;
|
nsIFrame* target;
|
||||||
switch (aReflowState.reason) {
|
switch (aReflowState.reason) {
|
||||||
case eReflowReason_Initial:
|
case eReflowReason_Initial:
|
||||||
|
@ -1535,7 +1556,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// reflow the line containing the target of the incr. reflow
|
// reflow the line containing the target of the incr. reflow
|
||||||
// first mark the line dirty and set up the state object
|
// first mark the line dirty and set up the state object
|
||||||
rv = PrepareChildIncrementalReflow(state);
|
rv = PrepareChildIncrementalReflow(state);
|
||||||
state.mIsInlineIncrReflow = PR_TRUE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_TRUE);
|
||||||
state.mPrevLine = prevLine;
|
state.mPrevLine = prevLine;
|
||||||
state.mCurrentLine = line;
|
state.mCurrentLine = line;
|
||||||
state.mNextRCFrame = state.mNextRCFrame;
|
state.mNextRCFrame = state.mNextRCFrame;
|
||||||
|
@ -1681,6 +1702,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
if (isStyleChange) {
|
if (isStyleChange) {
|
||||||
// Lots of things could have changed so damage our entire
|
// Lots of things could have changed so damage our entire
|
||||||
// bounds
|
// bounds
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 1 (%d, %d, %d, %d)\n",
|
||||||
|
this, 0, 0, mRect.width, mRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -1707,6 +1732,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = 0;
|
damageRect.y = 0;
|
||||||
damageRect.height = mRect.height;
|
damageRect.height = mRect.height;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 2 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1730,6 +1759,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = mRect.height - border.bottom;
|
damageRect.y = mRect.height - border.bottom;
|
||||||
damageRect.height = border.bottom;
|
damageRect.height = border.bottom;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 3 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1868,7 +1901,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
||||||
aState.mY, aState.mIsBottomMarginRoot ? "yes" : "no",
|
aState.mY, aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? "yes" : "no",
|
||||||
aState.mPrevBottomMargin,
|
aState.mPrevBottomMargin,
|
||||||
borderPadding.top, borderPadding.bottom);
|
borderPadding.top, borderPadding.bottom);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1946,7 +1979,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// contents or we fluff out to the maximum block width. Note:
|
// contents or we fluff out to the maximum block width. Note:
|
||||||
// We always shrink wrap when given an unconstrained width.
|
// We always shrink wrap when given an unconstrained width.
|
||||||
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
||||||
!aState.mUnconstrainedWidth && !aState.mShrinkWrapWidth &&
|
!aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) &&
|
||||||
!compact) {
|
!compact) {
|
||||||
// Set our width to the max width if we aren't already that
|
// Set our width to the max width if we aren't already that
|
||||||
// wide. Note that the max-width has nothing to do with our
|
// wide. Note that the max-width has nothing to do with our
|
||||||
|
@ -1956,9 +1989,9 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we should compute our max element size
|
// See if we should compute our max element size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Adjust the computedWidth
|
// Adjust the computedWidth
|
||||||
if (aState.mNoWrap) {
|
if (aState.GetFlag(BRS_NOWRAP)) {
|
||||||
// When no-wrap is true the max-element-size.width is the
|
// When no-wrap is true the max-element-size.width is the
|
||||||
// width of the widest line plus the right border. Note that
|
// width of the widest line plus the right border. Note that
|
||||||
// aState.mKidXMost already has the left border factored in
|
// aState.mKidXMost already has the left border factored in
|
||||||
|
@ -1996,7 +2029,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// need to do horizontal alignment of the inline lines and make sure
|
// need to do horizontal alignment of the inline lines and make sure
|
||||||
// blocks are correctly sized and positioned. Any lines that need
|
// blocks are correctly sized and positioned. Any lines that need
|
||||||
// final adjustment will have been marked as dirty
|
// final adjustment will have been marked as dirty
|
||||||
if (aState.mShrinkWrapWidth && aState.mNeedResizeReflow) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) {
|
||||||
// If the parent reflow state is also shrink wrap width, then
|
// If the parent reflow state is also shrink wrap width, then
|
||||||
// we don't need to do this, because it will reflow us after it
|
// we don't need to do this, because it will reflow us after it
|
||||||
// calculates the final width
|
// calculates the final width
|
||||||
|
@ -2025,7 +2058,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
||||||
if (aReflowState.parentReflowState) {
|
if (aReflowState.parentReflowState) {
|
||||||
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
||||||
|
@ -2047,7 +2080,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// Don't carry out a bottom margin when our height is fixed
|
// Don't carry out a bottom margin when our height is fixed
|
||||||
// unless the bottom of the last line adjoins the bottom of our
|
// unless the bottom of the last line adjoins the bottom of our
|
||||||
// content area.
|
// content area.
|
||||||
if (!aState.mIsBottomMarginRoot) {
|
if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
||||||
aState.mPrevBottomMargin = 0;
|
aState.mPrevBottomMargin = 0;
|
||||||
}
|
}
|
||||||
|
@ -2057,7 +2090,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
nscoord autoHeight = aState.mY;
|
nscoord autoHeight = aState.mY;
|
||||||
|
|
||||||
// Shrink wrap our height around our contents.
|
// Shrink wrap our height around our contents.
|
||||||
if (aState.mIsBottomMarginRoot) {
|
if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
// When we are a bottom-margin root make sure that our last
|
// When we are a bottom-margin root make sure that our last
|
||||||
// childs bottom margin is fully applied.
|
// childs bottom margin is fully applied.
|
||||||
// XXX check for a fit
|
// XXX check for a fit
|
||||||
|
@ -2082,7 +2115,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
aMetrics.height = autoHeight;
|
aMetrics.height = autoHeight;
|
||||||
|
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxHeight = aState.mMaxElementSize.height +
|
maxHeight = aState.mMaxElementSize.height +
|
||||||
borderPadding.top + borderPadding.bottom;
|
borderPadding.top + borderPadding.bottom;
|
||||||
}
|
}
|
||||||
|
@ -2090,7 +2123,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
aMetrics.ascent = aMetrics.height;
|
aMetrics.ascent = aMetrics.height;
|
||||||
aMetrics.descent = 0;
|
aMetrics.descent = 0;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Store away the final value
|
// Store away the final value
|
||||||
aMetrics.maxElementSize->width = maxWidth;
|
aMetrics.maxElementSize->width = maxWidth;
|
||||||
aMetrics.maxElementSize->height = maxHeight;
|
aMetrics.maxElementSize->height = maxHeight;
|
||||||
|
@ -2098,14 +2131,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Return bottom margin information
|
// Return bottom margin information
|
||||||
aMetrics.mCarriedOutBottomMargin =
|
aMetrics.mCarriedOutBottomMargin =
|
||||||
aState.mIsBottomMarginRoot ? 0 : aState.mPrevBottomMargin;
|
aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
||||||
}
|
}
|
||||||
if (aState.mComputeMaxElementSize &&
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) &&
|
||||||
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
||||||
|
@ -2115,7 +2148,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
printf("PASS1 ");
|
printf("PASS1 ");
|
||||||
|
@ -2130,7 +2163,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're requested to update our maximum width, then compute it
|
// If we're requested to update our maximum width, then compute it
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
// We need to add in for the right border/padding
|
// We need to add in for the right border/padding
|
||||||
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
||||||
}
|
}
|
||||||
|
@ -2337,8 +2370,13 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
// See if we can try and avoid marking all the lines as dirty
|
// See if we can try and avoid marking all the lines as dirty
|
||||||
PRBool tryAndSkipLines = PR_FALSE;
|
PRBool tryAndSkipLines = PR_FALSE;
|
||||||
|
|
||||||
// See if this is this a constrained resize reflow
|
// we need to calculate if any part of then block itself
|
||||||
if ((aState.mReflowState.reason == eReflowReason_Resize) &&
|
// is impacted by a floater (bug 19579)
|
||||||
|
aState.GetAvailableSpace();
|
||||||
|
|
||||||
|
// See if this is this a constrained resize reflow that is not impacted by floaters
|
||||||
|
if ((PR_FALSE==aState.IsImpactedByFloater()) &&
|
||||||
|
(aState.mReflowState.reason == eReflowReason_Resize) &&
|
||||||
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
||||||
|
|
||||||
// If the text is left-aligned, then we try and avoid reflowing the lines
|
// If the text is left-aligned, then we try and avoid reflowing the lines
|
||||||
|
@ -2389,7 +2427,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRBool notWrapping = aState.mNoWrap;
|
PRBool notWrapping = aState.GetFlag(BRS_NOWRAP);
|
||||||
while (nsnull != line) {
|
while (nsnull != line) {
|
||||||
|
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
|
@ -2402,8 +2440,6 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
||||||
line, line->IsImpactedByFloater() ? "" : "not ");
|
line, line->IsImpactedByFloater() ? "" : "not ");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (notWrapping) {
|
if (notWrapping) {
|
||||||
// When no-wrap is set then the only line-breaking that
|
// When no-wrap is set then the only line-breaking that
|
||||||
// occurs for inline lines is triggered by BR elements or by
|
// occurs for inline lines is triggered by BR elements or by
|
||||||
|
@ -2430,7 +2466,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
||||||
line, line->mNext,
|
line, line->mNext,
|
||||||
line->IsBlock() ? "block" : "inline",
|
line->IsBlock() ? "block" : "inline",
|
||||||
aState.mNoWrap ? "no-wrap" : "wrapping",
|
aState.GetFlag(BRS_NOWRAP) ? "no-wrap" : "wrapping",
|
||||||
line->HasBreak() ? "has-break " : "",
|
line->HasBreak() ? "has-break " : "",
|
||||||
line->HasFloaters() ? "has-floaters " : "",
|
line->HasFloaters() ? "has-floaters " : "",
|
||||||
line->IsImpactedByFloater() ? "impacted " : "",
|
line->IsImpactedByFloater() ? "impacted " : "",
|
||||||
|
@ -2628,7 +2664,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
||||||
kReflowCommandType[type], type,
|
kReflowCommandType[type], type,
|
||||||
aState.mIsInlineIncrReflow ? "true" : "false");
|
aState.GetFlag(BRS_ISINLINEINCRREFLOW) ? "true" : "false");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
IndentBy(stdout, gNoiseIndent);
|
IndentBy(stdout, gNoiseIndent);
|
||||||
|
@ -2651,7 +2687,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// Reflow the lines that are already ours
|
// Reflow the lines that are already ours
|
||||||
aState.mPrevLine = nsnull;
|
aState.mPrevLine = nsnull;
|
||||||
nsLineBox* line = mLines;
|
nsLineBox* line = mLines;
|
||||||
if (aState.mIsInlineIncrReflow && aState.mNextRCFrame)
|
if (aState.GetFlag(BRS_ISINLINEINCRREFLOW) && aState.mNextRCFrame)
|
||||||
{
|
{
|
||||||
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
||||||
aState.mCurrentLine = line;
|
aState.mCurrentLine = line;
|
||||||
|
@ -2662,6 +2698,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 4 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
aState.mPrevLine = line;
|
aState.mPrevLine = line;
|
||||||
|
@ -2689,7 +2729,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// If we're supposed to update our maximum width, then we'll also need to
|
// If we're supposed to update our maximum width, then we'll also need to
|
||||||
// reflow this line if it's line wrapped and any of the continuing lines
|
// reflow this line if it's line wrapped and any of the continuing lines
|
||||||
// are dirty
|
// are dirty
|
||||||
if (line->IsDirty() || (aState.mComputeMaximumWidth && ::WrappedLinesAreDirty(line))) {
|
if (line->IsDirty() || (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && ::WrappedLinesAreDirty(line))) {
|
||||||
// Compute the dirty lines "before" YMost, after factoring in
|
// Compute the dirty lines "before" YMost, after factoring in
|
||||||
// the running deltaY value - the running value is implicit in
|
// the running deltaY value - the running value is implicit in
|
||||||
// aState.mY.
|
// aState.mY.
|
||||||
|
@ -2729,6 +2769,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 5 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2902,6 +2946,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// XXX We need to improve on this...
|
// XXX We need to improve on this...
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 6 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -2918,6 +2966,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.x;
|
dirtyRect.x;
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
||||||
lineCombinedArea.height);
|
lineCombinedArea.height);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 7 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
if (oldCombinedArea.height != lineCombinedArea.height) {
|
if (oldCombinedArea.height != lineCombinedArea.height) {
|
||||||
|
@ -2933,6 +2985,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
||||||
lineCombinedArea.YMost()) -
|
lineCombinedArea.YMost()) -
|
||||||
dirtyRect.y;
|
dirtyRect.y;
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 8 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2951,21 +3007,21 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// we'll either need to recover the floater state that applies to the
|
// we'll either need to recover the floater state that applies to the
|
||||||
// unconstrained reflow or keep it around in a separate space manager...
|
// unconstrained reflow or keep it around in a separate space manager...
|
||||||
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
||||||
if (aState.mComputeMaximumWidth && isBeginningLine) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && isBeginningLine) {
|
||||||
nscoord oldY = aState.mY;
|
nscoord oldY = aState.mY;
|
||||||
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
||||||
PRBool oldUnconstrainedWidth = aState.mUnconstrainedWidth;
|
PRBool oldUnconstrainedWidth = aState.GetFlag(BRS_UNCONSTRAINEDWIDTH);
|
||||||
|
|
||||||
// First reflow the line with an unconstrained width. When doing this
|
// First reflow the line with an unconstrained width. When doing this
|
||||||
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
||||||
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
||||||
// associated floater we don't end up resetting the line's right edge and
|
// associated floater we don't end up resetting the line's right edge and
|
||||||
// have it think the width is unconstrained...
|
// have it think the width is unconstrained...
|
||||||
aState.mUnconstrainedWidth = PR_TRUE;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
||||||
aState.mY = oldY;
|
aState.mY = oldY;
|
||||||
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
||||||
aState.mUnconstrainedWidth = oldUnconstrainedWidth;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, oldUnconstrainedWidth);
|
||||||
|
|
||||||
// Update the line's maximum width
|
// Update the line's maximum width
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
|
@ -2980,14 +3036,14 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// Note: we need to reset both member variables, because the inline
|
// Note: we need to reset both member variables, because the inline
|
||||||
// code examines mComputeMaxElementSize and if there is a placeholder
|
// code examines mComputeMaxElementSize and if there is a placeholder
|
||||||
// on this line the code to reflow the floater looks at both...
|
// on this line the code to reflow the floater looks at both...
|
||||||
nscoord oldComputeMaxElementSize = aState.mComputeMaxElementSize;
|
nscoord oldComputeMaxElementSize = aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE);
|
||||||
nscoord oldComputeMaximumWidth = aState.mComputeMaximumWidth;
|
nscoord oldComputeMaximumWidth = aState.GetFlag(BRS_COMPUTEMAXWIDTH);
|
||||||
|
|
||||||
aState.mComputeMaxElementSize = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, PR_FALSE);
|
||||||
aState.mComputeMaximumWidth = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, PR_FALSE);
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
aState.mComputeMaxElementSize = oldComputeMaxElementSize;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, oldComputeMaxElementSize);
|
||||||
aState.mComputeMaximumWidth = oldComputeMaximumWidth;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, oldComputeMaximumWidth);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
|
@ -3001,6 +3057,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
|
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 9 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3368,7 +3428,7 @@ PRBool
|
||||||
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
nsLineBox* aLine)
|
nsLineBox* aLine)
|
||||||
{
|
{
|
||||||
if (aState.mApplyTopMargin) {
|
if (aState.GetFlag(BRS_APPLYTOPMARGIN)) {
|
||||||
// Apply short-circuit check to avoid searching the line list
|
// Apply short-circuit check to avoid searching the line list
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -3377,7 +3437,7 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
// If we aren't at the top Y coordinate then something of non-zero
|
// If we aren't at the top Y coordinate then something of non-zero
|
||||||
// height must have been placed. Therefore the childs top-margin
|
// height must have been placed. Therefore the childs top-margin
|
||||||
// applies.
|
// applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3387,13 +3447,13 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
// A line which preceeds aLine contains a block; therefore the
|
// A line which preceeds aLine contains a block; therefore the
|
||||||
// top margin applies.
|
// top margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else if (line->HasFloaters()) {
|
else if (line->HasFloaters()) {
|
||||||
// A line which preceeds aLine is not empty therefore the top
|
// A line which preceeds aLine is not empty therefore the top
|
||||||
// margin applies.
|
// margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
line = line->mNext;
|
line = line->mNext;
|
||||||
|
@ -3486,8 +3546,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
frame->GetStyleData(eStyleStruct_Display,
|
frame->GetStyleData(eStyleStruct_Display,
|
||||||
(const nsStyleStruct*&) display);
|
(const nsStyleStruct*&) display);
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// See if we should apply the top margin. If the block frame being
|
// See if we should apply the top margin. If the block frame being
|
||||||
|
@ -3611,14 +3671,14 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
&collapsedBottomMargin,
|
&collapsedBottomMargin,
|
||||||
aLine->mBounds, combinedArea);
|
aLine->mBounds, combinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line as block so once we known the final shrink wrap width
|
// Mark the line as block so once we known the final shrink wrap width
|
||||||
// we can reflow the block to the correct size
|
// we can reflow the block to the correct size
|
||||||
// XXX We don't always need to do this...
|
// XXX We don't always need to do this...
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (aState.mUnconstrainedWidth || aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Add the right margin to the line's bounnds. That way it will be taken into
|
// Add the right margin to the line's bounnds. That way it will be taken into
|
||||||
// account when we compute our shrink wrap size
|
// account when we compute our shrink wrap size
|
||||||
nscoord marginRight = brc.GetMargin().right;
|
nscoord marginRight = brc.GetMargin().right;
|
||||||
|
@ -3709,7 +3769,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Post-process the "line"
|
// Post-process the "line"
|
||||||
nsSize maxElementSize(0, 0);
|
nsSize maxElementSize(0, 0);
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxElementSize = brc.GetMaxElementSize();
|
maxElementSize = brc.GetMaxElementSize();
|
||||||
if (aState.IsImpactedByFloater() &&
|
if (aState.IsImpactedByFloater() &&
|
||||||
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
||||||
|
@ -3721,7 +3781,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
// If we asked the block to update its maximum width, then record the
|
// If we asked the block to update its maximum width, then record the
|
||||||
// updated value in the line, and update the current maximum width
|
// updated value in the line, and update the current maximum width
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
||||||
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
|
|
||||||
|
@ -3849,7 +3909,7 @@ nsBlockFrame::DoReflowInlineFramesMalloc(nsBlockReflowState& aState,
|
||||||
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -3872,7 +3932,7 @@ nsBlockFrame::DoReflowInlineFramesAuto(nsBlockReflowState& aState,
|
||||||
nsLineLayout lineLayout(aState.mPresContext,
|
nsLineLayout lineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
||||||
lineLayout.SetReflowTextRuns(mTextRuns);
|
lineLayout.SetReflowTextRuns(mTextRuns);
|
||||||
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
||||||
|
@ -3910,7 +3970,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
||||||
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
||||||
nscoord availWidth = aState.mAvailSpaceRect.width;
|
nscoord availWidth = aState.mAvailSpaceRect.width;
|
||||||
nscoord availHeight;
|
nscoord availHeight;
|
||||||
if (aState.mUnconstrainedHeight) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
|
||||||
availHeight = NS_UNCONSTRAINEDSIZE;
|
availHeight = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4359,7 +4419,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
nsSize maxElementSize;
|
nsSize maxElementSize;
|
||||||
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
||||||
// See if we're shrink wrapping the width
|
// See if we're shrink wrapping the width
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// When determining the line's width we also need to include any
|
// When determining the line's width we also need to include any
|
||||||
// right floaters that impact us. This represents the shrink wrap
|
// right floaters that impact us. This represents the shrink wrap
|
||||||
// width of the line
|
// width of the line
|
||||||
|
@ -4388,25 +4448,20 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// Only block frames horizontally align their children because
|
// Only block frames horizontally align their children because
|
||||||
// inline frames "shrink-wrap" around their children (therefore
|
// inline frames "shrink-wrap" around their children (therefore
|
||||||
// there is no extra horizontal space).
|
// there is no extra horizontal space).
|
||||||
#if XXX_fix_me
|
const nsStyleText* styleText = (const nsStyleText*)
|
||||||
PRBool allowJustify = PR_TRUE;
|
mStyleContext->GetStyleData(eStyleStruct_Text);
|
||||||
if (NS_STYLE_TEXT_ALIGN_JUSTIFY == aState.mStyleText->mTextAlign) {
|
PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign
|
||||||
allowJustify = ShouldJustifyLine(aState, aLine);
|
&& !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine);
|
||||||
}
|
PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
||||||
#else
|
aState.GetFlag(BRS_SHRINKWRAPWIDTH));
|
||||||
PRBool allowJustify = PR_FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PRBool successful;
|
|
||||||
nsRect combinedArea;
|
|
||||||
successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
|
||||||
aState.mShrinkWrapWidth);
|
|
||||||
if (!successful) {
|
if (!successful) {
|
||||||
// Mark the line dirty and then later once we've determined the width
|
// Mark the line dirty and then later once we've determined the width
|
||||||
// we can do the horizontal alignment
|
// we can do the horizontal alignment
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsRect combinedArea;
|
||||||
aLineLayout.RelativePositionFrames(combinedArea);
|
aLineLayout.RelativePositionFrames(combinedArea);
|
||||||
aLine->SetCombinedArea(combinedArea);
|
aLine->SetCombinedArea(combinedArea);
|
||||||
if (addedBullet) {
|
if (addedBullet) {
|
||||||
|
@ -4454,7 +4509,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
aState.mY = newY;
|
aState.mY = newY;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
|
@ -4478,7 +4533,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// we don't want updated...
|
// we don't want updated...
|
||||||
if (aUpdateMaximumWidth) {
|
if (aUpdateMaximumWidth) {
|
||||||
// However, we do need to update the max-element-size if requested
|
// However, we do need to update the max-element-size if requested
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(maxElementSize);
|
aState.UpdateMaxElementSize(maxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4519,7 +4574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mHaveRightFloaters &&
|
if (aState.mHaveRightFloaters &&
|
||||||
(aState.mUnconstrainedWidth || aState.mShrinkWrapWidth)) {
|
(aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// We are reflowing in an unconstrained situation or shrink wrapping and
|
// We are reflowing in an unconstrained situation or shrink wrapping and
|
||||||
// have some right floaters. They were placed at the infinite right edge
|
// have some right floaters. They were placed at the infinite right edge
|
||||||
// which will cause the combined area to be unusable.
|
// which will cause the combined area to be unusable.
|
||||||
|
@ -4540,11 +4595,11 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
||||||
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line dirty so we come back and re-place the floater once
|
// Mark the line dirty so we come back and re-place the floater once
|
||||||
// the shrink wrap width is determined
|
// the shrink wrap width is determined
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aLine->SetCombinedArea(lineCombinedArea);
|
aLine->SetCombinedArea(lineCombinedArea);
|
||||||
|
@ -4629,7 +4684,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update max-element-size
|
// Update max-element-size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(aMaxElementSize);
|
aState.UpdateMaxElementSize(aMaxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4639,7 +4694,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
// If this is an unconstrained reflow, then cache the line width in the
|
// If this is an unconstrained reflow, then cache the line width in the
|
||||||
// line. We'll need this during incremental reflow if we're asked to
|
// line. We'll need this during incremental reflow if we're asked to
|
||||||
// calculate the maximum width
|
// calculate the maximum width
|
||||||
if (aState.mUnconstrainedWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4653,7 +4708,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
#endif
|
#endif
|
||||||
// If we're shrink wrapping our width and the line was wrapped,
|
// If we're shrink wrapping our width and the line was wrapped,
|
||||||
// then make sure we take up all of the available width
|
// then make sure we take up all of the available width
|
||||||
if (aState.mShrinkWrapWidth && aLine->IsLineWrapped()) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aLine->IsLineWrapped()) {
|
||||||
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5187,6 +5242,10 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
||||||
// cases...
|
// cases...
|
||||||
nsRect lineCombinedArea;
|
nsRect lineCombinedArea;
|
||||||
line->GetCombinedArea(&lineCombinedArea);
|
line->GetCombinedArea(&lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 10 (%d, %d, %d, %d)\n",
|
||||||
|
this, lineCombinedArea.x, lineCombinedArea.y, lineCombinedArea.width, lineCombinedArea.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, lineCombinedArea);
|
Invalidate(aPresContext, lineCombinedArea);
|
||||||
line->Destroy(presShell);
|
line->Destroy(presShell);
|
||||||
line = next;
|
line = next;
|
||||||
|
@ -5282,8 +5341,8 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Setup block reflow state to reflow the floater
|
// Setup block reflow state to reflow the floater
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// Reflow the floater
|
// Reflow the floater
|
||||||
|
@ -5324,7 +5383,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||||
|
|
||||||
// If we computed it, then stash away the max-element-size for later
|
// If we computed it, then stash away the max-element-size for later
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5389,7 +5448,7 @@ nsBlockReflowState::AddFloater(nsLineLayout& aLineLayout,
|
||||||
// Pass on updated available space to the current inline reflow engine
|
// Pass on updated available space to the current inline reflow engine
|
||||||
GetAvailableSpace();
|
GetAvailableSpace();
|
||||||
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
||||||
mUnconstrainedWidth ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
GetFlag(BRS_UNCONSTRAINEDWIDTH) ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
||||||
mAvailSpaceRect.height,
|
mAvailSpaceRect.height,
|
||||||
isLeftFloater,
|
isLeftFloater,
|
||||||
aPlaceholder->GetOutOfFlowFrame());
|
aPlaceholder->GetOutOfFlowFrame());
|
||||||
|
@ -5615,7 +5674,12 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isLeftFloater = PR_FALSE;
|
isLeftFloater = PR_FALSE;
|
||||||
region.x = mAvailSpaceRect.XMost() - region.width;
|
if (NS_UNCONSTRAINEDSIZE != mAvailSpaceRect.XMost())
|
||||||
|
region.x = mAvailSpaceRect.XMost() - region.width;
|
||||||
|
else {
|
||||||
|
okToAddRectRegion = PR_FALSE;
|
||||||
|
region.x = mAvailSpaceRect.x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*aIsLeftFloater = isLeftFloater;
|
*aIsLeftFloater = isLeftFloater;
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
@ -5682,7 +5746,8 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
||||||
combinedArea.x += x;
|
combinedArea.x += x;
|
||||||
combinedArea.y += y;
|
combinedArea.y += y;
|
||||||
if (!isLeftFloater && (mUnconstrainedWidth || mShrinkWrapWidth)) {
|
if (!isLeftFloater &&
|
||||||
|
(GetFlag(BRS_UNCONSTRAINEDWIDTH) || GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// When we are placing a right floater in an unconstrained situation or
|
// When we are placing a right floater in an unconstrained situation or
|
||||||
// when shrink wrapping, we don't apply it to the floater combined area
|
// when shrink wrapping, we don't apply it to the floater combined area
|
||||||
// immediately. Otherwise we end up with an infinitely wide combined
|
// immediately. Otherwise we end up with an infinitely wide combined
|
||||||
|
|
|
@ -879,6 +879,13 @@ nsImageFrame::AttributeChanged(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (nsHTMLAtoms::width == aAttribute || nsHTMLAtoms::height == aAttribute)
|
||||||
|
{ // XXX: could check for new width == old width, and make that a no-op
|
||||||
|
nsCOMPtr<nsIPresShell> presShell;
|
||||||
|
aPresContext->GetShell(getter_AddRefs(presShell));
|
||||||
|
mState |= NS_FRAME_IS_DIRTY;
|
||||||
|
mParent->ReflowDirtyChild(presShell, (nsIFrame*) this);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,10 @@
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Steve Clark <buster@netscape.com>
|
||||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
* L. David Baron <dbaron@fas.harvard.edu>
|
* L. David Baron <dbaron@fas.harvard.edu>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
*/
|
*/
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsLineLayout.h"
|
#include "nsLineLayout.h"
|
||||||
|
@ -41,13 +43,14 @@
|
||||||
#include "nsIView.h"
|
#include "nsIView.h"
|
||||||
#include "nsIViewManager.h"
|
#include "nsIViewManager.h"
|
||||||
#include "nsHTMLAtoms.h"
|
#include "nsHTMLAtoms.h"
|
||||||
|
#include "nsTextFragment.h"
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#undef NOISY_HORIZONTAL_ALIGN
|
#undef NOISY_HORIZONTAL_ALIGN
|
||||||
#undef NOISY_VERTICAL_ALIGN
|
#undef NOISY_VERTICAL_ALIGN
|
||||||
#undef REALLY_NOISY_VERTICAL_ALIGN
|
#undef REALLY_NOISY_VERTICAL_ALIGN
|
||||||
#undef NOISY_REFLOW
|
#undef NOISY_REFLOW
|
||||||
#undef REALLY_NOISY_REFLOW
|
#undef REALLY_NOISY_REFLOW
|
||||||
#undef NOISY_PUSHING
|
#undef NOISY_PUSHING
|
||||||
#undef REALLY_NOISY_PUSHING
|
#undef REALLY_NOISY_PUSHING
|
||||||
#undef DEBUG_ADD_TEXT
|
#undef DEBUG_ADD_TEXT
|
||||||
|
@ -120,15 +123,9 @@ nsLineLayout::nsLineLayout(nsIPresContext* aPresContext,
|
||||||
mTextAlign = mStyleText->mTextAlign;
|
mTextAlign = mStyleText->mTextAlign;
|
||||||
mLineNumber = 0;
|
mLineNumber = 0;
|
||||||
mColumn = 0;
|
mColumn = 0;
|
||||||
mEndsInWhiteSpace = PR_TRUE;
|
mFlags = 0; // default all flags to false except those that follow here...
|
||||||
mUnderstandsWhiteSpace = PR_FALSE;
|
SetFlag(LL_ENDSINWHITESPACE, PR_TRUE);
|
||||||
mTextStartsWithNBSP = PR_FALSE;
|
|
||||||
mFirstLetterStyleOK = PR_FALSE;
|
|
||||||
mIsTopOfPage = PR_FALSE;
|
|
||||||
mUpdatedBand = PR_FALSE;
|
|
||||||
mPlacedFloaters = 0;
|
mPlacedFloaters = 0;
|
||||||
mImpactedByFloaters = PR_FALSE;
|
|
||||||
mLastFloaterWasLetterFrame = PR_FALSE;
|
|
||||||
mTotalPlacedFrames = 0;
|
mTotalPlacedFrames = 0;
|
||||||
mTopEdge = mBottomEdge = 0;
|
mTopEdge = mBottomEdge = 0;
|
||||||
mReflowTextRuns = nsnull;
|
mReflowTextRuns = nsnull;
|
||||||
|
@ -148,14 +145,17 @@ nsLineLayout::nsLineLayout(nsIPresContext* aPresContext,
|
||||||
mTextRuns = nsnull;
|
mTextRuns = nsnull;
|
||||||
mTextRunP = &mTextRuns;
|
mTextRunP = &mTextRuns;
|
||||||
mNewTextRun = nsnull;
|
mNewTextRun = nsnull;
|
||||||
mKnowStrictMode = PR_FALSE;
|
SetFlag(LL_KNOWSTRICTMODE, PR_FALSE);
|
||||||
|
PRInt32 size = sizeof nsLineLayout;
|
||||||
|
PRInt32 size_pfd = sizeof PerFrameData;
|
||||||
|
PRInt32 size_psd = sizeof PerSpanData;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsLineLayout::nsLineLayout(nsIPresContext* aPresContext)
|
nsLineLayout::nsLineLayout(nsIPresContext* aPresContext)
|
||||||
: mPresContext(aPresContext)
|
: mPresContext(aPresContext)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsLineLayout);
|
MOZ_COUNT_CTOR(nsLineLayout);
|
||||||
|
|
||||||
mTextRuns = nsnull;
|
mTextRuns = nsnull;
|
||||||
mTextRunP = &mTextRuns;
|
mTextRunP = &mTextRuns;
|
||||||
mNewTextRun = nsnull;
|
mNewTextRun = nsnull;
|
||||||
|
@ -197,9 +197,9 @@ nsLineLayout::~nsLineLayout()
|
||||||
PRBool
|
PRBool
|
||||||
nsLineLayout::InStrictMode()
|
nsLineLayout::InStrictMode()
|
||||||
{
|
{
|
||||||
if (!mKnowStrictMode) {
|
if (!GetFlag(LL_KNOWSTRICTMODE)) {
|
||||||
mKnowStrictMode = PR_TRUE;
|
SetFlag(LL_KNOWSTRICTMODE, PR_TRUE);
|
||||||
mInStrictMode = PR_TRUE;
|
SetFlag(LL_INSTRICTMODE, PR_TRUE);
|
||||||
|
|
||||||
// Get the compatabilty mode from pres context via the document and pres shell
|
// Get the compatabilty mode from pres context via the document and pres shell
|
||||||
if (mBlockReflowState->frame) {
|
if (mBlockReflowState->frame) {
|
||||||
|
@ -217,7 +217,7 @@ nsLineLayout::InStrictMode()
|
||||||
nsCompatibility mode;
|
nsCompatibility mode;
|
||||||
presContext->GetCompatibilityMode(&mode);
|
presContext->GetCompatibilityMode(&mode);
|
||||||
if (eCompatibility_NavQuirks == mode) {
|
if (eCompatibility_NavQuirks == mode) {
|
||||||
mInStrictMode = PR_FALSE;
|
SetFlag(LL_INSTRICTMODE, PR_FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_RELEASE(shell);
|
NS_RELEASE(shell);
|
||||||
|
@ -226,7 +226,7 @@ nsLineLayout::InStrictMode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mInStrictMode;
|
return GetFlag(LL_INSTRICTMODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -235,10 +235,6 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
|
||||||
PRBool aImpactedByFloaters,
|
PRBool aImpactedByFloaters,
|
||||||
PRBool aIsTopOfPage)
|
PRBool aIsTopOfPage)
|
||||||
{
|
{
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
|
||||||
printf("nsLL::BeginLineReflow %d, %d, %d, %d, impacted=%s\n",
|
|
||||||
aX, aY, aWidth, aHeight, aImpactedByFloaters?"true":"false");
|
|
||||||
#endif
|
|
||||||
NS_ASSERTION(nsnull == mRootSpan, "bad linelayout user");
|
NS_ASSERTION(nsnull == mRootSpan, "bad linelayout user");
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if ((aWidth != NS_UNCONSTRAINEDSIZE) && CRAZY_WIDTH(aWidth)) {
|
if ((aWidth != NS_UNCONSTRAINEDSIZE) && CRAZY_WIDTH(aWidth)) {
|
||||||
|
@ -256,8 +252,9 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
|
||||||
#endif
|
#endif
|
||||||
#ifdef NOISY_REFLOW
|
#ifdef NOISY_REFLOW
|
||||||
nsFrame::ListTag(stdout, mBlockReflowState->frame);
|
nsFrame::ListTag(stdout, mBlockReflowState->frame);
|
||||||
printf(": BeginLineReflow: %d,%d,%d,%d %s\n",
|
printf(": BeginLineReflow: %d,%d,%d,%d impacted=%s %s\n",
|
||||||
aX, aY, aWidth, aHeight,
|
aX, aY, aWidth, aHeight,
|
||||||
|
aImpactedByFloaters?"true":"false",
|
||||||
aIsTopOfPage ? "top-of-page" : "");
|
aIsTopOfPage ? "top-of-page" : "");
|
||||||
#endif
|
#endif
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -265,17 +262,18 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mColumn = 0;
|
mColumn = 0;
|
||||||
mEndsInWhiteSpace = PR_TRUE;
|
|
||||||
mUnderstandsWhiteSpace = PR_FALSE;
|
SetFlag(LL_ENDSINWHITESPACE, PR_TRUE);
|
||||||
mTextStartsWithNBSP = PR_FALSE;
|
SetFlag(LL_UNDERSTANDSNWHITESPACE, PR_FALSE);
|
||||||
mFirstLetterStyleOK = PR_FALSE;
|
SetFlag(LL_TEXTSTARTSWITHNBSP, PR_FALSE);
|
||||||
mIsTopOfPage = aIsTopOfPage;
|
SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
|
||||||
mUpdatedBand = PR_FALSE;
|
SetFlag(LL_ISTOPOFPAGE, aIsTopOfPage);
|
||||||
|
SetFlag(LL_UPDATEDBAND, PR_FALSE);
|
||||||
mPlacedFloaters = 0;
|
mPlacedFloaters = 0;
|
||||||
mImpactedByFloaters = aImpactedByFloaters;
|
SetFlag(LL_IMPACTEDBYFLOATERS, aImpactedByFloaters);
|
||||||
mTotalPlacedFrames = 0;
|
mTotalPlacedFrames = 0;
|
||||||
mCanPlaceFloater = PR_TRUE;
|
SetFlag(LL_CANPLACEFLOATER, PR_TRUE);
|
||||||
mLineEndsInBR = PR_FALSE;
|
SetFlag(LL_LINEENDSINBR, PR_FALSE);
|
||||||
mSpanDepth = 0;
|
mSpanDepth = 0;
|
||||||
mMaxTopBoxHeight = mMaxBottomBoxHeight = 0;
|
mMaxTopBoxHeight = mMaxBottomBoxHeight = 0;
|
||||||
|
|
||||||
|
@ -355,7 +353,7 @@ nsLineLayout::UpdateBand(nscoord aX, nscoord aY,
|
||||||
nsIFrame* aFloaterFrame)
|
nsIFrame* aFloaterFrame)
|
||||||
{
|
{
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
printf("nsLL::UpdateBand %d, %d, %d, %d, frame=%p placedLeft=%s\n will set mImpacted to PR_TRUE",
|
printf("nsLL::UpdateBand %d, %d, %d, %d, frame=%p placedLeft=%s\n will set mImpacted to PR_TRUE\n",
|
||||||
aX, aY, aWidth, aHeight, aFloaterFrame, aPlacedLeftFloater?"true":"false");
|
aX, aY, aWidth, aHeight, aFloaterFrame, aPlacedLeftFloater?"true":"false");
|
||||||
#endif
|
#endif
|
||||||
PerSpanData* psd = mRootSpan;
|
PerSpanData* psd = mRootSpan;
|
||||||
|
@ -404,13 +402,13 @@ nsLineLayout::UpdateBand(nscoord aX, nscoord aY,
|
||||||
else {
|
else {
|
||||||
mBottomEdge = aY + aHeight;
|
mBottomEdge = aY + aHeight;
|
||||||
}
|
}
|
||||||
mUpdatedBand = PR_TRUE;
|
SetFlag(LL_UPDATEDBAND, PR_TRUE);
|
||||||
mPlacedFloaters |= (aPlacedLeftFloater ? PLACED_LEFT : PLACED_RIGHT);
|
mPlacedFloaters |= (aPlacedLeftFloater ? PLACED_LEFT : PLACED_RIGHT);
|
||||||
mImpactedByFloaters = PR_TRUE;
|
SetFlag(LL_IMPACTEDBYFLOATERS, PR_TRUE);
|
||||||
|
|
||||||
nsCOMPtr<nsIAtom> frameType;
|
nsCOMPtr<nsIAtom> frameType;
|
||||||
aFloaterFrame->GetFrameType(getter_AddRefs(frameType));
|
aFloaterFrame->GetFrameType(getter_AddRefs(frameType));
|
||||||
mLastFloaterWasLetterFrame = nsLayoutAtoms::letterFrame == frameType.get();
|
SetFlag(LL_LASTFLOATERWASLETTERFRAME, (nsLayoutAtoms::letterFrame == frameType.get()));
|
||||||
|
|
||||||
// Now update all of the open spans...
|
// Now update all of the open spans...
|
||||||
mRootSpan->mContainsFloater = PR_TRUE; // make sure mRootSpan gets updated too
|
mRootSpan->mContainsFloater = PR_TRUE; // make sure mRootSpan gets updated too
|
||||||
|
@ -762,17 +760,10 @@ nsLineLayout::NewPerFrameData(PerFrameData** aResult)
|
||||||
pfd->mNext = nsnull;
|
pfd->mNext = nsnull;
|
||||||
pfd->mPrev = nsnull;
|
pfd->mPrev = nsnull;
|
||||||
pfd->mFrame = nsnull;
|
pfd->mFrame = nsnull;
|
||||||
pfd->mRelativePos = PR_FALSE;
|
pfd->mFlags = 0; // all flags default to false
|
||||||
pfd->mIsTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsNonEmptyTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsNonWhitespaceTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsLetterFrame = PR_FALSE;
|
|
||||||
pfd->mIsSticky = PR_FALSE;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
pfd->mVerticalAlign = 0xFF;
|
pfd->mVerticalAlign = 0xFF;
|
||||||
pfd->mRelativePos = PRBool(0xFF);
|
|
||||||
mFramesAllocated++;
|
mFramesAllocated++;
|
||||||
#endif
|
#endif
|
||||||
*aResult = pfd;
|
*aResult = pfd;
|
||||||
|
@ -782,7 +773,7 @@ nsLineLayout::NewPerFrameData(PerFrameData** aResult)
|
||||||
PRBool
|
PRBool
|
||||||
nsLineLayout::CanPlaceFloaterNow() const
|
nsLineLayout::CanPlaceFloaterNow() const
|
||||||
{
|
{
|
||||||
return mCanPlaceFloater;
|
return GetFlag(LL_CANPLACEFLOATER);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
|
@ -794,7 +785,7 @@ nsLineLayout::LineIsEmpty() const
|
||||||
PRBool
|
PRBool
|
||||||
nsLineLayout::LineIsBreakable() const
|
nsLineLayout::LineIsBreakable() const
|
||||||
{
|
{
|
||||||
if ((0 != mTotalPlacedFrames) || mImpactedByFloaters) {
|
if ((0 != mTotalPlacedFrames) || GetFlag(LL_IMPACTEDBYFLOATERS)) {
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
@ -903,9 +894,11 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
nsHTMLReflowState reflowState(mPresContext, *psd->mReflowState, aFrame,
|
nsHTMLReflowState reflowState(mPresContext, *psd->mReflowState, aFrame,
|
||||||
availSize, reason);
|
availSize, reason);
|
||||||
reflowState.mLineLayout = this;
|
reflowState.mLineLayout = this;
|
||||||
reflowState.isTopOfPage = mIsTopOfPage;
|
reflowState.isTopOfPage = GetFlag(LL_ISTOPOFPAGE);
|
||||||
mUnderstandsWhiteSpace = PR_FALSE;
|
SetFlag(LL_UNDERSTANDSNWHITESPACE, PR_FALSE);
|
||||||
mTextStartsWithNBSP = PR_FALSE;
|
SetFlag(LL_TEXTSTARTSWITHNBSP, PR_FALSE);
|
||||||
|
mTextJustificationNumSpaces = 0;
|
||||||
|
mTextJustificationNumLetters = 0;
|
||||||
|
|
||||||
// Stash copies of some of the computed state away for later
|
// Stash copies of some of the computed state away for later
|
||||||
// (vertical alignment, for example)
|
// (vertical alignment, for example)
|
||||||
|
@ -913,9 +906,9 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
pfd->mMargin = reflowState.mComputedMargin;
|
pfd->mMargin = reflowState.mComputedMargin;
|
||||||
pfd->mBorderPadding = reflowState.mComputedBorderPadding;
|
pfd->mBorderPadding = reflowState.mComputedBorderPadding;
|
||||||
pfd->mFrameType = reflowState.mFrameType;
|
pfd->mFrameType = reflowState.mFrameType;
|
||||||
pfd->mRelativePos =
|
pfd->SetFlag(PFD_RELATIVEPOS,
|
||||||
reflowState.mStylePosition->mPosition == NS_STYLE_POSITION_RELATIVE;
|
(reflowState.mStylePosition->mPosition == NS_STYLE_POSITION_RELATIVE));
|
||||||
if (pfd->mRelativePos) {
|
if (pfd->GetFlag(PFD_RELATIVEPOS)) {
|
||||||
pfd->mOffsets = reflowState.mComputedOffsets;
|
pfd->mOffsets = reflowState.mComputedOffsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -969,14 +962,18 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
|
nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
|
||||||
mSpaceManager->Translate(tx, ty);
|
mSpaceManager->Translate(tx, ty);
|
||||||
|
|
||||||
pfd->mIsTextFrame = PR_FALSE;
|
pfd->SetFlag(PFD_ISTEXTFRAME, PR_FALSE);
|
||||||
pfd->mIsLetterFrame = PR_FALSE;
|
pfd->SetFlag(PFD_ISLETTERFRAME, PR_FALSE);
|
||||||
pfd->mIsNonEmptyTextFrame = PR_FALSE;
|
pfd->SetFlag(PFD_ISNONEMPTYTEXTFRAME, PR_FALSE);
|
||||||
pfd->mIsNonWhitespaceTextFrame = PR_FALSE;
|
pfd->SetFlag(PFD_ISNONWHITESPACETEXTFRAME, PR_FALSE);
|
||||||
pfd->mIsSticky = PR_FALSE;
|
pfd->SetFlag(PFD_ISSTICKY, PR_FALSE);
|
||||||
|
pfd->SetFlag(PFD_ISBULLET, PR_FALSE);
|
||||||
|
|
||||||
aFrame->Reflow(mPresContext, metrics, reflowState, aReflowStatus);
|
aFrame->Reflow(mPresContext, metrics, reflowState, aReflowStatus);
|
||||||
|
|
||||||
|
pfd->mJustificationNumSpaces = mTextJustificationNumSpaces;
|
||||||
|
pfd->mJustificationNumLetters = mTextJustificationNumLetters;
|
||||||
|
|
||||||
// XXX See if the frame is a placeholderFrame and if it is process
|
// XXX See if the frame is a placeholderFrame and if it is process
|
||||||
// the floater.
|
// the floater.
|
||||||
nsIAtom* frameType;
|
nsIAtom* frameType;
|
||||||
|
@ -1000,7 +997,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
outOfFlowFrame->GetFrameType(&oofft);
|
outOfFlowFrame->GetFrameType(&oofft);
|
||||||
if (oofft) {
|
if (oofft) {
|
||||||
if (oofft == nsLayoutAtoms::letterFrame) {
|
if (oofft == nsLayoutAtoms::letterFrame) {
|
||||||
mFirstLetterStyleOK = PR_FALSE;
|
SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
|
||||||
}
|
}
|
||||||
NS_RELEASE(oofft);
|
NS_RELEASE(oofft);
|
||||||
}
|
}
|
||||||
|
@ -1009,11 +1006,11 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
}
|
}
|
||||||
else if (frameType == nsLayoutAtoms::textFrame) {
|
else if (frameType == nsLayoutAtoms::textFrame) {
|
||||||
// Note non-empty text-frames for inline frame compatability hackery
|
// Note non-empty text-frames for inline frame compatability hackery
|
||||||
pfd->mIsTextFrame = PR_TRUE;
|
pfd->SetFlag(PFD_ISTEXTFRAME, PR_TRUE);
|
||||||
// XXX An empty text frame at the end of the line seems not
|
// XXX An empty text frame at the end of the line seems not
|
||||||
// to have zero width.
|
// to have zero width.
|
||||||
if (metrics.width) {
|
if (metrics.width) {
|
||||||
pfd->mIsNonEmptyTextFrame = PR_TRUE;
|
pfd->SetFlag(PFD_ISNONEMPTYTEXTFRAME, PR_TRUE);
|
||||||
nsCOMPtr<nsIContent> content;
|
nsCOMPtr<nsIContent> content;
|
||||||
nsresult result = pfd->mFrame->GetContent(getter_AddRefs(content));
|
nsresult result = pfd->mFrame->GetContent(getter_AddRefs(content));
|
||||||
if ((NS_SUCCEEDED(result)) && content) {
|
if ((NS_SUCCEEDED(result)) && content) {
|
||||||
|
@ -1023,14 +1020,14 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
PRBool isWhitespace;
|
PRBool isWhitespace;
|
||||||
result = textContent->IsOnlyWhitespace(&isWhitespace);
|
result = textContent->IsOnlyWhitespace(&isWhitespace);
|
||||||
if (NS_SUCCEEDED(result)) {
|
if (NS_SUCCEEDED(result)) {
|
||||||
pfd->mIsNonWhitespaceTextFrame = !isWhitespace;
|
pfd->SetFlag(PFD_ISNONWHITESPACETEXTFRAME, !isWhitespace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (frameType == nsLayoutAtoms::letterFrame) {
|
else if (frameType == nsLayoutAtoms::letterFrame) {
|
||||||
pfd->mIsLetterFrame = PR_TRUE;
|
pfd->SetFlag(PFD_ISLETTERFRAME, PR_TRUE);
|
||||||
}
|
}
|
||||||
NS_RELEASE(frameType);
|
NS_RELEASE(frameType);
|
||||||
}
|
}
|
||||||
|
@ -1170,7 +1167,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
else {
|
else {
|
||||||
PushFrame(aFrame);
|
PushFrame(aFrame);
|
||||||
}
|
}
|
||||||
mTextStartsWithNBSP = PR_FALSE; // reset for next time
|
SetFlag(LL_TEXTSTARTSWITHNBSP, PR_FALSE); // reset for next time
|
||||||
|
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
nsFrame::IndentBy(stdout, mSpanDepth);
|
nsFrame::IndentBy(stdout, mSpanDepth);
|
||||||
|
@ -1330,7 +1327,7 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
// There are no frames on the line or we are in the first word on
|
// There are no frames on the line or we are in the first word on
|
||||||
// the line. If the line isn't impacted by a floater then the
|
// the line. If the line isn't impacted by a floater then the
|
||||||
// current frame fits.
|
// current frame fits.
|
||||||
if (!mImpactedByFloaters) {
|
if (!GetFlag(LL_IMPACTEDBYFLOATERS)) {
|
||||||
#ifdef NOISY_CAN_PLACE_FRAME
|
#ifdef NOISY_CAN_PLACE_FRAME
|
||||||
printf(" ==> not-safe and not-impacted fits: ");
|
printf(" ==> not-safe and not-impacted fits: ");
|
||||||
while (nsnull != psd) {
|
while (nsnull != psd) {
|
||||||
|
@ -1341,28 +1338,28 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
#endif
|
#endif
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else if (mLastFloaterWasLetterFrame) {
|
else if (GetFlag(LL_LASTFLOATERWASLETTERFRAME)) {
|
||||||
// Another special case: see if the floater is a letter
|
// Another special case: see if the floater is a letter
|
||||||
// frame. If it is, then allow the frame next to it to fit.
|
// frame. If it is, then allow the frame next to it to fit.
|
||||||
if (pfd->mIsNonEmptyTextFrame) {
|
if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME)) {
|
||||||
// This must be the first piece of non-empty text (because
|
// This must be the first piece of non-empty text (because
|
||||||
// aNotSafeToBreak is true) or its a piece of text that is
|
// aNotSafeToBreak is true) or its a piece of text that is
|
||||||
// part of a larger word.
|
// part of a larger word.
|
||||||
pfd->mIsSticky = PR_TRUE;
|
pfd->SetFlag(PFD_ISSTICKY, PR_TRUE);
|
||||||
}
|
}
|
||||||
else if (pfd->mSpan) {
|
else if (pfd->mSpan) {
|
||||||
PerFrameData* pf = pfd->mSpan->mFirstFrame;
|
PerFrameData* pf = pfd->mSpan->mFirstFrame;
|
||||||
while (pf) {
|
while (pf) {
|
||||||
if (pf->mIsSticky) {
|
if (pf->GetFlag(PFD_ISSTICKY)) {
|
||||||
// If one of the spans children was sticky then the span
|
// If one of the spans children was sticky then the span
|
||||||
// itself is sticky.
|
// itself is sticky.
|
||||||
pfd->mIsSticky = PR_TRUE;
|
pfd->SetFlag(PFD_ISSTICKY, PR_TRUE);
|
||||||
}
|
}
|
||||||
pf = pf->mNext;
|
pf = pf->mNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pfd->mIsSticky) {
|
if (pfd->GetFlag(PFD_ISSTICKY)) {
|
||||||
#ifdef NOISY_CAN_PLACE_FRAME
|
#ifdef NOISY_CAN_PLACE_FRAME
|
||||||
printf(" ==> last floater was letter frame && frame is sticky\n");
|
printf(" ==> last floater was letter frame && frame is sticky\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -1372,8 +1369,8 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a piece of text inside a letter frame...
|
// If this is a piece of text inside a letter frame...
|
||||||
if (pfd->mIsNonEmptyTextFrame) {
|
if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME)) {
|
||||||
if (psd->mFrame && psd->mFrame->mIsLetterFrame) {
|
if (psd->mFrame && psd->mFrame->GetFlag(PFD_ISLETTERFRAME)) {
|
||||||
nsIFrame* prevInFlow;
|
nsIFrame* prevInFlow;
|
||||||
psd->mFrame->mFrame->GetPrevInFlow(&prevInFlow);
|
psd->mFrame->mFrame->GetPrevInFlow(&prevInFlow);
|
||||||
if (prevInFlow) {
|
if (prevInFlow) {
|
||||||
|
@ -1387,7 +1384,7 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pfd->mIsLetterFrame) {
|
else if (pfd->GetFlag(PFD_ISLETTERFRAME)) {
|
||||||
// If this is the first continuation of the letter frame...
|
// If this is the first continuation of the letter frame...
|
||||||
nsIFrame* prevInFlow;
|
nsIFrame* prevInFlow;
|
||||||
pfd->mFrame->GetPrevInFlow(&prevInFlow);
|
pfd->mFrame->GetPrevInFlow(&prevInFlow);
|
||||||
|
@ -1433,7 +1430,7 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
// edge...Which means that whatever piece of text we just formatted
|
// edge...Which means that whatever piece of text we just formatted
|
||||||
// will be the piece that fits (the text frame logic knows to stop
|
// will be the piece that fits (the text frame logic knows to stop
|
||||||
// when it runs out of room).
|
// when it runs out of room).
|
||||||
if (pfd->mIsNonEmptyTextFrame && mTextStartsWithNBSP) {
|
if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME) && GetFlag(LL_TEXTSTARTSWITHNBSP)) {
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1467,9 +1464,9 @@ nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics)
|
||||||
|
|
||||||
// If the band was updated during the reflow of that frame then we
|
// If the band was updated during the reflow of that frame then we
|
||||||
// need to adjust any prior frames that were reflowed.
|
// need to adjust any prior frames that were reflowed.
|
||||||
if (mUpdatedBand && InBlockContext()) {
|
if (GetFlag(LL_UPDATEDBAND) && InBlockContext()) {
|
||||||
UpdateFrames();
|
UpdateFrames();
|
||||||
mUpdatedBand = PR_FALSE;
|
SetFlag(LL_UPDATEDBAND, PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance to next X coordinate
|
// Advance to next X coordinate
|
||||||
|
@ -1478,8 +1475,8 @@ nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics)
|
||||||
// If the frame is a not aware of white-space and it takes up some
|
// If the frame is a not aware of white-space and it takes up some
|
||||||
// width, disable leading white-space compression for the next frame
|
// width, disable leading white-space compression for the next frame
|
||||||
// to be reflowed.
|
// to be reflowed.
|
||||||
if (!mUnderstandsWhiteSpace && pfd->mBounds.width) {
|
if ((!GetFlag(LL_UNDERSTANDSNWHITESPACE)) && pfd->mBounds.width) {
|
||||||
mEndsInWhiteSpace = PR_FALSE;
|
SetFlag(LL_ENDSINWHITESPACE, PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count the number of frames on the line...
|
// Count the number of frames on the line...
|
||||||
|
@ -1487,7 +1484,7 @@ nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics)
|
||||||
if (psd->mX != psd->mLeftEdge) {
|
if (psd->mX != psd->mLeftEdge) {
|
||||||
// As soon as a frame placed on the line advances an X coordinate
|
// As soon as a frame placed on the line advances an X coordinate
|
||||||
// of any span we can no longer place a floater on the line.
|
// of any span we can no longer place a floater on the line.
|
||||||
mCanPlaceFloater = PR_FALSE;
|
SetFlag(LL_CANPLACEFLOATER, PR_FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1505,14 +1502,10 @@ nsLineLayout::AddBulletFrame(nsIFrame* aFrame,
|
||||||
pfd->mMargin.SizeTo(0, 0, 0, 0);
|
pfd->mMargin.SizeTo(0, 0, 0, 0);
|
||||||
pfd->mBorderPadding.SizeTo(0, 0, 0, 0);
|
pfd->mBorderPadding.SizeTo(0, 0, 0, 0);
|
||||||
pfd->mFrameType = NS_CSS_FRAME_TYPE_INLINE|NS_FRAME_REPLACED_ELEMENT;
|
pfd->mFrameType = NS_CSS_FRAME_TYPE_INLINE|NS_FRAME_REPLACED_ELEMENT;
|
||||||
pfd->mRelativePos = PR_FALSE;
|
pfd->mFlags = 0; // all flags default to false
|
||||||
|
pfd->SetFlag(PFD_ISBULLET, PR_TRUE);
|
||||||
pfd->mAscent = aMetrics.ascent;
|
pfd->mAscent = aMetrics.ascent;
|
||||||
pfd->mDescent = aMetrics.descent;
|
pfd->mDescent = aMetrics.descent;
|
||||||
pfd->mIsTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsNonEmptyTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsNonWhitespaceTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsLetterFrame = PR_FALSE;
|
|
||||||
pfd->mIsSticky = PR_FALSE;
|
|
||||||
|
|
||||||
// Note: y value will be updated during vertical alignment
|
// Note: y value will be updated during vertical alignment
|
||||||
aFrame->GetRect(pfd->mBounds);
|
aFrame->GetRect(pfd->mBounds);
|
||||||
|
@ -1857,7 +1850,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
|
||||||
zeroEffectiveSpanBox = PR_TRUE;
|
zeroEffectiveSpanBox = PR_TRUE;
|
||||||
PerFrameData* pfd = psd->mFirstFrame;
|
PerFrameData* pfd = psd->mFirstFrame;
|
||||||
while (nsnull != pfd) {
|
while (nsnull != pfd) {
|
||||||
if (preMode?pfd->mIsTextFrame:pfd->mIsNonWhitespaceTextFrame) {
|
if (preMode?pfd->GetFlag(PFD_ISTEXTFRAME):pfd->GetFlag(PFD_ISNONWHITESPACETEXTFRAME)) {
|
||||||
zeroEffectiveSpanBox = PR_FALSE;
|
zeroEffectiveSpanBox = PR_FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2154,7 +2147,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
|
||||||
if (pfd->mVerticalAlign == VALIGN_OTHER) {
|
if (pfd->mVerticalAlign == VALIGN_OTHER) {
|
||||||
// Text frames do not contribute to the min/max Y values for the
|
// Text frames do not contribute to the min/max Y values for the
|
||||||
// line (instead their parent frame's font-size contributes).
|
// line (instead their parent frame's font-size contributes).
|
||||||
if (!pfd->mIsTextFrame) {
|
if (!pfd->GetFlag(PFD_ISTEXTFRAME)) {
|
||||||
nscoord yTop, yBottom;
|
nscoord yTop, yBottom;
|
||||||
if (frameSpan) {
|
if (frameSpan) {
|
||||||
// For spans that were are now placing, use their position
|
// For spans that were are now placing, use their position
|
||||||
|
@ -2212,7 +2205,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
|
||||||
// BR) (NN4/IE5 quirk)
|
// BR) (NN4/IE5 quirk)
|
||||||
PRBool applyMinLH = !(psd->mZeroEffectiveSpanBox); // (1) above
|
PRBool applyMinLH = !(psd->mZeroEffectiveSpanBox); // (1) above
|
||||||
PRBool isFirstLine = !mLineNumber; // if the line number is 0
|
PRBool isFirstLine = !mLineNumber; // if the line number is 0
|
||||||
PRBool isLastLine = (!mLineBox->IsLineWrapped() && !mLineEndsInBR);
|
PRBool isLastLine = (!mLineBox->IsLineWrapped() && !GetFlag(LL_LINEENDSINBR));
|
||||||
//PRBool isLastLine = mBlockRS->mCurLine->IsLineWrapped();
|
//PRBool isLastLine = mBlockRS->mCurLine->IsLineWrapped();
|
||||||
if (!applyMinLH && (isFirstLine || isLastLine)) {
|
if (!applyMinLH && (isFirstLine || isLastLine)) {
|
||||||
nsCOMPtr<nsIContent> blockContent;
|
nsCOMPtr<nsIContent> blockContent;
|
||||||
|
@ -2412,13 +2405,13 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd,
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!pfd->mIsTextFrame) {
|
else if (!pfd->GetFlag(PFD_ISTEXTFRAME)) {
|
||||||
// If we hit a frame on the end that's not text, then there is
|
// If we hit a frame on the end that's not text, then there is
|
||||||
// no trailing whitespace to trim. Stop the search.
|
// no trailing whitespace to trim. Stop the search.
|
||||||
*aDeltaWidth = 0;
|
*aDeltaWidth = 0;
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else if (pfd->mIsNonEmptyTextFrame) {
|
else if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME)) {
|
||||||
nscoord deltaWidth = 0;
|
nscoord deltaWidth = 0;
|
||||||
pfd->mFrame->TrimTrailingWhiteSpace(mPresContext,
|
pfd->mFrame->TrimTrailingWhiteSpace(mPresContext,
|
||||||
*mBlockReflowState->rendContext,
|
*mBlockReflowState->rendContext,
|
||||||
|
@ -2432,6 +2425,10 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd,
|
||||||
printf(" returned %d\n", deltaWidth);
|
printf(" returned %d\n", deltaWidth);
|
||||||
#endif
|
#endif
|
||||||
if (deltaWidth) {
|
if (deltaWidth) {
|
||||||
|
if (pfd->mJustificationNumSpaces > 0) {
|
||||||
|
pfd->mJustificationNumSpaces--;
|
||||||
|
}
|
||||||
|
|
||||||
pfd->mBounds.width -= deltaWidth;
|
pfd->mBounds.width -= deltaWidth;
|
||||||
pfd->mCombinedArea.width -= deltaWidth;
|
pfd->mCombinedArea.width -= deltaWidth;
|
||||||
if (0 == pfd->mBounds.width) {
|
if (0 == pfd->mBounds.width) {
|
||||||
|
@ -2479,6 +2476,95 @@ nsLineLayout::TrimTrailingWhiteSpace()
|
||||||
return 0 != deltaWidth;
|
return 0 != deltaWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsLineLayout::ComputeJustificationWeights(PerSpanData* aPSD,
|
||||||
|
PRInt32* aNumSpaces,
|
||||||
|
PRInt32* aNumLetters)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aPSD, "null arg");
|
||||||
|
NS_ASSERTION(aNumSpaces, "null arg");
|
||||||
|
NS_ASSERTION(aNumLetters, "null arg");
|
||||||
|
PRInt32 numSpaces = 0;
|
||||||
|
PRInt32 numLetters = 0;
|
||||||
|
|
||||||
|
for (PerFrameData* pfd = aPSD->mFirstFrame; pfd != nsnull; pfd = pfd->mNext) {
|
||||||
|
nscoord dw = 0;
|
||||||
|
|
||||||
|
if (PR_TRUE == pfd->GetFlag(PFD_ISTEXTFRAME)) {
|
||||||
|
numSpaces += pfd->mJustificationNumSpaces;
|
||||||
|
numLetters += pfd->mJustificationNumLetters;
|
||||||
|
}
|
||||||
|
else if (pfd->mSpan != nsnull) {
|
||||||
|
PRInt32 spanSpaces;
|
||||||
|
PRInt32 spanLetters;
|
||||||
|
|
||||||
|
ComputeJustificationWeights(pfd->mSpan, &spanSpaces, &spanLetters);
|
||||||
|
|
||||||
|
numSpaces += spanSpaces;
|
||||||
|
numLetters += spanLetters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*aNumSpaces = numSpaces;
|
||||||
|
*aNumLetters = numLetters;
|
||||||
|
}
|
||||||
|
|
||||||
|
nscoord
|
||||||
|
nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState* aState)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aPSD, "null arg");
|
||||||
|
NS_ASSERTION(aState, "null arg");
|
||||||
|
|
||||||
|
nscoord deltaX = 0;
|
||||||
|
for (PerFrameData* pfd = aPSD->mFirstFrame; pfd != nsnull; pfd = pfd->mNext) {
|
||||||
|
// Don't reposition bullets (and other frames that occur out of X-order?)
|
||||||
|
if (!pfd->GetFlag(PFD_ISBULLET)) {
|
||||||
|
nscoord dw = 0;
|
||||||
|
|
||||||
|
pfd->mBounds.x += deltaX;
|
||||||
|
|
||||||
|
if (PR_TRUE == pfd->GetFlag(PFD_ISTEXTFRAME)) {
|
||||||
|
if (aState->mTotalWidthForSpaces > 0 &&
|
||||||
|
aState->mTotalNumSpaces > 0 && // we divide by this value, so must be non-zero
|
||||||
|
aState->mTotalNumLetters >0 // we divide by this value, so must be non-zero
|
||||||
|
) {
|
||||||
|
aState->mNumSpacesProcessed += pfd->mJustificationNumSpaces;
|
||||||
|
|
||||||
|
nscoord newAllocatedWidthForSpaces =
|
||||||
|
(aState->mTotalWidthForSpaces*aState->mNumSpacesProcessed)
|
||||||
|
/aState->mTotalNumSpaces;
|
||||||
|
|
||||||
|
dw += newAllocatedWidthForSpaces - aState->mWidthForSpacesProcessed;
|
||||||
|
|
||||||
|
aState->mWidthForSpacesProcessed = newAllocatedWidthForSpaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aState->mTotalWidthForLetters > 0) {
|
||||||
|
aState->mNumLettersProcessed += pfd->mJustificationNumLetters;
|
||||||
|
|
||||||
|
nscoord newAllocatedWidthForLetters =
|
||||||
|
(aState->mTotalWidthForLetters*aState->mNumLettersProcessed)
|
||||||
|
/aState->mTotalNumLetters;
|
||||||
|
|
||||||
|
dw += newAllocatedWidthForLetters - aState->mWidthForLettersProcessed;
|
||||||
|
|
||||||
|
aState->mWidthForLettersProcessed = newAllocatedWidthForLetters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (nsnull != pfd->mSpan) {
|
||||||
|
dw += ApplyFrameJustification(pfd->mSpan, aState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pfd->mBounds.width += dw;
|
||||||
|
deltaX += dw;
|
||||||
|
pfd->mFrame->SetRect(mPresContext, pfd->mBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deltaX;
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
||||||
PRBool aAllowJustify,
|
PRBool aAllowJustify,
|
||||||
|
@ -2525,7 +2611,18 @@ nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
||||||
// frames in the line. If it is the last line then if the
|
// frames in the line. If it is the last line then if the
|
||||||
// direction is right-to-left then we right-align the frames.
|
// direction is right-to-left then we right-align the frames.
|
||||||
if (aAllowJustify) {
|
if (aAllowJustify) {
|
||||||
break;
|
if (!aShrinkWrapWidth) {
|
||||||
|
PRInt32 numSpaces;
|
||||||
|
PRInt32 numLetters;
|
||||||
|
|
||||||
|
ComputeJustificationWeights(psd, &numSpaces, &numLetters);
|
||||||
|
|
||||||
|
if (numSpaces > 0) {
|
||||||
|
FrameJustificationState state = { numSpaces, numLetters, remainingWidth, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
ApplyFrameJustification(psd, &state);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (NS_STYLE_DIRECTION_RTL == psd->mDirection) {
|
else if (NS_STYLE_DIRECTION_RTL == psd->mDirection) {
|
||||||
// right align the frames
|
// right align the frames
|
||||||
|
@ -2617,7 +2714,7 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea)
|
||||||
nscoord y = pfd->mBounds.y;
|
nscoord y = pfd->mBounds.y;
|
||||||
|
|
||||||
// Adjust the origin of the frame
|
// Adjust the origin of the frame
|
||||||
if (pfd->mRelativePos) {
|
if (pfd->GetFlag(PFD_RELATIVEPOS)) {
|
||||||
nsIFrame* frame = pfd->mFrame;
|
nsIFrame* frame = pfd->mFrame;
|
||||||
frame->GetOrigin(origin);
|
frame->GetOrigin(origin);
|
||||||
// XXX what about right and bottom?
|
// XXX what about right and bottom?
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Steve Clark <buster@netscape.com>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
*/
|
*/
|
||||||
#ifndef nsLineLayout_h___
|
#ifndef nsLineLayout_h___
|
||||||
#define nsLineLayout_h___
|
#define nsLineLayout_h___
|
||||||
|
@ -32,7 +34,7 @@ class nsBlockReflowState;
|
||||||
class nsPlaceholderFrame;
|
class nsPlaceholderFrame;
|
||||||
struct nsStyleText;
|
struct nsStyleText;
|
||||||
|
|
||||||
#define NS_LINELAYOUT_NUM_FRAMES 10
|
#define NS_LINELAYOUT_NUM_FRAMES 5
|
||||||
#define NS_LINELAYOUT_NUM_SPANS 5
|
#define NS_LINELAYOUT_NUM_SPANS 5
|
||||||
|
|
||||||
class nsLineLayout {
|
class nsLineLayout {
|
||||||
|
@ -122,23 +124,69 @@ public:
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
|
// Supporting methods and data for flags
|
||||||
|
protected:
|
||||||
|
#define LL_ENDSINWHITESPACE 0x00000001
|
||||||
|
#define LL_UNDERSTANDSNWHITESPACE 0x00000002
|
||||||
|
#define LL_TEXTSTARTSWITHNBSP 0x00000004
|
||||||
|
#define LL_FIRSTLETTERSTYLEOK 0x00000008
|
||||||
|
#define LL_ISTOPOFPAGE 0x00000010
|
||||||
|
#define LL_UPDATEDBAND 0x00000020
|
||||||
|
#define LL_IMPACTEDBYFLOATERS 0x00000040
|
||||||
|
#define LL_LASTFLOATERWASLETTERFRAME 0x00000080
|
||||||
|
#define LL_CANPLACEFLOATER 0x00000100
|
||||||
|
#define LL_KNOWSTRICTMODE 0x00000200
|
||||||
|
#define LL_INSTRICTMODE 0x00000400
|
||||||
|
#define LL_LINEENDSINBR 0x00000800
|
||||||
|
#define LL_LASTFLAG LL_LINEENDSINBR
|
||||||
|
|
||||||
|
PRUint16 mFlags;
|
||||||
|
|
||||||
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=LL_LASTFLAG, "bad flag");
|
||||||
|
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
|
||||||
|
if (aValue) { // set flag
|
||||||
|
mFlags |= aFlag;
|
||||||
|
}
|
||||||
|
else { // unset flag
|
||||||
|
mFlags &= ~aFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GetFlag(PRUint32 aFlag) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=LL_LASTFLAG, "bad flag");
|
||||||
|
PRBool result = (mFlags & aFlag);
|
||||||
|
if (result) return PR_TRUE;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
// Support methods for white-space compression and word-wrapping
|
// Support methods for white-space compression and word-wrapping
|
||||||
// during line reflow
|
// during line reflow
|
||||||
|
|
||||||
void SetEndsInWhiteSpace(PRBool aState) {
|
void SetEndsInWhiteSpace(PRBool aState) {
|
||||||
mEndsInWhiteSpace = aState;
|
SetFlag(LL_ENDSINWHITESPACE, aState);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool GetEndsInWhiteSpace() const {
|
PRBool GetEndsInWhiteSpace() const {
|
||||||
return mEndsInWhiteSpace;
|
return GetFlag(LL_ENDSINWHITESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetUnderstandsWhiteSpace(PRBool aSetting) {
|
void SetUnderstandsWhiteSpace(PRBool aSetting) {
|
||||||
mUnderstandsWhiteSpace = aSetting;
|
SetFlag(LL_UNDERSTANDSNWHITESPACE, aSetting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetTextJustificationWeights(PRInt32 aNumSpaces, PRInt32 aNumLetters) {
|
||||||
|
mTextJustificationNumSpaces = aNumSpaces;
|
||||||
|
mTextJustificationNumLetters = aNumLetters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SetTextStartsWithNBSP(PRBool aYes) {
|
void SetTextStartsWithNBSP(PRBool aYes) {
|
||||||
mTextStartsWithNBSP = aYes;
|
SetFlag(LL_TEXTSTARTSWITHNBSP, aYes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordWordFrame(nsIFrame* aWordFrame) {
|
void RecordWordFrame(nsIFrame* aWordFrame) {
|
||||||
|
@ -163,9 +211,15 @@ public:
|
||||||
|
|
||||||
PRBool LineIsBreakable() const;
|
PRBool LineIsBreakable() const;
|
||||||
|
|
||||||
PRBool GetLineEndsInBR() const { return mLineEndsInBR; }
|
PRBool GetLineEndsInBR() const
|
||||||
|
{
|
||||||
|
return GetFlag(LL_LINEENDSINBR);
|
||||||
|
}
|
||||||
|
|
||||||
void SetLineEndsInBR(PRBool aOn) { mLineEndsInBR = aOn; }
|
void SetLineEndsInBR(PRBool aOn)
|
||||||
|
{
|
||||||
|
SetFlag(LL_LINEENDSINBR, aOn);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
// Inform the line-layout about the presence of a floating frame
|
// Inform the line-layout about the presence of a floating frame
|
||||||
|
@ -176,11 +230,11 @@ public:
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
PRBool GetFirstLetterStyleOK() const {
|
PRBool GetFirstLetterStyleOK() const {
|
||||||
return mFirstLetterStyleOK;
|
return GetFlag(LL_FIRSTLETTERSTYLEOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFirstLetterStyleOK(PRBool aSetting) {
|
void SetFirstLetterStyleOK(PRBool aSetting) {
|
||||||
mFirstLetterStyleOK = aSetting;
|
SetFlag(LL_FIRSTLETTERSTYLEOK, aSetting);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFirstLetterFrame(nsIFrame* aFrame) {
|
void SetFirstLetterFrame(nsIFrame* aFrame) {
|
||||||
|
@ -233,19 +287,11 @@ protected:
|
||||||
nsIFrame* mFirstLetterFrame;
|
nsIFrame* mFirstLetterFrame;
|
||||||
PRInt32 mLineNumber;
|
PRInt32 mLineNumber;
|
||||||
PRInt32 mColumn;
|
PRInt32 mColumn;
|
||||||
|
PRInt32 mTextJustificationNumSpaces;
|
||||||
|
PRInt32 mTextJustificationNumLetters;
|
||||||
|
|
||||||
nsLineBox* mLineBox;
|
nsLineBox* mLineBox;
|
||||||
PRPackedBool mEndsInWhiteSpace;
|
|
||||||
PRPackedBool mUnderstandsWhiteSpace;
|
|
||||||
PRPackedBool mTextStartsWithNBSP;
|
|
||||||
PRPackedBool mFirstLetterStyleOK;
|
|
||||||
PRPackedBool mIsTopOfPage;
|
|
||||||
PRPackedBool mUpdatedBand;
|
|
||||||
PRPackedBool mImpactedByFloaters;
|
|
||||||
PRPackedBool mLastFloaterWasLetterFrame;
|
|
||||||
PRPackedBool mCanPlaceFloater;
|
|
||||||
PRPackedBool mKnowStrictMode;
|
|
||||||
PRPackedBool mInStrictMode;
|
|
||||||
PRPackedBool mLineEndsInBR;
|
|
||||||
PRUint8 mPlacedFloaters;
|
PRUint8 mPlacedFloaters;
|
||||||
PRInt32 mTotalPlacedFrames;
|
PRInt32 mTotalPlacedFrames;
|
||||||
nsVoidArray mWordFrames;
|
nsVoidArray mWordFrames;
|
||||||
|
@ -294,15 +340,47 @@ protected:
|
||||||
nsMargin mMargin;
|
nsMargin mMargin;
|
||||||
nsMargin mBorderPadding;
|
nsMargin mBorderPadding;
|
||||||
nsMargin mOffsets;
|
nsMargin mOffsets;
|
||||||
PRPackedBool mRelativePos;
|
|
||||||
|
|
||||||
// Other state we use
|
// Other state we use
|
||||||
PRUint8 mVerticalAlign;
|
PRUint8 mVerticalAlign;
|
||||||
PRPackedBool mIsTextFrame;
|
|
||||||
PRPackedBool mIsNonEmptyTextFrame;
|
// state for text justification
|
||||||
PRPackedBool mIsNonWhitespaceTextFrame;
|
PRInt32 mJustificationNumSpaces;
|
||||||
PRPackedBool mIsLetterFrame;
|
PRInt32 mJustificationNumLetters;
|
||||||
PRPackedBool mIsSticky;
|
|
||||||
|
|
||||||
|
// PerFrameData flags
|
||||||
|
#define PFD_RELATIVEPOS 0x00000001
|
||||||
|
#define PFD_ISTEXTFRAME 0x00000002
|
||||||
|
#define PFD_ISNONEMPTYTEXTFRAME 0x00000004
|
||||||
|
#define PFD_ISNONWHITESPACETEXTFRAME 0x00000008
|
||||||
|
#define PFD_ISLETTERFRAME 0x00000010
|
||||||
|
#define PFD_ISSTICKY 0x00000020
|
||||||
|
#define PFD_ISBULLET 0x00000040
|
||||||
|
#define PFD_LASTFLAG PFD_ISBULLET
|
||||||
|
|
||||||
|
PRPackedBool mFlags;
|
||||||
|
|
||||||
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=PFD_LASTFLAG, "bad flag");
|
||||||
|
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
|
||||||
|
if (aValue) { // set flag
|
||||||
|
mFlags |= aFlag;
|
||||||
|
}
|
||||||
|
else { // unset flag
|
||||||
|
mFlags &= ~aFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GetFlag(PRUint32 aFlag) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=PFD_LASTFLAG, "bad flag");
|
||||||
|
PRBool result = (mFlags & aFlag);
|
||||||
|
if (result) return PR_TRUE;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PerFrameData* Last() {
|
PerFrameData* Last() {
|
||||||
PerFrameData* pfd = this;
|
PerFrameData* pfd = this;
|
||||||
|
@ -409,6 +487,22 @@ protected:
|
||||||
|
|
||||||
PRBool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaWidth);
|
PRBool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaWidth);
|
||||||
|
|
||||||
|
|
||||||
|
void ComputeJustificationWeights(PerSpanData* psd, PRInt32* numSpaces, PRInt32* numLetters);
|
||||||
|
|
||||||
|
struct FrameJustificationState {
|
||||||
|
PRInt32 mTotalNumSpaces;
|
||||||
|
PRInt32 mTotalNumLetters;
|
||||||
|
nscoord mTotalWidthForSpaces;
|
||||||
|
nscoord mTotalWidthForLetters;
|
||||||
|
PRInt32 mNumSpacesProcessed;
|
||||||
|
PRInt32 mNumLettersProcessed;
|
||||||
|
nscoord mWidthForSpacesProcessed;
|
||||||
|
nscoord mWidthForLettersProcessed;
|
||||||
|
};
|
||||||
|
nscoord ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState* aState);
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent);
|
void DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
*/
|
*/
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsHTMLParts.h"
|
#include "nsHTMLParts.h"
|
||||||
|
@ -458,9 +459,10 @@ public:
|
||||||
nscoord mAveCharWidth;
|
nscoord mAveCharWidth;
|
||||||
PRBool mJustifying;
|
PRBool mJustifying;
|
||||||
PRBool mPreformatted;
|
PRBool mPreformatted;
|
||||||
PRIntn mNumSpaces;
|
PRInt32 mNumSpacesToRender;
|
||||||
|
PRInt32 mNumSpacesToMeasure;
|
||||||
nscoord mExtraSpacePerSpace;
|
nscoord mExtraSpacePerSpace;
|
||||||
nscoord mRemainingExtraSpace;
|
PRInt32 mNumSpacesReceivingExtraJot;
|
||||||
|
|
||||||
TextStyle(nsIPresContext* aPresContext,
|
TextStyle(nsIPresContext* aPresContext,
|
||||||
nsIRenderingContext& aRenderingContext,
|
nsIRenderingContext& aRenderingContext,
|
||||||
|
@ -521,20 +523,25 @@ public:
|
||||||
|
|
||||||
// Get the word and letter spacing
|
// Get the word and letter spacing
|
||||||
mWordSpacing = 0;
|
mWordSpacing = 0;
|
||||||
mLetterSpacing = 0;
|
|
||||||
PRIntn unit = mText->mWordSpacing.GetUnit();
|
PRIntn unit = mText->mWordSpacing.GetUnit();
|
||||||
if (eStyleUnit_Coord == unit) {
|
if (eStyleUnit_Coord == unit) {
|
||||||
mWordSpacing = mText->mWordSpacing.GetCoordValue();
|
mWordSpacing = mText->mWordSpacing.GetCoordValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLetterSpacing = 0;
|
||||||
unit = mText->mLetterSpacing.GetUnit();
|
unit = mText->mLetterSpacing.GetUnit();
|
||||||
if (eStyleUnit_Coord == unit) {
|
if (eStyleUnit_Coord == unit) {
|
||||||
mLetterSpacing = mText->mLetterSpacing.GetCoordValue();
|
mLetterSpacing = mText->mLetterSpacing.GetCoordValue();
|
||||||
}
|
}
|
||||||
mNumSpaces = 0;
|
mNumSpacesToRender = 0;
|
||||||
mRemainingExtraSpace = 0;
|
mNumSpacesToMeasure = 0;
|
||||||
|
mNumSpacesReceivingExtraJot = 0;
|
||||||
mExtraSpacePerSpace = 0;
|
mExtraSpacePerSpace = 0;
|
||||||
mPreformatted = (NS_STYLE_WHITESPACE_PRE == mText->mWhiteSpace) ||
|
mPreformatted = (NS_STYLE_WHITESPACE_PRE == mText->mWhiteSpace) ||
|
||||||
(NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == mText->mWhiteSpace);
|
(NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == mText->mWhiteSpace);
|
||||||
|
|
||||||
|
mJustifying = (NS_STYLE_TEXT_ALIGN_JUSTIFY == mText->mTextAlign) &&
|
||||||
|
!mPreformatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
~TextStyle() {
|
~TextStyle() {
|
||||||
|
@ -590,6 +597,9 @@ public:
|
||||||
nsAutoIndexBuffer* aIndexBuffer,
|
nsAutoIndexBuffer* aIndexBuffer,
|
||||||
nsAutoTextBuffer* aTextBuffer,
|
nsAutoTextBuffer* aTextBuffer,
|
||||||
PRInt32* aTextLen);
|
PRInt32* aTextLen);
|
||||||
|
void ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
|
||||||
|
TextStyle& aTextStyle,
|
||||||
|
PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumSpaces);
|
||||||
|
|
||||||
void PaintTextDecorations(nsIRenderingContext& aRenderingContext,
|
void PaintTextDecorations(nsIRenderingContext& aRenderingContext,
|
||||||
nsIStyleContext* aStyleContext,
|
nsIStyleContext* aStyleContext,
|
||||||
|
@ -1192,7 +1202,8 @@ nsTextFrame::Paint(nsIPresContext* aPresContext,
|
||||||
sc->GetStyleData(eStyleStruct_Display);
|
sc->GetStyleData(eStyleStruct_Display);
|
||||||
if (disp->IsVisible()) {
|
if (disp->IsVisible()) {
|
||||||
TextStyle ts(aPresContext, aRenderingContext, mStyleContext);
|
TextStyle ts(aPresContext, aRenderingContext, mStyleContext);
|
||||||
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing)) {
|
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing)
|
||||||
|
|| ts.mJustifying) {
|
||||||
PaintTextSlowly(aPresContext, aRenderingContext, sc, ts, 0, 0);
|
PaintTextSlowly(aPresContext, aRenderingContext, sc, ts, 0, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1261,7 +1272,9 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
|
||||||
PRBool isWhitespace, wasTransformed;
|
PRBool isWhitespace, wasTransformed;
|
||||||
PRInt32 wordLen, contentLen;
|
PRInt32 wordLen, contentLen;
|
||||||
aTX.GetNextWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace, &wasTransformed);
|
aTX.GetNextWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace, &wasTransformed);
|
||||||
NS_ASSERTION(isWhitespace, "mState and content are out of sync");
|
// we trip this assertion in bug 31053, but I think it's unnecessary
|
||||||
|
//NS_ASSERTION(isWhitespace, "mState and content are out of sync");
|
||||||
|
|
||||||
if (isWhitespace) {
|
if (isWhitespace) {
|
||||||
if (nsnull != indexp) {
|
if (nsnull != indexp) {
|
||||||
// Point mapping indicies at the same content index since
|
// Point mapping indicies at the same content index since
|
||||||
|
@ -1301,7 +1314,6 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
|
||||||
}
|
}
|
||||||
inWord = PR_FALSE;
|
inWord = PR_FALSE;
|
||||||
if (isWhitespace) {
|
if (isWhitespace) {
|
||||||
numSpaces++;
|
|
||||||
if ('\t' == bp[0]) {
|
if ('\t' == bp[0]) {
|
||||||
PRInt32 spaces = 8 - (7 & column);
|
PRInt32 spaces = 8 - (7 & column);
|
||||||
PRUnichar* tp = bp;
|
PRUnichar* tp = bp;
|
||||||
|
@ -1339,20 +1351,30 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
numSpaces += wordLen;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
PRInt32 i;
|
||||||
if (nsnull != indexp) {
|
if (nsnull != indexp) {
|
||||||
// Point mapping indicies at each content index in the word
|
// Point mapping indicies at each content index in the word
|
||||||
PRInt32 i = contentLen;
|
i = contentLen;
|
||||||
while (--i >= 0) {
|
while (--i >= 0) {
|
||||||
*indexp++ = strInx++;
|
*indexp++ = strInx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Nonbreaking spaces count as spaces, not letters
|
||||||
|
PRUnichar* tp = bp;
|
||||||
|
i = wordLen;
|
||||||
|
while (--i >= 0) {
|
||||||
|
if (*tp++ == ' ') {
|
||||||
|
numSpaces++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grow the buffer before we run out of room. The only time this
|
// Grow the buffer before we run out of room. The only time this
|
||||||
// happens is because of tab expansion.
|
// happens is because of tab expansion.
|
||||||
if (dstOffset + wordLen > aTextBuffer->mBufferLen) {
|
if (aTextBuffer != nsnull && dstOffset + wordLen > aTextBuffer->mBufferLen) {
|
||||||
nsresult rv = aTextBuffer->GrowBy(wordLen);
|
nsresult rv = aTextBuffer->GrowBy(wordLen);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
break;
|
break;
|
||||||
|
@ -1362,8 +1384,10 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
|
||||||
column += wordLen;
|
column += wordLen;
|
||||||
textLength += wordLen;
|
textLength += wordLen;
|
||||||
n -= contentLen;
|
n -= contentLen;
|
||||||
nsCRT::memcpy(aTextBuffer->mBuffer + dstOffset, bp,
|
if (aTextBuffer != nsnull) {
|
||||||
sizeof(PRUnichar)*wordLen);
|
nsCRT::memcpy(aTextBuffer->mBuffer + dstOffset, bp,
|
||||||
|
sizeof(PRUnichar)*wordLen);
|
||||||
|
}
|
||||||
dstOffset += wordLen;
|
dstOffset += wordLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1372,19 +1396,24 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
|
||||||
NS_ASSERTION(indexp <= aIndexBuffer->mBuffer + aIndexBuffer->mBufferLen,
|
NS_ASSERTION(indexp <= aIndexBuffer->mBuffer + aIndexBuffer->mBufferLen,
|
||||||
"yikes - we just overwrote memory");
|
"yikes - we just overwrote memory");
|
||||||
}
|
}
|
||||||
NS_ASSERTION(dstOffset <= aTextBuffer->mBufferLen,
|
if (aTextBuffer) {
|
||||||
"yikes - we just overwrote memory");
|
NS_ASSERTION(dstOffset <= aTextBuffer->mBufferLen,
|
||||||
|
"yikes - we just overwrote memory");
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Remove trailing whitespace if it was trimmed after reflow
|
// Remove trailing whitespace if it was trimmed after reflow
|
||||||
if (TEXT_TRIMMED_WS & mState) {
|
if (TEXT_TRIMMED_WS & mState) {
|
||||||
|
NS_ASSERTION(aTextBuffer != nsnull,
|
||||||
|
"Nonexistent text buffer should only occur during reflow, i.e. before whitespace is trimmed");
|
||||||
if (--dstOffset >= 0) {
|
if (--dstOffset >= 0) {
|
||||||
PRUnichar ch = aTextBuffer->mBuffer[dstOffset];
|
PRUnichar ch = aTextBuffer->mBuffer[dstOffset];
|
||||||
if (XP_IS_SPACE(ch)) {
|
if (XP_IS_SPACE(ch)) {
|
||||||
textLength--;
|
textLength--;
|
||||||
|
numSpaces--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
numSpaces--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aIndexBuffer) {
|
if (aIndexBuffer) {
|
||||||
|
@ -1716,6 +1745,7 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext,
|
||||||
doc->GetLineBreaker(getter_AddRefs(lb));
|
doc->GetLineBreaker(getter_AddRefs(lb));
|
||||||
nsTextTransformer tx(lb, nsnull);
|
nsTextTransformer tx(lb, nsnull);
|
||||||
PRInt32 textLength;
|
PRInt32 textLength;
|
||||||
|
// no need to worry about justification, that's always on the slow path
|
||||||
PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
|
PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
|
||||||
&paintBuffer, &textLength);
|
&paintBuffer, &textLength);
|
||||||
|
|
||||||
|
@ -1833,7 +1863,7 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
TextStyle ts(aPresContext, *aRendContext, mStyleContext);
|
TextStyle ts(aPresContext, *aRendContext, mStyleContext);
|
||||||
if (!ts.mSmallCaps && !ts.mWordSpacing && !ts.mLetterSpacing) {
|
if (!ts.mSmallCaps && !ts.mWordSpacing && !ts.mLetterSpacing && !ts.mJustifying) {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
nsIView * view;
|
nsIView * view;
|
||||||
|
@ -1861,12 +1891,16 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext,
|
||||||
doc->GetLineBreaker(getter_AddRefs(lb));
|
doc->GetLineBreaker(getter_AddRefs(lb));
|
||||||
nsTextTransformer tx(lb, nsnull);
|
nsTextTransformer tx(lb, nsnull);
|
||||||
PRInt32 textLength;
|
PRInt32 textLength;
|
||||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
PRInt32 numSpaces;
|
||||||
|
|
||||||
|
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||||
if (textLength <= 0) {
|
if (textLength <= 0) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//IF STYLE SAYS TO SELCT TO END OF FRAME HERE...
|
ComputeExtraJustificationSpacing(*aRendContext, ts, paintBuffer.mBuffer, textLength, numSpaces);
|
||||||
|
|
||||||
|
//IF STYLE SAYS TO SELECT TO END OF FRAME HERE...
|
||||||
nsCOMPtr<nsIPref> prefs;
|
nsCOMPtr<nsIPref> prefs;
|
||||||
PRInt32 prefInt = 0;
|
PRInt32 prefInt = 0;
|
||||||
rv = nsServiceManager::GetService(kPrefCID,
|
rv = nsServiceManager::GetService(kPrefCID,
|
||||||
|
@ -1929,7 +1963,7 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
|
||||||
PRUnichar* bp = bp0;
|
PRUnichar* bp = bp0;
|
||||||
|
|
||||||
PRBool spacing = (0 != aTextStyle.mLetterSpacing) ||
|
PRBool spacing = (0 != aTextStyle.mLetterSpacing) ||
|
||||||
(0 != aTextStyle.mWordSpacing);
|
(0 != aTextStyle.mWordSpacing) || aTextStyle.mJustifying;
|
||||||
nscoord spacingMem[TEXT_BUF_SIZE];
|
nscoord spacingMem[TEXT_BUF_SIZE];
|
||||||
PRIntn* sp0 = spacingMem;
|
PRIntn* sp0 = spacingMem;
|
||||||
if (spacing && (aLength > TEXT_BUF_SIZE)) {
|
if (spacing && (aLength > TEXT_BUF_SIZE)) {
|
||||||
|
@ -1977,12 +2011,12 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
|
||||||
else if (ch == ' ') {
|
else if (ch == ' ') {
|
||||||
nextFont = aTextStyle.mNormalFont;
|
nextFont = aTextStyle.mNormalFont;
|
||||||
nextY = aY;
|
nextY = aY;
|
||||||
glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing;
|
glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing
|
||||||
nscoord extra = aTextStyle.mExtraSpacePerSpace;
|
+ aTextStyle.mExtraSpacePerSpace;
|
||||||
if (--aTextStyle.mNumSpaces == 0) {
|
if ((PRUint32)--aTextStyle.mNumSpacesToRender <
|
||||||
extra += aTextStyle.mRemainingExtraSpace;
|
(PRUint32)aTextStyle.mNumSpacesReceivingExtraJot) {
|
||||||
|
glyphWidth++;
|
||||||
}
|
}
|
||||||
glyphWidth += extra;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (lastFont != aTextStyle.mNormalFont) {
|
if (lastFont != aTextStyle.mNormalFont) {
|
||||||
|
@ -2096,12 +2130,12 @@ nsTextFrame::GetWidthOrLength(nsIRenderingContext& aRenderingContext,
|
||||||
glyphWidth = charWidth + aStyle.mLetterSpacing;
|
glyphWidth = charWidth + aStyle.mLetterSpacing;
|
||||||
}
|
}
|
||||||
else if (ch == ' ') {
|
else if (ch == ' ') {
|
||||||
glyphWidth = aStyle.mSpaceWidth + aStyle.mWordSpacing;
|
glyphWidth = aStyle.mSpaceWidth + aStyle.mWordSpacing
|
||||||
nscoord extra = aStyle.mExtraSpacePerSpace;
|
+ aStyle.mExtraSpacePerSpace;
|
||||||
if (--aStyle.mNumSpaces == 0) {
|
if ((PRUint32)--aStyle.mNumSpacesToMeasure
|
||||||
extra += aStyle.mRemainingExtraSpace;
|
< (PRUint32)aStyle.mNumSpacesReceivingExtraJot) {
|
||||||
|
glyphWidth++;
|
||||||
}
|
}
|
||||||
glyphWidth += extra;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (lastFont != aStyle.mNormalFont) {
|
if (lastFont != aStyle.mNormalFont) {
|
||||||
|
@ -2147,6 +2181,45 @@ nsTextFrame::GetLengthSlowly(nsIRenderingContext& aRenderingContext,
|
||||||
return GetWidthOrLength(aRenderingContext,aStyle,aBuffer,aLength,&aWidth,PR_FALSE);
|
return GetWidthOrLength(aRenderingContext,aStyle,aBuffer,aLength,&aWidth,PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTextFrame::ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
|
||||||
|
TextStyle& aTextStyle,
|
||||||
|
PRUnichar* aBuffer, PRInt32 aLength,
|
||||||
|
PRInt32 aNumSpaces)
|
||||||
|
{
|
||||||
|
if (aTextStyle.mJustifying) {
|
||||||
|
nscoord trueWidth;
|
||||||
|
|
||||||
|
// OK, so this is a bit ugly. The problem is that to get the right margin
|
||||||
|
// nice and clean, we have to apply a little extra space to *some* of the
|
||||||
|
// spaces. It has to be the same ones every time or things will go haywire.
|
||||||
|
// This implies that the GetWidthOrLength and RenderString functions depend
|
||||||
|
// on a little bit of secret state: which part of the prepared text they are
|
||||||
|
// looking at. It turns out that they get called in a regular way: they look
|
||||||
|
// at the text from the beginning to the end. So we just count which spaces
|
||||||
|
// we're up to, for each context.
|
||||||
|
// This is not a great solution, but a perfect solution requires much more
|
||||||
|
// widespread changes, to explicitly annotate all the transformed text fragments
|
||||||
|
// that are passed around with their position in the transformed text
|
||||||
|
// for the entire frame.
|
||||||
|
aTextStyle.mNumSpacesToMeasure = 0;
|
||||||
|
aTextStyle.mExtraSpacePerSpace = 0;
|
||||||
|
aTextStyle.mNumSpacesReceivingExtraJot = 0;
|
||||||
|
|
||||||
|
GetWidth(aRenderingContext, aTextStyle, aBuffer, aLength, &trueWidth);
|
||||||
|
|
||||||
|
aTextStyle.mNumSpacesToMeasure = aNumSpaces;
|
||||||
|
aTextStyle.mNumSpacesToRender = aNumSpaces;
|
||||||
|
|
||||||
|
nscoord extraSpace = mRect.width - trueWidth;
|
||||||
|
|
||||||
|
if (extraSpace > 0 && aNumSpaces > 0) {
|
||||||
|
aTextStyle.mExtraSpacePerSpace = extraSpace/aNumSpaces;
|
||||||
|
aTextStyle.mNumSpacesReceivingExtraJot =
|
||||||
|
extraSpace - aTextStyle.mExtraSpacePerSpace*aNumSpaces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
|
nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
|
||||||
|
@ -2173,10 +2246,11 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
|
||||||
nsCOMPtr<nsILineBreaker> lb;
|
nsCOMPtr<nsILineBreaker> lb;
|
||||||
doc->GetLineBreaker(getter_AddRefs(lb));
|
doc->GetLineBreaker(getter_AddRefs(lb));
|
||||||
nsTextTransformer tx(lb, nsnull);
|
nsTextTransformer tx(lb, nsnull);
|
||||||
aTextStyle.mNumSpaces = PrepareUnicodeText(tx,
|
PRInt32 numSpaces;
|
||||||
(displaySelection
|
|
||||||
? &indexBuffer : nsnull),
|
numSpaces = PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
|
||||||
&paintBuffer, &textLength);
|
&paintBuffer, &textLength);
|
||||||
|
|
||||||
|
|
||||||
PRInt32* ip = indexBuffer.mBuffer;
|
PRInt32* ip = indexBuffer.mBuffer;
|
||||||
PRUnichar* text = paintBuffer.mBuffer;
|
PRUnichar* text = paintBuffer.mBuffer;
|
||||||
|
@ -2185,6 +2259,7 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
|
||||||
GetFrameState(&frameState);
|
GetFrameState(&frameState);
|
||||||
isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
|
isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
|
||||||
if (0 != textLength) {
|
if (0 != textLength) {
|
||||||
|
ComputeExtraJustificationSpacing(aRenderingContext, aTextStyle, text, textLength, numSpaces);
|
||||||
if (!displaySelection || !isSelected) {
|
if (!displaySelection || !isSelected) {
|
||||||
// When there is no selection showing, use the fastest and
|
// When there is no selection showing, use the fastest and
|
||||||
// simplest rendering approach
|
// simplest rendering approach
|
||||||
|
@ -2550,8 +2625,7 @@ nsTextFrame::GetPosition(nsIPresContext* aCX,
|
||||||
rv = shell->CreateRenderingContext(this, getter_AddRefs(acx));
|
rv = shell->CreateRenderingContext(this, getter_AddRefs(acx));
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
TextStyle ts(aCX, *acx, mStyleContext);
|
TextStyle ts(aCX, *acx, mStyleContext);
|
||||||
if (ts.mSmallCaps || ts.mWordSpacing || ts.mLetterSpacing) {
|
if (ts.mSmallCaps || ts.mWordSpacing || ts.mLetterSpacing || ts.mJustifying) {
|
||||||
|
|
||||||
nsresult result = GetPositionSlowly(aCX, acx, aPoint, aNewContent,
|
nsresult result = GetPositionSlowly(aCX, acx, aPoint, aNewContent,
|
||||||
aContentOffset);
|
aContentOffset);
|
||||||
aContentOffsetEnd = aContentOffset;
|
aContentOffsetEnd = aContentOffset;
|
||||||
|
@ -2582,6 +2656,7 @@ nsTextFrame::GetPosition(nsIPresContext* aCX,
|
||||||
doc->GetLineBreaker(getter_AddRefs(lb));
|
doc->GetLineBreaker(getter_AddRefs(lb));
|
||||||
nsTextTransformer tx(lb, nsnull);
|
nsTextTransformer tx(lb, nsnull);
|
||||||
PRInt32 textLength;
|
PRInt32 textLength;
|
||||||
|
// no need to worry about justification, that's always on the slow path
|
||||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||||
|
|
||||||
if (textLength <=0) {
|
if (textLength <=0) {
|
||||||
|
@ -2593,7 +2668,7 @@ nsTextFrame::GetPosition(nsIPresContext* aCX,
|
||||||
nsIView * view;
|
nsIView * view;
|
||||||
GetOffsetFromView(aCX, origin, &view);
|
GetOffsetFromView(aCX, origin, &view);
|
||||||
|
|
||||||
//IF SYLE SAYS TO SELCT TO END OF FRAME HERE...
|
//IF STYLE SAYS TO SELECT TO END OF FRAME HERE...
|
||||||
nsCOMPtr<nsIPref> prefs;
|
nsCOMPtr<nsIPref> prefs;
|
||||||
PRInt32 prefInt = 0;
|
PRInt32 prefInt = 0;
|
||||||
rv = nsServiceManager::GetService(kPrefCID,
|
rv = nsServiceManager::GetService(kPrefCID,
|
||||||
|
@ -2880,7 +2955,12 @@ nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext,
|
||||||
doc->GetLineBreaker(getter_AddRefs(lb));
|
doc->GetLineBreaker(getter_AddRefs(lb));
|
||||||
nsTextTransformer tx(lb, nsnull);
|
nsTextTransformer tx(lb, nsnull);
|
||||||
PRInt32 textLength;
|
PRInt32 textLength;
|
||||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
PRInt32 numSpaces;
|
||||||
|
|
||||||
|
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||||
|
|
||||||
|
ComputeExtraJustificationSpacing(*inRendContext, ts, paintBuffer.mBuffer, textLength, numSpaces);
|
||||||
|
|
||||||
|
|
||||||
PRInt32* ip = indexBuffer.mBuffer;
|
PRInt32* ip = indexBuffer.mBuffer;
|
||||||
if (inOffset > mContentLength){
|
if (inOffset > mContentLength){
|
||||||
|
@ -2889,7 +2969,7 @@ nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
nscoord width = mRect.width;
|
nscoord width = mRect.width;
|
||||||
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing))
|
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing) || ts.mJustifying)
|
||||||
{
|
{
|
||||||
GetWidth(*inRendContext, ts,
|
GetWidth(*inRendContext, ts,
|
||||||
paintBuffer.mBuffer, ip[inOffset]-mContentOffset,
|
paintBuffer.mBuffer, ip[inOffset]-mContentOffset,
|
||||||
|
@ -2907,7 +2987,8 @@ nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext,
|
||||||
// to the total width, so the caret appears
|
// to the total width, so the caret appears
|
||||||
// in the proper place!
|
// in the proper place!
|
||||||
//
|
//
|
||||||
width += ts.mSpaceWidth;
|
// NOTE: the trailing whitespace includes the word spacing!!
|
||||||
|
width += ts.mSpaceWidth + ts.mWordSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
outPoint->x = width;
|
outPoint->x = width;
|
||||||
|
@ -3502,6 +3583,7 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
PRBool measureTextRuns = !aTextData.mComputeMaxWordWidth && !aTs.mPreformatted &&
|
PRBool measureTextRuns = !aTextData.mComputeMaxWordWidth && !aTs.mPreformatted &&
|
||||||
!aTs.mSmallCaps && !aTs.mWordSpacing && !aTs.mLetterSpacing;
|
!aTs.mSmallCaps && !aTs.mWordSpacing && !aTs.mLetterSpacing;
|
||||||
|
// Don't measure text runs with letter spacing active, it doesn't work
|
||||||
#else
|
#else
|
||||||
PRBool measureTextRuns = PR_FALSE;
|
PRBool measureTextRuns = PR_FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
@ -3579,10 +3661,17 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
mState |= TEXT_SKIP_LEADING_WS;
|
mState |= TEXT_SKIP_LEADING_WS;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Even if the textRun absorbs the whitespace below, we still
|
||||||
|
// want to remember that we're breakable.
|
||||||
|
aTextData.mIsBreakable = PR_TRUE;
|
||||||
|
aTextData.mFirstLetterOK = PR_FALSE;
|
||||||
|
|
||||||
if ('\t' == firstChar) {
|
if ('\t' == firstChar) {
|
||||||
// Expand tabs to the proper width
|
// Expand tabs to the proper width
|
||||||
wordLen = 8 - (7 & column);
|
wordLen = 8 - (7 & column);
|
||||||
width = aTs.mSpaceWidth * wordLen;
|
// Apply word spacing to every space derived from a tab
|
||||||
|
width = (aTs.mSpaceWidth + aTs.mWordSpacing)*wordLen;
|
||||||
|
|
||||||
// Because we have to expand the tab when rendering consider that
|
// Because we have to expand the tab when rendering consider that
|
||||||
// a transformation of the text
|
// a transformation of the text
|
||||||
|
@ -3594,10 +3683,9 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
width = (wordLen * aTs.mSpaceWidth) + aTs.mWordSpacing;// XXX simplistic
|
// Apply word spacing to every space, if there's more than one
|
||||||
|
width = wordLen*(aTs.mWordSpacing + aTs.mSpaceWidth);// XXX simplistic
|
||||||
}
|
}
|
||||||
aTextData.mIsBreakable = PR_TRUE;
|
|
||||||
aTextData.mFirstLetterOK = PR_FALSE;
|
|
||||||
|
|
||||||
if (aTextData.mMeasureText) {
|
if (aTextData.mMeasureText) {
|
||||||
// See if there is room for the text
|
// See if there is room for the text
|
||||||
|
@ -3612,7 +3700,6 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
endsInWhitespace = PR_TRUE;
|
endsInWhitespace = PR_TRUE;
|
||||||
prevOffset = aTextData.mOffset;
|
prevOffset = aTextData.mOffset;
|
||||||
aTextData.mOffset += contentLen;
|
aTextData.mOffset += contentLen;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// See if the first thing in the section of text is a
|
// See if the first thing in the section of text is a
|
||||||
// non-breaking space (html nbsp entity). If it is then make
|
// non-breaking space (html nbsp entity). If it is then make
|
||||||
|
@ -3704,6 +3791,7 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
MeasureTextRun:
|
MeasureTextRun:
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
PRInt32 numCharsFit;
|
PRInt32 numCharsFit;
|
||||||
|
// These calls can return numCharsFit not positioned at a break in the textRun. Beware.
|
||||||
if (aTx.TransformedTextIsAscii()) {
|
if (aTx.TransformedTextIsAscii()) {
|
||||||
aReflowState.rendContext->GetWidth((char*)aTx.GetWordBuffer(), textRun.mTotalNumChars,
|
aReflowState.rendContext->GetWidth((char*)aTx.GetWordBuffer(), textRun.mTotalNumChars,
|
||||||
maxWidth - aTextData.mX,
|
maxWidth - aTextData.mX,
|
||||||
|
@ -3722,22 +3810,43 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the index of the last segment that fit
|
// Find the index of the last segment that fit
|
||||||
PRInt32 lastSegment = textRun.mNumSegments - 1;
|
PRInt32 lastSegment;
|
||||||
if (numCharsFit != textRun.mTotalNumChars) {
|
if (numCharsFit == textRun.mTotalNumChars) { // fast path, normal case
|
||||||
|
lastSegment = textRun.mNumSegments - 1;
|
||||||
|
} else {
|
||||||
for (lastSegment = 0; textRun.mBreaks[lastSegment] < numCharsFit; lastSegment++) ;
|
for (lastSegment = 0; textRun.mBreaks[lastSegment] < numCharsFit; lastSegment++) ;
|
||||||
NS_ASSERTION(lastSegment < textRun.mNumSegments, "failed to find segment");
|
NS_ASSERTION(lastSegment < textRun.mNumSegments, "failed to find segment");
|
||||||
|
// now we have textRun.mBreaks[lastSegment] >= numCharsFit
|
||||||
|
/* O'Callahan XXX: This snippet together with the snippet below prevents mail from loading
|
||||||
|
Justification seems to work just fine without these changes.
|
||||||
|
We get into trouble in a case where lastSegment gets set to -1
|
||||||
|
|
||||||
|
if (textRun.mBreaks[lastSegment] > numCharsFit) {
|
||||||
|
// NOTE: this segment did not actually fit!
|
||||||
|
lastSegment--;
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* O'Callahan XXX: This snippet together with the snippet above prevents mail from loading
|
||||||
|
|
||||||
|
if (lastSegment < 0) {
|
||||||
|
// no segments fit
|
||||||
|
break;
|
||||||
|
} else */
|
||||||
if (lastSegment == 0) {
|
if (lastSegment == 0) {
|
||||||
// Only one segment fit
|
// Only one segment fit
|
||||||
prevColumn = column;
|
prevColumn = column;
|
||||||
prevOffset = aTextData.mOffset;
|
prevOffset = aTextData.mOffset;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// The previous state is for the next to last word
|
// The previous state is for the next to last word
|
||||||
prevColumn = textRun.mBreaks[lastSegment - 1];
|
prevColumn = textRun.mBreaks[lastSegment - 1];
|
||||||
prevOffset = textRun.mSegments[lastSegment - 1].ContentLen();
|
prevOffset = textRun.mSegments[lastSegment - 1].ContentLen();
|
||||||
|
// NOTE: The textRun data are relative to the last updated column and offset!
|
||||||
|
prevColumn = column + textRun.mBreaks[lastSegment - 1];
|
||||||
|
prevOffset = aTextData.mOffset + textRun.mSegments[lastSegment - 1].ContentLen();
|
||||||
}
|
}
|
||||||
|
|
||||||
aTextData.mX += width;
|
aTextData.mX += width;
|
||||||
column += numCharsFit;
|
column += numCharsFit;
|
||||||
aTextData.mOffset += textRun.mSegments[lastSegment].ContentLen();
|
aTextData.mOffset += textRun.mSegments[lastSegment].ContentLen();
|
||||||
|
@ -3775,7 +3884,8 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
aTextData.mX = mRect.width;
|
aTextData.mX = mRect.width;
|
||||||
if (mState & TEXT_TRIMMED_WS) {
|
if (mState & TEXT_TRIMMED_WS) {
|
||||||
// Add back in the width of a space since it was trimmed away last time
|
// Add back in the width of a space since it was trimmed away last time
|
||||||
aTextData.mX += aTs.mSpaceWidth;
|
// NOTE: Trailing whitespace includes word spacing!
|
||||||
|
aTextData.mX += aTs.mSpaceWidth + aTs.mWordSpacing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4056,19 +4166,22 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// current frame width -or-
|
// current frame width -or-
|
||||||
// we're not wrapping text and we're at the same column as before (this is
|
// we're not wrapping text and we're at the same column as before (this is
|
||||||
// an issue for preformatted tabbed text only)
|
// an issue for preformatted tabbed text only)
|
||||||
|
// - AND we aren't justified (in which case the frame width has already been tweaked and can't be used)
|
||||||
if ((eReflowReason_Resize == aReflowState.reason) &&
|
if ((eReflowReason_Resize == aReflowState.reason) &&
|
||||||
(0 == (mState & NS_FRAME_IS_DIRTY))) {
|
(0 == (mState & NS_FRAME_IS_DIRTY))) {
|
||||||
|
|
||||||
nscoord realWidth = mRect.width;
|
nscoord realWidth = mRect.width;
|
||||||
if (mState & TEXT_TRIMMED_WS) {
|
if (mState & TEXT_TRIMMED_WS) {
|
||||||
realWidth += ts.mSpaceWidth;
|
// NOTE: Trailing whitespace includes word spacing!
|
||||||
|
realWidth += ts.mSpaceWidth + ts.mWordSpacing;
|
||||||
}
|
}
|
||||||
if (!mNextInFlow &&
|
if (!mNextInFlow &&
|
||||||
(mState & TEXT_OPTIMIZE_RESIZE) &&
|
(mState & TEXT_OPTIMIZE_RESIZE) &&
|
||||||
!aMetrics.maxElementSize &&
|
!aMetrics.maxElementSize &&
|
||||||
(lastTimeWeSkippedLeadingWS == skipWhitespace) &&
|
(lastTimeWeSkippedLeadingWS == skipWhitespace) &&
|
||||||
((wrapping && (maxWidth >= realWidth)) ||
|
((wrapping && (maxWidth >= realWidth)) ||
|
||||||
(!wrapping && (prevColumn == column)))) {
|
(!wrapping && (prevColumn == column))) &&
|
||||||
|
!ts.mJustifying) {
|
||||||
// We can skip measuring of text and use the value from our
|
// We can skip measuring of text and use the value from our
|
||||||
// previous reflow
|
// previous reflow
|
||||||
measureText = PR_FALSE;
|
measureText = PR_FALSE;
|
||||||
|
@ -4120,6 +4233,23 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
mContentOffset = startingOffset;
|
mContentOffset = startingOffset;
|
||||||
mContentLength = textData.mOffset - startingOffset;
|
mContentLength = textData.mOffset - startingOffset;
|
||||||
|
|
||||||
|
// Compute space and letter counts for justification, if required
|
||||||
|
if (ts.mJustifying) {
|
||||||
|
PRInt32 numSpaces;
|
||||||
|
PRInt32 textLength;
|
||||||
|
|
||||||
|
// This will include a space for trailing whitespace, if any is present.
|
||||||
|
// This is corrected for in nsLineLayout::TrimWhiteSpaceIn.
|
||||||
|
|
||||||
|
// This work could be done in MeasureText, but it's complex to do accurately
|
||||||
|
// there because of the need to repair counts when wrapped words are backed out.
|
||||||
|
// So I do it via PrepareUnicodeText ... a little slower perhaps, but a lot saner,
|
||||||
|
// and it localizes the counting logic to one place.
|
||||||
|
numSpaces = PrepareUnicodeText(tx, nsnull, nsnull, &textLength);
|
||||||
|
lineLayout.SetTextJustificationWeights(numSpaces, textLength - numSpaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef MOZ_MATHML
|
#ifdef MOZ_MATHML
|
||||||
// Simple minded code to also return the bounding metrics if the caller wants it...
|
// Simple minded code to also return the bounding metrics if the caller wants it...
|
||||||
// More consolidation is needed -- a better approach is to follow what is done by
|
// More consolidation is needed -- a better approach is to follow what is done by
|
||||||
|
@ -4226,6 +4356,11 @@ nsTextFrame::TrimTrailingWhiteSpace(nsIPresContext* aPresContext,
|
||||||
mStyleContext->GetStyleData(eStyleStruct_Font);
|
mStyleContext->GetStyleData(eStyleStruct_Font);
|
||||||
aRC.SetFont(fontStyle->mFont);
|
aRC.SetFont(fontStyle->mFont);
|
||||||
aRC.GetWidth(' ', dw);
|
aRC.GetWidth(' ', dw);
|
||||||
|
// NOTE: Trailing whitespace includes word spacing!
|
||||||
|
PRIntn unit = textStyle->mWordSpacing.GetUnit();
|
||||||
|
if (eStyleUnit_Coord == unit) {
|
||||||
|
dw += textStyle->mWordSpacing.GetCoordValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4406,6 +4541,8 @@ nsTextFrame::ComputeWordFragmentWidth(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rc.GetWidth(bp, wordLen, width);
|
rc.GetWidth(bp, wordLen, width);
|
||||||
|
// NOTE: Don't forget to add letter spacing for the word fragment!
|
||||||
|
width += wordLen*ts.mLetterSpacing;
|
||||||
}
|
}
|
||||||
rc.SetFont(oldfm);
|
rc.SetFont(oldfm);
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,10 @@ nsBlockBandData::GetAvailableSpace(nscoord aY, nsRect& aResult)
|
||||||
// between any left and right floaters.
|
// between any left and right floaters.
|
||||||
ComputeAvailSpaceRect();
|
ComputeAvailSpaceRect();
|
||||||
aResult = mAvailSpace;
|
aResult = mAvailSpace;
|
||||||
|
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||||
|
printf("nsBBD %p GetAvailableSpace(%d) returing (%d, %d, %d, %d)\n",
|
||||||
|
this, aY, aResult.x, aResult.y, aResult.width, aResult.height);
|
||||||
|
#endif
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +138,7 @@ void
|
||||||
nsBlockBandData::ComputeAvailSpaceRect()
|
nsBlockBandData::ComputeAvailSpaceRect()
|
||||||
{
|
{
|
||||||
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||||
printf("nsBlockBandData::ComputeAvailSpaceRect %p \n", this);
|
printf("nsBlockBandData::ComputeAvailSpaceRect %p with count %d\n", this, mCount);
|
||||||
#endif
|
#endif
|
||||||
if (0 == mCount) {
|
if (0 == mCount) {
|
||||||
mAvailSpace.x = 0;
|
mAvailSpace.x = 0;
|
||||||
|
@ -248,6 +252,11 @@ nsBlockBandData::ComputeAvailSpaceRect()
|
||||||
if (NS_UNCONSTRAINEDSIZE == mSpace.width) {
|
if (NS_UNCONSTRAINEDSIZE == mSpace.width) {
|
||||||
mAvailSpace.width = NS_UNCONSTRAINEDSIZE;
|
mAvailSpace.width = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
#ifdef REALLY_NOISY_COMPUTEAVAILSPACERECT
|
||||||
|
printf(" ComputeAvailSpaceRect settting state mAvailSpace (%d,%d,%d,%d)\n",
|
||||||
|
mAvailSpace.x, mAvailSpace.y, mAvailSpace.width, mAvailSpace.height);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -471,3 +480,15 @@ nsBlockBandData::GetMaxElementSize(nsIPresContext* aPresContext,
|
||||||
*aWidthResult = maxWidth;
|
*aWidthResult = maxWidth;
|
||||||
*aHeightResult = maxHeight;
|
*aHeightResult = maxHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void nsBlockBandData::List()
|
||||||
|
{
|
||||||
|
printf("nsBlockBandData %p sm=%p, sm coord = (%d,%d), mSpace = (%d,%d)\n",
|
||||||
|
this, mSpaceManager, mSpaceManagerX, mSpaceManagerY,
|
||||||
|
mSpace.width, mSpace.height);
|
||||||
|
printf(" availSpace=(%d, %d, %d, %d), floaters l=%d r=%d\n",
|
||||||
|
mAvailSpace.x, mAvailSpace.y, mAvailSpace.width, mAvailSpace.height,
|
||||||
|
mLeftFloaters, mRightFloaters);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -89,6 +89,10 @@ public:
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
nsSize* aResult);
|
nsSize* aResult);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void List();
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/** utility method to calculate the band data at aY.
|
/** utility method to calculate the band data at aY.
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Steve Clark <buster@netscape.com>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
*/
|
*/
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
@ -61,6 +63,8 @@
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
//#define NOISY_BLOCK_INVALIDATE // DO NOT CHECK THIS IN TURNED ON!
|
||||||
|
|
||||||
static PRBool gLamePaintMetrics;
|
static PRBool gLamePaintMetrics;
|
||||||
static PRBool gLameReflowMetrics;
|
static PRBool gLameReflowMetrics;
|
||||||
static PRBool gNoisy;
|
static PRBool gNoisy;
|
||||||
|
@ -451,12 +455,6 @@ public:
|
||||||
|
|
||||||
nscoord mBottomEdge;
|
nscoord mBottomEdge;
|
||||||
|
|
||||||
PRPackedBool mUnconstrainedWidth;
|
|
||||||
PRPackedBool mUnconstrainedHeight;
|
|
||||||
PRPackedBool mShrinkWrapWidth;
|
|
||||||
PRPackedBool mNeedResizeReflow;
|
|
||||||
PRPackedBool mIsInlineIncrReflow;
|
|
||||||
|
|
||||||
// The content area to reflow child frames within. The x/y
|
// The content area to reflow child frames within. The x/y
|
||||||
// coordinates are known to be mBorderPadding.left and
|
// coordinates are known to be mBorderPadding.left and
|
||||||
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
||||||
|
@ -464,15 +462,6 @@ public:
|
||||||
// unconstrained area.
|
// unconstrained area.
|
||||||
nsSize mContentArea;
|
nsSize mContentArea;
|
||||||
|
|
||||||
// Our wrapping behavior
|
|
||||||
PRPackedBool mNoWrap;
|
|
||||||
|
|
||||||
// Is this frame a root for top/bottom margin collapsing?
|
|
||||||
PRPackedBool mIsTopMarginRoot, mIsBottomMarginRoot;
|
|
||||||
|
|
||||||
// See ShouldApplyTopMargin
|
|
||||||
PRPackedBool mApplyTopMargin;
|
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
// This state is "running" state updated by the reflow of each line
|
// This state is "running" state updated by the reflow of each line
|
||||||
|
@ -541,15 +530,48 @@ public:
|
||||||
// being N^2.
|
// being N^2.
|
||||||
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
||||||
|
|
||||||
PRPackedBool mComputeMaxElementSize;
|
|
||||||
PRPackedBool mComputeMaximumWidth;
|
|
||||||
|
|
||||||
nsSize mMaxElementSize;
|
nsSize mMaxElementSize;
|
||||||
nscoord mMaximumWidth;
|
nscoord mMaximumWidth;
|
||||||
|
|
||||||
nscoord mMinLineHeight;
|
nscoord mMinLineHeight;
|
||||||
|
|
||||||
PRInt32 mLineNumber;
|
PRInt32 mLineNumber;
|
||||||
|
|
||||||
|
// block reflow state flags
|
||||||
|
#define BRS_UNCONSTRAINEDWIDTH 0x00000001
|
||||||
|
#define BRS_UNCONSTRAINEDHEIGHT 0x00000002
|
||||||
|
#define BRS_SHRINKWRAPWIDTH 0x00000004
|
||||||
|
#define BRS_NEEDRESIZEREFLOW 0x00000008
|
||||||
|
#define BRS_ISINLINEINCRREFLOW 0x00000010
|
||||||
|
#define BRS_NOWRAP 0x00000020
|
||||||
|
#define BRS_ISTOPMARGINROOT 0x00000040 // Is this frame a root for top/bottom margin collapsing?
|
||||||
|
#define BRS_ISBOTTOMMARGINROOT 0x00000080
|
||||||
|
#define BRS_APPLYTOPMARGIN 0x00000100 // See ShouldApplyTopMargin
|
||||||
|
#define BRS_COMPUTEMAXELEMENTSIZE 0x00000200
|
||||||
|
#define BRS_COMPUTEMAXWIDTH 0x00000400
|
||||||
|
#define BRS_LASTFLAG BRS_COMPUTEMAXWIDTH
|
||||||
|
|
||||||
|
PRInt16 mFlags;
|
||||||
|
|
||||||
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
|
||||||
|
if (aValue) { // set flag
|
||||||
|
mFlags |= aFlag;
|
||||||
|
}
|
||||||
|
else { // unset flag
|
||||||
|
mFlags &= ~aFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GetFlag(PRUint32 aFlag) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
PRBool result = (mFlags & aFlag);
|
||||||
|
if (result) return PR_TRUE;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX This is vile. Make it go away
|
// XXX This is vile. Make it go away
|
||||||
|
@ -574,29 +596,25 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
: mBlock(aFrame),
|
: mBlock(aFrame),
|
||||||
mPresContext(aPresContext),
|
mPresContext(aPresContext),
|
||||||
mReflowState(aReflowState),
|
mReflowState(aReflowState),
|
||||||
mNeedResizeReflow(PR_FALSE),
|
|
||||||
mIsInlineIncrReflow(PR_FALSE),
|
|
||||||
mIsTopMarginRoot(PR_FALSE),
|
|
||||||
mIsBottomMarginRoot(PR_FALSE),
|
|
||||||
mApplyTopMargin(PR_FALSE),
|
|
||||||
mNextRCFrame(nsnull),
|
mNextRCFrame(nsnull),
|
||||||
mPrevBottomMargin(0),
|
mPrevBottomMargin(0),
|
||||||
mLineNumber(0)
|
mLineNumber(0),
|
||||||
|
mFlags(0)
|
||||||
{
|
{
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
|
||||||
if (aBlockMarginRoot) {
|
if (aBlockMarginRoot) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.top) {
|
if (0 != aReflowState.mComputedBorderPadding.top) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (mIsTopMarginRoot) {
|
if (GetFlag(BRS_ISTOPMARGINROOT)) {
|
||||||
mApplyTopMargin = PR_TRUE;
|
SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSpaceManager = aReflowState.mSpaceManager;
|
mSpaceManager = aReflowState.mSpaceManager;
|
||||||
|
@ -617,21 +635,19 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Compute content area width (the content area is inside the border
|
// Compute content area width (the content area is inside the border
|
||||||
// and padding)
|
// and padding)
|
||||||
mUnconstrainedWidth = PR_FALSE;
|
|
||||||
mShrinkWrapWidth = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
||||||
mContentArea.width = aReflowState.mComputedWidth;
|
mContentArea.width = aReflowState.mComputedWidth;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
||||||
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
||||||
mUnconstrainedWidth = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
||||||
// Choose a width based on the content (shrink wrap width) up
|
// Choose a width based on the content (shrink wrap width) up
|
||||||
// to the maximum width
|
// to the maximum width
|
||||||
mContentArea.width = aReflowState.mComputedMaxWidth;
|
mContentArea.width = aReflowState.mComputedMaxWidth;
|
||||||
mShrinkWrapWidth = PR_TRUE;
|
SetFlag(BRS_SHRINKWRAPWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nscoord lr = borderPadding.left + borderPadding.right;
|
nscoord lr = borderPadding.left + borderPadding.right;
|
||||||
|
@ -646,7 +662,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
// specified style height then we may end up limiting our height if
|
// specified style height then we may end up limiting our height if
|
||||||
// the availableHeight is constrained (this situation occurs when we
|
// the availableHeight is constrained (this situation occurs when we
|
||||||
// are paginated).
|
// are paginated).
|
||||||
mUnconstrainedHeight = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
||||||
// We are in a paginated situation. The bottom edge is just inside
|
// We are in a paginated situation. The bottom edge is just inside
|
||||||
// the bottom border and padding. The content area height doesn't
|
// the bottom border and padding. The content area height doesn't
|
||||||
|
@ -657,7 +672,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
else {
|
else {
|
||||||
// When we are not in a paginated situation then we always use
|
// When we are not in a paginated situation then we always use
|
||||||
// an constrained height.
|
// an constrained height.
|
||||||
mUnconstrainedHeight = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE);
|
||||||
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,16 +689,17 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
switch (styleText->mWhiteSpace) {
|
switch (styleText->mWhiteSpace) {
|
||||||
case NS_STYLE_WHITESPACE_PRE:
|
case NS_STYLE_WHITESPACE_PRE:
|
||||||
case NS_STYLE_WHITESPACE_NOWRAP:
|
case NS_STYLE_WHITESPACE_NOWRAP:
|
||||||
mNoWrap = PR_TRUE;
|
SetFlag(BRS_NOWRAP, PR_TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mNoWrap = PR_FALSE;
|
SetFlag(BRS_NOWRAP, PR_FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mComputeMaxElementSize = nsnull != aMetrics.maxElementSize;
|
SetFlag(BRS_COMPUTEMAXELEMENTSIZE, (nsnull != aMetrics.maxElementSize));
|
||||||
mMaxElementSize.SizeTo(0, 0);
|
mMaxElementSize.SizeTo(0, 0);
|
||||||
mComputeMaximumWidth = NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH);
|
SetFlag(BRS_COMPUTEMAXWIDTH,
|
||||||
|
(NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH)));
|
||||||
mMaximumWidth = 0;
|
mMaximumWidth = 0;
|
||||||
|
|
||||||
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
||||||
|
@ -729,8 +745,12 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
const nsStyleDisplay* aDisplay,
|
const nsStyleDisplay* aDisplay,
|
||||||
nsRect& aResult)
|
nsRect& aResult)
|
||||||
{
|
{
|
||||||
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
|
printf("CBAS frame=%p has floater count %d\n", aFrame, mBand.GetFloaterCount());
|
||||||
|
mBand.List();
|
||||||
|
#endif
|
||||||
aResult.y = mY;
|
aResult.y = mY;
|
||||||
aResult.height = mUnconstrainedHeight
|
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mBottomEdge - mY;
|
: mBottomEdge - mY;
|
||||||
|
|
||||||
|
@ -749,7 +769,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// The child block will flow around the floater. Therefore
|
// The child block will flow around the floater. Therefore
|
||||||
// give it all of the available space.
|
// give it all of the available space.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
break;
|
break;
|
||||||
|
@ -776,7 +796,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine width
|
// determine width
|
||||||
if (mUnconstrainedWidth) {
|
if (GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -810,7 +830,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// doesn't matter therefore give the block element all of the
|
// doesn't matter therefore give the block element all of the
|
||||||
// available space since it will flow around the floater itself.
|
// available space since it will flow around the floater itself.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
}
|
}
|
||||||
|
@ -957,12 +977,12 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
|
||||||
#endif
|
#endif
|
||||||
mKidXMost = xmost;
|
mKidXMost = xmost;
|
||||||
}
|
}
|
||||||
if (mComputeMaxElementSize) {
|
if (GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If computing the maximum width, then update mMaximumWidth
|
// If computing the maximum width, then update mMaximumWidth
|
||||||
if (mComputeMaximumWidth) {
|
if (GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
UpdateMaximumWidth(aLine->mMaximumWidth);
|
UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,6 +1474,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
||||||
NS_BLOCK_MARGIN_ROOT & mState);
|
NS_BLOCK_MARGIN_ROOT & mState);
|
||||||
|
PRInt32 sizeofBRS = sizeof nsBlockReflowState;
|
||||||
|
|
||||||
if (eReflowReason_Resize != aReflowState.reason) {
|
if (eReflowReason_Resize != aReflowState.reason) {
|
||||||
RenumberLists(aPresContext);
|
RenumberLists(aPresContext);
|
||||||
|
@ -1462,7 +1483,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
PRBool isStyleChange = PR_FALSE;
|
PRBool isStyleChange = PR_FALSE;
|
||||||
state.mIsInlineIncrReflow = PR_FALSE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_FALSE);
|
||||||
nsIFrame* target;
|
nsIFrame* target;
|
||||||
switch (aReflowState.reason) {
|
switch (aReflowState.reason) {
|
||||||
case eReflowReason_Initial:
|
case eReflowReason_Initial:
|
||||||
|
@ -1535,7 +1556,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// reflow the line containing the target of the incr. reflow
|
// reflow the line containing the target of the incr. reflow
|
||||||
// first mark the line dirty and set up the state object
|
// first mark the line dirty and set up the state object
|
||||||
rv = PrepareChildIncrementalReflow(state);
|
rv = PrepareChildIncrementalReflow(state);
|
||||||
state.mIsInlineIncrReflow = PR_TRUE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_TRUE);
|
||||||
state.mPrevLine = prevLine;
|
state.mPrevLine = prevLine;
|
||||||
state.mCurrentLine = line;
|
state.mCurrentLine = line;
|
||||||
state.mNextRCFrame = state.mNextRCFrame;
|
state.mNextRCFrame = state.mNextRCFrame;
|
||||||
|
@ -1681,6 +1702,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
if (isStyleChange) {
|
if (isStyleChange) {
|
||||||
// Lots of things could have changed so damage our entire
|
// Lots of things could have changed so damage our entire
|
||||||
// bounds
|
// bounds
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 1 (%d, %d, %d, %d)\n",
|
||||||
|
this, 0, 0, mRect.width, mRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -1707,6 +1732,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = 0;
|
damageRect.y = 0;
|
||||||
damageRect.height = mRect.height;
|
damageRect.height = mRect.height;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 2 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1730,6 +1759,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = mRect.height - border.bottom;
|
damageRect.y = mRect.height - border.bottom;
|
||||||
damageRect.height = border.bottom;
|
damageRect.height = border.bottom;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 3 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1868,7 +1901,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
||||||
aState.mY, aState.mIsBottomMarginRoot ? "yes" : "no",
|
aState.mY, aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? "yes" : "no",
|
||||||
aState.mPrevBottomMargin,
|
aState.mPrevBottomMargin,
|
||||||
borderPadding.top, borderPadding.bottom);
|
borderPadding.top, borderPadding.bottom);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1946,7 +1979,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// contents or we fluff out to the maximum block width. Note:
|
// contents or we fluff out to the maximum block width. Note:
|
||||||
// We always shrink wrap when given an unconstrained width.
|
// We always shrink wrap when given an unconstrained width.
|
||||||
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
||||||
!aState.mUnconstrainedWidth && !aState.mShrinkWrapWidth &&
|
!aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) &&
|
||||||
!compact) {
|
!compact) {
|
||||||
// Set our width to the max width if we aren't already that
|
// Set our width to the max width if we aren't already that
|
||||||
// wide. Note that the max-width has nothing to do with our
|
// wide. Note that the max-width has nothing to do with our
|
||||||
|
@ -1956,9 +1989,9 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we should compute our max element size
|
// See if we should compute our max element size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Adjust the computedWidth
|
// Adjust the computedWidth
|
||||||
if (aState.mNoWrap) {
|
if (aState.GetFlag(BRS_NOWRAP)) {
|
||||||
// When no-wrap is true the max-element-size.width is the
|
// When no-wrap is true the max-element-size.width is the
|
||||||
// width of the widest line plus the right border. Note that
|
// width of the widest line plus the right border. Note that
|
||||||
// aState.mKidXMost already has the left border factored in
|
// aState.mKidXMost already has the left border factored in
|
||||||
|
@ -1996,7 +2029,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// need to do horizontal alignment of the inline lines and make sure
|
// need to do horizontal alignment of the inline lines and make sure
|
||||||
// blocks are correctly sized and positioned. Any lines that need
|
// blocks are correctly sized and positioned. Any lines that need
|
||||||
// final adjustment will have been marked as dirty
|
// final adjustment will have been marked as dirty
|
||||||
if (aState.mShrinkWrapWidth && aState.mNeedResizeReflow) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) {
|
||||||
// If the parent reflow state is also shrink wrap width, then
|
// If the parent reflow state is also shrink wrap width, then
|
||||||
// we don't need to do this, because it will reflow us after it
|
// we don't need to do this, because it will reflow us after it
|
||||||
// calculates the final width
|
// calculates the final width
|
||||||
|
@ -2025,7 +2058,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
||||||
if (aReflowState.parentReflowState) {
|
if (aReflowState.parentReflowState) {
|
||||||
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
||||||
|
@ -2047,7 +2080,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// Don't carry out a bottom margin when our height is fixed
|
// Don't carry out a bottom margin when our height is fixed
|
||||||
// unless the bottom of the last line adjoins the bottom of our
|
// unless the bottom of the last line adjoins the bottom of our
|
||||||
// content area.
|
// content area.
|
||||||
if (!aState.mIsBottomMarginRoot) {
|
if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
||||||
aState.mPrevBottomMargin = 0;
|
aState.mPrevBottomMargin = 0;
|
||||||
}
|
}
|
||||||
|
@ -2057,7 +2090,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
nscoord autoHeight = aState.mY;
|
nscoord autoHeight = aState.mY;
|
||||||
|
|
||||||
// Shrink wrap our height around our contents.
|
// Shrink wrap our height around our contents.
|
||||||
if (aState.mIsBottomMarginRoot) {
|
if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
// When we are a bottom-margin root make sure that our last
|
// When we are a bottom-margin root make sure that our last
|
||||||
// childs bottom margin is fully applied.
|
// childs bottom margin is fully applied.
|
||||||
// XXX check for a fit
|
// XXX check for a fit
|
||||||
|
@ -2082,7 +2115,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
aMetrics.height = autoHeight;
|
aMetrics.height = autoHeight;
|
||||||
|
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxHeight = aState.mMaxElementSize.height +
|
maxHeight = aState.mMaxElementSize.height +
|
||||||
borderPadding.top + borderPadding.bottom;
|
borderPadding.top + borderPadding.bottom;
|
||||||
}
|
}
|
||||||
|
@ -2090,7 +2123,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
aMetrics.ascent = aMetrics.height;
|
aMetrics.ascent = aMetrics.height;
|
||||||
aMetrics.descent = 0;
|
aMetrics.descent = 0;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Store away the final value
|
// Store away the final value
|
||||||
aMetrics.maxElementSize->width = maxWidth;
|
aMetrics.maxElementSize->width = maxWidth;
|
||||||
aMetrics.maxElementSize->height = maxHeight;
|
aMetrics.maxElementSize->height = maxHeight;
|
||||||
|
@ -2098,14 +2131,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Return bottom margin information
|
// Return bottom margin information
|
||||||
aMetrics.mCarriedOutBottomMargin =
|
aMetrics.mCarriedOutBottomMargin =
|
||||||
aState.mIsBottomMarginRoot ? 0 : aState.mPrevBottomMargin;
|
aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
||||||
}
|
}
|
||||||
if (aState.mComputeMaxElementSize &&
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) &&
|
||||||
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
||||||
|
@ -2115,7 +2148,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
printf("PASS1 ");
|
printf("PASS1 ");
|
||||||
|
@ -2130,7 +2163,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're requested to update our maximum width, then compute it
|
// If we're requested to update our maximum width, then compute it
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
// We need to add in for the right border/padding
|
// We need to add in for the right border/padding
|
||||||
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
||||||
}
|
}
|
||||||
|
@ -2337,8 +2370,13 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
// See if we can try and avoid marking all the lines as dirty
|
// See if we can try and avoid marking all the lines as dirty
|
||||||
PRBool tryAndSkipLines = PR_FALSE;
|
PRBool tryAndSkipLines = PR_FALSE;
|
||||||
|
|
||||||
// See if this is this a constrained resize reflow
|
// we need to calculate if any part of then block itself
|
||||||
if ((aState.mReflowState.reason == eReflowReason_Resize) &&
|
// is impacted by a floater (bug 19579)
|
||||||
|
aState.GetAvailableSpace();
|
||||||
|
|
||||||
|
// See if this is this a constrained resize reflow that is not impacted by floaters
|
||||||
|
if ((PR_FALSE==aState.IsImpactedByFloater()) &&
|
||||||
|
(aState.mReflowState.reason == eReflowReason_Resize) &&
|
||||||
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
||||||
|
|
||||||
// If the text is left-aligned, then we try and avoid reflowing the lines
|
// If the text is left-aligned, then we try and avoid reflowing the lines
|
||||||
|
@ -2389,7 +2427,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRBool notWrapping = aState.mNoWrap;
|
PRBool notWrapping = aState.GetFlag(BRS_NOWRAP);
|
||||||
while (nsnull != line) {
|
while (nsnull != line) {
|
||||||
|
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
|
@ -2402,8 +2440,6 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
||||||
line, line->IsImpactedByFloater() ? "" : "not ");
|
line, line->IsImpactedByFloater() ? "" : "not ");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (notWrapping) {
|
if (notWrapping) {
|
||||||
// When no-wrap is set then the only line-breaking that
|
// When no-wrap is set then the only line-breaking that
|
||||||
// occurs for inline lines is triggered by BR elements or by
|
// occurs for inline lines is triggered by BR elements or by
|
||||||
|
@ -2430,7 +2466,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
||||||
line, line->mNext,
|
line, line->mNext,
|
||||||
line->IsBlock() ? "block" : "inline",
|
line->IsBlock() ? "block" : "inline",
|
||||||
aState.mNoWrap ? "no-wrap" : "wrapping",
|
aState.GetFlag(BRS_NOWRAP) ? "no-wrap" : "wrapping",
|
||||||
line->HasBreak() ? "has-break " : "",
|
line->HasBreak() ? "has-break " : "",
|
||||||
line->HasFloaters() ? "has-floaters " : "",
|
line->HasFloaters() ? "has-floaters " : "",
|
||||||
line->IsImpactedByFloater() ? "impacted " : "",
|
line->IsImpactedByFloater() ? "impacted " : "",
|
||||||
|
@ -2628,7 +2664,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
||||||
kReflowCommandType[type], type,
|
kReflowCommandType[type], type,
|
||||||
aState.mIsInlineIncrReflow ? "true" : "false");
|
aState.GetFlag(BRS_ISINLINEINCRREFLOW) ? "true" : "false");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
IndentBy(stdout, gNoiseIndent);
|
IndentBy(stdout, gNoiseIndent);
|
||||||
|
@ -2651,7 +2687,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// Reflow the lines that are already ours
|
// Reflow the lines that are already ours
|
||||||
aState.mPrevLine = nsnull;
|
aState.mPrevLine = nsnull;
|
||||||
nsLineBox* line = mLines;
|
nsLineBox* line = mLines;
|
||||||
if (aState.mIsInlineIncrReflow && aState.mNextRCFrame)
|
if (aState.GetFlag(BRS_ISINLINEINCRREFLOW) && aState.mNextRCFrame)
|
||||||
{
|
{
|
||||||
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
||||||
aState.mCurrentLine = line;
|
aState.mCurrentLine = line;
|
||||||
|
@ -2662,6 +2698,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 4 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
aState.mPrevLine = line;
|
aState.mPrevLine = line;
|
||||||
|
@ -2689,7 +2729,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// If we're supposed to update our maximum width, then we'll also need to
|
// If we're supposed to update our maximum width, then we'll also need to
|
||||||
// reflow this line if it's line wrapped and any of the continuing lines
|
// reflow this line if it's line wrapped and any of the continuing lines
|
||||||
// are dirty
|
// are dirty
|
||||||
if (line->IsDirty() || (aState.mComputeMaximumWidth && ::WrappedLinesAreDirty(line))) {
|
if (line->IsDirty() || (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && ::WrappedLinesAreDirty(line))) {
|
||||||
// Compute the dirty lines "before" YMost, after factoring in
|
// Compute the dirty lines "before" YMost, after factoring in
|
||||||
// the running deltaY value - the running value is implicit in
|
// the running deltaY value - the running value is implicit in
|
||||||
// aState.mY.
|
// aState.mY.
|
||||||
|
@ -2729,6 +2769,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 5 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2902,6 +2946,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// XXX We need to improve on this...
|
// XXX We need to improve on this...
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 6 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -2918,6 +2966,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.x;
|
dirtyRect.x;
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
||||||
lineCombinedArea.height);
|
lineCombinedArea.height);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 7 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
if (oldCombinedArea.height != lineCombinedArea.height) {
|
if (oldCombinedArea.height != lineCombinedArea.height) {
|
||||||
|
@ -2933,6 +2985,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
||||||
lineCombinedArea.YMost()) -
|
lineCombinedArea.YMost()) -
|
||||||
dirtyRect.y;
|
dirtyRect.y;
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 8 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2951,21 +3007,21 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// we'll either need to recover the floater state that applies to the
|
// we'll either need to recover the floater state that applies to the
|
||||||
// unconstrained reflow or keep it around in a separate space manager...
|
// unconstrained reflow or keep it around in a separate space manager...
|
||||||
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
||||||
if (aState.mComputeMaximumWidth && isBeginningLine) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && isBeginningLine) {
|
||||||
nscoord oldY = aState.mY;
|
nscoord oldY = aState.mY;
|
||||||
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
||||||
PRBool oldUnconstrainedWidth = aState.mUnconstrainedWidth;
|
PRBool oldUnconstrainedWidth = aState.GetFlag(BRS_UNCONSTRAINEDWIDTH);
|
||||||
|
|
||||||
// First reflow the line with an unconstrained width. When doing this
|
// First reflow the line with an unconstrained width. When doing this
|
||||||
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
||||||
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
||||||
// associated floater we don't end up resetting the line's right edge and
|
// associated floater we don't end up resetting the line's right edge and
|
||||||
// have it think the width is unconstrained...
|
// have it think the width is unconstrained...
|
||||||
aState.mUnconstrainedWidth = PR_TRUE;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
||||||
aState.mY = oldY;
|
aState.mY = oldY;
|
||||||
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
||||||
aState.mUnconstrainedWidth = oldUnconstrainedWidth;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, oldUnconstrainedWidth);
|
||||||
|
|
||||||
// Update the line's maximum width
|
// Update the line's maximum width
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
|
@ -2980,14 +3036,14 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// Note: we need to reset both member variables, because the inline
|
// Note: we need to reset both member variables, because the inline
|
||||||
// code examines mComputeMaxElementSize and if there is a placeholder
|
// code examines mComputeMaxElementSize and if there is a placeholder
|
||||||
// on this line the code to reflow the floater looks at both...
|
// on this line the code to reflow the floater looks at both...
|
||||||
nscoord oldComputeMaxElementSize = aState.mComputeMaxElementSize;
|
nscoord oldComputeMaxElementSize = aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE);
|
||||||
nscoord oldComputeMaximumWidth = aState.mComputeMaximumWidth;
|
nscoord oldComputeMaximumWidth = aState.GetFlag(BRS_COMPUTEMAXWIDTH);
|
||||||
|
|
||||||
aState.mComputeMaxElementSize = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, PR_FALSE);
|
||||||
aState.mComputeMaximumWidth = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, PR_FALSE);
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
aState.mComputeMaxElementSize = oldComputeMaxElementSize;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, oldComputeMaxElementSize);
|
||||||
aState.mComputeMaximumWidth = oldComputeMaximumWidth;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, oldComputeMaximumWidth);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
|
@ -3001,6 +3057,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
|
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 9 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3368,7 +3428,7 @@ PRBool
|
||||||
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
nsLineBox* aLine)
|
nsLineBox* aLine)
|
||||||
{
|
{
|
||||||
if (aState.mApplyTopMargin) {
|
if (aState.GetFlag(BRS_APPLYTOPMARGIN)) {
|
||||||
// Apply short-circuit check to avoid searching the line list
|
// Apply short-circuit check to avoid searching the line list
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -3377,7 +3437,7 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
// If we aren't at the top Y coordinate then something of non-zero
|
// If we aren't at the top Y coordinate then something of non-zero
|
||||||
// height must have been placed. Therefore the childs top-margin
|
// height must have been placed. Therefore the childs top-margin
|
||||||
// applies.
|
// applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3387,13 +3447,13 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
// A line which preceeds aLine contains a block; therefore the
|
// A line which preceeds aLine contains a block; therefore the
|
||||||
// top margin applies.
|
// top margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else if (line->HasFloaters()) {
|
else if (line->HasFloaters()) {
|
||||||
// A line which preceeds aLine is not empty therefore the top
|
// A line which preceeds aLine is not empty therefore the top
|
||||||
// margin applies.
|
// margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
line = line->mNext;
|
line = line->mNext;
|
||||||
|
@ -3486,8 +3546,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
frame->GetStyleData(eStyleStruct_Display,
|
frame->GetStyleData(eStyleStruct_Display,
|
||||||
(const nsStyleStruct*&) display);
|
(const nsStyleStruct*&) display);
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// See if we should apply the top margin. If the block frame being
|
// See if we should apply the top margin. If the block frame being
|
||||||
|
@ -3611,14 +3671,14 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
&collapsedBottomMargin,
|
&collapsedBottomMargin,
|
||||||
aLine->mBounds, combinedArea);
|
aLine->mBounds, combinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line as block so once we known the final shrink wrap width
|
// Mark the line as block so once we known the final shrink wrap width
|
||||||
// we can reflow the block to the correct size
|
// we can reflow the block to the correct size
|
||||||
// XXX We don't always need to do this...
|
// XXX We don't always need to do this...
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (aState.mUnconstrainedWidth || aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Add the right margin to the line's bounnds. That way it will be taken into
|
// Add the right margin to the line's bounnds. That way it will be taken into
|
||||||
// account when we compute our shrink wrap size
|
// account when we compute our shrink wrap size
|
||||||
nscoord marginRight = brc.GetMargin().right;
|
nscoord marginRight = brc.GetMargin().right;
|
||||||
|
@ -3709,7 +3769,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Post-process the "line"
|
// Post-process the "line"
|
||||||
nsSize maxElementSize(0, 0);
|
nsSize maxElementSize(0, 0);
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxElementSize = brc.GetMaxElementSize();
|
maxElementSize = brc.GetMaxElementSize();
|
||||||
if (aState.IsImpactedByFloater() &&
|
if (aState.IsImpactedByFloater() &&
|
||||||
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
||||||
|
@ -3721,7 +3781,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
// If we asked the block to update its maximum width, then record the
|
// If we asked the block to update its maximum width, then record the
|
||||||
// updated value in the line, and update the current maximum width
|
// updated value in the line, and update the current maximum width
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
||||||
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
|
|
||||||
|
@ -3849,7 +3909,7 @@ nsBlockFrame::DoReflowInlineFramesMalloc(nsBlockReflowState& aState,
|
||||||
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -3872,7 +3932,7 @@ nsBlockFrame::DoReflowInlineFramesAuto(nsBlockReflowState& aState,
|
||||||
nsLineLayout lineLayout(aState.mPresContext,
|
nsLineLayout lineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
||||||
lineLayout.SetReflowTextRuns(mTextRuns);
|
lineLayout.SetReflowTextRuns(mTextRuns);
|
||||||
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
||||||
|
@ -3910,7 +3970,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
||||||
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
||||||
nscoord availWidth = aState.mAvailSpaceRect.width;
|
nscoord availWidth = aState.mAvailSpaceRect.width;
|
||||||
nscoord availHeight;
|
nscoord availHeight;
|
||||||
if (aState.mUnconstrainedHeight) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
|
||||||
availHeight = NS_UNCONSTRAINEDSIZE;
|
availHeight = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4359,7 +4419,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
nsSize maxElementSize;
|
nsSize maxElementSize;
|
||||||
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
||||||
// See if we're shrink wrapping the width
|
// See if we're shrink wrapping the width
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// When determining the line's width we also need to include any
|
// When determining the line's width we also need to include any
|
||||||
// right floaters that impact us. This represents the shrink wrap
|
// right floaters that impact us. This represents the shrink wrap
|
||||||
// width of the line
|
// width of the line
|
||||||
|
@ -4388,25 +4448,20 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// Only block frames horizontally align their children because
|
// Only block frames horizontally align their children because
|
||||||
// inline frames "shrink-wrap" around their children (therefore
|
// inline frames "shrink-wrap" around their children (therefore
|
||||||
// there is no extra horizontal space).
|
// there is no extra horizontal space).
|
||||||
#if XXX_fix_me
|
const nsStyleText* styleText = (const nsStyleText*)
|
||||||
PRBool allowJustify = PR_TRUE;
|
mStyleContext->GetStyleData(eStyleStruct_Text);
|
||||||
if (NS_STYLE_TEXT_ALIGN_JUSTIFY == aState.mStyleText->mTextAlign) {
|
PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign
|
||||||
allowJustify = ShouldJustifyLine(aState, aLine);
|
&& !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine);
|
||||||
}
|
PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
||||||
#else
|
aState.GetFlag(BRS_SHRINKWRAPWIDTH));
|
||||||
PRBool allowJustify = PR_FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PRBool successful;
|
|
||||||
nsRect combinedArea;
|
|
||||||
successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
|
||||||
aState.mShrinkWrapWidth);
|
|
||||||
if (!successful) {
|
if (!successful) {
|
||||||
// Mark the line dirty and then later once we've determined the width
|
// Mark the line dirty and then later once we've determined the width
|
||||||
// we can do the horizontal alignment
|
// we can do the horizontal alignment
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsRect combinedArea;
|
||||||
aLineLayout.RelativePositionFrames(combinedArea);
|
aLineLayout.RelativePositionFrames(combinedArea);
|
||||||
aLine->SetCombinedArea(combinedArea);
|
aLine->SetCombinedArea(combinedArea);
|
||||||
if (addedBullet) {
|
if (addedBullet) {
|
||||||
|
@ -4454,7 +4509,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
aState.mY = newY;
|
aState.mY = newY;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
|
@ -4478,7 +4533,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// we don't want updated...
|
// we don't want updated...
|
||||||
if (aUpdateMaximumWidth) {
|
if (aUpdateMaximumWidth) {
|
||||||
// However, we do need to update the max-element-size if requested
|
// However, we do need to update the max-element-size if requested
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(maxElementSize);
|
aState.UpdateMaxElementSize(maxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4519,7 +4574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mHaveRightFloaters &&
|
if (aState.mHaveRightFloaters &&
|
||||||
(aState.mUnconstrainedWidth || aState.mShrinkWrapWidth)) {
|
(aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// We are reflowing in an unconstrained situation or shrink wrapping and
|
// We are reflowing in an unconstrained situation or shrink wrapping and
|
||||||
// have some right floaters. They were placed at the infinite right edge
|
// have some right floaters. They were placed at the infinite right edge
|
||||||
// which will cause the combined area to be unusable.
|
// which will cause the combined area to be unusable.
|
||||||
|
@ -4540,11 +4595,11 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
||||||
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line dirty so we come back and re-place the floater once
|
// Mark the line dirty so we come back and re-place the floater once
|
||||||
// the shrink wrap width is determined
|
// the shrink wrap width is determined
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aLine->SetCombinedArea(lineCombinedArea);
|
aLine->SetCombinedArea(lineCombinedArea);
|
||||||
|
@ -4629,7 +4684,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update max-element-size
|
// Update max-element-size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(aMaxElementSize);
|
aState.UpdateMaxElementSize(aMaxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4639,7 +4694,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
// If this is an unconstrained reflow, then cache the line width in the
|
// If this is an unconstrained reflow, then cache the line width in the
|
||||||
// line. We'll need this during incremental reflow if we're asked to
|
// line. We'll need this during incremental reflow if we're asked to
|
||||||
// calculate the maximum width
|
// calculate the maximum width
|
||||||
if (aState.mUnconstrainedWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4653,7 +4708,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
#endif
|
#endif
|
||||||
// If we're shrink wrapping our width and the line was wrapped,
|
// If we're shrink wrapping our width and the line was wrapped,
|
||||||
// then make sure we take up all of the available width
|
// then make sure we take up all of the available width
|
||||||
if (aState.mShrinkWrapWidth && aLine->IsLineWrapped()) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aLine->IsLineWrapped()) {
|
||||||
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5187,6 +5242,10 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
||||||
// cases...
|
// cases...
|
||||||
nsRect lineCombinedArea;
|
nsRect lineCombinedArea;
|
||||||
line->GetCombinedArea(&lineCombinedArea);
|
line->GetCombinedArea(&lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 10 (%d, %d, %d, %d)\n",
|
||||||
|
this, lineCombinedArea.x, lineCombinedArea.y, lineCombinedArea.width, lineCombinedArea.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, lineCombinedArea);
|
Invalidate(aPresContext, lineCombinedArea);
|
||||||
line->Destroy(presShell);
|
line->Destroy(presShell);
|
||||||
line = next;
|
line = next;
|
||||||
|
@ -5282,8 +5341,8 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Setup block reflow state to reflow the floater
|
// Setup block reflow state to reflow the floater
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// Reflow the floater
|
// Reflow the floater
|
||||||
|
@ -5324,7 +5383,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||||
|
|
||||||
// If we computed it, then stash away the max-element-size for later
|
// If we computed it, then stash away the max-element-size for later
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5389,7 +5448,7 @@ nsBlockReflowState::AddFloater(nsLineLayout& aLineLayout,
|
||||||
// Pass on updated available space to the current inline reflow engine
|
// Pass on updated available space to the current inline reflow engine
|
||||||
GetAvailableSpace();
|
GetAvailableSpace();
|
||||||
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
||||||
mUnconstrainedWidth ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
GetFlag(BRS_UNCONSTRAINEDWIDTH) ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
||||||
mAvailSpaceRect.height,
|
mAvailSpaceRect.height,
|
||||||
isLeftFloater,
|
isLeftFloater,
|
||||||
aPlaceholder->GetOutOfFlowFrame());
|
aPlaceholder->GetOutOfFlowFrame());
|
||||||
|
@ -5615,7 +5674,12 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isLeftFloater = PR_FALSE;
|
isLeftFloater = PR_FALSE;
|
||||||
region.x = mAvailSpaceRect.XMost() - region.width;
|
if (NS_UNCONSTRAINEDSIZE != mAvailSpaceRect.XMost())
|
||||||
|
region.x = mAvailSpaceRect.XMost() - region.width;
|
||||||
|
else {
|
||||||
|
okToAddRectRegion = PR_FALSE;
|
||||||
|
region.x = mAvailSpaceRect.x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*aIsLeftFloater = isLeftFloater;
|
*aIsLeftFloater = isLeftFloater;
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
@ -5682,7 +5746,8 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
||||||
combinedArea.x += x;
|
combinedArea.x += x;
|
||||||
combinedArea.y += y;
|
combinedArea.y += y;
|
||||||
if (!isLeftFloater && (mUnconstrainedWidth || mShrinkWrapWidth)) {
|
if (!isLeftFloater &&
|
||||||
|
(GetFlag(BRS_UNCONSTRAINEDWIDTH) || GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// When we are placing a right floater in an unconstrained situation or
|
// When we are placing a right floater in an unconstrained situation or
|
||||||
// when shrink wrapping, we don't apply it to the floater combined area
|
// when shrink wrapping, we don't apply it to the floater combined area
|
||||||
// immediately. Otherwise we end up with an infinitely wide combined
|
// immediately. Otherwise we end up with an infinitely wide combined
|
||||||
|
|
|
@ -197,10 +197,12 @@ nsBlockReflowContext::AlignBlockHorizontally(nscoord aWidth,
|
||||||
// compatability cases.
|
// compatability cases.
|
||||||
switch (styleText->mTextAlign) {
|
switch (styleText->mTextAlign) {
|
||||||
case NS_STYLE_TEXT_ALIGN_MOZ_RIGHT:
|
case NS_STYLE_TEXT_ALIGN_MOZ_RIGHT:
|
||||||
|
case NS_STYLE_TEXT_ALIGN_RIGHT:
|
||||||
aAlign.mXOffset += remainingSpace;
|
aAlign.mXOffset += remainingSpace;
|
||||||
doCSS = PR_FALSE;
|
doCSS = PR_FALSE;
|
||||||
break;
|
break;
|
||||||
case NS_STYLE_TEXT_ALIGN_MOZ_CENTER:
|
case NS_STYLE_TEXT_ALIGN_MOZ_CENTER:
|
||||||
|
case NS_STYLE_TEXT_ALIGN_CENTER:
|
||||||
aAlign.mXOffset += remainingSpace / 2;
|
aAlign.mXOffset += remainingSpace / 2;
|
||||||
doCSS = PR_FALSE;
|
doCSS = PR_FALSE;
|
||||||
break;
|
break;
|
||||||
|
@ -359,7 +361,11 @@ nsBlockReflowContext::ReflowBlock(nsIFrame* aFrame,
|
||||||
reflowState.mComputedBorderPadding.right;
|
reflowState.mComputedBorderPadding.right;
|
||||||
}
|
}
|
||||||
|
|
||||||
x = aSpace.XMost() - mMargin.right - frameWidth;
|
// if this is an unconstrained width reflow, then just place the floater at the left margin
|
||||||
|
if (NS_UNCONSTRAINEDSIZE == aSpace.width)
|
||||||
|
x = aSpace.x;
|
||||||
|
else
|
||||||
|
x = aSpace.XMost() - mMargin.right - frameWidth;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
x = aSpace.x + mMargin.left;
|
x = aSpace.x + mMargin.left;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Steve Clark <buster@netscape.com>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
*/
|
*/
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
@ -61,6 +63,8 @@
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
//#define NOISY_BLOCK_INVALIDATE // DO NOT CHECK THIS IN TURNED ON!
|
||||||
|
|
||||||
static PRBool gLamePaintMetrics;
|
static PRBool gLamePaintMetrics;
|
||||||
static PRBool gLameReflowMetrics;
|
static PRBool gLameReflowMetrics;
|
||||||
static PRBool gNoisy;
|
static PRBool gNoisy;
|
||||||
|
@ -451,12 +455,6 @@ public:
|
||||||
|
|
||||||
nscoord mBottomEdge;
|
nscoord mBottomEdge;
|
||||||
|
|
||||||
PRPackedBool mUnconstrainedWidth;
|
|
||||||
PRPackedBool mUnconstrainedHeight;
|
|
||||||
PRPackedBool mShrinkWrapWidth;
|
|
||||||
PRPackedBool mNeedResizeReflow;
|
|
||||||
PRPackedBool mIsInlineIncrReflow;
|
|
||||||
|
|
||||||
// The content area to reflow child frames within. The x/y
|
// The content area to reflow child frames within. The x/y
|
||||||
// coordinates are known to be mBorderPadding.left and
|
// coordinates are known to be mBorderPadding.left and
|
||||||
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
||||||
|
@ -464,15 +462,6 @@ public:
|
||||||
// unconstrained area.
|
// unconstrained area.
|
||||||
nsSize mContentArea;
|
nsSize mContentArea;
|
||||||
|
|
||||||
// Our wrapping behavior
|
|
||||||
PRPackedBool mNoWrap;
|
|
||||||
|
|
||||||
// Is this frame a root for top/bottom margin collapsing?
|
|
||||||
PRPackedBool mIsTopMarginRoot, mIsBottomMarginRoot;
|
|
||||||
|
|
||||||
// See ShouldApplyTopMargin
|
|
||||||
PRPackedBool mApplyTopMargin;
|
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
// This state is "running" state updated by the reflow of each line
|
// This state is "running" state updated by the reflow of each line
|
||||||
|
@ -541,15 +530,48 @@ public:
|
||||||
// being N^2.
|
// being N^2.
|
||||||
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
||||||
|
|
||||||
PRPackedBool mComputeMaxElementSize;
|
|
||||||
PRPackedBool mComputeMaximumWidth;
|
|
||||||
|
|
||||||
nsSize mMaxElementSize;
|
nsSize mMaxElementSize;
|
||||||
nscoord mMaximumWidth;
|
nscoord mMaximumWidth;
|
||||||
|
|
||||||
nscoord mMinLineHeight;
|
nscoord mMinLineHeight;
|
||||||
|
|
||||||
PRInt32 mLineNumber;
|
PRInt32 mLineNumber;
|
||||||
|
|
||||||
|
// block reflow state flags
|
||||||
|
#define BRS_UNCONSTRAINEDWIDTH 0x00000001
|
||||||
|
#define BRS_UNCONSTRAINEDHEIGHT 0x00000002
|
||||||
|
#define BRS_SHRINKWRAPWIDTH 0x00000004
|
||||||
|
#define BRS_NEEDRESIZEREFLOW 0x00000008
|
||||||
|
#define BRS_ISINLINEINCRREFLOW 0x00000010
|
||||||
|
#define BRS_NOWRAP 0x00000020
|
||||||
|
#define BRS_ISTOPMARGINROOT 0x00000040 // Is this frame a root for top/bottom margin collapsing?
|
||||||
|
#define BRS_ISBOTTOMMARGINROOT 0x00000080
|
||||||
|
#define BRS_APPLYTOPMARGIN 0x00000100 // See ShouldApplyTopMargin
|
||||||
|
#define BRS_COMPUTEMAXELEMENTSIZE 0x00000200
|
||||||
|
#define BRS_COMPUTEMAXWIDTH 0x00000400
|
||||||
|
#define BRS_LASTFLAG BRS_COMPUTEMAXWIDTH
|
||||||
|
|
||||||
|
PRInt16 mFlags;
|
||||||
|
|
||||||
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
|
||||||
|
if (aValue) { // set flag
|
||||||
|
mFlags |= aFlag;
|
||||||
|
}
|
||||||
|
else { // unset flag
|
||||||
|
mFlags &= ~aFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GetFlag(PRUint32 aFlag) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
PRBool result = (mFlags & aFlag);
|
||||||
|
if (result) return PR_TRUE;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX This is vile. Make it go away
|
// XXX This is vile. Make it go away
|
||||||
|
@ -574,29 +596,25 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
: mBlock(aFrame),
|
: mBlock(aFrame),
|
||||||
mPresContext(aPresContext),
|
mPresContext(aPresContext),
|
||||||
mReflowState(aReflowState),
|
mReflowState(aReflowState),
|
||||||
mNeedResizeReflow(PR_FALSE),
|
|
||||||
mIsInlineIncrReflow(PR_FALSE),
|
|
||||||
mIsTopMarginRoot(PR_FALSE),
|
|
||||||
mIsBottomMarginRoot(PR_FALSE),
|
|
||||||
mApplyTopMargin(PR_FALSE),
|
|
||||||
mNextRCFrame(nsnull),
|
mNextRCFrame(nsnull),
|
||||||
mPrevBottomMargin(0),
|
mPrevBottomMargin(0),
|
||||||
mLineNumber(0)
|
mLineNumber(0),
|
||||||
|
mFlags(0)
|
||||||
{
|
{
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
|
||||||
if (aBlockMarginRoot) {
|
if (aBlockMarginRoot) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.top) {
|
if (0 != aReflowState.mComputedBorderPadding.top) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (mIsTopMarginRoot) {
|
if (GetFlag(BRS_ISTOPMARGINROOT)) {
|
||||||
mApplyTopMargin = PR_TRUE;
|
SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSpaceManager = aReflowState.mSpaceManager;
|
mSpaceManager = aReflowState.mSpaceManager;
|
||||||
|
@ -617,21 +635,19 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Compute content area width (the content area is inside the border
|
// Compute content area width (the content area is inside the border
|
||||||
// and padding)
|
// and padding)
|
||||||
mUnconstrainedWidth = PR_FALSE;
|
|
||||||
mShrinkWrapWidth = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
||||||
mContentArea.width = aReflowState.mComputedWidth;
|
mContentArea.width = aReflowState.mComputedWidth;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
||||||
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
||||||
mUnconstrainedWidth = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
||||||
// Choose a width based on the content (shrink wrap width) up
|
// Choose a width based on the content (shrink wrap width) up
|
||||||
// to the maximum width
|
// to the maximum width
|
||||||
mContentArea.width = aReflowState.mComputedMaxWidth;
|
mContentArea.width = aReflowState.mComputedMaxWidth;
|
||||||
mShrinkWrapWidth = PR_TRUE;
|
SetFlag(BRS_SHRINKWRAPWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nscoord lr = borderPadding.left + borderPadding.right;
|
nscoord lr = borderPadding.left + borderPadding.right;
|
||||||
|
@ -646,7 +662,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
// specified style height then we may end up limiting our height if
|
// specified style height then we may end up limiting our height if
|
||||||
// the availableHeight is constrained (this situation occurs when we
|
// the availableHeight is constrained (this situation occurs when we
|
||||||
// are paginated).
|
// are paginated).
|
||||||
mUnconstrainedHeight = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
||||||
// We are in a paginated situation. The bottom edge is just inside
|
// We are in a paginated situation. The bottom edge is just inside
|
||||||
// the bottom border and padding. The content area height doesn't
|
// the bottom border and padding. The content area height doesn't
|
||||||
|
@ -657,7 +672,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
else {
|
else {
|
||||||
// When we are not in a paginated situation then we always use
|
// When we are not in a paginated situation then we always use
|
||||||
// an constrained height.
|
// an constrained height.
|
||||||
mUnconstrainedHeight = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE);
|
||||||
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,16 +689,17 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
switch (styleText->mWhiteSpace) {
|
switch (styleText->mWhiteSpace) {
|
||||||
case NS_STYLE_WHITESPACE_PRE:
|
case NS_STYLE_WHITESPACE_PRE:
|
||||||
case NS_STYLE_WHITESPACE_NOWRAP:
|
case NS_STYLE_WHITESPACE_NOWRAP:
|
||||||
mNoWrap = PR_TRUE;
|
SetFlag(BRS_NOWRAP, PR_TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mNoWrap = PR_FALSE;
|
SetFlag(BRS_NOWRAP, PR_FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mComputeMaxElementSize = nsnull != aMetrics.maxElementSize;
|
SetFlag(BRS_COMPUTEMAXELEMENTSIZE, (nsnull != aMetrics.maxElementSize));
|
||||||
mMaxElementSize.SizeTo(0, 0);
|
mMaxElementSize.SizeTo(0, 0);
|
||||||
mComputeMaximumWidth = NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH);
|
SetFlag(BRS_COMPUTEMAXWIDTH,
|
||||||
|
(NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH)));
|
||||||
mMaximumWidth = 0;
|
mMaximumWidth = 0;
|
||||||
|
|
||||||
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
||||||
|
@ -729,8 +745,12 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
const nsStyleDisplay* aDisplay,
|
const nsStyleDisplay* aDisplay,
|
||||||
nsRect& aResult)
|
nsRect& aResult)
|
||||||
{
|
{
|
||||||
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
|
printf("CBAS frame=%p has floater count %d\n", aFrame, mBand.GetFloaterCount());
|
||||||
|
mBand.List();
|
||||||
|
#endif
|
||||||
aResult.y = mY;
|
aResult.y = mY;
|
||||||
aResult.height = mUnconstrainedHeight
|
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mBottomEdge - mY;
|
: mBottomEdge - mY;
|
||||||
|
|
||||||
|
@ -749,7 +769,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// The child block will flow around the floater. Therefore
|
// The child block will flow around the floater. Therefore
|
||||||
// give it all of the available space.
|
// give it all of the available space.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
break;
|
break;
|
||||||
|
@ -776,7 +796,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine width
|
// determine width
|
||||||
if (mUnconstrainedWidth) {
|
if (GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -810,7 +830,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// doesn't matter therefore give the block element all of the
|
// doesn't matter therefore give the block element all of the
|
||||||
// available space since it will flow around the floater itself.
|
// available space since it will flow around the floater itself.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
}
|
}
|
||||||
|
@ -957,12 +977,12 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
|
||||||
#endif
|
#endif
|
||||||
mKidXMost = xmost;
|
mKidXMost = xmost;
|
||||||
}
|
}
|
||||||
if (mComputeMaxElementSize) {
|
if (GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If computing the maximum width, then update mMaximumWidth
|
// If computing the maximum width, then update mMaximumWidth
|
||||||
if (mComputeMaximumWidth) {
|
if (GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
UpdateMaximumWidth(aLine->mMaximumWidth);
|
UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,6 +1474,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
||||||
NS_BLOCK_MARGIN_ROOT & mState);
|
NS_BLOCK_MARGIN_ROOT & mState);
|
||||||
|
PRInt32 sizeofBRS = sizeof nsBlockReflowState;
|
||||||
|
|
||||||
if (eReflowReason_Resize != aReflowState.reason) {
|
if (eReflowReason_Resize != aReflowState.reason) {
|
||||||
RenumberLists(aPresContext);
|
RenumberLists(aPresContext);
|
||||||
|
@ -1462,7 +1483,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
PRBool isStyleChange = PR_FALSE;
|
PRBool isStyleChange = PR_FALSE;
|
||||||
state.mIsInlineIncrReflow = PR_FALSE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_FALSE);
|
||||||
nsIFrame* target;
|
nsIFrame* target;
|
||||||
switch (aReflowState.reason) {
|
switch (aReflowState.reason) {
|
||||||
case eReflowReason_Initial:
|
case eReflowReason_Initial:
|
||||||
|
@ -1535,7 +1556,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// reflow the line containing the target of the incr. reflow
|
// reflow the line containing the target of the incr. reflow
|
||||||
// first mark the line dirty and set up the state object
|
// first mark the line dirty and set up the state object
|
||||||
rv = PrepareChildIncrementalReflow(state);
|
rv = PrepareChildIncrementalReflow(state);
|
||||||
state.mIsInlineIncrReflow = PR_TRUE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_TRUE);
|
||||||
state.mPrevLine = prevLine;
|
state.mPrevLine = prevLine;
|
||||||
state.mCurrentLine = line;
|
state.mCurrentLine = line;
|
||||||
state.mNextRCFrame = state.mNextRCFrame;
|
state.mNextRCFrame = state.mNextRCFrame;
|
||||||
|
@ -1681,6 +1702,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
if (isStyleChange) {
|
if (isStyleChange) {
|
||||||
// Lots of things could have changed so damage our entire
|
// Lots of things could have changed so damage our entire
|
||||||
// bounds
|
// bounds
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 1 (%d, %d, %d, %d)\n",
|
||||||
|
this, 0, 0, mRect.width, mRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -1707,6 +1732,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = 0;
|
damageRect.y = 0;
|
||||||
damageRect.height = mRect.height;
|
damageRect.height = mRect.height;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 2 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1730,6 +1759,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = mRect.height - border.bottom;
|
damageRect.y = mRect.height - border.bottom;
|
||||||
damageRect.height = border.bottom;
|
damageRect.height = border.bottom;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 3 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1868,7 +1901,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
||||||
aState.mY, aState.mIsBottomMarginRoot ? "yes" : "no",
|
aState.mY, aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? "yes" : "no",
|
||||||
aState.mPrevBottomMargin,
|
aState.mPrevBottomMargin,
|
||||||
borderPadding.top, borderPadding.bottom);
|
borderPadding.top, borderPadding.bottom);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1946,7 +1979,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// contents or we fluff out to the maximum block width. Note:
|
// contents or we fluff out to the maximum block width. Note:
|
||||||
// We always shrink wrap when given an unconstrained width.
|
// We always shrink wrap when given an unconstrained width.
|
||||||
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
||||||
!aState.mUnconstrainedWidth && !aState.mShrinkWrapWidth &&
|
!aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) &&
|
||||||
!compact) {
|
!compact) {
|
||||||
// Set our width to the max width if we aren't already that
|
// Set our width to the max width if we aren't already that
|
||||||
// wide. Note that the max-width has nothing to do with our
|
// wide. Note that the max-width has nothing to do with our
|
||||||
|
@ -1956,9 +1989,9 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we should compute our max element size
|
// See if we should compute our max element size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Adjust the computedWidth
|
// Adjust the computedWidth
|
||||||
if (aState.mNoWrap) {
|
if (aState.GetFlag(BRS_NOWRAP)) {
|
||||||
// When no-wrap is true the max-element-size.width is the
|
// When no-wrap is true the max-element-size.width is the
|
||||||
// width of the widest line plus the right border. Note that
|
// width of the widest line plus the right border. Note that
|
||||||
// aState.mKidXMost already has the left border factored in
|
// aState.mKidXMost already has the left border factored in
|
||||||
|
@ -1996,7 +2029,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// need to do horizontal alignment of the inline lines and make sure
|
// need to do horizontal alignment of the inline lines and make sure
|
||||||
// blocks are correctly sized and positioned. Any lines that need
|
// blocks are correctly sized and positioned. Any lines that need
|
||||||
// final adjustment will have been marked as dirty
|
// final adjustment will have been marked as dirty
|
||||||
if (aState.mShrinkWrapWidth && aState.mNeedResizeReflow) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) {
|
||||||
// If the parent reflow state is also shrink wrap width, then
|
// If the parent reflow state is also shrink wrap width, then
|
||||||
// we don't need to do this, because it will reflow us after it
|
// we don't need to do this, because it will reflow us after it
|
||||||
// calculates the final width
|
// calculates the final width
|
||||||
|
@ -2025,7 +2058,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
||||||
if (aReflowState.parentReflowState) {
|
if (aReflowState.parentReflowState) {
|
||||||
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
||||||
|
@ -2047,7 +2080,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// Don't carry out a bottom margin when our height is fixed
|
// Don't carry out a bottom margin when our height is fixed
|
||||||
// unless the bottom of the last line adjoins the bottom of our
|
// unless the bottom of the last line adjoins the bottom of our
|
||||||
// content area.
|
// content area.
|
||||||
if (!aState.mIsBottomMarginRoot) {
|
if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
||||||
aState.mPrevBottomMargin = 0;
|
aState.mPrevBottomMargin = 0;
|
||||||
}
|
}
|
||||||
|
@ -2057,7 +2090,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
nscoord autoHeight = aState.mY;
|
nscoord autoHeight = aState.mY;
|
||||||
|
|
||||||
// Shrink wrap our height around our contents.
|
// Shrink wrap our height around our contents.
|
||||||
if (aState.mIsBottomMarginRoot) {
|
if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
// When we are a bottom-margin root make sure that our last
|
// When we are a bottom-margin root make sure that our last
|
||||||
// childs bottom margin is fully applied.
|
// childs bottom margin is fully applied.
|
||||||
// XXX check for a fit
|
// XXX check for a fit
|
||||||
|
@ -2082,7 +2115,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
aMetrics.height = autoHeight;
|
aMetrics.height = autoHeight;
|
||||||
|
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxHeight = aState.mMaxElementSize.height +
|
maxHeight = aState.mMaxElementSize.height +
|
||||||
borderPadding.top + borderPadding.bottom;
|
borderPadding.top + borderPadding.bottom;
|
||||||
}
|
}
|
||||||
|
@ -2090,7 +2123,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
aMetrics.ascent = aMetrics.height;
|
aMetrics.ascent = aMetrics.height;
|
||||||
aMetrics.descent = 0;
|
aMetrics.descent = 0;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Store away the final value
|
// Store away the final value
|
||||||
aMetrics.maxElementSize->width = maxWidth;
|
aMetrics.maxElementSize->width = maxWidth;
|
||||||
aMetrics.maxElementSize->height = maxHeight;
|
aMetrics.maxElementSize->height = maxHeight;
|
||||||
|
@ -2098,14 +2131,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Return bottom margin information
|
// Return bottom margin information
|
||||||
aMetrics.mCarriedOutBottomMargin =
|
aMetrics.mCarriedOutBottomMargin =
|
||||||
aState.mIsBottomMarginRoot ? 0 : aState.mPrevBottomMargin;
|
aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
||||||
}
|
}
|
||||||
if (aState.mComputeMaxElementSize &&
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) &&
|
||||||
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
||||||
|
@ -2115,7 +2148,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
printf("PASS1 ");
|
printf("PASS1 ");
|
||||||
|
@ -2130,7 +2163,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're requested to update our maximum width, then compute it
|
// If we're requested to update our maximum width, then compute it
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
// We need to add in for the right border/padding
|
// We need to add in for the right border/padding
|
||||||
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
||||||
}
|
}
|
||||||
|
@ -2337,8 +2370,13 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
// See if we can try and avoid marking all the lines as dirty
|
// See if we can try and avoid marking all the lines as dirty
|
||||||
PRBool tryAndSkipLines = PR_FALSE;
|
PRBool tryAndSkipLines = PR_FALSE;
|
||||||
|
|
||||||
// See if this is this a constrained resize reflow
|
// we need to calculate if any part of then block itself
|
||||||
if ((aState.mReflowState.reason == eReflowReason_Resize) &&
|
// is impacted by a floater (bug 19579)
|
||||||
|
aState.GetAvailableSpace();
|
||||||
|
|
||||||
|
// See if this is this a constrained resize reflow that is not impacted by floaters
|
||||||
|
if ((PR_FALSE==aState.IsImpactedByFloater()) &&
|
||||||
|
(aState.mReflowState.reason == eReflowReason_Resize) &&
|
||||||
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
||||||
|
|
||||||
// If the text is left-aligned, then we try and avoid reflowing the lines
|
// If the text is left-aligned, then we try and avoid reflowing the lines
|
||||||
|
@ -2389,7 +2427,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRBool notWrapping = aState.mNoWrap;
|
PRBool notWrapping = aState.GetFlag(BRS_NOWRAP);
|
||||||
while (nsnull != line) {
|
while (nsnull != line) {
|
||||||
|
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
|
@ -2402,8 +2440,6 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
||||||
line, line->IsImpactedByFloater() ? "" : "not ");
|
line, line->IsImpactedByFloater() ? "" : "not ");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (notWrapping) {
|
if (notWrapping) {
|
||||||
// When no-wrap is set then the only line-breaking that
|
// When no-wrap is set then the only line-breaking that
|
||||||
// occurs for inline lines is triggered by BR elements or by
|
// occurs for inline lines is triggered by BR elements or by
|
||||||
|
@ -2430,7 +2466,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
||||||
line, line->mNext,
|
line, line->mNext,
|
||||||
line->IsBlock() ? "block" : "inline",
|
line->IsBlock() ? "block" : "inline",
|
||||||
aState.mNoWrap ? "no-wrap" : "wrapping",
|
aState.GetFlag(BRS_NOWRAP) ? "no-wrap" : "wrapping",
|
||||||
line->HasBreak() ? "has-break " : "",
|
line->HasBreak() ? "has-break " : "",
|
||||||
line->HasFloaters() ? "has-floaters " : "",
|
line->HasFloaters() ? "has-floaters " : "",
|
||||||
line->IsImpactedByFloater() ? "impacted " : "",
|
line->IsImpactedByFloater() ? "impacted " : "",
|
||||||
|
@ -2628,7 +2664,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
||||||
kReflowCommandType[type], type,
|
kReflowCommandType[type], type,
|
||||||
aState.mIsInlineIncrReflow ? "true" : "false");
|
aState.GetFlag(BRS_ISINLINEINCRREFLOW) ? "true" : "false");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
IndentBy(stdout, gNoiseIndent);
|
IndentBy(stdout, gNoiseIndent);
|
||||||
|
@ -2651,7 +2687,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// Reflow the lines that are already ours
|
// Reflow the lines that are already ours
|
||||||
aState.mPrevLine = nsnull;
|
aState.mPrevLine = nsnull;
|
||||||
nsLineBox* line = mLines;
|
nsLineBox* line = mLines;
|
||||||
if (aState.mIsInlineIncrReflow && aState.mNextRCFrame)
|
if (aState.GetFlag(BRS_ISINLINEINCRREFLOW) && aState.mNextRCFrame)
|
||||||
{
|
{
|
||||||
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
||||||
aState.mCurrentLine = line;
|
aState.mCurrentLine = line;
|
||||||
|
@ -2662,6 +2698,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 4 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
aState.mPrevLine = line;
|
aState.mPrevLine = line;
|
||||||
|
@ -2689,7 +2729,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// If we're supposed to update our maximum width, then we'll also need to
|
// If we're supposed to update our maximum width, then we'll also need to
|
||||||
// reflow this line if it's line wrapped and any of the continuing lines
|
// reflow this line if it's line wrapped and any of the continuing lines
|
||||||
// are dirty
|
// are dirty
|
||||||
if (line->IsDirty() || (aState.mComputeMaximumWidth && ::WrappedLinesAreDirty(line))) {
|
if (line->IsDirty() || (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && ::WrappedLinesAreDirty(line))) {
|
||||||
// Compute the dirty lines "before" YMost, after factoring in
|
// Compute the dirty lines "before" YMost, after factoring in
|
||||||
// the running deltaY value - the running value is implicit in
|
// the running deltaY value - the running value is implicit in
|
||||||
// aState.mY.
|
// aState.mY.
|
||||||
|
@ -2729,6 +2769,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 5 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2902,6 +2946,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// XXX We need to improve on this...
|
// XXX We need to improve on this...
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 6 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -2918,6 +2966,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.x;
|
dirtyRect.x;
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
||||||
lineCombinedArea.height);
|
lineCombinedArea.height);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 7 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
if (oldCombinedArea.height != lineCombinedArea.height) {
|
if (oldCombinedArea.height != lineCombinedArea.height) {
|
||||||
|
@ -2933,6 +2985,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
||||||
lineCombinedArea.YMost()) -
|
lineCombinedArea.YMost()) -
|
||||||
dirtyRect.y;
|
dirtyRect.y;
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 8 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2951,21 +3007,21 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// we'll either need to recover the floater state that applies to the
|
// we'll either need to recover the floater state that applies to the
|
||||||
// unconstrained reflow or keep it around in a separate space manager...
|
// unconstrained reflow or keep it around in a separate space manager...
|
||||||
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
||||||
if (aState.mComputeMaximumWidth && isBeginningLine) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && isBeginningLine) {
|
||||||
nscoord oldY = aState.mY;
|
nscoord oldY = aState.mY;
|
||||||
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
||||||
PRBool oldUnconstrainedWidth = aState.mUnconstrainedWidth;
|
PRBool oldUnconstrainedWidth = aState.GetFlag(BRS_UNCONSTRAINEDWIDTH);
|
||||||
|
|
||||||
// First reflow the line with an unconstrained width. When doing this
|
// First reflow the line with an unconstrained width. When doing this
|
||||||
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
||||||
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
||||||
// associated floater we don't end up resetting the line's right edge and
|
// associated floater we don't end up resetting the line's right edge and
|
||||||
// have it think the width is unconstrained...
|
// have it think the width is unconstrained...
|
||||||
aState.mUnconstrainedWidth = PR_TRUE;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
||||||
aState.mY = oldY;
|
aState.mY = oldY;
|
||||||
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
||||||
aState.mUnconstrainedWidth = oldUnconstrainedWidth;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, oldUnconstrainedWidth);
|
||||||
|
|
||||||
// Update the line's maximum width
|
// Update the line's maximum width
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
|
@ -2980,14 +3036,14 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// Note: we need to reset both member variables, because the inline
|
// Note: we need to reset both member variables, because the inline
|
||||||
// code examines mComputeMaxElementSize and if there is a placeholder
|
// code examines mComputeMaxElementSize and if there is a placeholder
|
||||||
// on this line the code to reflow the floater looks at both...
|
// on this line the code to reflow the floater looks at both...
|
||||||
nscoord oldComputeMaxElementSize = aState.mComputeMaxElementSize;
|
nscoord oldComputeMaxElementSize = aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE);
|
||||||
nscoord oldComputeMaximumWidth = aState.mComputeMaximumWidth;
|
nscoord oldComputeMaximumWidth = aState.GetFlag(BRS_COMPUTEMAXWIDTH);
|
||||||
|
|
||||||
aState.mComputeMaxElementSize = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, PR_FALSE);
|
||||||
aState.mComputeMaximumWidth = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, PR_FALSE);
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
aState.mComputeMaxElementSize = oldComputeMaxElementSize;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, oldComputeMaxElementSize);
|
||||||
aState.mComputeMaximumWidth = oldComputeMaximumWidth;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, oldComputeMaximumWidth);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
|
@ -3001,6 +3057,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
|
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 9 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3368,7 +3428,7 @@ PRBool
|
||||||
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
nsLineBox* aLine)
|
nsLineBox* aLine)
|
||||||
{
|
{
|
||||||
if (aState.mApplyTopMargin) {
|
if (aState.GetFlag(BRS_APPLYTOPMARGIN)) {
|
||||||
// Apply short-circuit check to avoid searching the line list
|
// Apply short-circuit check to avoid searching the line list
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -3377,7 +3437,7 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
// If we aren't at the top Y coordinate then something of non-zero
|
// If we aren't at the top Y coordinate then something of non-zero
|
||||||
// height must have been placed. Therefore the childs top-margin
|
// height must have been placed. Therefore the childs top-margin
|
||||||
// applies.
|
// applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3387,13 +3447,13 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
// A line which preceeds aLine contains a block; therefore the
|
// A line which preceeds aLine contains a block; therefore the
|
||||||
// top margin applies.
|
// top margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else if (line->HasFloaters()) {
|
else if (line->HasFloaters()) {
|
||||||
// A line which preceeds aLine is not empty therefore the top
|
// A line which preceeds aLine is not empty therefore the top
|
||||||
// margin applies.
|
// margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
line = line->mNext;
|
line = line->mNext;
|
||||||
|
@ -3486,8 +3546,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
frame->GetStyleData(eStyleStruct_Display,
|
frame->GetStyleData(eStyleStruct_Display,
|
||||||
(const nsStyleStruct*&) display);
|
(const nsStyleStruct*&) display);
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// See if we should apply the top margin. If the block frame being
|
// See if we should apply the top margin. If the block frame being
|
||||||
|
@ -3611,14 +3671,14 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
&collapsedBottomMargin,
|
&collapsedBottomMargin,
|
||||||
aLine->mBounds, combinedArea);
|
aLine->mBounds, combinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line as block so once we known the final shrink wrap width
|
// Mark the line as block so once we known the final shrink wrap width
|
||||||
// we can reflow the block to the correct size
|
// we can reflow the block to the correct size
|
||||||
// XXX We don't always need to do this...
|
// XXX We don't always need to do this...
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (aState.mUnconstrainedWidth || aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Add the right margin to the line's bounnds. That way it will be taken into
|
// Add the right margin to the line's bounnds. That way it will be taken into
|
||||||
// account when we compute our shrink wrap size
|
// account when we compute our shrink wrap size
|
||||||
nscoord marginRight = brc.GetMargin().right;
|
nscoord marginRight = brc.GetMargin().right;
|
||||||
|
@ -3709,7 +3769,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Post-process the "line"
|
// Post-process the "line"
|
||||||
nsSize maxElementSize(0, 0);
|
nsSize maxElementSize(0, 0);
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxElementSize = brc.GetMaxElementSize();
|
maxElementSize = brc.GetMaxElementSize();
|
||||||
if (aState.IsImpactedByFloater() &&
|
if (aState.IsImpactedByFloater() &&
|
||||||
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
||||||
|
@ -3721,7 +3781,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
// If we asked the block to update its maximum width, then record the
|
// If we asked the block to update its maximum width, then record the
|
||||||
// updated value in the line, and update the current maximum width
|
// updated value in the line, and update the current maximum width
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
||||||
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
|
|
||||||
|
@ -3849,7 +3909,7 @@ nsBlockFrame::DoReflowInlineFramesMalloc(nsBlockReflowState& aState,
|
||||||
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -3872,7 +3932,7 @@ nsBlockFrame::DoReflowInlineFramesAuto(nsBlockReflowState& aState,
|
||||||
nsLineLayout lineLayout(aState.mPresContext,
|
nsLineLayout lineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
||||||
lineLayout.SetReflowTextRuns(mTextRuns);
|
lineLayout.SetReflowTextRuns(mTextRuns);
|
||||||
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
||||||
|
@ -3910,7 +3970,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
||||||
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
||||||
nscoord availWidth = aState.mAvailSpaceRect.width;
|
nscoord availWidth = aState.mAvailSpaceRect.width;
|
||||||
nscoord availHeight;
|
nscoord availHeight;
|
||||||
if (aState.mUnconstrainedHeight) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
|
||||||
availHeight = NS_UNCONSTRAINEDSIZE;
|
availHeight = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4359,7 +4419,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
nsSize maxElementSize;
|
nsSize maxElementSize;
|
||||||
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
||||||
// See if we're shrink wrapping the width
|
// See if we're shrink wrapping the width
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// When determining the line's width we also need to include any
|
// When determining the line's width we also need to include any
|
||||||
// right floaters that impact us. This represents the shrink wrap
|
// right floaters that impact us. This represents the shrink wrap
|
||||||
// width of the line
|
// width of the line
|
||||||
|
@ -4388,25 +4448,20 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// Only block frames horizontally align their children because
|
// Only block frames horizontally align their children because
|
||||||
// inline frames "shrink-wrap" around their children (therefore
|
// inline frames "shrink-wrap" around their children (therefore
|
||||||
// there is no extra horizontal space).
|
// there is no extra horizontal space).
|
||||||
#if XXX_fix_me
|
const nsStyleText* styleText = (const nsStyleText*)
|
||||||
PRBool allowJustify = PR_TRUE;
|
mStyleContext->GetStyleData(eStyleStruct_Text);
|
||||||
if (NS_STYLE_TEXT_ALIGN_JUSTIFY == aState.mStyleText->mTextAlign) {
|
PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign
|
||||||
allowJustify = ShouldJustifyLine(aState, aLine);
|
&& !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine);
|
||||||
}
|
PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
||||||
#else
|
aState.GetFlag(BRS_SHRINKWRAPWIDTH));
|
||||||
PRBool allowJustify = PR_FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PRBool successful;
|
|
||||||
nsRect combinedArea;
|
|
||||||
successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
|
||||||
aState.mShrinkWrapWidth);
|
|
||||||
if (!successful) {
|
if (!successful) {
|
||||||
// Mark the line dirty and then later once we've determined the width
|
// Mark the line dirty and then later once we've determined the width
|
||||||
// we can do the horizontal alignment
|
// we can do the horizontal alignment
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsRect combinedArea;
|
||||||
aLineLayout.RelativePositionFrames(combinedArea);
|
aLineLayout.RelativePositionFrames(combinedArea);
|
||||||
aLine->SetCombinedArea(combinedArea);
|
aLine->SetCombinedArea(combinedArea);
|
||||||
if (addedBullet) {
|
if (addedBullet) {
|
||||||
|
@ -4454,7 +4509,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
aState.mY = newY;
|
aState.mY = newY;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
|
@ -4478,7 +4533,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// we don't want updated...
|
// we don't want updated...
|
||||||
if (aUpdateMaximumWidth) {
|
if (aUpdateMaximumWidth) {
|
||||||
// However, we do need to update the max-element-size if requested
|
// However, we do need to update the max-element-size if requested
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(maxElementSize);
|
aState.UpdateMaxElementSize(maxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4519,7 +4574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mHaveRightFloaters &&
|
if (aState.mHaveRightFloaters &&
|
||||||
(aState.mUnconstrainedWidth || aState.mShrinkWrapWidth)) {
|
(aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// We are reflowing in an unconstrained situation or shrink wrapping and
|
// We are reflowing in an unconstrained situation or shrink wrapping and
|
||||||
// have some right floaters. They were placed at the infinite right edge
|
// have some right floaters. They were placed at the infinite right edge
|
||||||
// which will cause the combined area to be unusable.
|
// which will cause the combined area to be unusable.
|
||||||
|
@ -4540,11 +4595,11 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
||||||
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line dirty so we come back and re-place the floater once
|
// Mark the line dirty so we come back and re-place the floater once
|
||||||
// the shrink wrap width is determined
|
// the shrink wrap width is determined
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aLine->SetCombinedArea(lineCombinedArea);
|
aLine->SetCombinedArea(lineCombinedArea);
|
||||||
|
@ -4629,7 +4684,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update max-element-size
|
// Update max-element-size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(aMaxElementSize);
|
aState.UpdateMaxElementSize(aMaxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4639,7 +4694,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
// If this is an unconstrained reflow, then cache the line width in the
|
// If this is an unconstrained reflow, then cache the line width in the
|
||||||
// line. We'll need this during incremental reflow if we're asked to
|
// line. We'll need this during incremental reflow if we're asked to
|
||||||
// calculate the maximum width
|
// calculate the maximum width
|
||||||
if (aState.mUnconstrainedWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4653,7 +4708,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
#endif
|
#endif
|
||||||
// If we're shrink wrapping our width and the line was wrapped,
|
// If we're shrink wrapping our width and the line was wrapped,
|
||||||
// then make sure we take up all of the available width
|
// then make sure we take up all of the available width
|
||||||
if (aState.mShrinkWrapWidth && aLine->IsLineWrapped()) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aLine->IsLineWrapped()) {
|
||||||
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5187,6 +5242,10 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
||||||
// cases...
|
// cases...
|
||||||
nsRect lineCombinedArea;
|
nsRect lineCombinedArea;
|
||||||
line->GetCombinedArea(&lineCombinedArea);
|
line->GetCombinedArea(&lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 10 (%d, %d, %d, %d)\n",
|
||||||
|
this, lineCombinedArea.x, lineCombinedArea.y, lineCombinedArea.width, lineCombinedArea.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, lineCombinedArea);
|
Invalidate(aPresContext, lineCombinedArea);
|
||||||
line->Destroy(presShell);
|
line->Destroy(presShell);
|
||||||
line = next;
|
line = next;
|
||||||
|
@ -5282,8 +5341,8 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Setup block reflow state to reflow the floater
|
// Setup block reflow state to reflow the floater
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// Reflow the floater
|
// Reflow the floater
|
||||||
|
@ -5324,7 +5383,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||||
|
|
||||||
// If we computed it, then stash away the max-element-size for later
|
// If we computed it, then stash away the max-element-size for later
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5389,7 +5448,7 @@ nsBlockReflowState::AddFloater(nsLineLayout& aLineLayout,
|
||||||
// Pass on updated available space to the current inline reflow engine
|
// Pass on updated available space to the current inline reflow engine
|
||||||
GetAvailableSpace();
|
GetAvailableSpace();
|
||||||
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
||||||
mUnconstrainedWidth ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
GetFlag(BRS_UNCONSTRAINEDWIDTH) ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
||||||
mAvailSpaceRect.height,
|
mAvailSpaceRect.height,
|
||||||
isLeftFloater,
|
isLeftFloater,
|
||||||
aPlaceholder->GetOutOfFlowFrame());
|
aPlaceholder->GetOutOfFlowFrame());
|
||||||
|
@ -5615,7 +5674,12 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isLeftFloater = PR_FALSE;
|
isLeftFloater = PR_FALSE;
|
||||||
region.x = mAvailSpaceRect.XMost() - region.width;
|
if (NS_UNCONSTRAINEDSIZE != mAvailSpaceRect.XMost())
|
||||||
|
region.x = mAvailSpaceRect.XMost() - region.width;
|
||||||
|
else {
|
||||||
|
okToAddRectRegion = PR_FALSE;
|
||||||
|
region.x = mAvailSpaceRect.x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*aIsLeftFloater = isLeftFloater;
|
*aIsLeftFloater = isLeftFloater;
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
@ -5682,7 +5746,8 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
||||||
combinedArea.x += x;
|
combinedArea.x += x;
|
||||||
combinedArea.y += y;
|
combinedArea.y += y;
|
||||||
if (!isLeftFloater && (mUnconstrainedWidth || mShrinkWrapWidth)) {
|
if (!isLeftFloater &&
|
||||||
|
(GetFlag(BRS_UNCONSTRAINEDWIDTH) || GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// When we are placing a right floater in an unconstrained situation or
|
// When we are placing a right floater in an unconstrained situation or
|
||||||
// when shrink wrapping, we don't apply it to the floater combined area
|
// when shrink wrapping, we don't apply it to the floater combined area
|
||||||
// immediately. Otherwise we end up with an infinitely wide combined
|
// immediately. Otherwise we end up with an infinitely wide combined
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Steve Clark <buster@netscape.com>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
*/
|
*/
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
@ -61,6 +63,8 @@
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
|
//#define NOISY_BLOCK_INVALIDATE // DO NOT CHECK THIS IN TURNED ON!
|
||||||
|
|
||||||
static PRBool gLamePaintMetrics;
|
static PRBool gLamePaintMetrics;
|
||||||
static PRBool gLameReflowMetrics;
|
static PRBool gLameReflowMetrics;
|
||||||
static PRBool gNoisy;
|
static PRBool gNoisy;
|
||||||
|
@ -451,12 +455,6 @@ public:
|
||||||
|
|
||||||
nscoord mBottomEdge;
|
nscoord mBottomEdge;
|
||||||
|
|
||||||
PRPackedBool mUnconstrainedWidth;
|
|
||||||
PRPackedBool mUnconstrainedHeight;
|
|
||||||
PRPackedBool mShrinkWrapWidth;
|
|
||||||
PRPackedBool mNeedResizeReflow;
|
|
||||||
PRPackedBool mIsInlineIncrReflow;
|
|
||||||
|
|
||||||
// The content area to reflow child frames within. The x/y
|
// The content area to reflow child frames within. The x/y
|
||||||
// coordinates are known to be mBorderPadding.left and
|
// coordinates are known to be mBorderPadding.left and
|
||||||
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
// mBorderPadding.top. The width/height may be NS_UNCONSTRAINEDSIZE
|
||||||
|
@ -464,15 +462,6 @@ public:
|
||||||
// unconstrained area.
|
// unconstrained area.
|
||||||
nsSize mContentArea;
|
nsSize mContentArea;
|
||||||
|
|
||||||
// Our wrapping behavior
|
|
||||||
PRPackedBool mNoWrap;
|
|
||||||
|
|
||||||
// Is this frame a root for top/bottom margin collapsing?
|
|
||||||
PRPackedBool mIsTopMarginRoot, mIsBottomMarginRoot;
|
|
||||||
|
|
||||||
// See ShouldApplyTopMargin
|
|
||||||
PRPackedBool mApplyTopMargin;
|
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
// This state is "running" state updated by the reflow of each line
|
// This state is "running" state updated by the reflow of each line
|
||||||
|
@ -541,15 +530,48 @@ public:
|
||||||
// being N^2.
|
// being N^2.
|
||||||
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
nsFloaterCacheFreeList mBelowCurrentLineFloaters;
|
||||||
|
|
||||||
PRPackedBool mComputeMaxElementSize;
|
|
||||||
PRPackedBool mComputeMaximumWidth;
|
|
||||||
|
|
||||||
nsSize mMaxElementSize;
|
nsSize mMaxElementSize;
|
||||||
nscoord mMaximumWidth;
|
nscoord mMaximumWidth;
|
||||||
|
|
||||||
nscoord mMinLineHeight;
|
nscoord mMinLineHeight;
|
||||||
|
|
||||||
PRInt32 mLineNumber;
|
PRInt32 mLineNumber;
|
||||||
|
|
||||||
|
// block reflow state flags
|
||||||
|
#define BRS_UNCONSTRAINEDWIDTH 0x00000001
|
||||||
|
#define BRS_UNCONSTRAINEDHEIGHT 0x00000002
|
||||||
|
#define BRS_SHRINKWRAPWIDTH 0x00000004
|
||||||
|
#define BRS_NEEDRESIZEREFLOW 0x00000008
|
||||||
|
#define BRS_ISINLINEINCRREFLOW 0x00000010
|
||||||
|
#define BRS_NOWRAP 0x00000020
|
||||||
|
#define BRS_ISTOPMARGINROOT 0x00000040 // Is this frame a root for top/bottom margin collapsing?
|
||||||
|
#define BRS_ISBOTTOMMARGINROOT 0x00000080
|
||||||
|
#define BRS_APPLYTOPMARGIN 0x00000100 // See ShouldApplyTopMargin
|
||||||
|
#define BRS_COMPUTEMAXELEMENTSIZE 0x00000200
|
||||||
|
#define BRS_COMPUTEMAXWIDTH 0x00000400
|
||||||
|
#define BRS_LASTFLAG BRS_COMPUTEMAXWIDTH
|
||||||
|
|
||||||
|
PRInt16 mFlags;
|
||||||
|
|
||||||
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
|
||||||
|
if (aValue) { // set flag
|
||||||
|
mFlags |= aFlag;
|
||||||
|
}
|
||||||
|
else { // unset flag
|
||||||
|
mFlags &= ~aFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GetFlag(PRUint32 aFlag) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=BRS_LASTFLAG, "bad flag");
|
||||||
|
PRBool result = (mFlags & aFlag);
|
||||||
|
if (result) return PR_TRUE;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// XXX This is vile. Make it go away
|
// XXX This is vile. Make it go away
|
||||||
|
@ -574,29 +596,25 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
: mBlock(aFrame),
|
: mBlock(aFrame),
|
||||||
mPresContext(aPresContext),
|
mPresContext(aPresContext),
|
||||||
mReflowState(aReflowState),
|
mReflowState(aReflowState),
|
||||||
mNeedResizeReflow(PR_FALSE),
|
|
||||||
mIsInlineIncrReflow(PR_FALSE),
|
|
||||||
mIsTopMarginRoot(PR_FALSE),
|
|
||||||
mIsBottomMarginRoot(PR_FALSE),
|
|
||||||
mApplyTopMargin(PR_FALSE),
|
|
||||||
mNextRCFrame(nsnull),
|
mNextRCFrame(nsnull),
|
||||||
mPrevBottomMargin(0),
|
mPrevBottomMargin(0),
|
||||||
mLineNumber(0)
|
mLineNumber(0),
|
||||||
|
mFlags(0)
|
||||||
{
|
{
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
|
||||||
if (aBlockMarginRoot) {
|
if (aBlockMarginRoot) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.top) {
|
if (0 != aReflowState.mComputedBorderPadding.top) {
|
||||||
mIsTopMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISTOPMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
if (0 != aReflowState.mComputedBorderPadding.bottom) {
|
||||||
mIsBottomMarginRoot = PR_TRUE;
|
SetFlag(BRS_ISBOTTOMMARGINROOT, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (mIsTopMarginRoot) {
|
if (GetFlag(BRS_ISTOPMARGINROOT)) {
|
||||||
mApplyTopMargin = PR_TRUE;
|
SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSpaceManager = aReflowState.mSpaceManager;
|
mSpaceManager = aReflowState.mSpaceManager;
|
||||||
|
@ -617,21 +635,19 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Compute content area width (the content area is inside the border
|
// Compute content area width (the content area is inside the border
|
||||||
// and padding)
|
// and padding)
|
||||||
mUnconstrainedWidth = PR_FALSE;
|
|
||||||
mShrinkWrapWidth = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
||||||
mContentArea.width = aReflowState.mComputedWidth;
|
mContentArea.width = aReflowState.mComputedWidth;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
||||||
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
||||||
mUnconstrainedWidth = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
||||||
// Choose a width based on the content (shrink wrap width) up
|
// Choose a width based on the content (shrink wrap width) up
|
||||||
// to the maximum width
|
// to the maximum width
|
||||||
mContentArea.width = aReflowState.mComputedMaxWidth;
|
mContentArea.width = aReflowState.mComputedMaxWidth;
|
||||||
mShrinkWrapWidth = PR_TRUE;
|
SetFlag(BRS_SHRINKWRAPWIDTH, PR_TRUE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nscoord lr = borderPadding.left + borderPadding.right;
|
nscoord lr = borderPadding.left + borderPadding.right;
|
||||||
|
@ -646,7 +662,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
// specified style height then we may end up limiting our height if
|
// specified style height then we may end up limiting our height if
|
||||||
// the availableHeight is constrained (this situation occurs when we
|
// the availableHeight is constrained (this situation occurs when we
|
||||||
// are paginated).
|
// are paginated).
|
||||||
mUnconstrainedHeight = PR_FALSE;
|
|
||||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) {
|
||||||
// We are in a paginated situation. The bottom edge is just inside
|
// We are in a paginated situation. The bottom edge is just inside
|
||||||
// the bottom border and padding. The content area height doesn't
|
// the bottom border and padding. The content area height doesn't
|
||||||
|
@ -657,7 +672,7 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
else {
|
else {
|
||||||
// When we are not in a paginated situation then we always use
|
// When we are not in a paginated situation then we always use
|
||||||
// an constrained height.
|
// an constrained height.
|
||||||
mUnconstrainedHeight = PR_TRUE;
|
SetFlag(BRS_UNCONSTRAINEDHEIGHT, PR_TRUE);
|
||||||
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
mContentArea.height = mBottomEdge = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,16 +689,17 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||||
switch (styleText->mWhiteSpace) {
|
switch (styleText->mWhiteSpace) {
|
||||||
case NS_STYLE_WHITESPACE_PRE:
|
case NS_STYLE_WHITESPACE_PRE:
|
||||||
case NS_STYLE_WHITESPACE_NOWRAP:
|
case NS_STYLE_WHITESPACE_NOWRAP:
|
||||||
mNoWrap = PR_TRUE;
|
SetFlag(BRS_NOWRAP, PR_TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mNoWrap = PR_FALSE;
|
SetFlag(BRS_NOWRAP, PR_FALSE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mComputeMaxElementSize = nsnull != aMetrics.maxElementSize;
|
SetFlag(BRS_COMPUTEMAXELEMENTSIZE, (nsnull != aMetrics.maxElementSize));
|
||||||
mMaxElementSize.SizeTo(0, 0);
|
mMaxElementSize.SizeTo(0, 0);
|
||||||
mComputeMaximumWidth = NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH);
|
SetFlag(BRS_COMPUTEMAXWIDTH,
|
||||||
|
(NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH)));
|
||||||
mMaximumWidth = 0;
|
mMaximumWidth = 0;
|
||||||
|
|
||||||
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
||||||
|
@ -729,8 +745,12 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
const nsStyleDisplay* aDisplay,
|
const nsStyleDisplay* aDisplay,
|
||||||
nsRect& aResult)
|
nsRect& aResult)
|
||||||
{
|
{
|
||||||
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
|
printf("CBAS frame=%p has floater count %d\n", aFrame, mBand.GetFloaterCount());
|
||||||
|
mBand.List();
|
||||||
|
#endif
|
||||||
aResult.y = mY;
|
aResult.y = mY;
|
||||||
aResult.height = mUnconstrainedHeight
|
aResult.height = GetFlag(BRS_UNCONSTRAINEDHEIGHT)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mBottomEdge - mY;
|
: mBottomEdge - mY;
|
||||||
|
|
||||||
|
@ -749,7 +769,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// The child block will flow around the floater. Therefore
|
// The child block will flow around the floater. Therefore
|
||||||
// give it all of the available space.
|
// give it all of the available space.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
break;
|
break;
|
||||||
|
@ -776,7 +796,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine width
|
// determine width
|
||||||
if (mUnconstrainedWidth) {
|
if (GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -810,7 +830,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||||
// doesn't matter therefore give the block element all of the
|
// doesn't matter therefore give the block element all of the
|
||||||
// available space since it will flow around the floater itself.
|
// available space since it will flow around the floater itself.
|
||||||
aResult.x = borderPadding.left;
|
aResult.x = borderPadding.left;
|
||||||
aResult.width = mUnconstrainedWidth
|
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||||
? NS_UNCONSTRAINEDSIZE
|
? NS_UNCONSTRAINEDSIZE
|
||||||
: mContentArea.width;
|
: mContentArea.width;
|
||||||
}
|
}
|
||||||
|
@ -957,12 +977,12 @@ nsBlockReflowState::RecoverStateFrom(nsLineBox* aLine,
|
||||||
#endif
|
#endif
|
||||||
mKidXMost = xmost;
|
mKidXMost = xmost;
|
||||||
}
|
}
|
||||||
if (mComputeMaxElementSize) {
|
if (GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
UpdateMaxElementSize(nsSize(aLine->mMaxElementWidth, aLine->mBounds.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If computing the maximum width, then update mMaximumWidth
|
// If computing the maximum width, then update mMaximumWidth
|
||||||
if (mComputeMaximumWidth) {
|
if (GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
UpdateMaximumWidth(aLine->mMaximumWidth);
|
UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1454,6 +1474,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
nsBlockReflowState state(aReflowState, aPresContext, this, aMetrics,
|
||||||
NS_BLOCK_MARGIN_ROOT & mState);
|
NS_BLOCK_MARGIN_ROOT & mState);
|
||||||
|
PRInt32 sizeofBRS = sizeof nsBlockReflowState;
|
||||||
|
|
||||||
if (eReflowReason_Resize != aReflowState.reason) {
|
if (eReflowReason_Resize != aReflowState.reason) {
|
||||||
RenumberLists(aPresContext);
|
RenumberLists(aPresContext);
|
||||||
|
@ -1462,7 +1483,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
PRBool isStyleChange = PR_FALSE;
|
PRBool isStyleChange = PR_FALSE;
|
||||||
state.mIsInlineIncrReflow = PR_FALSE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_FALSE);
|
||||||
nsIFrame* target;
|
nsIFrame* target;
|
||||||
switch (aReflowState.reason) {
|
switch (aReflowState.reason) {
|
||||||
case eReflowReason_Initial:
|
case eReflowReason_Initial:
|
||||||
|
@ -1535,7 +1556,7 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// reflow the line containing the target of the incr. reflow
|
// reflow the line containing the target of the incr. reflow
|
||||||
// first mark the line dirty and set up the state object
|
// first mark the line dirty and set up the state object
|
||||||
rv = PrepareChildIncrementalReflow(state);
|
rv = PrepareChildIncrementalReflow(state);
|
||||||
state.mIsInlineIncrReflow = PR_TRUE;
|
state.SetFlag(BRS_ISINLINEINCRREFLOW, PR_TRUE);
|
||||||
state.mPrevLine = prevLine;
|
state.mPrevLine = prevLine;
|
||||||
state.mCurrentLine = line;
|
state.mCurrentLine = line;
|
||||||
state.mNextRCFrame = state.mNextRCFrame;
|
state.mNextRCFrame = state.mNextRCFrame;
|
||||||
|
@ -1681,6 +1702,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
if (isStyleChange) {
|
if (isStyleChange) {
|
||||||
// Lots of things could have changed so damage our entire
|
// Lots of things could have changed so damage our entire
|
||||||
// bounds
|
// bounds
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 1 (%d, %d, %d, %d)\n",
|
||||||
|
this, 0, 0, mRect.width, mRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
Invalidate(aPresContext, nsRect(0, 0, mRect.width, mRect.height));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -1707,6 +1732,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = 0;
|
damageRect.y = 0;
|
||||||
damageRect.height = mRect.height;
|
damageRect.height = mRect.height;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 2 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1730,6 +1759,10 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
damageRect.y = mRect.height - border.bottom;
|
damageRect.y = mRect.height - border.bottom;
|
||||||
damageRect.height = border.bottom;
|
damageRect.height = border.bottom;
|
||||||
}
|
}
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 3 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, damageRect);
|
Invalidate(aPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1868,7 +1901,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
#ifdef NOISY_FINAL_SIZE
|
#ifdef NOISY_FINAL_SIZE
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
printf(": mY=%d mIsBottomMarginRoot=%s mPrevBottomMargin=%d bp=%d,%d\n",
|
||||||
aState.mY, aState.mIsBottomMarginRoot ? "yes" : "no",
|
aState.mY, aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? "yes" : "no",
|
||||||
aState.mPrevBottomMargin,
|
aState.mPrevBottomMargin,
|
||||||
borderPadding.top, borderPadding.bottom);
|
borderPadding.top, borderPadding.bottom);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1946,7 +1979,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// contents or we fluff out to the maximum block width. Note:
|
// contents or we fluff out to the maximum block width. Note:
|
||||||
// We always shrink wrap when given an unconstrained width.
|
// We always shrink wrap when given an unconstrained width.
|
||||||
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
if ((0 == (NS_BLOCK_SHRINK_WRAP & mState)) &&
|
||||||
!aState.mUnconstrainedWidth && !aState.mShrinkWrapWidth &&
|
!aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) && !aState.GetFlag(BRS_SHRINKWRAPWIDTH) &&
|
||||||
!compact) {
|
!compact) {
|
||||||
// Set our width to the max width if we aren't already that
|
// Set our width to the max width if we aren't already that
|
||||||
// wide. Note that the max-width has nothing to do with our
|
// wide. Note that the max-width has nothing to do with our
|
||||||
|
@ -1956,9 +1989,9 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we should compute our max element size
|
// See if we should compute our max element size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Adjust the computedWidth
|
// Adjust the computedWidth
|
||||||
if (aState.mNoWrap) {
|
if (aState.GetFlag(BRS_NOWRAP)) {
|
||||||
// When no-wrap is true the max-element-size.width is the
|
// When no-wrap is true the max-element-size.width is the
|
||||||
// width of the widest line plus the right border. Note that
|
// width of the widest line plus the right border. Note that
|
||||||
// aState.mKidXMost already has the left border factored in
|
// aState.mKidXMost already has the left border factored in
|
||||||
|
@ -1996,7 +2029,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// need to do horizontal alignment of the inline lines and make sure
|
// need to do horizontal alignment of the inline lines and make sure
|
||||||
// blocks are correctly sized and positioned. Any lines that need
|
// blocks are correctly sized and positioned. Any lines that need
|
||||||
// final adjustment will have been marked as dirty
|
// final adjustment will have been marked as dirty
|
||||||
if (aState.mShrinkWrapWidth && aState.mNeedResizeReflow) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aState.GetFlag(BRS_NEEDRESIZEREFLOW)) {
|
||||||
// If the parent reflow state is also shrink wrap width, then
|
// If the parent reflow state is also shrink wrap width, then
|
||||||
// we don't need to do this, because it will reflow us after it
|
// we don't need to do this, because it will reflow us after it
|
||||||
// calculates the final width
|
// calculates the final width
|
||||||
|
@ -2025,7 +2058,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
PRBool parentIsShrinkWrapWidth = PR_FALSE;
|
||||||
if (aReflowState.parentReflowState) {
|
if (aReflowState.parentReflowState) {
|
||||||
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
if (NS_SHRINKWRAPWIDTH == aReflowState.parentReflowState->mComputedWidth) {
|
||||||
|
@ -2047,7 +2080,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
// Don't carry out a bottom margin when our height is fixed
|
// Don't carry out a bottom margin when our height is fixed
|
||||||
// unless the bottom of the last line adjoins the bottom of our
|
// unless the bottom of the last line adjoins the bottom of our
|
||||||
// content area.
|
// content area.
|
||||||
if (!aState.mIsBottomMarginRoot) {
|
if (!aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
if (aState.mY + aState.mPrevBottomMargin != aMetrics.height) {
|
||||||
aState.mPrevBottomMargin = 0;
|
aState.mPrevBottomMargin = 0;
|
||||||
}
|
}
|
||||||
|
@ -2057,7 +2090,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
nscoord autoHeight = aState.mY;
|
nscoord autoHeight = aState.mY;
|
||||||
|
|
||||||
// Shrink wrap our height around our contents.
|
// Shrink wrap our height around our contents.
|
||||||
if (aState.mIsBottomMarginRoot) {
|
if (aState.GetFlag(BRS_ISBOTTOMMARGINROOT)) {
|
||||||
// When we are a bottom-margin root make sure that our last
|
// When we are a bottom-margin root make sure that our last
|
||||||
// childs bottom margin is fully applied.
|
// childs bottom margin is fully applied.
|
||||||
// XXX check for a fit
|
// XXX check for a fit
|
||||||
|
@ -2082,7 +2115,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
aMetrics.height = autoHeight;
|
aMetrics.height = autoHeight;
|
||||||
|
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxHeight = aState.mMaxElementSize.height +
|
maxHeight = aState.mMaxElementSize.height +
|
||||||
borderPadding.top + borderPadding.bottom;
|
borderPadding.top + borderPadding.bottom;
|
||||||
}
|
}
|
||||||
|
@ -2090,7 +2123,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
aMetrics.ascent = aMetrics.height;
|
aMetrics.ascent = aMetrics.height;
|
||||||
aMetrics.descent = 0;
|
aMetrics.descent = 0;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
// Store away the final value
|
// Store away the final value
|
||||||
aMetrics.maxElementSize->width = maxWidth;
|
aMetrics.maxElementSize->width = maxWidth;
|
||||||
aMetrics.maxElementSize->height = maxHeight;
|
aMetrics.maxElementSize->height = maxHeight;
|
||||||
|
@ -2098,14 +2131,14 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
|
|
||||||
// Return bottom margin information
|
// Return bottom margin information
|
||||||
aMetrics.mCarriedOutBottomMargin =
|
aMetrics.mCarriedOutBottomMargin =
|
||||||
aState.mIsBottomMarginRoot ? 0 : aState.mPrevBottomMargin;
|
aState.GetFlag(BRS_ISBOTTOMMARGINROOT) ? 0 : aState.mPrevBottomMargin;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
if (CRAZY_WIDTH(aMetrics.width) || CRAZY_HEIGHT(aMetrics.height)) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
printf(": WARNING: desired:%d,%d\n", aMetrics.width, aMetrics.height);
|
||||||
}
|
}
|
||||||
if (aState.mComputeMaxElementSize &&
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE) &&
|
||||||
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
((maxWidth > aMetrics.width) || (maxHeight > aMetrics.height))) {
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
printf(": WARNING: max-element-size:%d,%d desired:%d,%d maxSize:%d,%d\n",
|
||||||
|
@ -2115,7 +2148,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
printf("PASS1 ");
|
printf("PASS1 ");
|
||||||
|
@ -2130,7 +2163,7 @@ nsBlockFrame::ComputeFinalSize(const nsHTMLReflowState& aReflowState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're requested to update our maximum width, then compute it
|
// If we're requested to update our maximum width, then compute it
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
// We need to add in for the right border/padding
|
// We need to add in for the right border/padding
|
||||||
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
aMetrics.mMaximumWidth = aState.mMaximumWidth + borderPadding.right;
|
||||||
}
|
}
|
||||||
|
@ -2337,8 +2370,13 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
// See if we can try and avoid marking all the lines as dirty
|
// See if we can try and avoid marking all the lines as dirty
|
||||||
PRBool tryAndSkipLines = PR_FALSE;
|
PRBool tryAndSkipLines = PR_FALSE;
|
||||||
|
|
||||||
// See if this is this a constrained resize reflow
|
// we need to calculate if any part of then block itself
|
||||||
if ((aState.mReflowState.reason == eReflowReason_Resize) &&
|
// is impacted by a floater (bug 19579)
|
||||||
|
aState.GetAvailableSpace();
|
||||||
|
|
||||||
|
// See if this is this a constrained resize reflow that is not impacted by floaters
|
||||||
|
if ((PR_FALSE==aState.IsImpactedByFloater()) &&
|
||||||
|
(aState.mReflowState.reason == eReflowReason_Resize) &&
|
||||||
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
(NS_UNCONSTRAINEDSIZE != aState.mReflowState.availableWidth)) {
|
||||||
|
|
||||||
// If the text is left-aligned, then we try and avoid reflowing the lines
|
// If the text is left-aligned, then we try and avoid reflowing the lines
|
||||||
|
@ -2389,7 +2427,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRBool notWrapping = aState.mNoWrap;
|
PRBool notWrapping = aState.GetFlag(BRS_NOWRAP);
|
||||||
while (nsnull != line) {
|
while (nsnull != line) {
|
||||||
|
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
|
@ -2402,8 +2440,6 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
printf("PrepareResizeReflow thinks line %p is %simpacted by floaters\n",
|
||||||
line, line->IsImpactedByFloater() ? "" : "not ");
|
line, line->IsImpactedByFloater() ? "" : "not ");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (notWrapping) {
|
if (notWrapping) {
|
||||||
// When no-wrap is set then the only line-breaking that
|
// When no-wrap is set then the only line-breaking that
|
||||||
// occurs for inline lines is triggered by BR elements or by
|
// occurs for inline lines is triggered by BR elements or by
|
||||||
|
@ -2430,7 +2466,7 @@ nsBlockFrame::PrepareResizeReflow(nsBlockReflowState& aState)
|
||||||
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
printf("skipped: line=%p next=%p %s %s %s%s%s breakType=%d xmost=%d\n",
|
||||||
line, line->mNext,
|
line, line->mNext,
|
||||||
line->IsBlock() ? "block" : "inline",
|
line->IsBlock() ? "block" : "inline",
|
||||||
aState.mNoWrap ? "no-wrap" : "wrapping",
|
aState.GetFlag(BRS_NOWRAP) ? "no-wrap" : "wrapping",
|
||||||
line->HasBreak() ? "has-break " : "",
|
line->HasBreak() ? "has-break " : "",
|
||||||
line->HasFloaters() ? "has-floaters " : "",
|
line->HasFloaters() ? "has-floaters " : "",
|
||||||
line->IsImpactedByFloater() ? "impacted " : "",
|
line->IsImpactedByFloater() ? "impacted " : "",
|
||||||
|
@ -2628,7 +2664,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
ListTag(stdout);
|
ListTag(stdout);
|
||||||
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
printf(": incrementally reflowing dirty lines: type=%s(%d) isInline=%s",
|
||||||
kReflowCommandType[type], type,
|
kReflowCommandType[type], type,
|
||||||
aState.mIsInlineIncrReflow ? "true" : "false");
|
aState.GetFlag(BRS_ISINLINEINCRREFLOW) ? "true" : "false");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
IndentBy(stdout, gNoiseIndent);
|
IndentBy(stdout, gNoiseIndent);
|
||||||
|
@ -2651,7 +2687,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// Reflow the lines that are already ours
|
// Reflow the lines that are already ours
|
||||||
aState.mPrevLine = nsnull;
|
aState.mPrevLine = nsnull;
|
||||||
nsLineBox* line = mLines;
|
nsLineBox* line = mLines;
|
||||||
if (aState.mIsInlineIncrReflow && aState.mNextRCFrame)
|
if (aState.GetFlag(BRS_ISINLINEINCRREFLOW) && aState.mNextRCFrame)
|
||||||
{
|
{
|
||||||
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
const nsLineBox* incrTargetLine = aState.mCurrentLine;
|
||||||
aState.mCurrentLine = line;
|
aState.mCurrentLine = line;
|
||||||
|
@ -2662,6 +2698,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 4 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
aState.mPrevLine = line;
|
aState.mPrevLine = line;
|
||||||
|
@ -2689,7 +2729,7 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
// If we're supposed to update our maximum width, then we'll also need to
|
// If we're supposed to update our maximum width, then we'll also need to
|
||||||
// reflow this line if it's line wrapped and any of the continuing lines
|
// reflow this line if it's line wrapped and any of the continuing lines
|
||||||
// are dirty
|
// are dirty
|
||||||
if (line->IsDirty() || (aState.mComputeMaximumWidth && ::WrappedLinesAreDirty(line))) {
|
if (line->IsDirty() || (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && ::WrappedLinesAreDirty(line))) {
|
||||||
// Compute the dirty lines "before" YMost, after factoring in
|
// Compute the dirty lines "before" YMost, after factoring in
|
||||||
// the running deltaY value - the running value is implicit in
|
// the running deltaY value - the running value is implicit in
|
||||||
// aState.mY.
|
// aState.mY.
|
||||||
|
@ -2729,6 +2769,10 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState)
|
||||||
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
RecoverStateFrom(aState, line, deltaY, incrementalReflow ?
|
||||||
&damageRect : 0);
|
&damageRect : 0);
|
||||||
if (incrementalReflow && !damageRect.IsEmpty()) {
|
if (incrementalReflow && !damageRect.IsEmpty()) {
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 5 (%d, %d, %d, %d)\n",
|
||||||
|
this, damageRect.x, damageRect.y, damageRect.width, damageRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, damageRect);
|
Invalidate(aState.mPresContext, damageRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2902,6 +2946,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// XXX We need to improve on this...
|
// XXX We need to improve on this...
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 6 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -2918,6 +2966,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.x;
|
dirtyRect.x;
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
dirtyRect.height = PR_MAX(oldCombinedArea.height,
|
||||||
lineCombinedArea.height);
|
lineCombinedArea.height);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 7 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
if (oldCombinedArea.height != lineCombinedArea.height) {
|
if (oldCombinedArea.height != lineCombinedArea.height) {
|
||||||
|
@ -2933,6 +2985,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
dirtyRect.height = PR_MAX(oldCombinedArea.YMost(),
|
||||||
lineCombinedArea.YMost()) -
|
lineCombinedArea.YMost()) -
|
||||||
dirtyRect.y;
|
dirtyRect.y;
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 8 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2951,21 +3007,21 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// we'll either need to recover the floater state that applies to the
|
// we'll either need to recover the floater state that applies to the
|
||||||
// unconstrained reflow or keep it around in a separate space manager...
|
// unconstrained reflow or keep it around in a separate space manager...
|
||||||
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
PRBool isBeginningLine = !aState.mPrevLine || !aState.mPrevLine->IsLineWrapped();
|
||||||
if (aState.mComputeMaximumWidth && isBeginningLine) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH) && isBeginningLine) {
|
||||||
nscoord oldY = aState.mY;
|
nscoord oldY = aState.mY;
|
||||||
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
nscoord oldPrevBottomMargin = aState.mPrevBottomMargin;
|
||||||
PRBool oldUnconstrainedWidth = aState.mUnconstrainedWidth;
|
PRBool oldUnconstrainedWidth = aState.GetFlag(BRS_UNCONSTRAINEDWIDTH);
|
||||||
|
|
||||||
// First reflow the line with an unconstrained width. When doing this
|
// First reflow the line with an unconstrained width. When doing this
|
||||||
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
// we need to set the block reflow state's "mUnconstrainedWidth" variable
|
||||||
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
// to PR_TRUE so if we encounter a placeholder and then reflow its
|
||||||
// associated floater we don't end up resetting the line's right edge and
|
// associated floater we don't end up resetting the line's right edge and
|
||||||
// have it think the width is unconstrained...
|
// have it think the width is unconstrained...
|
||||||
aState.mUnconstrainedWidth = PR_TRUE;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||||
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
ReflowInlineFrames(aState, aLine, aKeepReflowGoing, PR_TRUE);
|
||||||
aState.mY = oldY;
|
aState.mY = oldY;
|
||||||
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
aState.mPrevBottomMargin = oldPrevBottomMargin;
|
||||||
aState.mUnconstrainedWidth = oldUnconstrainedWidth;
|
aState.SetFlag(BRS_UNCONSTRAINEDWIDTH, oldUnconstrainedWidth);
|
||||||
|
|
||||||
// Update the line's maximum width
|
// Update the line's maximum width
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
|
@ -2980,14 +3036,14 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
// Note: we need to reset both member variables, because the inline
|
// Note: we need to reset both member variables, because the inline
|
||||||
// code examines mComputeMaxElementSize and if there is a placeholder
|
// code examines mComputeMaxElementSize and if there is a placeholder
|
||||||
// on this line the code to reflow the floater looks at both...
|
// on this line the code to reflow the floater looks at both...
|
||||||
nscoord oldComputeMaxElementSize = aState.mComputeMaxElementSize;
|
nscoord oldComputeMaxElementSize = aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE);
|
||||||
nscoord oldComputeMaximumWidth = aState.mComputeMaximumWidth;
|
nscoord oldComputeMaximumWidth = aState.GetFlag(BRS_COMPUTEMAXWIDTH);
|
||||||
|
|
||||||
aState.mComputeMaxElementSize = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, PR_FALSE);
|
||||||
aState.mComputeMaximumWidth = PR_FALSE;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, PR_FALSE);
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
aState.mComputeMaxElementSize = oldComputeMaxElementSize;
|
aState.SetFlag(BRS_COMPUTEMAXELEMENTSIZE, oldComputeMaxElementSize);
|
||||||
aState.mComputeMaximumWidth = oldComputeMaximumWidth;
|
aState.SetFlag(BRS_COMPUTEMAXWIDTH, oldComputeMaximumWidth);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
rv = ReflowInlineFrames(aState, aLine, aKeepReflowGoing);
|
||||||
|
@ -3001,6 +3057,10 @@ nsBlockFrame::ReflowLine(nsBlockReflowState& aState,
|
||||||
|
|
||||||
nsRect dirtyRect;
|
nsRect dirtyRect;
|
||||||
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
dirtyRect.UnionRect(oldCombinedArea, combinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 9 (%d, %d, %d, %d)\n",
|
||||||
|
this, dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height);
|
||||||
|
#endif
|
||||||
Invalidate(aState.mPresContext, dirtyRect);
|
Invalidate(aState.mPresContext, dirtyRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3368,7 +3428,7 @@ PRBool
|
||||||
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
nsLineBox* aLine)
|
nsLineBox* aLine)
|
||||||
{
|
{
|
||||||
if (aState.mApplyTopMargin) {
|
if (aState.GetFlag(BRS_APPLYTOPMARGIN)) {
|
||||||
// Apply short-circuit check to avoid searching the line list
|
// Apply short-circuit check to avoid searching the line list
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -3377,7 +3437,7 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
// If we aren't at the top Y coordinate then something of non-zero
|
// If we aren't at the top Y coordinate then something of non-zero
|
||||||
// height must have been placed. Therefore the childs top-margin
|
// height must have been placed. Therefore the childs top-margin
|
||||||
// applies.
|
// applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3387,13 +3447,13 @@ nsBlockFrame::ShouldApplyTopMargin(nsBlockReflowState& aState,
|
||||||
if (line->IsBlock()) {
|
if (line->IsBlock()) {
|
||||||
// A line which preceeds aLine contains a block; therefore the
|
// A line which preceeds aLine contains a block; therefore the
|
||||||
// top margin applies.
|
// top margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else if (line->HasFloaters()) {
|
else if (line->HasFloaters()) {
|
||||||
// A line which preceeds aLine is not empty therefore the top
|
// A line which preceeds aLine is not empty therefore the top
|
||||||
// margin applies.
|
// margin applies.
|
||||||
aState.mApplyTopMargin = PR_TRUE;
|
aState.SetFlag(BRS_APPLYTOPMARGIN, PR_TRUE);
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
line = line->mNext;
|
line = line->mNext;
|
||||||
|
@ -3486,8 +3546,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
frame->GetStyleData(eStyleStruct_Display,
|
frame->GetStyleData(eStyleStruct_Display,
|
||||||
(const nsStyleStruct*&) display);
|
(const nsStyleStruct*&) display);
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// See if we should apply the top margin. If the block frame being
|
// See if we should apply the top margin. If the block frame being
|
||||||
|
@ -3611,14 +3671,14 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
&collapsedBottomMargin,
|
&collapsedBottomMargin,
|
||||||
aLine->mBounds, combinedArea);
|
aLine->mBounds, combinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line as block so once we known the final shrink wrap width
|
// Mark the line as block so once we known the final shrink wrap width
|
||||||
// we can reflow the block to the correct size
|
// we can reflow the block to the correct size
|
||||||
// XXX We don't always need to do this...
|
// XXX We don't always need to do this...
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
if (aState.mUnconstrainedWidth || aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Add the right margin to the line's bounnds. That way it will be taken into
|
// Add the right margin to the line's bounnds. That way it will be taken into
|
||||||
// account when we compute our shrink wrap size
|
// account when we compute our shrink wrap size
|
||||||
nscoord marginRight = brc.GetMargin().right;
|
nscoord marginRight = brc.GetMargin().right;
|
||||||
|
@ -3709,7 +3769,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Post-process the "line"
|
// Post-process the "line"
|
||||||
nsSize maxElementSize(0, 0);
|
nsSize maxElementSize(0, 0);
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
maxElementSize = brc.GetMaxElementSize();
|
maxElementSize = brc.GetMaxElementSize();
|
||||||
if (aState.IsImpactedByFloater() &&
|
if (aState.IsImpactedByFloater() &&
|
||||||
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
(NS_FRAME_SPLITTABLE_NON_RECTANGULAR != splitType)) {
|
||||||
|
@ -3721,7 +3781,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
// If we asked the block to update its maximum width, then record the
|
// If we asked the block to update its maximum width, then record the
|
||||||
// updated value in the line, and update the current maximum width
|
// updated value in the line, and update the current maximum width
|
||||||
if (aState.mComputeMaximumWidth) {
|
if (aState.GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||||
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
aLine->mMaximumWidth = brc.GetMaximumWidth();
|
||||||
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
aState.UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||||
|
|
||||||
|
@ -3849,7 +3909,7 @@ nsBlockFrame::DoReflowInlineFramesMalloc(nsBlockReflowState& aState,
|
||||||
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
nsLineLayout* ll = new nsLineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -3872,7 +3932,7 @@ nsBlockFrame::DoReflowInlineFramesAuto(nsBlockReflowState& aState,
|
||||||
nsLineLayout lineLayout(aState.mPresContext,
|
nsLineLayout lineLayout(aState.mPresContext,
|
||||||
aState.mReflowState.mSpaceManager,
|
aState.mReflowState.mSpaceManager,
|
||||||
&aState.mReflowState,
|
&aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize);
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE));
|
||||||
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
lineLayout.Init(&aState, aState.mMinLineHeight, aState.mLineNumber);
|
||||||
lineLayout.SetReflowTextRuns(mTextRuns);
|
lineLayout.SetReflowTextRuns(mTextRuns);
|
||||||
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
nsresult rv = DoReflowInlineFrames(aState, lineLayout, aLine,
|
||||||
|
@ -3910,7 +3970,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
|
||||||
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
nscoord x = aState.mAvailSpaceRect.x + borderPadding.left;
|
||||||
nscoord availWidth = aState.mAvailSpaceRect.width;
|
nscoord availWidth = aState.mAvailSpaceRect.width;
|
||||||
nscoord availHeight;
|
nscoord availHeight;
|
||||||
if (aState.mUnconstrainedHeight) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDHEIGHT)) {
|
||||||
availHeight = NS_UNCONSTRAINEDSIZE;
|
availHeight = NS_UNCONSTRAINEDSIZE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -4359,7 +4419,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
nsSize maxElementSize;
|
nsSize maxElementSize;
|
||||||
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
aLineLayout.VerticalAlignFrames(aLine, maxElementSize);
|
||||||
// See if we're shrink wrapping the width
|
// See if we're shrink wrapping the width
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// When determining the line's width we also need to include any
|
// When determining the line's width we also need to include any
|
||||||
// right floaters that impact us. This represents the shrink wrap
|
// right floaters that impact us. This represents the shrink wrap
|
||||||
// width of the line
|
// width of the line
|
||||||
|
@ -4388,25 +4448,20 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// Only block frames horizontally align their children because
|
// Only block frames horizontally align their children because
|
||||||
// inline frames "shrink-wrap" around their children (therefore
|
// inline frames "shrink-wrap" around their children (therefore
|
||||||
// there is no extra horizontal space).
|
// there is no extra horizontal space).
|
||||||
#if XXX_fix_me
|
const nsStyleText* styleText = (const nsStyleText*)
|
||||||
PRBool allowJustify = PR_TRUE;
|
mStyleContext->GetStyleData(eStyleStruct_Text);
|
||||||
if (NS_STYLE_TEXT_ALIGN_JUSTIFY == aState.mStyleText->mTextAlign) {
|
PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign
|
||||||
allowJustify = ShouldJustifyLine(aState, aLine);
|
&& !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine);
|
||||||
}
|
PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
||||||
#else
|
aState.GetFlag(BRS_SHRINKWRAPWIDTH));
|
||||||
PRBool allowJustify = PR_FALSE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PRBool successful;
|
|
||||||
nsRect combinedArea;
|
|
||||||
successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify,
|
|
||||||
aState.mShrinkWrapWidth);
|
|
||||||
if (!successful) {
|
if (!successful) {
|
||||||
// Mark the line dirty and then later once we've determined the width
|
// Mark the line dirty and then later once we've determined the width
|
||||||
// we can do the horizontal alignment
|
// we can do the horizontal alignment
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsRect combinedArea;
|
||||||
aLineLayout.RelativePositionFrames(combinedArea);
|
aLineLayout.RelativePositionFrames(combinedArea);
|
||||||
aLine->SetCombinedArea(combinedArea);
|
aLine->SetCombinedArea(combinedArea);
|
||||||
if (addedBullet) {
|
if (addedBullet) {
|
||||||
|
@ -4454,7 +4509,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
aState.mY = newY;
|
aState.mY = newY;
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
#ifdef NOISY_MAX_ELEMENT_SIZE
|
#ifdef NOISY_MAX_ELEMENT_SIZE
|
||||||
IndentBy(stdout, GetDepth());
|
IndentBy(stdout, GetDepth());
|
||||||
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
if (NS_UNCONSTRAINEDSIZE == aState.mReflowState.availableWidth) {
|
||||||
|
@ -4478,7 +4533,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
// we don't want updated...
|
// we don't want updated...
|
||||||
if (aUpdateMaximumWidth) {
|
if (aUpdateMaximumWidth) {
|
||||||
// However, we do need to update the max-element-size if requested
|
// However, we do need to update the max-element-size if requested
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(maxElementSize);
|
aState.UpdateMaxElementSize(maxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4519,7 +4574,7 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mHaveRightFloaters &&
|
if (aState.mHaveRightFloaters &&
|
||||||
(aState.mUnconstrainedWidth || aState.mShrinkWrapWidth)) {
|
(aState.GetFlag(BRS_UNCONSTRAINEDWIDTH) || aState.GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// We are reflowing in an unconstrained situation or shrink wrapping and
|
// We are reflowing in an unconstrained situation or shrink wrapping and
|
||||||
// have some right floaters. They were placed at the infinite right edge
|
// have some right floaters. They were placed at the infinite right edge
|
||||||
// which will cause the combined area to be unusable.
|
// which will cause the combined area to be unusable.
|
||||||
|
@ -4540,11 +4595,11 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
|
||||||
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
aState.mRightFloaterCombinedArea.x = aLine->mBounds.XMost();
|
||||||
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
CombineRects(aState.mRightFloaterCombinedArea, lineCombinedArea);
|
||||||
|
|
||||||
if (aState.mShrinkWrapWidth) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||||
// Mark the line dirty so we come back and re-place the floater once
|
// Mark the line dirty so we come back and re-place the floater once
|
||||||
// the shrink wrap width is determined
|
// the shrink wrap width is determined
|
||||||
aLine->MarkDirty();
|
aLine->MarkDirty();
|
||||||
aState.mNeedResizeReflow = PR_TRUE;
|
aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aLine->SetCombinedArea(lineCombinedArea);
|
aLine->SetCombinedArea(lineCombinedArea);
|
||||||
|
@ -4629,7 +4684,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update max-element-size
|
// Update max-element-size
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.UpdateMaxElementSize(aMaxElementSize);
|
aState.UpdateMaxElementSize(aMaxElementSize);
|
||||||
// We also cache the max element width in the line. This is needed for
|
// We also cache the max element width in the line. This is needed for
|
||||||
// incremental reflow
|
// incremental reflow
|
||||||
|
@ -4639,7 +4694,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
// If this is an unconstrained reflow, then cache the line width in the
|
// If this is an unconstrained reflow, then cache the line width in the
|
||||||
// line. We'll need this during incremental reflow if we're asked to
|
// line. We'll need this during incremental reflow if we're asked to
|
||||||
// calculate the maximum width
|
// calculate the maximum width
|
||||||
if (aState.mUnconstrainedWidth) {
|
if (aState.GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||||
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
aLine->mMaximumWidth = aLine->mBounds.XMost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4653,7 +4708,7 @@ nsBlockFrame::PostPlaceLine(nsBlockReflowState& aState,
|
||||||
#endif
|
#endif
|
||||||
// If we're shrink wrapping our width and the line was wrapped,
|
// If we're shrink wrapping our width and the line was wrapped,
|
||||||
// then make sure we take up all of the available width
|
// then make sure we take up all of the available width
|
||||||
if (aState.mShrinkWrapWidth && aLine->IsLineWrapped()) {
|
if (aState.GetFlag(BRS_SHRINKWRAPWIDTH) && aLine->IsLineWrapped()) {
|
||||||
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
aState.mKidXMost = aState.BorderPadding().left + aState.mContentArea.width;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5187,6 +5242,10 @@ nsBlockFrame::DoRemoveFrame(nsIPresContext* aPresContext,
|
||||||
// cases...
|
// cases...
|
||||||
nsRect lineCombinedArea;
|
nsRect lineCombinedArea;
|
||||||
line->GetCombinedArea(&lineCombinedArea);
|
line->GetCombinedArea(&lineCombinedArea);
|
||||||
|
#ifdef NOISY_BLOCK_INVALIDATE
|
||||||
|
printf("%p invalidate 10 (%d, %d, %d, %d)\n",
|
||||||
|
this, lineCombinedArea.x, lineCombinedArea.y, lineCombinedArea.width, lineCombinedArea.height);
|
||||||
|
#endif
|
||||||
Invalidate(aPresContext, lineCombinedArea);
|
Invalidate(aPresContext, lineCombinedArea);
|
||||||
line->Destroy(presShell);
|
line->Destroy(presShell);
|
||||||
line = next;
|
line = next;
|
||||||
|
@ -5282,8 +5341,8 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
|
|
||||||
// Setup block reflow state to reflow the floater
|
// Setup block reflow state to reflow the floater
|
||||||
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
nsBlockReflowContext brc(aState.mPresContext, aState.mReflowState,
|
||||||
aState.mComputeMaxElementSize,
|
aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE),
|
||||||
aState.mComputeMaximumWidth);
|
aState.GetFlag(BRS_COMPUTEMAXWIDTH));
|
||||||
brc.SetNextRCFrame(aState.mNextRCFrame);
|
brc.SetNextRCFrame(aState.mNextRCFrame);
|
||||||
|
|
||||||
// Reflow the floater
|
// Reflow the floater
|
||||||
|
@ -5324,7 +5383,7 @@ nsBlockFrame::ReflowFloater(nsBlockReflowState& aState,
|
||||||
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
floater->DidReflow(aState.mPresContext, NS_FRAME_REFLOW_FINISHED);
|
||||||
|
|
||||||
// If we computed it, then stash away the max-element-size for later
|
// If we computed it, then stash away the max-element-size for later
|
||||||
if (aState.mComputeMaxElementSize) {
|
if (aState.GetFlag(BRS_COMPUTEMAXELEMENTSIZE)) {
|
||||||
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
aState.StoreMaxElementSize(floater, brc.GetMaxElementSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5389,7 +5448,7 @@ nsBlockReflowState::AddFloater(nsLineLayout& aLineLayout,
|
||||||
// Pass on updated available space to the current inline reflow engine
|
// Pass on updated available space to the current inline reflow engine
|
||||||
GetAvailableSpace();
|
GetAvailableSpace();
|
||||||
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
||||||
mUnconstrainedWidth ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
GetFlag(BRS_UNCONSTRAINEDWIDTH) ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
||||||
mAvailSpaceRect.height,
|
mAvailSpaceRect.height,
|
||||||
isLeftFloater,
|
isLeftFloater,
|
||||||
aPlaceholder->GetOutOfFlowFrame());
|
aPlaceholder->GetOutOfFlowFrame());
|
||||||
|
@ -5615,7 +5674,12 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isLeftFloater = PR_FALSE;
|
isLeftFloater = PR_FALSE;
|
||||||
region.x = mAvailSpaceRect.XMost() - region.width;
|
if (NS_UNCONSTRAINEDSIZE != mAvailSpaceRect.XMost())
|
||||||
|
region.x = mAvailSpaceRect.XMost() - region.width;
|
||||||
|
else {
|
||||||
|
okToAddRectRegion = PR_FALSE;
|
||||||
|
region.x = mAvailSpaceRect.x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*aIsLeftFloater = isLeftFloater;
|
*aIsLeftFloater = isLeftFloater;
|
||||||
const nsMargin& borderPadding = BorderPadding();
|
const nsMargin& borderPadding = BorderPadding();
|
||||||
|
@ -5682,7 +5746,8 @@ nsBlockReflowState::PlaceFloater(nsFloaterCache* aFloaterCache,
|
||||||
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
nsRect combinedArea = aFloaterCache->mCombinedArea;
|
||||||
combinedArea.x += x;
|
combinedArea.x += x;
|
||||||
combinedArea.y += y;
|
combinedArea.y += y;
|
||||||
if (!isLeftFloater && (mUnconstrainedWidth || mShrinkWrapWidth)) {
|
if (!isLeftFloater &&
|
||||||
|
(GetFlag(BRS_UNCONSTRAINEDWIDTH) || GetFlag(BRS_SHRINKWRAPWIDTH))) {
|
||||||
// When we are placing a right floater in an unconstrained situation or
|
// When we are placing a right floater in an unconstrained situation or
|
||||||
// when shrink wrapping, we don't apply it to the floater combined area
|
// when shrink wrapping, we don't apply it to the floater combined area
|
||||||
// immediately. Otherwise we end up with an infinitely wide combined
|
// immediately. Otherwise we end up with an infinitely wide combined
|
||||||
|
|
|
@ -879,6 +879,13 @@ nsImageFrame::AttributeChanged(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (nsHTMLAtoms::width == aAttribute || nsHTMLAtoms::height == aAttribute)
|
||||||
|
{ // XXX: could check for new width == old width, and make that a no-op
|
||||||
|
nsCOMPtr<nsIPresShell> presShell;
|
||||||
|
aPresContext->GetShell(getter_AddRefs(presShell));
|
||||||
|
mState |= NS_FRAME_IS_DIRTY;
|
||||||
|
mParent->ReflowDirtyChild(presShell, (nsIFrame*) this);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,10 @@
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Steve Clark <buster@netscape.com>
|
||||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
* L. David Baron <dbaron@fas.harvard.edu>
|
* L. David Baron <dbaron@fas.harvard.edu>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
*/
|
*/
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsLineLayout.h"
|
#include "nsLineLayout.h"
|
||||||
|
@ -41,13 +43,14 @@
|
||||||
#include "nsIView.h"
|
#include "nsIView.h"
|
||||||
#include "nsIViewManager.h"
|
#include "nsIViewManager.h"
|
||||||
#include "nsHTMLAtoms.h"
|
#include "nsHTMLAtoms.h"
|
||||||
|
#include "nsTextFragment.h"
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#undef NOISY_HORIZONTAL_ALIGN
|
#undef NOISY_HORIZONTAL_ALIGN
|
||||||
#undef NOISY_VERTICAL_ALIGN
|
#undef NOISY_VERTICAL_ALIGN
|
||||||
#undef REALLY_NOISY_VERTICAL_ALIGN
|
#undef REALLY_NOISY_VERTICAL_ALIGN
|
||||||
#undef NOISY_REFLOW
|
#undef NOISY_REFLOW
|
||||||
#undef REALLY_NOISY_REFLOW
|
#undef REALLY_NOISY_REFLOW
|
||||||
#undef NOISY_PUSHING
|
#undef NOISY_PUSHING
|
||||||
#undef REALLY_NOISY_PUSHING
|
#undef REALLY_NOISY_PUSHING
|
||||||
#undef DEBUG_ADD_TEXT
|
#undef DEBUG_ADD_TEXT
|
||||||
|
@ -120,15 +123,9 @@ nsLineLayout::nsLineLayout(nsIPresContext* aPresContext,
|
||||||
mTextAlign = mStyleText->mTextAlign;
|
mTextAlign = mStyleText->mTextAlign;
|
||||||
mLineNumber = 0;
|
mLineNumber = 0;
|
||||||
mColumn = 0;
|
mColumn = 0;
|
||||||
mEndsInWhiteSpace = PR_TRUE;
|
mFlags = 0; // default all flags to false except those that follow here...
|
||||||
mUnderstandsWhiteSpace = PR_FALSE;
|
SetFlag(LL_ENDSINWHITESPACE, PR_TRUE);
|
||||||
mTextStartsWithNBSP = PR_FALSE;
|
|
||||||
mFirstLetterStyleOK = PR_FALSE;
|
|
||||||
mIsTopOfPage = PR_FALSE;
|
|
||||||
mUpdatedBand = PR_FALSE;
|
|
||||||
mPlacedFloaters = 0;
|
mPlacedFloaters = 0;
|
||||||
mImpactedByFloaters = PR_FALSE;
|
|
||||||
mLastFloaterWasLetterFrame = PR_FALSE;
|
|
||||||
mTotalPlacedFrames = 0;
|
mTotalPlacedFrames = 0;
|
||||||
mTopEdge = mBottomEdge = 0;
|
mTopEdge = mBottomEdge = 0;
|
||||||
mReflowTextRuns = nsnull;
|
mReflowTextRuns = nsnull;
|
||||||
|
@ -148,14 +145,17 @@ nsLineLayout::nsLineLayout(nsIPresContext* aPresContext,
|
||||||
mTextRuns = nsnull;
|
mTextRuns = nsnull;
|
||||||
mTextRunP = &mTextRuns;
|
mTextRunP = &mTextRuns;
|
||||||
mNewTextRun = nsnull;
|
mNewTextRun = nsnull;
|
||||||
mKnowStrictMode = PR_FALSE;
|
SetFlag(LL_KNOWSTRICTMODE, PR_FALSE);
|
||||||
|
PRInt32 size = sizeof nsLineLayout;
|
||||||
|
PRInt32 size_pfd = sizeof PerFrameData;
|
||||||
|
PRInt32 size_psd = sizeof PerSpanData;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsLineLayout::nsLineLayout(nsIPresContext* aPresContext)
|
nsLineLayout::nsLineLayout(nsIPresContext* aPresContext)
|
||||||
: mPresContext(aPresContext)
|
: mPresContext(aPresContext)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsLineLayout);
|
MOZ_COUNT_CTOR(nsLineLayout);
|
||||||
|
|
||||||
mTextRuns = nsnull;
|
mTextRuns = nsnull;
|
||||||
mTextRunP = &mTextRuns;
|
mTextRunP = &mTextRuns;
|
||||||
mNewTextRun = nsnull;
|
mNewTextRun = nsnull;
|
||||||
|
@ -197,9 +197,9 @@ nsLineLayout::~nsLineLayout()
|
||||||
PRBool
|
PRBool
|
||||||
nsLineLayout::InStrictMode()
|
nsLineLayout::InStrictMode()
|
||||||
{
|
{
|
||||||
if (!mKnowStrictMode) {
|
if (!GetFlag(LL_KNOWSTRICTMODE)) {
|
||||||
mKnowStrictMode = PR_TRUE;
|
SetFlag(LL_KNOWSTRICTMODE, PR_TRUE);
|
||||||
mInStrictMode = PR_TRUE;
|
SetFlag(LL_INSTRICTMODE, PR_TRUE);
|
||||||
|
|
||||||
// Get the compatabilty mode from pres context via the document and pres shell
|
// Get the compatabilty mode from pres context via the document and pres shell
|
||||||
if (mBlockReflowState->frame) {
|
if (mBlockReflowState->frame) {
|
||||||
|
@ -217,7 +217,7 @@ nsLineLayout::InStrictMode()
|
||||||
nsCompatibility mode;
|
nsCompatibility mode;
|
||||||
presContext->GetCompatibilityMode(&mode);
|
presContext->GetCompatibilityMode(&mode);
|
||||||
if (eCompatibility_NavQuirks == mode) {
|
if (eCompatibility_NavQuirks == mode) {
|
||||||
mInStrictMode = PR_FALSE;
|
SetFlag(LL_INSTRICTMODE, PR_FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NS_RELEASE(shell);
|
NS_RELEASE(shell);
|
||||||
|
@ -226,7 +226,7 @@ nsLineLayout::InStrictMode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mInStrictMode;
|
return GetFlag(LL_INSTRICTMODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -235,10 +235,6 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
|
||||||
PRBool aImpactedByFloaters,
|
PRBool aImpactedByFloaters,
|
||||||
PRBool aIsTopOfPage)
|
PRBool aIsTopOfPage)
|
||||||
{
|
{
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
|
||||||
printf("nsLL::BeginLineReflow %d, %d, %d, %d, impacted=%s\n",
|
|
||||||
aX, aY, aWidth, aHeight, aImpactedByFloaters?"true":"false");
|
|
||||||
#endif
|
|
||||||
NS_ASSERTION(nsnull == mRootSpan, "bad linelayout user");
|
NS_ASSERTION(nsnull == mRootSpan, "bad linelayout user");
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if ((aWidth != NS_UNCONSTRAINEDSIZE) && CRAZY_WIDTH(aWidth)) {
|
if ((aWidth != NS_UNCONSTRAINEDSIZE) && CRAZY_WIDTH(aWidth)) {
|
||||||
|
@ -256,8 +252,9 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
|
||||||
#endif
|
#endif
|
||||||
#ifdef NOISY_REFLOW
|
#ifdef NOISY_REFLOW
|
||||||
nsFrame::ListTag(stdout, mBlockReflowState->frame);
|
nsFrame::ListTag(stdout, mBlockReflowState->frame);
|
||||||
printf(": BeginLineReflow: %d,%d,%d,%d %s\n",
|
printf(": BeginLineReflow: %d,%d,%d,%d impacted=%s %s\n",
|
||||||
aX, aY, aWidth, aHeight,
|
aX, aY, aWidth, aHeight,
|
||||||
|
aImpactedByFloaters?"true":"false",
|
||||||
aIsTopOfPage ? "top-of-page" : "");
|
aIsTopOfPage ? "top-of-page" : "");
|
||||||
#endif
|
#endif
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -265,17 +262,18 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mColumn = 0;
|
mColumn = 0;
|
||||||
mEndsInWhiteSpace = PR_TRUE;
|
|
||||||
mUnderstandsWhiteSpace = PR_FALSE;
|
SetFlag(LL_ENDSINWHITESPACE, PR_TRUE);
|
||||||
mTextStartsWithNBSP = PR_FALSE;
|
SetFlag(LL_UNDERSTANDSNWHITESPACE, PR_FALSE);
|
||||||
mFirstLetterStyleOK = PR_FALSE;
|
SetFlag(LL_TEXTSTARTSWITHNBSP, PR_FALSE);
|
||||||
mIsTopOfPage = aIsTopOfPage;
|
SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
|
||||||
mUpdatedBand = PR_FALSE;
|
SetFlag(LL_ISTOPOFPAGE, aIsTopOfPage);
|
||||||
|
SetFlag(LL_UPDATEDBAND, PR_FALSE);
|
||||||
mPlacedFloaters = 0;
|
mPlacedFloaters = 0;
|
||||||
mImpactedByFloaters = aImpactedByFloaters;
|
SetFlag(LL_IMPACTEDBYFLOATERS, aImpactedByFloaters);
|
||||||
mTotalPlacedFrames = 0;
|
mTotalPlacedFrames = 0;
|
||||||
mCanPlaceFloater = PR_TRUE;
|
SetFlag(LL_CANPLACEFLOATER, PR_TRUE);
|
||||||
mLineEndsInBR = PR_FALSE;
|
SetFlag(LL_LINEENDSINBR, PR_FALSE);
|
||||||
mSpanDepth = 0;
|
mSpanDepth = 0;
|
||||||
mMaxTopBoxHeight = mMaxBottomBoxHeight = 0;
|
mMaxTopBoxHeight = mMaxBottomBoxHeight = 0;
|
||||||
|
|
||||||
|
@ -355,7 +353,7 @@ nsLineLayout::UpdateBand(nscoord aX, nscoord aY,
|
||||||
nsIFrame* aFloaterFrame)
|
nsIFrame* aFloaterFrame)
|
||||||
{
|
{
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
printf("nsLL::UpdateBand %d, %d, %d, %d, frame=%p placedLeft=%s\n will set mImpacted to PR_TRUE",
|
printf("nsLL::UpdateBand %d, %d, %d, %d, frame=%p placedLeft=%s\n will set mImpacted to PR_TRUE\n",
|
||||||
aX, aY, aWidth, aHeight, aFloaterFrame, aPlacedLeftFloater?"true":"false");
|
aX, aY, aWidth, aHeight, aFloaterFrame, aPlacedLeftFloater?"true":"false");
|
||||||
#endif
|
#endif
|
||||||
PerSpanData* psd = mRootSpan;
|
PerSpanData* psd = mRootSpan;
|
||||||
|
@ -404,13 +402,13 @@ nsLineLayout::UpdateBand(nscoord aX, nscoord aY,
|
||||||
else {
|
else {
|
||||||
mBottomEdge = aY + aHeight;
|
mBottomEdge = aY + aHeight;
|
||||||
}
|
}
|
||||||
mUpdatedBand = PR_TRUE;
|
SetFlag(LL_UPDATEDBAND, PR_TRUE);
|
||||||
mPlacedFloaters |= (aPlacedLeftFloater ? PLACED_LEFT : PLACED_RIGHT);
|
mPlacedFloaters |= (aPlacedLeftFloater ? PLACED_LEFT : PLACED_RIGHT);
|
||||||
mImpactedByFloaters = PR_TRUE;
|
SetFlag(LL_IMPACTEDBYFLOATERS, PR_TRUE);
|
||||||
|
|
||||||
nsCOMPtr<nsIAtom> frameType;
|
nsCOMPtr<nsIAtom> frameType;
|
||||||
aFloaterFrame->GetFrameType(getter_AddRefs(frameType));
|
aFloaterFrame->GetFrameType(getter_AddRefs(frameType));
|
||||||
mLastFloaterWasLetterFrame = nsLayoutAtoms::letterFrame == frameType.get();
|
SetFlag(LL_LASTFLOATERWASLETTERFRAME, (nsLayoutAtoms::letterFrame == frameType.get()));
|
||||||
|
|
||||||
// Now update all of the open spans...
|
// Now update all of the open spans...
|
||||||
mRootSpan->mContainsFloater = PR_TRUE; // make sure mRootSpan gets updated too
|
mRootSpan->mContainsFloater = PR_TRUE; // make sure mRootSpan gets updated too
|
||||||
|
@ -762,17 +760,10 @@ nsLineLayout::NewPerFrameData(PerFrameData** aResult)
|
||||||
pfd->mNext = nsnull;
|
pfd->mNext = nsnull;
|
||||||
pfd->mPrev = nsnull;
|
pfd->mPrev = nsnull;
|
||||||
pfd->mFrame = nsnull;
|
pfd->mFrame = nsnull;
|
||||||
pfd->mRelativePos = PR_FALSE;
|
pfd->mFlags = 0; // all flags default to false
|
||||||
pfd->mIsTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsNonEmptyTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsNonWhitespaceTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsLetterFrame = PR_FALSE;
|
|
||||||
pfd->mIsSticky = PR_FALSE;
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
pfd->mVerticalAlign = 0xFF;
|
pfd->mVerticalAlign = 0xFF;
|
||||||
pfd->mRelativePos = PRBool(0xFF);
|
|
||||||
mFramesAllocated++;
|
mFramesAllocated++;
|
||||||
#endif
|
#endif
|
||||||
*aResult = pfd;
|
*aResult = pfd;
|
||||||
|
@ -782,7 +773,7 @@ nsLineLayout::NewPerFrameData(PerFrameData** aResult)
|
||||||
PRBool
|
PRBool
|
||||||
nsLineLayout::CanPlaceFloaterNow() const
|
nsLineLayout::CanPlaceFloaterNow() const
|
||||||
{
|
{
|
||||||
return mCanPlaceFloater;
|
return GetFlag(LL_CANPLACEFLOATER);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
|
@ -794,7 +785,7 @@ nsLineLayout::LineIsEmpty() const
|
||||||
PRBool
|
PRBool
|
||||||
nsLineLayout::LineIsBreakable() const
|
nsLineLayout::LineIsBreakable() const
|
||||||
{
|
{
|
||||||
if ((0 != mTotalPlacedFrames) || mImpactedByFloaters) {
|
if ((0 != mTotalPlacedFrames) || GetFlag(LL_IMPACTEDBYFLOATERS)) {
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
return PR_FALSE;
|
return PR_FALSE;
|
||||||
|
@ -903,9 +894,11 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
nsHTMLReflowState reflowState(mPresContext, *psd->mReflowState, aFrame,
|
nsHTMLReflowState reflowState(mPresContext, *psd->mReflowState, aFrame,
|
||||||
availSize, reason);
|
availSize, reason);
|
||||||
reflowState.mLineLayout = this;
|
reflowState.mLineLayout = this;
|
||||||
reflowState.isTopOfPage = mIsTopOfPage;
|
reflowState.isTopOfPage = GetFlag(LL_ISTOPOFPAGE);
|
||||||
mUnderstandsWhiteSpace = PR_FALSE;
|
SetFlag(LL_UNDERSTANDSNWHITESPACE, PR_FALSE);
|
||||||
mTextStartsWithNBSP = PR_FALSE;
|
SetFlag(LL_TEXTSTARTSWITHNBSP, PR_FALSE);
|
||||||
|
mTextJustificationNumSpaces = 0;
|
||||||
|
mTextJustificationNumLetters = 0;
|
||||||
|
|
||||||
// Stash copies of some of the computed state away for later
|
// Stash copies of some of the computed state away for later
|
||||||
// (vertical alignment, for example)
|
// (vertical alignment, for example)
|
||||||
|
@ -913,9 +906,9 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
pfd->mMargin = reflowState.mComputedMargin;
|
pfd->mMargin = reflowState.mComputedMargin;
|
||||||
pfd->mBorderPadding = reflowState.mComputedBorderPadding;
|
pfd->mBorderPadding = reflowState.mComputedBorderPadding;
|
||||||
pfd->mFrameType = reflowState.mFrameType;
|
pfd->mFrameType = reflowState.mFrameType;
|
||||||
pfd->mRelativePos =
|
pfd->SetFlag(PFD_RELATIVEPOS,
|
||||||
reflowState.mStylePosition->mPosition == NS_STYLE_POSITION_RELATIVE;
|
(reflowState.mStylePosition->mPosition == NS_STYLE_POSITION_RELATIVE));
|
||||||
if (pfd->mRelativePos) {
|
if (pfd->GetFlag(PFD_RELATIVEPOS)) {
|
||||||
pfd->mOffsets = reflowState.mComputedOffsets;
|
pfd->mOffsets = reflowState.mComputedOffsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -969,14 +962,18 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
|
nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
|
||||||
mSpaceManager->Translate(tx, ty);
|
mSpaceManager->Translate(tx, ty);
|
||||||
|
|
||||||
pfd->mIsTextFrame = PR_FALSE;
|
pfd->SetFlag(PFD_ISTEXTFRAME, PR_FALSE);
|
||||||
pfd->mIsLetterFrame = PR_FALSE;
|
pfd->SetFlag(PFD_ISLETTERFRAME, PR_FALSE);
|
||||||
pfd->mIsNonEmptyTextFrame = PR_FALSE;
|
pfd->SetFlag(PFD_ISNONEMPTYTEXTFRAME, PR_FALSE);
|
||||||
pfd->mIsNonWhitespaceTextFrame = PR_FALSE;
|
pfd->SetFlag(PFD_ISNONWHITESPACETEXTFRAME, PR_FALSE);
|
||||||
pfd->mIsSticky = PR_FALSE;
|
pfd->SetFlag(PFD_ISSTICKY, PR_FALSE);
|
||||||
|
pfd->SetFlag(PFD_ISBULLET, PR_FALSE);
|
||||||
|
|
||||||
aFrame->Reflow(mPresContext, metrics, reflowState, aReflowStatus);
|
aFrame->Reflow(mPresContext, metrics, reflowState, aReflowStatus);
|
||||||
|
|
||||||
|
pfd->mJustificationNumSpaces = mTextJustificationNumSpaces;
|
||||||
|
pfd->mJustificationNumLetters = mTextJustificationNumLetters;
|
||||||
|
|
||||||
// XXX See if the frame is a placeholderFrame and if it is process
|
// XXX See if the frame is a placeholderFrame and if it is process
|
||||||
// the floater.
|
// the floater.
|
||||||
nsIAtom* frameType;
|
nsIAtom* frameType;
|
||||||
|
@ -1000,7 +997,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
outOfFlowFrame->GetFrameType(&oofft);
|
outOfFlowFrame->GetFrameType(&oofft);
|
||||||
if (oofft) {
|
if (oofft) {
|
||||||
if (oofft == nsLayoutAtoms::letterFrame) {
|
if (oofft == nsLayoutAtoms::letterFrame) {
|
||||||
mFirstLetterStyleOK = PR_FALSE;
|
SetFlag(LL_FIRSTLETTERSTYLEOK, PR_FALSE);
|
||||||
}
|
}
|
||||||
NS_RELEASE(oofft);
|
NS_RELEASE(oofft);
|
||||||
}
|
}
|
||||||
|
@ -1009,11 +1006,11 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
}
|
}
|
||||||
else if (frameType == nsLayoutAtoms::textFrame) {
|
else if (frameType == nsLayoutAtoms::textFrame) {
|
||||||
// Note non-empty text-frames for inline frame compatability hackery
|
// Note non-empty text-frames for inline frame compatability hackery
|
||||||
pfd->mIsTextFrame = PR_TRUE;
|
pfd->SetFlag(PFD_ISTEXTFRAME, PR_TRUE);
|
||||||
// XXX An empty text frame at the end of the line seems not
|
// XXX An empty text frame at the end of the line seems not
|
||||||
// to have zero width.
|
// to have zero width.
|
||||||
if (metrics.width) {
|
if (metrics.width) {
|
||||||
pfd->mIsNonEmptyTextFrame = PR_TRUE;
|
pfd->SetFlag(PFD_ISNONEMPTYTEXTFRAME, PR_TRUE);
|
||||||
nsCOMPtr<nsIContent> content;
|
nsCOMPtr<nsIContent> content;
|
||||||
nsresult result = pfd->mFrame->GetContent(getter_AddRefs(content));
|
nsresult result = pfd->mFrame->GetContent(getter_AddRefs(content));
|
||||||
if ((NS_SUCCEEDED(result)) && content) {
|
if ((NS_SUCCEEDED(result)) && content) {
|
||||||
|
@ -1023,14 +1020,14 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
PRBool isWhitespace;
|
PRBool isWhitespace;
|
||||||
result = textContent->IsOnlyWhitespace(&isWhitespace);
|
result = textContent->IsOnlyWhitespace(&isWhitespace);
|
||||||
if (NS_SUCCEEDED(result)) {
|
if (NS_SUCCEEDED(result)) {
|
||||||
pfd->mIsNonWhitespaceTextFrame = !isWhitespace;
|
pfd->SetFlag(PFD_ISNONWHITESPACETEXTFRAME, !isWhitespace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (frameType == nsLayoutAtoms::letterFrame) {
|
else if (frameType == nsLayoutAtoms::letterFrame) {
|
||||||
pfd->mIsLetterFrame = PR_TRUE;
|
pfd->SetFlag(PFD_ISLETTERFRAME, PR_TRUE);
|
||||||
}
|
}
|
||||||
NS_RELEASE(frameType);
|
NS_RELEASE(frameType);
|
||||||
}
|
}
|
||||||
|
@ -1170,7 +1167,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||||
else {
|
else {
|
||||||
PushFrame(aFrame);
|
PushFrame(aFrame);
|
||||||
}
|
}
|
||||||
mTextStartsWithNBSP = PR_FALSE; // reset for next time
|
SetFlag(LL_TEXTSTARTSWITHNBSP, PR_FALSE); // reset for next time
|
||||||
|
|
||||||
#ifdef REALLY_NOISY_REFLOW
|
#ifdef REALLY_NOISY_REFLOW
|
||||||
nsFrame::IndentBy(stdout, mSpanDepth);
|
nsFrame::IndentBy(stdout, mSpanDepth);
|
||||||
|
@ -1330,7 +1327,7 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
// There are no frames on the line or we are in the first word on
|
// There are no frames on the line or we are in the first word on
|
||||||
// the line. If the line isn't impacted by a floater then the
|
// the line. If the line isn't impacted by a floater then the
|
||||||
// current frame fits.
|
// current frame fits.
|
||||||
if (!mImpactedByFloaters) {
|
if (!GetFlag(LL_IMPACTEDBYFLOATERS)) {
|
||||||
#ifdef NOISY_CAN_PLACE_FRAME
|
#ifdef NOISY_CAN_PLACE_FRAME
|
||||||
printf(" ==> not-safe and not-impacted fits: ");
|
printf(" ==> not-safe and not-impacted fits: ");
|
||||||
while (nsnull != psd) {
|
while (nsnull != psd) {
|
||||||
|
@ -1341,28 +1338,28 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
#endif
|
#endif
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else if (mLastFloaterWasLetterFrame) {
|
else if (GetFlag(LL_LASTFLOATERWASLETTERFRAME)) {
|
||||||
// Another special case: see if the floater is a letter
|
// Another special case: see if the floater is a letter
|
||||||
// frame. If it is, then allow the frame next to it to fit.
|
// frame. If it is, then allow the frame next to it to fit.
|
||||||
if (pfd->mIsNonEmptyTextFrame) {
|
if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME)) {
|
||||||
// This must be the first piece of non-empty text (because
|
// This must be the first piece of non-empty text (because
|
||||||
// aNotSafeToBreak is true) or its a piece of text that is
|
// aNotSafeToBreak is true) or its a piece of text that is
|
||||||
// part of a larger word.
|
// part of a larger word.
|
||||||
pfd->mIsSticky = PR_TRUE;
|
pfd->SetFlag(PFD_ISSTICKY, PR_TRUE);
|
||||||
}
|
}
|
||||||
else if (pfd->mSpan) {
|
else if (pfd->mSpan) {
|
||||||
PerFrameData* pf = pfd->mSpan->mFirstFrame;
|
PerFrameData* pf = pfd->mSpan->mFirstFrame;
|
||||||
while (pf) {
|
while (pf) {
|
||||||
if (pf->mIsSticky) {
|
if (pf->GetFlag(PFD_ISSTICKY)) {
|
||||||
// If one of the spans children was sticky then the span
|
// If one of the spans children was sticky then the span
|
||||||
// itself is sticky.
|
// itself is sticky.
|
||||||
pfd->mIsSticky = PR_TRUE;
|
pfd->SetFlag(PFD_ISSTICKY, PR_TRUE);
|
||||||
}
|
}
|
||||||
pf = pf->mNext;
|
pf = pf->mNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pfd->mIsSticky) {
|
if (pfd->GetFlag(PFD_ISSTICKY)) {
|
||||||
#ifdef NOISY_CAN_PLACE_FRAME
|
#ifdef NOISY_CAN_PLACE_FRAME
|
||||||
printf(" ==> last floater was letter frame && frame is sticky\n");
|
printf(" ==> last floater was letter frame && frame is sticky\n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -1372,8 +1369,8 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a piece of text inside a letter frame...
|
// If this is a piece of text inside a letter frame...
|
||||||
if (pfd->mIsNonEmptyTextFrame) {
|
if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME)) {
|
||||||
if (psd->mFrame && psd->mFrame->mIsLetterFrame) {
|
if (psd->mFrame && psd->mFrame->GetFlag(PFD_ISLETTERFRAME)) {
|
||||||
nsIFrame* prevInFlow;
|
nsIFrame* prevInFlow;
|
||||||
psd->mFrame->mFrame->GetPrevInFlow(&prevInFlow);
|
psd->mFrame->mFrame->GetPrevInFlow(&prevInFlow);
|
||||||
if (prevInFlow) {
|
if (prevInFlow) {
|
||||||
|
@ -1387,7 +1384,7 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pfd->mIsLetterFrame) {
|
else if (pfd->GetFlag(PFD_ISLETTERFRAME)) {
|
||||||
// If this is the first continuation of the letter frame...
|
// If this is the first continuation of the letter frame...
|
||||||
nsIFrame* prevInFlow;
|
nsIFrame* prevInFlow;
|
||||||
pfd->mFrame->GetPrevInFlow(&prevInFlow);
|
pfd->mFrame->GetPrevInFlow(&prevInFlow);
|
||||||
|
@ -1433,7 +1430,7 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
||||||
// edge...Which means that whatever piece of text we just formatted
|
// edge...Which means that whatever piece of text we just formatted
|
||||||
// will be the piece that fits (the text frame logic knows to stop
|
// will be the piece that fits (the text frame logic knows to stop
|
||||||
// when it runs out of room).
|
// when it runs out of room).
|
||||||
if (pfd->mIsNonEmptyTextFrame && mTextStartsWithNBSP) {
|
if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME) && GetFlag(LL_TEXTSTARTSWITHNBSP)) {
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1467,9 +1464,9 @@ nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics)
|
||||||
|
|
||||||
// If the band was updated during the reflow of that frame then we
|
// If the band was updated during the reflow of that frame then we
|
||||||
// need to adjust any prior frames that were reflowed.
|
// need to adjust any prior frames that were reflowed.
|
||||||
if (mUpdatedBand && InBlockContext()) {
|
if (GetFlag(LL_UPDATEDBAND) && InBlockContext()) {
|
||||||
UpdateFrames();
|
UpdateFrames();
|
||||||
mUpdatedBand = PR_FALSE;
|
SetFlag(LL_UPDATEDBAND, PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance to next X coordinate
|
// Advance to next X coordinate
|
||||||
|
@ -1478,8 +1475,8 @@ nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics)
|
||||||
// If the frame is a not aware of white-space and it takes up some
|
// If the frame is a not aware of white-space and it takes up some
|
||||||
// width, disable leading white-space compression for the next frame
|
// width, disable leading white-space compression for the next frame
|
||||||
// to be reflowed.
|
// to be reflowed.
|
||||||
if (!mUnderstandsWhiteSpace && pfd->mBounds.width) {
|
if ((!GetFlag(LL_UNDERSTANDSNWHITESPACE)) && pfd->mBounds.width) {
|
||||||
mEndsInWhiteSpace = PR_FALSE;
|
SetFlag(LL_ENDSINWHITESPACE, PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count the number of frames on the line...
|
// Count the number of frames on the line...
|
||||||
|
@ -1487,7 +1484,7 @@ nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics)
|
||||||
if (psd->mX != psd->mLeftEdge) {
|
if (psd->mX != psd->mLeftEdge) {
|
||||||
// As soon as a frame placed on the line advances an X coordinate
|
// As soon as a frame placed on the line advances an X coordinate
|
||||||
// of any span we can no longer place a floater on the line.
|
// of any span we can no longer place a floater on the line.
|
||||||
mCanPlaceFloater = PR_FALSE;
|
SetFlag(LL_CANPLACEFLOATER, PR_FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1505,14 +1502,10 @@ nsLineLayout::AddBulletFrame(nsIFrame* aFrame,
|
||||||
pfd->mMargin.SizeTo(0, 0, 0, 0);
|
pfd->mMargin.SizeTo(0, 0, 0, 0);
|
||||||
pfd->mBorderPadding.SizeTo(0, 0, 0, 0);
|
pfd->mBorderPadding.SizeTo(0, 0, 0, 0);
|
||||||
pfd->mFrameType = NS_CSS_FRAME_TYPE_INLINE|NS_FRAME_REPLACED_ELEMENT;
|
pfd->mFrameType = NS_CSS_FRAME_TYPE_INLINE|NS_FRAME_REPLACED_ELEMENT;
|
||||||
pfd->mRelativePos = PR_FALSE;
|
pfd->mFlags = 0; // all flags default to false
|
||||||
|
pfd->SetFlag(PFD_ISBULLET, PR_TRUE);
|
||||||
pfd->mAscent = aMetrics.ascent;
|
pfd->mAscent = aMetrics.ascent;
|
||||||
pfd->mDescent = aMetrics.descent;
|
pfd->mDescent = aMetrics.descent;
|
||||||
pfd->mIsTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsNonEmptyTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsNonWhitespaceTextFrame = PR_FALSE;
|
|
||||||
pfd->mIsLetterFrame = PR_FALSE;
|
|
||||||
pfd->mIsSticky = PR_FALSE;
|
|
||||||
|
|
||||||
// Note: y value will be updated during vertical alignment
|
// Note: y value will be updated during vertical alignment
|
||||||
aFrame->GetRect(pfd->mBounds);
|
aFrame->GetRect(pfd->mBounds);
|
||||||
|
@ -1857,7 +1850,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
|
||||||
zeroEffectiveSpanBox = PR_TRUE;
|
zeroEffectiveSpanBox = PR_TRUE;
|
||||||
PerFrameData* pfd = psd->mFirstFrame;
|
PerFrameData* pfd = psd->mFirstFrame;
|
||||||
while (nsnull != pfd) {
|
while (nsnull != pfd) {
|
||||||
if (preMode?pfd->mIsTextFrame:pfd->mIsNonWhitespaceTextFrame) {
|
if (preMode?pfd->GetFlag(PFD_ISTEXTFRAME):pfd->GetFlag(PFD_ISNONWHITESPACETEXTFRAME)) {
|
||||||
zeroEffectiveSpanBox = PR_FALSE;
|
zeroEffectiveSpanBox = PR_FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2154,7 +2147,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
|
||||||
if (pfd->mVerticalAlign == VALIGN_OTHER) {
|
if (pfd->mVerticalAlign == VALIGN_OTHER) {
|
||||||
// Text frames do not contribute to the min/max Y values for the
|
// Text frames do not contribute to the min/max Y values for the
|
||||||
// line (instead their parent frame's font-size contributes).
|
// line (instead their parent frame's font-size contributes).
|
||||||
if (!pfd->mIsTextFrame) {
|
if (!pfd->GetFlag(PFD_ISTEXTFRAME)) {
|
||||||
nscoord yTop, yBottom;
|
nscoord yTop, yBottom;
|
||||||
if (frameSpan) {
|
if (frameSpan) {
|
||||||
// For spans that were are now placing, use their position
|
// For spans that were are now placing, use their position
|
||||||
|
@ -2212,7 +2205,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd)
|
||||||
// BR) (NN4/IE5 quirk)
|
// BR) (NN4/IE5 quirk)
|
||||||
PRBool applyMinLH = !(psd->mZeroEffectiveSpanBox); // (1) above
|
PRBool applyMinLH = !(psd->mZeroEffectiveSpanBox); // (1) above
|
||||||
PRBool isFirstLine = !mLineNumber; // if the line number is 0
|
PRBool isFirstLine = !mLineNumber; // if the line number is 0
|
||||||
PRBool isLastLine = (!mLineBox->IsLineWrapped() && !mLineEndsInBR);
|
PRBool isLastLine = (!mLineBox->IsLineWrapped() && !GetFlag(LL_LINEENDSINBR));
|
||||||
//PRBool isLastLine = mBlockRS->mCurLine->IsLineWrapped();
|
//PRBool isLastLine = mBlockRS->mCurLine->IsLineWrapped();
|
||||||
if (!applyMinLH && (isFirstLine || isLastLine)) {
|
if (!applyMinLH && (isFirstLine || isLastLine)) {
|
||||||
nsCOMPtr<nsIContent> blockContent;
|
nsCOMPtr<nsIContent> blockContent;
|
||||||
|
@ -2412,13 +2405,13 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd,
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!pfd->mIsTextFrame) {
|
else if (!pfd->GetFlag(PFD_ISTEXTFRAME)) {
|
||||||
// If we hit a frame on the end that's not text, then there is
|
// If we hit a frame on the end that's not text, then there is
|
||||||
// no trailing whitespace to trim. Stop the search.
|
// no trailing whitespace to trim. Stop the search.
|
||||||
*aDeltaWidth = 0;
|
*aDeltaWidth = 0;
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
else if (pfd->mIsNonEmptyTextFrame) {
|
else if (pfd->GetFlag(PFD_ISNONEMPTYTEXTFRAME)) {
|
||||||
nscoord deltaWidth = 0;
|
nscoord deltaWidth = 0;
|
||||||
pfd->mFrame->TrimTrailingWhiteSpace(mPresContext,
|
pfd->mFrame->TrimTrailingWhiteSpace(mPresContext,
|
||||||
*mBlockReflowState->rendContext,
|
*mBlockReflowState->rendContext,
|
||||||
|
@ -2432,6 +2425,10 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd,
|
||||||
printf(" returned %d\n", deltaWidth);
|
printf(" returned %d\n", deltaWidth);
|
||||||
#endif
|
#endif
|
||||||
if (deltaWidth) {
|
if (deltaWidth) {
|
||||||
|
if (pfd->mJustificationNumSpaces > 0) {
|
||||||
|
pfd->mJustificationNumSpaces--;
|
||||||
|
}
|
||||||
|
|
||||||
pfd->mBounds.width -= deltaWidth;
|
pfd->mBounds.width -= deltaWidth;
|
||||||
pfd->mCombinedArea.width -= deltaWidth;
|
pfd->mCombinedArea.width -= deltaWidth;
|
||||||
if (0 == pfd->mBounds.width) {
|
if (0 == pfd->mBounds.width) {
|
||||||
|
@ -2479,6 +2476,95 @@ nsLineLayout::TrimTrailingWhiteSpace()
|
||||||
return 0 != deltaWidth;
|
return 0 != deltaWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsLineLayout::ComputeJustificationWeights(PerSpanData* aPSD,
|
||||||
|
PRInt32* aNumSpaces,
|
||||||
|
PRInt32* aNumLetters)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aPSD, "null arg");
|
||||||
|
NS_ASSERTION(aNumSpaces, "null arg");
|
||||||
|
NS_ASSERTION(aNumLetters, "null arg");
|
||||||
|
PRInt32 numSpaces = 0;
|
||||||
|
PRInt32 numLetters = 0;
|
||||||
|
|
||||||
|
for (PerFrameData* pfd = aPSD->mFirstFrame; pfd != nsnull; pfd = pfd->mNext) {
|
||||||
|
nscoord dw = 0;
|
||||||
|
|
||||||
|
if (PR_TRUE == pfd->GetFlag(PFD_ISTEXTFRAME)) {
|
||||||
|
numSpaces += pfd->mJustificationNumSpaces;
|
||||||
|
numLetters += pfd->mJustificationNumLetters;
|
||||||
|
}
|
||||||
|
else if (pfd->mSpan != nsnull) {
|
||||||
|
PRInt32 spanSpaces;
|
||||||
|
PRInt32 spanLetters;
|
||||||
|
|
||||||
|
ComputeJustificationWeights(pfd->mSpan, &spanSpaces, &spanLetters);
|
||||||
|
|
||||||
|
numSpaces += spanSpaces;
|
||||||
|
numLetters += spanLetters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*aNumSpaces = numSpaces;
|
||||||
|
*aNumLetters = numLetters;
|
||||||
|
}
|
||||||
|
|
||||||
|
nscoord
|
||||||
|
nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState* aState)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aPSD, "null arg");
|
||||||
|
NS_ASSERTION(aState, "null arg");
|
||||||
|
|
||||||
|
nscoord deltaX = 0;
|
||||||
|
for (PerFrameData* pfd = aPSD->mFirstFrame; pfd != nsnull; pfd = pfd->mNext) {
|
||||||
|
// Don't reposition bullets (and other frames that occur out of X-order?)
|
||||||
|
if (!pfd->GetFlag(PFD_ISBULLET)) {
|
||||||
|
nscoord dw = 0;
|
||||||
|
|
||||||
|
pfd->mBounds.x += deltaX;
|
||||||
|
|
||||||
|
if (PR_TRUE == pfd->GetFlag(PFD_ISTEXTFRAME)) {
|
||||||
|
if (aState->mTotalWidthForSpaces > 0 &&
|
||||||
|
aState->mTotalNumSpaces > 0 && // we divide by this value, so must be non-zero
|
||||||
|
aState->mTotalNumLetters >0 // we divide by this value, so must be non-zero
|
||||||
|
) {
|
||||||
|
aState->mNumSpacesProcessed += pfd->mJustificationNumSpaces;
|
||||||
|
|
||||||
|
nscoord newAllocatedWidthForSpaces =
|
||||||
|
(aState->mTotalWidthForSpaces*aState->mNumSpacesProcessed)
|
||||||
|
/aState->mTotalNumSpaces;
|
||||||
|
|
||||||
|
dw += newAllocatedWidthForSpaces - aState->mWidthForSpacesProcessed;
|
||||||
|
|
||||||
|
aState->mWidthForSpacesProcessed = newAllocatedWidthForSpaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aState->mTotalWidthForLetters > 0) {
|
||||||
|
aState->mNumLettersProcessed += pfd->mJustificationNumLetters;
|
||||||
|
|
||||||
|
nscoord newAllocatedWidthForLetters =
|
||||||
|
(aState->mTotalWidthForLetters*aState->mNumLettersProcessed)
|
||||||
|
/aState->mTotalNumLetters;
|
||||||
|
|
||||||
|
dw += newAllocatedWidthForLetters - aState->mWidthForLettersProcessed;
|
||||||
|
|
||||||
|
aState->mWidthForLettersProcessed = newAllocatedWidthForLetters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (nsnull != pfd->mSpan) {
|
||||||
|
dw += ApplyFrameJustification(pfd->mSpan, aState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pfd->mBounds.width += dw;
|
||||||
|
deltaX += dw;
|
||||||
|
pfd->mFrame->SetRect(mPresContext, pfd->mBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deltaX;
|
||||||
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
||||||
PRBool aAllowJustify,
|
PRBool aAllowJustify,
|
||||||
|
@ -2525,7 +2611,18 @@ nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
||||||
// frames in the line. If it is the last line then if the
|
// frames in the line. If it is the last line then if the
|
||||||
// direction is right-to-left then we right-align the frames.
|
// direction is right-to-left then we right-align the frames.
|
||||||
if (aAllowJustify) {
|
if (aAllowJustify) {
|
||||||
break;
|
if (!aShrinkWrapWidth) {
|
||||||
|
PRInt32 numSpaces;
|
||||||
|
PRInt32 numLetters;
|
||||||
|
|
||||||
|
ComputeJustificationWeights(psd, &numSpaces, &numLetters);
|
||||||
|
|
||||||
|
if (numSpaces > 0) {
|
||||||
|
FrameJustificationState state = { numSpaces, numLetters, remainingWidth, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
ApplyFrameJustification(psd, &state);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (NS_STYLE_DIRECTION_RTL == psd->mDirection) {
|
else if (NS_STYLE_DIRECTION_RTL == psd->mDirection) {
|
||||||
// right align the frames
|
// right align the frames
|
||||||
|
@ -2617,7 +2714,7 @@ nsLineLayout::RelativePositionFrames(PerSpanData* psd, nsRect& aCombinedArea)
|
||||||
nscoord y = pfd->mBounds.y;
|
nscoord y = pfd->mBounds.y;
|
||||||
|
|
||||||
// Adjust the origin of the frame
|
// Adjust the origin of the frame
|
||||||
if (pfd->mRelativePos) {
|
if (pfd->GetFlag(PFD_RELATIVEPOS)) {
|
||||||
nsIFrame* frame = pfd->mFrame;
|
nsIFrame* frame = pfd->mFrame;
|
||||||
frame->GetOrigin(origin);
|
frame->GetOrigin(origin);
|
||||||
// XXX what about right and bottom?
|
// XXX what about right and bottom?
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* Rights Reserved.
|
* Rights Reserved.
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
|
* Steve Clark <buster@netscape.com>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
*/
|
*/
|
||||||
#ifndef nsLineLayout_h___
|
#ifndef nsLineLayout_h___
|
||||||
#define nsLineLayout_h___
|
#define nsLineLayout_h___
|
||||||
|
@ -32,7 +34,7 @@ class nsBlockReflowState;
|
||||||
class nsPlaceholderFrame;
|
class nsPlaceholderFrame;
|
||||||
struct nsStyleText;
|
struct nsStyleText;
|
||||||
|
|
||||||
#define NS_LINELAYOUT_NUM_FRAMES 10
|
#define NS_LINELAYOUT_NUM_FRAMES 5
|
||||||
#define NS_LINELAYOUT_NUM_SPANS 5
|
#define NS_LINELAYOUT_NUM_SPANS 5
|
||||||
|
|
||||||
class nsLineLayout {
|
class nsLineLayout {
|
||||||
|
@ -122,23 +124,69 @@ public:
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
|
// Supporting methods and data for flags
|
||||||
|
protected:
|
||||||
|
#define LL_ENDSINWHITESPACE 0x00000001
|
||||||
|
#define LL_UNDERSTANDSNWHITESPACE 0x00000002
|
||||||
|
#define LL_TEXTSTARTSWITHNBSP 0x00000004
|
||||||
|
#define LL_FIRSTLETTERSTYLEOK 0x00000008
|
||||||
|
#define LL_ISTOPOFPAGE 0x00000010
|
||||||
|
#define LL_UPDATEDBAND 0x00000020
|
||||||
|
#define LL_IMPACTEDBYFLOATERS 0x00000040
|
||||||
|
#define LL_LASTFLOATERWASLETTERFRAME 0x00000080
|
||||||
|
#define LL_CANPLACEFLOATER 0x00000100
|
||||||
|
#define LL_KNOWSTRICTMODE 0x00000200
|
||||||
|
#define LL_INSTRICTMODE 0x00000400
|
||||||
|
#define LL_LINEENDSINBR 0x00000800
|
||||||
|
#define LL_LASTFLAG LL_LINEENDSINBR
|
||||||
|
|
||||||
|
PRUint16 mFlags;
|
||||||
|
|
||||||
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=LL_LASTFLAG, "bad flag");
|
||||||
|
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
|
||||||
|
if (aValue) { // set flag
|
||||||
|
mFlags |= aFlag;
|
||||||
|
}
|
||||||
|
else { // unset flag
|
||||||
|
mFlags &= ~aFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GetFlag(PRUint32 aFlag) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=LL_LASTFLAG, "bad flag");
|
||||||
|
PRBool result = (mFlags & aFlag);
|
||||||
|
if (result) return PR_TRUE;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
// Support methods for white-space compression and word-wrapping
|
// Support methods for white-space compression and word-wrapping
|
||||||
// during line reflow
|
// during line reflow
|
||||||
|
|
||||||
void SetEndsInWhiteSpace(PRBool aState) {
|
void SetEndsInWhiteSpace(PRBool aState) {
|
||||||
mEndsInWhiteSpace = aState;
|
SetFlag(LL_ENDSINWHITESPACE, aState);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool GetEndsInWhiteSpace() const {
|
PRBool GetEndsInWhiteSpace() const {
|
||||||
return mEndsInWhiteSpace;
|
return GetFlag(LL_ENDSINWHITESPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetUnderstandsWhiteSpace(PRBool aSetting) {
|
void SetUnderstandsWhiteSpace(PRBool aSetting) {
|
||||||
mUnderstandsWhiteSpace = aSetting;
|
SetFlag(LL_UNDERSTANDSNWHITESPACE, aSetting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetTextJustificationWeights(PRInt32 aNumSpaces, PRInt32 aNumLetters) {
|
||||||
|
mTextJustificationNumSpaces = aNumSpaces;
|
||||||
|
mTextJustificationNumLetters = aNumLetters;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SetTextStartsWithNBSP(PRBool aYes) {
|
void SetTextStartsWithNBSP(PRBool aYes) {
|
||||||
mTextStartsWithNBSP = aYes;
|
SetFlag(LL_TEXTSTARTSWITHNBSP, aYes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordWordFrame(nsIFrame* aWordFrame) {
|
void RecordWordFrame(nsIFrame* aWordFrame) {
|
||||||
|
@ -163,9 +211,15 @@ public:
|
||||||
|
|
||||||
PRBool LineIsBreakable() const;
|
PRBool LineIsBreakable() const;
|
||||||
|
|
||||||
PRBool GetLineEndsInBR() const { return mLineEndsInBR; }
|
PRBool GetLineEndsInBR() const
|
||||||
|
{
|
||||||
|
return GetFlag(LL_LINEENDSINBR);
|
||||||
|
}
|
||||||
|
|
||||||
void SetLineEndsInBR(PRBool aOn) { mLineEndsInBR = aOn; }
|
void SetLineEndsInBR(PRBool aOn)
|
||||||
|
{
|
||||||
|
SetFlag(LL_LINEENDSINBR, aOn);
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
// Inform the line-layout about the presence of a floating frame
|
// Inform the line-layout about the presence of a floating frame
|
||||||
|
@ -176,11 +230,11 @@ public:
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
PRBool GetFirstLetterStyleOK() const {
|
PRBool GetFirstLetterStyleOK() const {
|
||||||
return mFirstLetterStyleOK;
|
return GetFlag(LL_FIRSTLETTERSTYLEOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFirstLetterStyleOK(PRBool aSetting) {
|
void SetFirstLetterStyleOK(PRBool aSetting) {
|
||||||
mFirstLetterStyleOK = aSetting;
|
SetFlag(LL_FIRSTLETTERSTYLEOK, aSetting);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFirstLetterFrame(nsIFrame* aFrame) {
|
void SetFirstLetterFrame(nsIFrame* aFrame) {
|
||||||
|
@ -233,19 +287,11 @@ protected:
|
||||||
nsIFrame* mFirstLetterFrame;
|
nsIFrame* mFirstLetterFrame;
|
||||||
PRInt32 mLineNumber;
|
PRInt32 mLineNumber;
|
||||||
PRInt32 mColumn;
|
PRInt32 mColumn;
|
||||||
|
PRInt32 mTextJustificationNumSpaces;
|
||||||
|
PRInt32 mTextJustificationNumLetters;
|
||||||
|
|
||||||
nsLineBox* mLineBox;
|
nsLineBox* mLineBox;
|
||||||
PRPackedBool mEndsInWhiteSpace;
|
|
||||||
PRPackedBool mUnderstandsWhiteSpace;
|
|
||||||
PRPackedBool mTextStartsWithNBSP;
|
|
||||||
PRPackedBool mFirstLetterStyleOK;
|
|
||||||
PRPackedBool mIsTopOfPage;
|
|
||||||
PRPackedBool mUpdatedBand;
|
|
||||||
PRPackedBool mImpactedByFloaters;
|
|
||||||
PRPackedBool mLastFloaterWasLetterFrame;
|
|
||||||
PRPackedBool mCanPlaceFloater;
|
|
||||||
PRPackedBool mKnowStrictMode;
|
|
||||||
PRPackedBool mInStrictMode;
|
|
||||||
PRPackedBool mLineEndsInBR;
|
|
||||||
PRUint8 mPlacedFloaters;
|
PRUint8 mPlacedFloaters;
|
||||||
PRInt32 mTotalPlacedFrames;
|
PRInt32 mTotalPlacedFrames;
|
||||||
nsVoidArray mWordFrames;
|
nsVoidArray mWordFrames;
|
||||||
|
@ -294,15 +340,47 @@ protected:
|
||||||
nsMargin mMargin;
|
nsMargin mMargin;
|
||||||
nsMargin mBorderPadding;
|
nsMargin mBorderPadding;
|
||||||
nsMargin mOffsets;
|
nsMargin mOffsets;
|
||||||
PRPackedBool mRelativePos;
|
|
||||||
|
|
||||||
// Other state we use
|
// Other state we use
|
||||||
PRUint8 mVerticalAlign;
|
PRUint8 mVerticalAlign;
|
||||||
PRPackedBool mIsTextFrame;
|
|
||||||
PRPackedBool mIsNonEmptyTextFrame;
|
// state for text justification
|
||||||
PRPackedBool mIsNonWhitespaceTextFrame;
|
PRInt32 mJustificationNumSpaces;
|
||||||
PRPackedBool mIsLetterFrame;
|
PRInt32 mJustificationNumLetters;
|
||||||
PRPackedBool mIsSticky;
|
|
||||||
|
|
||||||
|
// PerFrameData flags
|
||||||
|
#define PFD_RELATIVEPOS 0x00000001
|
||||||
|
#define PFD_ISTEXTFRAME 0x00000002
|
||||||
|
#define PFD_ISNONEMPTYTEXTFRAME 0x00000004
|
||||||
|
#define PFD_ISNONWHITESPACETEXTFRAME 0x00000008
|
||||||
|
#define PFD_ISLETTERFRAME 0x00000010
|
||||||
|
#define PFD_ISSTICKY 0x00000020
|
||||||
|
#define PFD_ISBULLET 0x00000040
|
||||||
|
#define PFD_LASTFLAG PFD_ISBULLET
|
||||||
|
|
||||||
|
PRPackedBool mFlags;
|
||||||
|
|
||||||
|
void SetFlag(PRUint32 aFlag, PRBool aValue)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=PFD_LASTFLAG, "bad flag");
|
||||||
|
NS_ASSERTION(aValue==PR_FALSE || aValue==PR_TRUE, "bad value");
|
||||||
|
if (aValue) { // set flag
|
||||||
|
mFlags |= aFlag;
|
||||||
|
}
|
||||||
|
else { // unset flag
|
||||||
|
mFlags &= ~aFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PRBool GetFlag(PRUint32 aFlag) const
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aFlag<=PFD_LASTFLAG, "bad flag");
|
||||||
|
PRBool result = (mFlags & aFlag);
|
||||||
|
if (result) return PR_TRUE;
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PerFrameData* Last() {
|
PerFrameData* Last() {
|
||||||
PerFrameData* pfd = this;
|
PerFrameData* pfd = this;
|
||||||
|
@ -409,6 +487,22 @@ protected:
|
||||||
|
|
||||||
PRBool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaWidth);
|
PRBool TrimTrailingWhiteSpaceIn(PerSpanData* psd, nscoord* aDeltaWidth);
|
||||||
|
|
||||||
|
|
||||||
|
void ComputeJustificationWeights(PerSpanData* psd, PRInt32* numSpaces, PRInt32* numLetters);
|
||||||
|
|
||||||
|
struct FrameJustificationState {
|
||||||
|
PRInt32 mTotalNumSpaces;
|
||||||
|
PRInt32 mTotalNumLetters;
|
||||||
|
nscoord mTotalWidthForSpaces;
|
||||||
|
nscoord mTotalWidthForLetters;
|
||||||
|
PRInt32 mNumSpacesProcessed;
|
||||||
|
PRInt32 mNumLettersProcessed;
|
||||||
|
nscoord mWidthForSpacesProcessed;
|
||||||
|
nscoord mWidthForLettersProcessed;
|
||||||
|
};
|
||||||
|
nscoord ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState* aState);
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent);
|
void DumpPerSpanData(PerSpanData* psd, PRInt32 aIndent);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3874,6 +3874,9 @@ FindTopFrame(nsIFrame* aRoot)
|
||||||
PRBool
|
PRBool
|
||||||
PresShell::VerifyIncrementalReflow()
|
PresShell::VerifyIncrementalReflow()
|
||||||
{
|
{
|
||||||
|
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
|
||||||
|
printf("Building Verification Tree...\n");
|
||||||
|
}
|
||||||
// All the stuff we are creating that needs releasing
|
// All the stuff we are creating that needs releasing
|
||||||
nsIPresContext* cx;
|
nsIPresContext* cx;
|
||||||
nsIViewManager* vm;
|
nsIViewManager* vm;
|
||||||
|
@ -3976,6 +3979,9 @@ PresShell::VerifyIncrementalReflow()
|
||||||
vm->SetViewObserver((nsIViewObserver *)((PresShell*)sh));
|
vm->SetViewObserver((nsIViewObserver *)((PresShell*)sh));
|
||||||
sh->InitialReflow(r.width, r.height);
|
sh->InitialReflow(r.width, r.height);
|
||||||
sh->SetVerifyReflowEnable(PR_TRUE); // turn on verify reflow again now that we're done reflowing the test frame tree
|
sh->SetVerifyReflowEnable(PR_TRUE); // turn on verify reflow again now that we're done reflowing the test frame tree
|
||||||
|
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
|
||||||
|
printf("Verification Tree built, comparing...\n");
|
||||||
|
}
|
||||||
|
|
||||||
// Now that the document has been reflowed, use its frame tree to
|
// Now that the document has been reflowed, use its frame tree to
|
||||||
// compare against our frame tree.
|
// compare against our frame tree.
|
||||||
|
@ -3999,15 +4005,15 @@ PresShell::VerifyIncrementalReflow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("Incremental reflow doomed view tree:\n");
|
|
||||||
// view->List(stdout, 1);
|
|
||||||
// view->SetVisibility(nsViewVisibility_kHide);
|
|
||||||
cx->Stop();
|
cx->Stop();
|
||||||
cx->SetContainer(nsnull);
|
cx->SetContainer(nsnull);
|
||||||
NS_RELEASE(cx);
|
NS_RELEASE(cx);
|
||||||
sh->EndObservingDocument();
|
sh->EndObservingDocument();
|
||||||
NS_RELEASE(sh);
|
NS_RELEASE(sh);
|
||||||
NS_RELEASE(vm);
|
NS_RELEASE(vm);
|
||||||
|
if (VERIFY_REFLOW_NOISY & gVerifyReflowFlags) {
|
||||||
|
printf("Finished Verifying Reflow...\n");
|
||||||
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*
|
*
|
||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||||
|
* Robert O'Callahan <roc+moz@cs.cmu.edu>
|
||||||
*/
|
*/
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsHTMLParts.h"
|
#include "nsHTMLParts.h"
|
||||||
|
@ -458,9 +459,10 @@ public:
|
||||||
nscoord mAveCharWidth;
|
nscoord mAveCharWidth;
|
||||||
PRBool mJustifying;
|
PRBool mJustifying;
|
||||||
PRBool mPreformatted;
|
PRBool mPreformatted;
|
||||||
PRIntn mNumSpaces;
|
PRInt32 mNumSpacesToRender;
|
||||||
|
PRInt32 mNumSpacesToMeasure;
|
||||||
nscoord mExtraSpacePerSpace;
|
nscoord mExtraSpacePerSpace;
|
||||||
nscoord mRemainingExtraSpace;
|
PRInt32 mNumSpacesReceivingExtraJot;
|
||||||
|
|
||||||
TextStyle(nsIPresContext* aPresContext,
|
TextStyle(nsIPresContext* aPresContext,
|
||||||
nsIRenderingContext& aRenderingContext,
|
nsIRenderingContext& aRenderingContext,
|
||||||
|
@ -521,20 +523,25 @@ public:
|
||||||
|
|
||||||
// Get the word and letter spacing
|
// Get the word and letter spacing
|
||||||
mWordSpacing = 0;
|
mWordSpacing = 0;
|
||||||
mLetterSpacing = 0;
|
|
||||||
PRIntn unit = mText->mWordSpacing.GetUnit();
|
PRIntn unit = mText->mWordSpacing.GetUnit();
|
||||||
if (eStyleUnit_Coord == unit) {
|
if (eStyleUnit_Coord == unit) {
|
||||||
mWordSpacing = mText->mWordSpacing.GetCoordValue();
|
mWordSpacing = mText->mWordSpacing.GetCoordValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLetterSpacing = 0;
|
||||||
unit = mText->mLetterSpacing.GetUnit();
|
unit = mText->mLetterSpacing.GetUnit();
|
||||||
if (eStyleUnit_Coord == unit) {
|
if (eStyleUnit_Coord == unit) {
|
||||||
mLetterSpacing = mText->mLetterSpacing.GetCoordValue();
|
mLetterSpacing = mText->mLetterSpacing.GetCoordValue();
|
||||||
}
|
}
|
||||||
mNumSpaces = 0;
|
mNumSpacesToRender = 0;
|
||||||
mRemainingExtraSpace = 0;
|
mNumSpacesToMeasure = 0;
|
||||||
|
mNumSpacesReceivingExtraJot = 0;
|
||||||
mExtraSpacePerSpace = 0;
|
mExtraSpacePerSpace = 0;
|
||||||
mPreformatted = (NS_STYLE_WHITESPACE_PRE == mText->mWhiteSpace) ||
|
mPreformatted = (NS_STYLE_WHITESPACE_PRE == mText->mWhiteSpace) ||
|
||||||
(NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == mText->mWhiteSpace);
|
(NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == mText->mWhiteSpace);
|
||||||
|
|
||||||
|
mJustifying = (NS_STYLE_TEXT_ALIGN_JUSTIFY == mText->mTextAlign) &&
|
||||||
|
!mPreformatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
~TextStyle() {
|
~TextStyle() {
|
||||||
|
@ -590,6 +597,9 @@ public:
|
||||||
nsAutoIndexBuffer* aIndexBuffer,
|
nsAutoIndexBuffer* aIndexBuffer,
|
||||||
nsAutoTextBuffer* aTextBuffer,
|
nsAutoTextBuffer* aTextBuffer,
|
||||||
PRInt32* aTextLen);
|
PRInt32* aTextLen);
|
||||||
|
void ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
|
||||||
|
TextStyle& aTextStyle,
|
||||||
|
PRUnichar* aBuffer, PRInt32 aLength, PRInt32 aNumSpaces);
|
||||||
|
|
||||||
void PaintTextDecorations(nsIRenderingContext& aRenderingContext,
|
void PaintTextDecorations(nsIRenderingContext& aRenderingContext,
|
||||||
nsIStyleContext* aStyleContext,
|
nsIStyleContext* aStyleContext,
|
||||||
|
@ -1192,7 +1202,8 @@ nsTextFrame::Paint(nsIPresContext* aPresContext,
|
||||||
sc->GetStyleData(eStyleStruct_Display);
|
sc->GetStyleData(eStyleStruct_Display);
|
||||||
if (disp->IsVisible()) {
|
if (disp->IsVisible()) {
|
||||||
TextStyle ts(aPresContext, aRenderingContext, mStyleContext);
|
TextStyle ts(aPresContext, aRenderingContext, mStyleContext);
|
||||||
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing)) {
|
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing)
|
||||||
|
|| ts.mJustifying) {
|
||||||
PaintTextSlowly(aPresContext, aRenderingContext, sc, ts, 0, 0);
|
PaintTextSlowly(aPresContext, aRenderingContext, sc, ts, 0, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1261,7 +1272,9 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
|
||||||
PRBool isWhitespace, wasTransformed;
|
PRBool isWhitespace, wasTransformed;
|
||||||
PRInt32 wordLen, contentLen;
|
PRInt32 wordLen, contentLen;
|
||||||
aTX.GetNextWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace, &wasTransformed);
|
aTX.GetNextWord(PR_FALSE, &wordLen, &contentLen, &isWhitespace, &wasTransformed);
|
||||||
NS_ASSERTION(isWhitespace, "mState and content are out of sync");
|
// we trip this assertion in bug 31053, but I think it's unnecessary
|
||||||
|
//NS_ASSERTION(isWhitespace, "mState and content are out of sync");
|
||||||
|
|
||||||
if (isWhitespace) {
|
if (isWhitespace) {
|
||||||
if (nsnull != indexp) {
|
if (nsnull != indexp) {
|
||||||
// Point mapping indicies at the same content index since
|
// Point mapping indicies at the same content index since
|
||||||
|
@ -1301,7 +1314,6 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
|
||||||
}
|
}
|
||||||
inWord = PR_FALSE;
|
inWord = PR_FALSE;
|
||||||
if (isWhitespace) {
|
if (isWhitespace) {
|
||||||
numSpaces++;
|
|
||||||
if ('\t' == bp[0]) {
|
if ('\t' == bp[0]) {
|
||||||
PRInt32 spaces = 8 - (7 & column);
|
PRInt32 spaces = 8 - (7 & column);
|
||||||
PRUnichar* tp = bp;
|
PRUnichar* tp = bp;
|
||||||
|
@ -1339,20 +1351,30 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
numSpaces += wordLen;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
PRInt32 i;
|
||||||
if (nsnull != indexp) {
|
if (nsnull != indexp) {
|
||||||
// Point mapping indicies at each content index in the word
|
// Point mapping indicies at each content index in the word
|
||||||
PRInt32 i = contentLen;
|
i = contentLen;
|
||||||
while (--i >= 0) {
|
while (--i >= 0) {
|
||||||
*indexp++ = strInx++;
|
*indexp++ = strInx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Nonbreaking spaces count as spaces, not letters
|
||||||
|
PRUnichar* tp = bp;
|
||||||
|
i = wordLen;
|
||||||
|
while (--i >= 0) {
|
||||||
|
if (*tp++ == ' ') {
|
||||||
|
numSpaces++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grow the buffer before we run out of room. The only time this
|
// Grow the buffer before we run out of room. The only time this
|
||||||
// happens is because of tab expansion.
|
// happens is because of tab expansion.
|
||||||
if (dstOffset + wordLen > aTextBuffer->mBufferLen) {
|
if (aTextBuffer != nsnull && dstOffset + wordLen > aTextBuffer->mBufferLen) {
|
||||||
nsresult rv = aTextBuffer->GrowBy(wordLen);
|
nsresult rv = aTextBuffer->GrowBy(wordLen);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
break;
|
break;
|
||||||
|
@ -1362,8 +1384,10 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
|
||||||
column += wordLen;
|
column += wordLen;
|
||||||
textLength += wordLen;
|
textLength += wordLen;
|
||||||
n -= contentLen;
|
n -= contentLen;
|
||||||
nsCRT::memcpy(aTextBuffer->mBuffer + dstOffset, bp,
|
if (aTextBuffer != nsnull) {
|
||||||
sizeof(PRUnichar)*wordLen);
|
nsCRT::memcpy(aTextBuffer->mBuffer + dstOffset, bp,
|
||||||
|
sizeof(PRUnichar)*wordLen);
|
||||||
|
}
|
||||||
dstOffset += wordLen;
|
dstOffset += wordLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1372,19 +1396,24 @@ nsTextFrame::PrepareUnicodeText(nsTextTransformer& aTX,
|
||||||
NS_ASSERTION(indexp <= aIndexBuffer->mBuffer + aIndexBuffer->mBufferLen,
|
NS_ASSERTION(indexp <= aIndexBuffer->mBuffer + aIndexBuffer->mBufferLen,
|
||||||
"yikes - we just overwrote memory");
|
"yikes - we just overwrote memory");
|
||||||
}
|
}
|
||||||
NS_ASSERTION(dstOffset <= aTextBuffer->mBufferLen,
|
if (aTextBuffer) {
|
||||||
"yikes - we just overwrote memory");
|
NS_ASSERTION(dstOffset <= aTextBuffer->mBufferLen,
|
||||||
|
"yikes - we just overwrote memory");
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Remove trailing whitespace if it was trimmed after reflow
|
// Remove trailing whitespace if it was trimmed after reflow
|
||||||
if (TEXT_TRIMMED_WS & mState) {
|
if (TEXT_TRIMMED_WS & mState) {
|
||||||
|
NS_ASSERTION(aTextBuffer != nsnull,
|
||||||
|
"Nonexistent text buffer should only occur during reflow, i.e. before whitespace is trimmed");
|
||||||
if (--dstOffset >= 0) {
|
if (--dstOffset >= 0) {
|
||||||
PRUnichar ch = aTextBuffer->mBuffer[dstOffset];
|
PRUnichar ch = aTextBuffer->mBuffer[dstOffset];
|
||||||
if (XP_IS_SPACE(ch)) {
|
if (XP_IS_SPACE(ch)) {
|
||||||
textLength--;
|
textLength--;
|
||||||
|
numSpaces--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
numSpaces--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aIndexBuffer) {
|
if (aIndexBuffer) {
|
||||||
|
@ -1716,6 +1745,7 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext,
|
||||||
doc->GetLineBreaker(getter_AddRefs(lb));
|
doc->GetLineBreaker(getter_AddRefs(lb));
|
||||||
nsTextTransformer tx(lb, nsnull);
|
nsTextTransformer tx(lb, nsnull);
|
||||||
PRInt32 textLength;
|
PRInt32 textLength;
|
||||||
|
// no need to worry about justification, that's always on the slow path
|
||||||
PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
|
PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
|
||||||
&paintBuffer, &textLength);
|
&paintBuffer, &textLength);
|
||||||
|
|
||||||
|
@ -1833,7 +1863,7 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
TextStyle ts(aPresContext, *aRendContext, mStyleContext);
|
TextStyle ts(aPresContext, *aRendContext, mStyleContext);
|
||||||
if (!ts.mSmallCaps && !ts.mWordSpacing && !ts.mLetterSpacing) {
|
if (!ts.mSmallCaps && !ts.mWordSpacing && !ts.mLetterSpacing && !ts.mJustifying) {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
nsIView * view;
|
nsIView * view;
|
||||||
|
@ -1861,12 +1891,16 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext,
|
||||||
doc->GetLineBreaker(getter_AddRefs(lb));
|
doc->GetLineBreaker(getter_AddRefs(lb));
|
||||||
nsTextTransformer tx(lb, nsnull);
|
nsTextTransformer tx(lb, nsnull);
|
||||||
PRInt32 textLength;
|
PRInt32 textLength;
|
||||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
PRInt32 numSpaces;
|
||||||
|
|
||||||
|
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||||
if (textLength <= 0) {
|
if (textLength <= 0) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
//IF STYLE SAYS TO SELCT TO END OF FRAME HERE...
|
ComputeExtraJustificationSpacing(*aRendContext, ts, paintBuffer.mBuffer, textLength, numSpaces);
|
||||||
|
|
||||||
|
//IF STYLE SAYS TO SELECT TO END OF FRAME HERE...
|
||||||
nsCOMPtr<nsIPref> prefs;
|
nsCOMPtr<nsIPref> prefs;
|
||||||
PRInt32 prefInt = 0;
|
PRInt32 prefInt = 0;
|
||||||
rv = nsServiceManager::GetService(kPrefCID,
|
rv = nsServiceManager::GetService(kPrefCID,
|
||||||
|
@ -1929,7 +1963,7 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
|
||||||
PRUnichar* bp = bp0;
|
PRUnichar* bp = bp0;
|
||||||
|
|
||||||
PRBool spacing = (0 != aTextStyle.mLetterSpacing) ||
|
PRBool spacing = (0 != aTextStyle.mLetterSpacing) ||
|
||||||
(0 != aTextStyle.mWordSpacing);
|
(0 != aTextStyle.mWordSpacing) || aTextStyle.mJustifying;
|
||||||
nscoord spacingMem[TEXT_BUF_SIZE];
|
nscoord spacingMem[TEXT_BUF_SIZE];
|
||||||
PRIntn* sp0 = spacingMem;
|
PRIntn* sp0 = spacingMem;
|
||||||
if (spacing && (aLength > TEXT_BUF_SIZE)) {
|
if (spacing && (aLength > TEXT_BUF_SIZE)) {
|
||||||
|
@ -1977,12 +2011,12 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
|
||||||
else if (ch == ' ') {
|
else if (ch == ' ') {
|
||||||
nextFont = aTextStyle.mNormalFont;
|
nextFont = aTextStyle.mNormalFont;
|
||||||
nextY = aY;
|
nextY = aY;
|
||||||
glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing;
|
glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing
|
||||||
nscoord extra = aTextStyle.mExtraSpacePerSpace;
|
+ aTextStyle.mExtraSpacePerSpace;
|
||||||
if (--aTextStyle.mNumSpaces == 0) {
|
if ((PRUint32)--aTextStyle.mNumSpacesToRender <
|
||||||
extra += aTextStyle.mRemainingExtraSpace;
|
(PRUint32)aTextStyle.mNumSpacesReceivingExtraJot) {
|
||||||
|
glyphWidth++;
|
||||||
}
|
}
|
||||||
glyphWidth += extra;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (lastFont != aTextStyle.mNormalFont) {
|
if (lastFont != aTextStyle.mNormalFont) {
|
||||||
|
@ -2096,12 +2130,12 @@ nsTextFrame::GetWidthOrLength(nsIRenderingContext& aRenderingContext,
|
||||||
glyphWidth = charWidth + aStyle.mLetterSpacing;
|
glyphWidth = charWidth + aStyle.mLetterSpacing;
|
||||||
}
|
}
|
||||||
else if (ch == ' ') {
|
else if (ch == ' ') {
|
||||||
glyphWidth = aStyle.mSpaceWidth + aStyle.mWordSpacing;
|
glyphWidth = aStyle.mSpaceWidth + aStyle.mWordSpacing
|
||||||
nscoord extra = aStyle.mExtraSpacePerSpace;
|
+ aStyle.mExtraSpacePerSpace;
|
||||||
if (--aStyle.mNumSpaces == 0) {
|
if ((PRUint32)--aStyle.mNumSpacesToMeasure
|
||||||
extra += aStyle.mRemainingExtraSpace;
|
< (PRUint32)aStyle.mNumSpacesReceivingExtraJot) {
|
||||||
|
glyphWidth++;
|
||||||
}
|
}
|
||||||
glyphWidth += extra;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (lastFont != aStyle.mNormalFont) {
|
if (lastFont != aStyle.mNormalFont) {
|
||||||
|
@ -2147,6 +2181,45 @@ nsTextFrame::GetLengthSlowly(nsIRenderingContext& aRenderingContext,
|
||||||
return GetWidthOrLength(aRenderingContext,aStyle,aBuffer,aLength,&aWidth,PR_FALSE);
|
return GetWidthOrLength(aRenderingContext,aStyle,aBuffer,aLength,&aWidth,PR_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTextFrame::ComputeExtraJustificationSpacing(nsIRenderingContext& aRenderingContext,
|
||||||
|
TextStyle& aTextStyle,
|
||||||
|
PRUnichar* aBuffer, PRInt32 aLength,
|
||||||
|
PRInt32 aNumSpaces)
|
||||||
|
{
|
||||||
|
if (aTextStyle.mJustifying) {
|
||||||
|
nscoord trueWidth;
|
||||||
|
|
||||||
|
// OK, so this is a bit ugly. The problem is that to get the right margin
|
||||||
|
// nice and clean, we have to apply a little extra space to *some* of the
|
||||||
|
// spaces. It has to be the same ones every time or things will go haywire.
|
||||||
|
// This implies that the GetWidthOrLength and RenderString functions depend
|
||||||
|
// on a little bit of secret state: which part of the prepared text they are
|
||||||
|
// looking at. It turns out that they get called in a regular way: they look
|
||||||
|
// at the text from the beginning to the end. So we just count which spaces
|
||||||
|
// we're up to, for each context.
|
||||||
|
// This is not a great solution, but a perfect solution requires much more
|
||||||
|
// widespread changes, to explicitly annotate all the transformed text fragments
|
||||||
|
// that are passed around with their position in the transformed text
|
||||||
|
// for the entire frame.
|
||||||
|
aTextStyle.mNumSpacesToMeasure = 0;
|
||||||
|
aTextStyle.mExtraSpacePerSpace = 0;
|
||||||
|
aTextStyle.mNumSpacesReceivingExtraJot = 0;
|
||||||
|
|
||||||
|
GetWidth(aRenderingContext, aTextStyle, aBuffer, aLength, &trueWidth);
|
||||||
|
|
||||||
|
aTextStyle.mNumSpacesToMeasure = aNumSpaces;
|
||||||
|
aTextStyle.mNumSpacesToRender = aNumSpaces;
|
||||||
|
|
||||||
|
nscoord extraSpace = mRect.width - trueWidth;
|
||||||
|
|
||||||
|
if (extraSpace > 0 && aNumSpaces > 0) {
|
||||||
|
aTextStyle.mExtraSpacePerSpace = extraSpace/aNumSpaces;
|
||||||
|
aTextStyle.mNumSpacesReceivingExtraJot =
|
||||||
|
extraSpace - aTextStyle.mExtraSpacePerSpace*aNumSpaces;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
|
nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
|
||||||
|
@ -2173,10 +2246,11 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
|
||||||
nsCOMPtr<nsILineBreaker> lb;
|
nsCOMPtr<nsILineBreaker> lb;
|
||||||
doc->GetLineBreaker(getter_AddRefs(lb));
|
doc->GetLineBreaker(getter_AddRefs(lb));
|
||||||
nsTextTransformer tx(lb, nsnull);
|
nsTextTransformer tx(lb, nsnull);
|
||||||
aTextStyle.mNumSpaces = PrepareUnicodeText(tx,
|
PRInt32 numSpaces;
|
||||||
(displaySelection
|
|
||||||
? &indexBuffer : nsnull),
|
numSpaces = PrepareUnicodeText(tx, (displaySelection ? &indexBuffer : nsnull),
|
||||||
&paintBuffer, &textLength);
|
&paintBuffer, &textLength);
|
||||||
|
|
||||||
|
|
||||||
PRInt32* ip = indexBuffer.mBuffer;
|
PRInt32* ip = indexBuffer.mBuffer;
|
||||||
PRUnichar* text = paintBuffer.mBuffer;
|
PRUnichar* text = paintBuffer.mBuffer;
|
||||||
|
@ -2185,6 +2259,7 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext,
|
||||||
GetFrameState(&frameState);
|
GetFrameState(&frameState);
|
||||||
isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
|
isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT;
|
||||||
if (0 != textLength) {
|
if (0 != textLength) {
|
||||||
|
ComputeExtraJustificationSpacing(aRenderingContext, aTextStyle, text, textLength, numSpaces);
|
||||||
if (!displaySelection || !isSelected) {
|
if (!displaySelection || !isSelected) {
|
||||||
// When there is no selection showing, use the fastest and
|
// When there is no selection showing, use the fastest and
|
||||||
// simplest rendering approach
|
// simplest rendering approach
|
||||||
|
@ -2550,8 +2625,7 @@ nsTextFrame::GetPosition(nsIPresContext* aCX,
|
||||||
rv = shell->CreateRenderingContext(this, getter_AddRefs(acx));
|
rv = shell->CreateRenderingContext(this, getter_AddRefs(acx));
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
TextStyle ts(aCX, *acx, mStyleContext);
|
TextStyle ts(aCX, *acx, mStyleContext);
|
||||||
if (ts.mSmallCaps || ts.mWordSpacing || ts.mLetterSpacing) {
|
if (ts.mSmallCaps || ts.mWordSpacing || ts.mLetterSpacing || ts.mJustifying) {
|
||||||
|
|
||||||
nsresult result = GetPositionSlowly(aCX, acx, aPoint, aNewContent,
|
nsresult result = GetPositionSlowly(aCX, acx, aPoint, aNewContent,
|
||||||
aContentOffset);
|
aContentOffset);
|
||||||
aContentOffsetEnd = aContentOffset;
|
aContentOffsetEnd = aContentOffset;
|
||||||
|
@ -2582,6 +2656,7 @@ nsTextFrame::GetPosition(nsIPresContext* aCX,
|
||||||
doc->GetLineBreaker(getter_AddRefs(lb));
|
doc->GetLineBreaker(getter_AddRefs(lb));
|
||||||
nsTextTransformer tx(lb, nsnull);
|
nsTextTransformer tx(lb, nsnull);
|
||||||
PRInt32 textLength;
|
PRInt32 textLength;
|
||||||
|
// no need to worry about justification, that's always on the slow path
|
||||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||||
|
|
||||||
if (textLength <=0) {
|
if (textLength <=0) {
|
||||||
|
@ -2593,7 +2668,7 @@ nsTextFrame::GetPosition(nsIPresContext* aCX,
|
||||||
nsIView * view;
|
nsIView * view;
|
||||||
GetOffsetFromView(aCX, origin, &view);
|
GetOffsetFromView(aCX, origin, &view);
|
||||||
|
|
||||||
//IF SYLE SAYS TO SELCT TO END OF FRAME HERE...
|
//IF STYLE SAYS TO SELECT TO END OF FRAME HERE...
|
||||||
nsCOMPtr<nsIPref> prefs;
|
nsCOMPtr<nsIPref> prefs;
|
||||||
PRInt32 prefInt = 0;
|
PRInt32 prefInt = 0;
|
||||||
rv = nsServiceManager::GetService(kPrefCID,
|
rv = nsServiceManager::GetService(kPrefCID,
|
||||||
|
@ -2880,7 +2955,12 @@ nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext,
|
||||||
doc->GetLineBreaker(getter_AddRefs(lb));
|
doc->GetLineBreaker(getter_AddRefs(lb));
|
||||||
nsTextTransformer tx(lb, nsnull);
|
nsTextTransformer tx(lb, nsnull);
|
||||||
PRInt32 textLength;
|
PRInt32 textLength;
|
||||||
PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
PRInt32 numSpaces;
|
||||||
|
|
||||||
|
numSpaces = PrepareUnicodeText(tx, &indexBuffer, &paintBuffer, &textLength);
|
||||||
|
|
||||||
|
ComputeExtraJustificationSpacing(*inRendContext, ts, paintBuffer.mBuffer, textLength, numSpaces);
|
||||||
|
|
||||||
|
|
||||||
PRInt32* ip = indexBuffer.mBuffer;
|
PRInt32* ip = indexBuffer.mBuffer;
|
||||||
if (inOffset > mContentLength){
|
if (inOffset > mContentLength){
|
||||||
|
@ -2889,7 +2969,7 @@ nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
nscoord width = mRect.width;
|
nscoord width = mRect.width;
|
||||||
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing))
|
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing) || ts.mJustifying)
|
||||||
{
|
{
|
||||||
GetWidth(*inRendContext, ts,
|
GetWidth(*inRendContext, ts,
|
||||||
paintBuffer.mBuffer, ip[inOffset]-mContentOffset,
|
paintBuffer.mBuffer, ip[inOffset]-mContentOffset,
|
||||||
|
@ -2907,7 +2987,8 @@ nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext,
|
||||||
// to the total width, so the caret appears
|
// to the total width, so the caret appears
|
||||||
// in the proper place!
|
// in the proper place!
|
||||||
//
|
//
|
||||||
width += ts.mSpaceWidth;
|
// NOTE: the trailing whitespace includes the word spacing!!
|
||||||
|
width += ts.mSpaceWidth + ts.mWordSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
outPoint->x = width;
|
outPoint->x = width;
|
||||||
|
@ -3502,6 +3583,7 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
PRBool measureTextRuns = !aTextData.mComputeMaxWordWidth && !aTs.mPreformatted &&
|
PRBool measureTextRuns = !aTextData.mComputeMaxWordWidth && !aTs.mPreformatted &&
|
||||||
!aTs.mSmallCaps && !aTs.mWordSpacing && !aTs.mLetterSpacing;
|
!aTs.mSmallCaps && !aTs.mWordSpacing && !aTs.mLetterSpacing;
|
||||||
|
// Don't measure text runs with letter spacing active, it doesn't work
|
||||||
#else
|
#else
|
||||||
PRBool measureTextRuns = PR_FALSE;
|
PRBool measureTextRuns = PR_FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
@ -3579,10 +3661,17 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
mState |= TEXT_SKIP_LEADING_WS;
|
mState |= TEXT_SKIP_LEADING_WS;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Even if the textRun absorbs the whitespace below, we still
|
||||||
|
// want to remember that we're breakable.
|
||||||
|
aTextData.mIsBreakable = PR_TRUE;
|
||||||
|
aTextData.mFirstLetterOK = PR_FALSE;
|
||||||
|
|
||||||
if ('\t' == firstChar) {
|
if ('\t' == firstChar) {
|
||||||
// Expand tabs to the proper width
|
// Expand tabs to the proper width
|
||||||
wordLen = 8 - (7 & column);
|
wordLen = 8 - (7 & column);
|
||||||
width = aTs.mSpaceWidth * wordLen;
|
// Apply word spacing to every space derived from a tab
|
||||||
|
width = (aTs.mSpaceWidth + aTs.mWordSpacing)*wordLen;
|
||||||
|
|
||||||
// Because we have to expand the tab when rendering consider that
|
// Because we have to expand the tab when rendering consider that
|
||||||
// a transformation of the text
|
// a transformation of the text
|
||||||
|
@ -3594,10 +3683,9 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
width = (wordLen * aTs.mSpaceWidth) + aTs.mWordSpacing;// XXX simplistic
|
// Apply word spacing to every space, if there's more than one
|
||||||
|
width = wordLen*(aTs.mWordSpacing + aTs.mSpaceWidth);// XXX simplistic
|
||||||
}
|
}
|
||||||
aTextData.mIsBreakable = PR_TRUE;
|
|
||||||
aTextData.mFirstLetterOK = PR_FALSE;
|
|
||||||
|
|
||||||
if (aTextData.mMeasureText) {
|
if (aTextData.mMeasureText) {
|
||||||
// See if there is room for the text
|
// See if there is room for the text
|
||||||
|
@ -3612,7 +3700,6 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
endsInWhitespace = PR_TRUE;
|
endsInWhitespace = PR_TRUE;
|
||||||
prevOffset = aTextData.mOffset;
|
prevOffset = aTextData.mOffset;
|
||||||
aTextData.mOffset += contentLen;
|
aTextData.mOffset += contentLen;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// See if the first thing in the section of text is a
|
// See if the first thing in the section of text is a
|
||||||
// non-breaking space (html nbsp entity). If it is then make
|
// non-breaking space (html nbsp entity). If it is then make
|
||||||
|
@ -3704,6 +3791,7 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
MeasureTextRun:
|
MeasureTextRun:
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
PRInt32 numCharsFit;
|
PRInt32 numCharsFit;
|
||||||
|
// These calls can return numCharsFit not positioned at a break in the textRun. Beware.
|
||||||
if (aTx.TransformedTextIsAscii()) {
|
if (aTx.TransformedTextIsAscii()) {
|
||||||
aReflowState.rendContext->GetWidth((char*)aTx.GetWordBuffer(), textRun.mTotalNumChars,
|
aReflowState.rendContext->GetWidth((char*)aTx.GetWordBuffer(), textRun.mTotalNumChars,
|
||||||
maxWidth - aTextData.mX,
|
maxWidth - aTextData.mX,
|
||||||
|
@ -3722,22 +3810,43 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the index of the last segment that fit
|
// Find the index of the last segment that fit
|
||||||
PRInt32 lastSegment = textRun.mNumSegments - 1;
|
PRInt32 lastSegment;
|
||||||
if (numCharsFit != textRun.mTotalNumChars) {
|
if (numCharsFit == textRun.mTotalNumChars) { // fast path, normal case
|
||||||
|
lastSegment = textRun.mNumSegments - 1;
|
||||||
|
} else {
|
||||||
for (lastSegment = 0; textRun.mBreaks[lastSegment] < numCharsFit; lastSegment++) ;
|
for (lastSegment = 0; textRun.mBreaks[lastSegment] < numCharsFit; lastSegment++) ;
|
||||||
NS_ASSERTION(lastSegment < textRun.mNumSegments, "failed to find segment");
|
NS_ASSERTION(lastSegment < textRun.mNumSegments, "failed to find segment");
|
||||||
|
// now we have textRun.mBreaks[lastSegment] >= numCharsFit
|
||||||
|
/* O'Callahan XXX: This snippet together with the snippet below prevents mail from loading
|
||||||
|
Justification seems to work just fine without these changes.
|
||||||
|
We get into trouble in a case where lastSegment gets set to -1
|
||||||
|
|
||||||
|
if (textRun.mBreaks[lastSegment] > numCharsFit) {
|
||||||
|
// NOTE: this segment did not actually fit!
|
||||||
|
lastSegment--;
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* O'Callahan XXX: This snippet together with the snippet above prevents mail from loading
|
||||||
|
|
||||||
|
if (lastSegment < 0) {
|
||||||
|
// no segments fit
|
||||||
|
break;
|
||||||
|
} else */
|
||||||
if (lastSegment == 0) {
|
if (lastSegment == 0) {
|
||||||
// Only one segment fit
|
// Only one segment fit
|
||||||
prevColumn = column;
|
prevColumn = column;
|
||||||
prevOffset = aTextData.mOffset;
|
prevOffset = aTextData.mOffset;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// The previous state is for the next to last word
|
// The previous state is for the next to last word
|
||||||
prevColumn = textRun.mBreaks[lastSegment - 1];
|
prevColumn = textRun.mBreaks[lastSegment - 1];
|
||||||
prevOffset = textRun.mSegments[lastSegment - 1].ContentLen();
|
prevOffset = textRun.mSegments[lastSegment - 1].ContentLen();
|
||||||
|
// NOTE: The textRun data are relative to the last updated column and offset!
|
||||||
|
prevColumn = column + textRun.mBreaks[lastSegment - 1];
|
||||||
|
prevOffset = aTextData.mOffset + textRun.mSegments[lastSegment - 1].ContentLen();
|
||||||
}
|
}
|
||||||
|
|
||||||
aTextData.mX += width;
|
aTextData.mX += width;
|
||||||
column += numCharsFit;
|
column += numCharsFit;
|
||||||
aTextData.mOffset += textRun.mSegments[lastSegment].ContentLen();
|
aTextData.mOffset += textRun.mSegments[lastSegment].ContentLen();
|
||||||
|
@ -3775,7 +3884,8 @@ nsTextFrame::MeasureText(nsIPresContext* aPresContext,
|
||||||
aTextData.mX = mRect.width;
|
aTextData.mX = mRect.width;
|
||||||
if (mState & TEXT_TRIMMED_WS) {
|
if (mState & TEXT_TRIMMED_WS) {
|
||||||
// Add back in the width of a space since it was trimmed away last time
|
// Add back in the width of a space since it was trimmed away last time
|
||||||
aTextData.mX += aTs.mSpaceWidth;
|
// NOTE: Trailing whitespace includes word spacing!
|
||||||
|
aTextData.mX += aTs.mSpaceWidth + aTs.mWordSpacing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4056,19 +4166,22 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
// current frame width -or-
|
// current frame width -or-
|
||||||
// we're not wrapping text and we're at the same column as before (this is
|
// we're not wrapping text and we're at the same column as before (this is
|
||||||
// an issue for preformatted tabbed text only)
|
// an issue for preformatted tabbed text only)
|
||||||
|
// - AND we aren't justified (in which case the frame width has already been tweaked and can't be used)
|
||||||
if ((eReflowReason_Resize == aReflowState.reason) &&
|
if ((eReflowReason_Resize == aReflowState.reason) &&
|
||||||
(0 == (mState & NS_FRAME_IS_DIRTY))) {
|
(0 == (mState & NS_FRAME_IS_DIRTY))) {
|
||||||
|
|
||||||
nscoord realWidth = mRect.width;
|
nscoord realWidth = mRect.width;
|
||||||
if (mState & TEXT_TRIMMED_WS) {
|
if (mState & TEXT_TRIMMED_WS) {
|
||||||
realWidth += ts.mSpaceWidth;
|
// NOTE: Trailing whitespace includes word spacing!
|
||||||
|
realWidth += ts.mSpaceWidth + ts.mWordSpacing;
|
||||||
}
|
}
|
||||||
if (!mNextInFlow &&
|
if (!mNextInFlow &&
|
||||||
(mState & TEXT_OPTIMIZE_RESIZE) &&
|
(mState & TEXT_OPTIMIZE_RESIZE) &&
|
||||||
!aMetrics.maxElementSize &&
|
!aMetrics.maxElementSize &&
|
||||||
(lastTimeWeSkippedLeadingWS == skipWhitespace) &&
|
(lastTimeWeSkippedLeadingWS == skipWhitespace) &&
|
||||||
((wrapping && (maxWidth >= realWidth)) ||
|
((wrapping && (maxWidth >= realWidth)) ||
|
||||||
(!wrapping && (prevColumn == column)))) {
|
(!wrapping && (prevColumn == column))) &&
|
||||||
|
!ts.mJustifying) {
|
||||||
// We can skip measuring of text and use the value from our
|
// We can skip measuring of text and use the value from our
|
||||||
// previous reflow
|
// previous reflow
|
||||||
measureText = PR_FALSE;
|
measureText = PR_FALSE;
|
||||||
|
@ -4120,6 +4233,23 @@ nsTextFrame::Reflow(nsIPresContext* aPresContext,
|
||||||
mContentOffset = startingOffset;
|
mContentOffset = startingOffset;
|
||||||
mContentLength = textData.mOffset - startingOffset;
|
mContentLength = textData.mOffset - startingOffset;
|
||||||
|
|
||||||
|
// Compute space and letter counts for justification, if required
|
||||||
|
if (ts.mJustifying) {
|
||||||
|
PRInt32 numSpaces;
|
||||||
|
PRInt32 textLength;
|
||||||
|
|
||||||
|
// This will include a space for trailing whitespace, if any is present.
|
||||||
|
// This is corrected for in nsLineLayout::TrimWhiteSpaceIn.
|
||||||
|
|
||||||
|
// This work could be done in MeasureText, but it's complex to do accurately
|
||||||
|
// there because of the need to repair counts when wrapped words are backed out.
|
||||||
|
// So I do it via PrepareUnicodeText ... a little slower perhaps, but a lot saner,
|
||||||
|
// and it localizes the counting logic to one place.
|
||||||
|
numSpaces = PrepareUnicodeText(tx, nsnull, nsnull, &textLength);
|
||||||
|
lineLayout.SetTextJustificationWeights(numSpaces, textLength - numSpaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef MOZ_MATHML
|
#ifdef MOZ_MATHML
|
||||||
// Simple minded code to also return the bounding metrics if the caller wants it...
|
// Simple minded code to also return the bounding metrics if the caller wants it...
|
||||||
// More consolidation is needed -- a better approach is to follow what is done by
|
// More consolidation is needed -- a better approach is to follow what is done by
|
||||||
|
@ -4226,6 +4356,11 @@ nsTextFrame::TrimTrailingWhiteSpace(nsIPresContext* aPresContext,
|
||||||
mStyleContext->GetStyleData(eStyleStruct_Font);
|
mStyleContext->GetStyleData(eStyleStruct_Font);
|
||||||
aRC.SetFont(fontStyle->mFont);
|
aRC.SetFont(fontStyle->mFont);
|
||||||
aRC.GetWidth(' ', dw);
|
aRC.GetWidth(' ', dw);
|
||||||
|
// NOTE: Trailing whitespace includes word spacing!
|
||||||
|
PRIntn unit = textStyle->mWordSpacing.GetUnit();
|
||||||
|
if (eStyleUnit_Coord == unit) {
|
||||||
|
dw += textStyle->mWordSpacing.GetCoordValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4406,6 +4541,8 @@ nsTextFrame::ComputeWordFragmentWidth(nsIPresContext* aPresContext,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rc.GetWidth(bp, wordLen, width);
|
rc.GetWidth(bp, wordLen, width);
|
||||||
|
// NOTE: Don't forget to add letter spacing for the word fragment!
|
||||||
|
width += wordLen*ts.mLetterSpacing;
|
||||||
}
|
}
|
||||||
rc.SetFont(oldfm);
|
rc.SetFont(oldfm);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче