1998-12-01 19:13:49 +03:00
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
1999-11-06 06:40:37 +03:00
* The contents of this file are subject to the Netscape Public
* License Version 1.1 ( the " License " ) ; you may not use this file
* except in compliance with the License . You may obtain a copy of
* the License at http : //www.mozilla.org/NPL/
1998-12-01 19:13:49 +03:00
*
1999-11-06 06:40:37 +03:00
* Software distributed under the License is distributed on an " AS
* IS " basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied . See the License for the specific language governing
* rights and limitations under the License .
1998-12-01 19:13:49 +03:00
*
* The Original Code is Mozilla Communicator client code .
*
* The Initial Developer of the Original Code is Netscape Communications
1999-11-06 06:40:37 +03:00
* Corporation . Portions created by Netscape are
* Copyright ( C ) 1998 Netscape Communications Corporation . All
* Rights Reserved .
*
* Contributor ( s ) :
1998-12-01 19:13:49 +03:00
*/
# ifndef nsLineBox_h___
# define nsLineBox_h___
# include "nsVoidArray.h"
# include "nsPlaceholderFrame.h"
1999-05-13 04:54:28 +04:00
# include "nsILineIterator.h"
1999-10-02 06:51:03 +04:00
# include "nsISizeOfHandler.h"
1998-12-01 19:13:49 +03:00
class nsISpaceManager ;
class nsLineBox ;
1999-09-15 04:28:10 +04:00
class nsFloaterCache ;
class nsFloaterCacheList ;
class nsFloaterCacheFreeList ;
// State cached after reflowing a floater. This state is used during
// incremental reflow when we avoid reflowing a floater.
class nsFloaterCache {
public :
nsFloaterCache ( ) ;
1999-10-09 00:41:19 +04:00
# ifdef DEBUG
~ nsFloaterCache ( ) ;
# else
1999-09-15 04:28:10 +04:00
~ nsFloaterCache ( ) { }
1999-10-09 00:41:19 +04:00
# endif
1999-09-15 04:28:10 +04:00
nsFloaterCache * Next ( ) const { return mNext ; }
nsPlaceholderFrame * mPlaceholder ; // nsPlaceholderFrame
// This will be true if the floater was placed on the current line
// instead of below the current line.
PRBool mIsCurrentLineFloater ;
nsMargin mMargins ; // computed margins
nsMargin mOffsets ; // computed offsets (relative pos)
// Region in the spacemanager impacted by this floater; the
// coordinates are relative to the containing block frame. The
// region includes the margins around the floater, but doesn't
// include the relative offsets.
nsRect mRegion ;
// Combined area for the floater. This will not include the margins
// for the floater. Like mRegion, the coordinates are relative to
// the containing block frame.
nsRect mCombinedArea ;
protected :
nsFloaterCache * mNext ;
friend class nsFloaterCacheList ;
friend class nsFloaterCacheFreeList ;
} ;
//----------------------------------------
class nsFloaterCacheList {
public :
nsFloaterCacheList ( ) : mHead ( nsnull ) { }
~ nsFloaterCacheList ( ) ;
PRBool IsEmpty ( ) const {
return nsnull = = mHead ;
}
PRBool NotEmpty ( ) const {
return nsnull ! = mHead ;
}
nsFloaterCache * Head ( ) const {
return mHead ;
}
nsFloaterCache * Tail ( ) const ;
nsFloaterCache * Find ( nsIFrame * aOutOfFlowFrame ) ;
void Remove ( nsFloaterCache * aElement ) ;
void Append ( nsFloaterCacheFreeList & aList ) ;
1999-10-02 06:51:03 +04:00
# ifdef DEBUG
void SizeOf ( nsISizeOfHandler * aHandler , PRUint32 * aResult ) const ;
# endif
1999-09-15 04:28:10 +04:00
protected :
nsFloaterCache * mHead ;
friend class nsFloaterCacheFreeList ;
} ;
//---------------------------------------
class nsFloaterCacheFreeList : public nsFloaterCacheList {
public :
nsFloaterCacheFreeList ( ) : mTail ( nsnull ) { }
~ nsFloaterCacheFreeList ( ) { }
// Steal away aList's nsFloaterCache objects and put them on this
// free-list.
void Append ( nsFloaterCacheList & aList ) ;
void Append ( nsFloaterCache * aFloaterCache ) ;
// Allocate a new nsFloaterCache object
nsFloaterCache * Alloc ( ) ;
protected :
nsFloaterCache * mTail ;
friend class nsFloaterCacheList ;
} ;
//----------------------------------------------------------------------
1999-10-15 03:10:03 +04:00
# define LINE_MAX_BREAK_TYPE ((1 << 4) - 1)
2000-09-12 00:46:44 +04:00
# define LINE_MAX_CHILD_COUNT ((1 << 20) - 1)
1999-10-15 03:10:03 +04:00
# if NS_STYLE_CLEAR_LAST_VALUE > 15
need to rearrange the mBits bitfield ;
# endif
2000-03-12 06:00:51 +03:00
// Funtion to create a line box
nsLineBox * NS_NewLineBox ( nsIPresShell * aPresShell , nsIFrame * aFrame ,
PRInt32 aCount , PRBool aIsBlock ) ;
1998-12-01 19:13:49 +03:00
/**
* The nsLineBox class represents a horizontal line of frames . It contains
* enough state to support incremental reflow of the frames , event handling
* for the frames , and rendering of the frames .
*/
class nsLineBox {
2000-03-12 06:00:51 +03:00
private :
1999-10-13 03:24:22 +04:00
nsLineBox ( nsIFrame * aFrame , PRInt32 aCount , PRBool aIsBlock ) ;
~ nsLineBox ( ) ;
2000-03-12 06:00:51 +03:00
// Overloaded new operator. Uses an arena (which comes from the presShell)
// to perform the allocation.
void * operator new ( size_t sz , nsIPresShell * aPresShell ) ;
void operator delete ( void * aPtr , size_t sz ) ;
public :
// Use these two functions to allocate and destroy line boxes
friend nsLineBox * NS_NewLineBox ( nsIPresShell * aPresShell , nsIFrame * aFrame ,
PRInt32 aCount , PRBool aIsBlock ) ;
1999-10-13 03:24:22 +04:00
2000-03-12 06:00:51 +03:00
void Destroy ( nsIPresShell * aPresShell ) ;
1999-10-20 03:04:19 +04:00
1999-10-15 03:10:03 +04:00
// mBlock bit
1999-10-13 03:24:22 +04:00
PRBool IsBlock ( ) const {
return mFlags . mBlock ;
}
PRBool IsInline ( ) const {
return 0 = = mFlags . mBlock ;
}
1999-10-15 03:10:03 +04:00
// mDirty bit
void MarkDirty ( ) {
mFlags . mDirty = 1 ;
}
void ClearDirty ( ) {
mFlags . mDirty = 0 ;
}
PRBool IsDirty ( ) const {
return mFlags . mDirty ;
}
// mImpactedByFloater bit
void SetLineIsImpactedByFloater ( PRBool aValue ) {
2000-03-23 02:19:10 +03:00
NS_ASSERTION ( ( PR_FALSE = = aValue | | PR_TRUE = = aValue ) , " somebody is playing fast and loose with bools and bits! " ) ;
1999-10-15 03:10:03 +04:00
mFlags . mImpactedByFloater = aValue ;
}
PRBool IsImpactedByFloater ( ) const {
return mFlags . mImpactedByFloater ;
}
// mTrimmed bit
1999-10-13 03:24:22 +04:00
void SetTrimmed ( PRBool aOn ) {
2000-03-23 02:19:10 +03:00
NS_ASSERTION ( ( PR_FALSE = = aOn | | PR_TRUE = = aOn ) , " somebody is playing fast and loose with bools and bits! " ) ;
1999-10-13 03:24:22 +04:00
mFlags . mTrimmed = aOn ;
}
PRBool IsTrimmed ( ) const {
return mFlags . mTrimmed ;
}
2000-01-03 07:32:13 +03:00
// mHasPercentageChild bit
1999-10-29 18:35:36 +04:00
void SetHasPercentageChild ( PRBool aOn ) {
2000-03-23 02:19:10 +03:00
NS_ASSERTION ( ( PR_FALSE = = aOn | | PR_TRUE = = aOn ) , " somebody is playing fast and loose with bools and bits! " ) ;
1999-10-29 18:35:36 +04:00
mFlags . mHasPercentageChild = aOn ;
}
PRBool HasPercentageChild ( ) const {
return mFlags . mHasPercentageChild ;
}
2000-01-03 07:32:13 +03:00
// mLineWrapped bit
void SetLineWrapped ( PRBool aOn ) {
2000-03-23 02:19:10 +03:00
NS_ASSERTION ( ( PR_FALSE = = aOn | | PR_TRUE = = aOn ) , " somebody is playing fast and loose with bools and bits! " ) ;
2000-01-03 07:32:13 +03:00
mFlags . mLineWrapped = aOn ;
}
PRBool IsLineWrapped ( ) const {
return mFlags . mLineWrapped ;
}
2000-08-24 08:26:43 +04:00
// mLineWrapped bit
void SetForceInvalidate ( PRBool aOn ) {
NS_ASSERTION ( ( PR_FALSE = = aOn | | PR_TRUE = = aOn ) , " somebody is playing fast and loose with bools and bits! " ) ;
mFlags . mForceInvalidate = aOn ;
}
PRBool IsForceInvalidate ( ) const {
return mFlags . mForceInvalidate ;
}
2000-09-12 00:46:44 +04:00
// mResizeReflowOptimizationDisabled bit
void DisableResizeReflowOptimization ( ) {
mFlags . mResizeReflowOptimizationDisabled = PR_TRUE ;
}
void EnableResizeReflowOptimization ( ) {
mFlags . mResizeReflowOptimizationDisabled = PR_FALSE ;
}
PRBool ResizeReflowOptimizationDisabled ( ) const {
return mFlags . mResizeReflowOptimizationDisabled ;
}
2000-01-03 07:32:13 +03:00
1999-10-15 03:10:03 +04:00
// mChildCount value
PRInt32 GetChildCount ( ) const {
return ( PRInt32 ) mFlags . mChildCount ;
}
void SetChildCount ( PRInt32 aNewCount ) {
if ( NS_WARN_IF_FALSE ( aNewCount > = 0 , " negative child count " ) ) {
aNewCount = 0 ;
}
if ( aNewCount > LINE_MAX_CHILD_COUNT ) {
aNewCount = LINE_MAX_CHILD_COUNT ;
}
mFlags . mChildCount = aNewCount ;
}
// mBreakType value
1999-10-13 03:24:22 +04:00
PRBool HasBreak ( ) const {
return NS_STYLE_CLEAR_NONE ! = mFlags . mBreakType ;
}
void SetBreakType ( PRUint8 aBreakType ) {
1999-10-15 03:10:03 +04:00
NS_WARN_IF_FALSE ( aBreakType < = LINE_MAX_BREAK_TYPE , " bad break type " ) ;
1999-10-13 03:24:22 +04:00
mFlags . mBreakType = aBreakType ;
}
PRUint8 GetBreakType ( ) const {
return mFlags . mBreakType ;
}
1998-12-01 19:13:49 +03:00
1999-10-15 03:10:03 +04:00
// mCarriedOutBottomMargin value
nscoord GetCarriedOutBottomMargin ( ) const ;
void SetCarriedOutBottomMargin ( nscoord aValue ) ;
// mFloaters
PRBool HasFloaters ( ) const {
return ( IsInline ( ) & & mInlineData ) & & mInlineData - > mFloaters . NotEmpty ( ) ;
1998-12-01 19:13:49 +03:00
}
1999-10-15 03:10:03 +04:00
nsFloaterCache * GetFirstFloater ( ) ;
void FreeFloaters ( nsFloaterCacheFreeList & aFreeList ) ;
void AppendFloaters ( nsFloaterCacheFreeList & aFreeList ) ;
PRBool RemoveFloater ( nsIFrame * aFrame ) ;
2000-01-08 06:58:27 +03:00
void RemoveFloatersFromSpaceManager ( nsISpaceManager * aSpaceManager ) ;
1998-12-01 19:13:49 +03:00
1999-10-20 03:04:19 +04:00
// Combined area
1999-10-15 03:10:03 +04:00
void SetCombinedArea ( const nsRect & aCombinedArea ) ;
void GetCombinedArea ( nsRect * aResult ) ;
1999-10-20 03:04:19 +04:00
PRBool CombinedAreaIntersects ( const nsRect & aDamageRect ) {
nsRect * ca = ( mData ? & mData - > mCombinedArea : & mBounds ) ;
return ! ( ( ca - > YMost ( ) < = aDamageRect . y ) | |
( ca - > y > = aDamageRect . YMost ( ) ) ) ;
}
1998-12-01 19:13:49 +03:00
1999-10-15 03:10:03 +04:00
void SlideBy ( nscoord aDY ) {
mBounds . y + = aDY ;
if ( mData ) {
mData - > mCombinedArea . y + = aDY ;
}
}
//----------------------------------------
nscoord GetHeight ( ) const {
return mBounds . height ;
}
1998-12-01 19:13:49 +03:00
1999-11-03 02:42:52 +03:00
static void DeleteLineList ( nsIPresContext * aPresContext , nsLineBox * aLine ) ;
1998-12-01 19:13:49 +03:00
static nsLineBox * LastLine ( nsLineBox * aLine ) ;
1999-04-21 01:52:22 +04:00
static nsLineBox * FindLineContaining ( nsLineBox * aLine , nsIFrame * aFrame ,
PRInt32 * aFrameIndexInLine ) ;
1998-12-01 19:13:49 +03:00
1999-11-02 01:12:45 +03:00
# ifdef DEBUG
1999-10-26 08:44:41 +04:00
void List ( nsIPresContext * aPresContext , FILE * out , PRInt32 aIndent ) const ;
1999-11-02 01:12:45 +03:00
# endif
1998-12-01 19:13:49 +03:00
nsIFrame * LastChild ( ) const ;
PRBool IsLastChild ( nsIFrame * aFrame ) const ;
char * StateToString ( char * aBuf , PRInt32 aBufSize ) const ;
1999-04-21 01:52:22 +04:00
PRInt32 IndexOf ( nsIFrame * aFrame ) const ;
PRBool Contains ( nsIFrame * aFrame ) const {
return IndexOf ( aFrame ) > = 0 ;
}
1998-12-01 19:13:49 +03:00
1999-10-02 06:51:03 +04:00
# ifdef DEBUG
1999-10-15 03:10:03 +04:00
nsIAtom * SizeOf ( nsISizeOfHandler * aHandler , PRUint32 * aResult ) const ;
1999-10-20 03:04:19 +04:00
static PRInt32 GetCtorCount ( ) ;
static PRInt32 ListLength ( nsLineBox * aLine ) ;
1999-10-02 06:51:03 +04:00
# endif
1998-12-01 19:13:49 +03:00
nsIFrame * mFirstChild ;
nsLineBox * mNext ;
1999-10-15 03:10:03 +04:00
nsRect mBounds ;
1999-08-28 04:39:55 +04:00
nscoord mMaxElementWidth ; // width part of max-element-size
1999-12-30 07:15:45 +03:00
nscoord mMaximumWidth ; // maximum width (needed for incremental reflow of tables)
1999-10-13 03:24:22 +04:00
struct FlagBits {
PRUint32 mDirty : 1 ;
PRUint32 mBlock : 1 ;
PRUint32 mImpactedByFloater : 1 ;
PRUint32 mTrimmed : 1 ;
1999-10-29 18:35:36 +04:00
PRUint32 mHasPercentageChild : 1 ;
2000-01-03 07:32:13 +03:00
PRUint32 mLineWrapped : 1 ;
2000-09-12 00:46:44 +04:00
PRUint32 mForceInvalidate : 1 ; // default 0 = means this line handles it's own invalidation. 1 = always invalidate this entire line
PRUint32 mResizeReflowOptimizationDisabled : 1 ; // default 0 = means that the opt potentially applies to this line. 1 = never skip reflowing this line for a resize reflow
1999-10-15 03:10:03 +04:00
PRUint32 mBreakType : 4 ;
2000-09-12 00:46:44 +04:00
PRUint32 mChildCount : 20 ;
1999-10-15 03:10:03 +04:00
} ;
struct ExtraData {
ExtraData ( const nsRect & aBounds ) : mCombinedArea ( aBounds ) {
}
nsRect mCombinedArea ;
} ;
struct ExtraBlockData : public ExtraData {
ExtraBlockData ( const nsRect & aBounds ) : ExtraData ( aBounds ) {
mCarriedOutBottomMargin = 0 ;
}
nscoord mCarriedOutBottomMargin ;
} ;
1999-10-13 03:24:22 +04:00
1999-10-15 03:10:03 +04:00
struct ExtraInlineData : public ExtraData {
ExtraInlineData ( const nsRect & aBounds ) : ExtraData ( aBounds ) {
}
nsFloaterCacheList mFloaters ;
1999-10-13 03:24:22 +04:00
} ;
protected :
union {
PRUint32 mAllFlags ;
FlagBits mFlags ;
} ;
1999-10-15 03:10:03 +04:00
union {
ExtraData * mData ;
ExtraBlockData * mBlockData ;
ExtraInlineData * mInlineData ;
} ;
1999-10-20 03:04:19 +04:00
void Cleanup ( ) ;
1999-10-15 03:10:03 +04:00
void MaybeFreeData ( ) ;
1998-12-01 19:13:49 +03:00
} ;
1999-05-11 02:28:49 +04:00
//----------------------------------------------------------------------
2000-05-16 12:11:14 +04:00
class nsLineIterator : public nsILineIteratorNavigator {
1999-05-13 04:54:28 +04:00
public :
1999-05-11 02:28:49 +04:00
nsLineIterator ( ) ;
1999-05-13 04:54:28 +04:00
virtual ~ nsLineIterator ( ) ;
NS_DECL_ISUPPORTS
NS_IMETHOD GetNumLines ( PRInt32 * aResult ) ;
NS_IMETHOD GetDirection ( PRBool * aIsRightToLeft ) ;
NS_IMETHOD GetLine ( PRInt32 aLineNumber ,
nsIFrame * * aFirstFrameOnLine ,
PRInt32 * aNumFramesOnLine ,
1999-10-13 03:24:22 +04:00
nsRect & aLineBounds ,
PRUint32 * aLineFlags ) ;
1999-05-13 04:54:28 +04:00
NS_IMETHOD FindLineContaining ( nsIFrame * aFrame ,
PRInt32 * aLineNumberResult ) ;
NS_IMETHOD FindLineAt ( nscoord aY ,
PRInt32 * aLineNumberResult ) ;
NS_IMETHOD FindFrameAt ( PRInt32 aLineNumber ,
nscoord aX ,
nsIFrame * * aFrameFound ,
PRBool * aXIsBeforeFirstFrame ,
PRBool * aXIsAfterLastFrame ) ;
2000-06-17 02:28:10 +04:00
NS_IMETHOD GetNextSiblingOnLine ( nsIFrame * & aFrame , PRInt32 aLineNumber ) ;
2000-05-11 05:04:39 +04:00
1999-05-13 04:54:28 +04:00
nsresult Init ( nsLineBox * aLines , PRBool aRightToLeft ) ;
protected :
1999-05-11 02:28:49 +04:00
PRInt32 NumLines ( ) const {
return mNumLines ;
}
nsLineBox * CurrentLine ( ) {
return mLines [ mIndex ] ;
}
nsLineBox * PrevLine ( ) {
if ( 0 = = mIndex ) {
return nsnull ;
}
return mLines [ - - mIndex ] ;
}
nsLineBox * NextLine ( ) {
if ( mIndex > = mNumLines - 1 ) {
return nsnull ;
}
return mLines [ + + mIndex ] ;
}
nsLineBox * LineAt ( PRInt32 aIndex ) {
if ( ( aIndex < 0 ) | | ( aIndex > = mNumLines ) ) {
return nsnull ;
}
return mLines [ aIndex ] ;
}
nsLineBox * * mLines ;
PRInt32 mIndex ;
PRInt32 mNumLines ;
2000-09-12 00:46:44 +04:00
PRPackedBool mRightToLeft ;
1999-05-11 02:28:49 +04:00
} ;
1998-12-01 19:13:49 +03:00
# endif /* nsLineBox_h___ */