1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 // vim:cindent:ts=2:et:sw=2:
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* representation of one line within a block frame, a CSS line box */
12 #include "nsPresArena.h"
13 #include "nsBidiPresUtils.h"
14 #include "nsIFrameInlines.h"
15 #include "WritingModes.h"
16 #include "mozilla/Assertions.h"
17 #include "mozilla/Likely.h"
18 #include "nsPrintfCString.h"
21 static int32_t ctorCount
;
22 int32_t nsLineBox::GetCtorCount() { return ctorCount
; }
26 // static nsLineBox constant; initialized in the header file.
27 const uint32_t nsLineBox::kMinChildCountForHashtable
;
30 using namespace mozilla
;
32 nsLineBox::nsLineBox(nsIFrame
* aFrame
, int32_t aCount
, bool aIsBlock
)
35 , mBounds(WritingMode()) // mBounds will be initialized with the correct
36 // writing mode when it is set
37 // NOTE: memory is already zeroed since we allocate with AllocateByObjectID.
39 MOZ_COUNT_CTOR(nsLineBox
);
42 NS_ASSERTION(!aIsBlock
|| aCount
== 1, "Blocks must have exactly one child");
44 for (int32_t n
= aCount
; n
> 0; f
= f
->GetNextSibling(), --n
) {
45 NS_ASSERTION(aIsBlock
== f
->IsBlockOutside(),
46 "wrong kind of child frame");
50 static_assert(NS_STYLE_CLEAR_MAX
<= 15,
51 "FlagBits needs more bits to store the full range of "
52 "break type ('clear') values");
53 #if NS_STYLE_CLEAR_NONE > 0
54 mFlags
.mBreakType
= NS_STYLE_CLEAR_NONE
;
58 mFlags
.mBlock
= aIsBlock
;
61 nsLineBox::~nsLineBox()
63 MOZ_COUNT_DTOR(nsLineBox
);
64 if (MOZ_UNLIKELY(mFlags
.mHasHashedFrames
)) {
71 NS_NewLineBox(nsIPresShell
* aPresShell
, nsIFrame
* aFrame
, bool aIsBlock
)
73 return new (aPresShell
) nsLineBox(aFrame
, 1, aIsBlock
);
77 NS_NewLineBox(nsIPresShell
* aPresShell
, nsLineBox
* aFromLine
,
78 nsIFrame
* aFrame
, int32_t aCount
)
80 nsLineBox
* newLine
= new (aPresShell
) nsLineBox(aFrame
, aCount
, false);
81 newLine
->NoteFramesMovedFrom(aFromLine
);
82 newLine
->mContainerWidth
= aFromLine
->mContainerWidth
;
87 nsLineBox::StealHashTableFrom(nsLineBox
* aFromLine
, uint32_t aFromLineNewCount
)
89 MOZ_ASSERT(!mFlags
.mHasHashedFrames
);
90 MOZ_ASSERT(GetChildCount() >= int32_t(aFromLineNewCount
));
91 mFrames
= aFromLine
->mFrames
;
92 mFlags
.mHasHashedFrames
= 1;
93 aFromLine
->mFlags
.mHasHashedFrames
= 0;
94 aFromLine
->mChildCount
= aFromLineNewCount
;
95 // remove aFromLine's frames that aren't on this line
96 nsIFrame
* f
= aFromLine
->mFirstChild
;
97 for (uint32_t i
= 0; i
< aFromLineNewCount
; f
= f
->GetNextSibling(), ++i
) {
98 mFrames
->RemoveEntry(f
);
103 nsLineBox::NoteFramesMovedFrom(nsLineBox
* aFromLine
)
105 uint32_t fromCount
= aFromLine
->GetChildCount();
106 uint32_t toCount
= GetChildCount();
107 MOZ_ASSERT(toCount
<= fromCount
, "moved more frames than aFromLine has");
108 uint32_t fromNewCount
= fromCount
- toCount
;
109 if (MOZ_LIKELY(!aFromLine
->mFlags
.mHasHashedFrames
)) {
110 aFromLine
->mChildCount
= fromNewCount
;
111 MOZ_ASSERT(toCount
< kMinChildCountForHashtable
);
112 } else if (fromNewCount
< kMinChildCountForHashtable
) {
113 // aFromLine has a hash table but will not have it after moving the frames
114 // so this line can steal the hash table if it needs it.
115 if (toCount
>= kMinChildCountForHashtable
) {
116 StealHashTableFrom(aFromLine
, fromNewCount
);
118 delete aFromLine
->mFrames
;
119 aFromLine
->mFlags
.mHasHashedFrames
= 0;
120 aFromLine
->mChildCount
= fromNewCount
;
123 // aFromLine still needs a hash table.
124 if (toCount
< kMinChildCountForHashtable
) {
125 // remove the moved frames from it
126 nsIFrame
* f
= mFirstChild
;
127 for (uint32_t i
= 0; i
< toCount
; f
= f
->GetNextSibling(), ++i
) {
128 aFromLine
->mFrames
->RemoveEntry(f
);
130 } else if (toCount
<= fromNewCount
) {
131 // This line needs a hash table, allocate a hash table for it since that
132 // means fewer hash ops.
133 nsIFrame
* f
= mFirstChild
;
134 for (uint32_t i
= 0; i
< toCount
; f
= f
->GetNextSibling(), ++i
) {
135 aFromLine
->mFrames
->RemoveEntry(f
); // toCount RemoveEntry
137 SwitchToHashtable(); // toCount PutEntry
139 // This line needs a hash table, but it's fewer hash ops to steal
140 // aFromLine's hash table and allocate a new hash table for that line.
141 StealHashTableFrom(aFromLine
, fromNewCount
); // fromNewCount RemoveEntry
142 aFromLine
->SwitchToHashtable(); // fromNewCount PutEntry
147 // Overloaded new operator. Uses an arena (which comes from the presShell)
148 // to perform the allocation.
150 nsLineBox::operator new(size_t sz
, nsIPresShell
* aPresShell
) CPP_THROW_NEW
152 return aPresShell
->AllocateByObjectID(nsPresArena::nsLineBox_id
, sz
);
156 nsLineBox::Destroy(nsIPresShell
* aPresShell
)
158 this->nsLineBox::~nsLineBox();
159 aPresShell
->FreeByObjectID(nsPresArena::nsLineBox_id
, this);
176 #ifdef DEBUG_FRAME_DUMP
178 ListFloats(FILE* out
, const char* aPrefix
, const nsFloatCacheList
& aFloats
)
180 nsFloatCache
* fc
= aFloats
.Head();
182 nsCString
str(aPrefix
);
183 nsIFrame
* frame
= fc
->mFloat
;
184 str
+= nsPrintfCString("floatframe@%p ", static_cast<void*>(frame
));
186 nsAutoString frameName
;
187 frame
->GetFrameName(frameName
);
188 str
+= NS_ConvertUTF16toUTF8(frameName
).get();
191 str
+= "\n###!!! NULL out-of-flow frame";
193 fprintf_stderr(out
, "%s\n", str
.get());
199 BreakTypeToString(uint8_t aBreakType
)
201 switch (aBreakType
) {
202 case NS_STYLE_CLEAR_NONE
: return "nobr";
203 case NS_STYLE_CLEAR_LEFT
: return "leftbr";
204 case NS_STYLE_CLEAR_RIGHT
: return "rightbr";
205 case NS_STYLE_CLEAR_BOTH
: return "leftbr+rightbr";
206 case NS_STYLE_CLEAR_LINE
: return "linebr";
214 nsLineBox::StateToString(char* aBuf
, int32_t aBufSize
) const
216 PR_snprintf(aBuf
, aBufSize
, "%s,%s,%s,%s,%s,before:%s,after:%s[0x%x]",
217 IsBlock() ? "block" : "inline",
218 IsDirty() ? "dirty" : "clean",
219 IsPreviousMarginDirty() ? "prevmargindirty" : "prevmarginclean",
220 IsImpactedByFloat() ? "impacted" : "not impacted",
221 IsLineWrapped() ? "wrapped" : "not wrapped",
222 BreakTypeToString(GetBreakTypeBefore()),
223 BreakTypeToString(GetBreakTypeAfter()),
229 nsLineBox::List(FILE* out
, int32_t aIndent
, uint32_t aFlags
) const
232 while (aIndent
-- > 0) {
235 List(out
, str
.get(), aFlags
);
239 nsLineBox::List(FILE* out
, const char* aPrefix
, uint32_t aFlags
) const
241 nsCString
str(aPrefix
);
243 str
+= nsPrintfCString("line %p: count=%d state=%s ",
244 static_cast<const void*>(this), GetChildCount(),
245 StateToString(cbuf
, sizeof(cbuf
)));
246 if (IsBlock() && !GetCarriedOutBEndMargin().IsZero()) {
247 str
+= nsPrintfCString("bm=%d ", GetCarriedOutBEndMargin().get());
249 nsRect bounds
= GetPhysicalBounds();
250 str
+= nsPrintfCString("{%d,%d,%d,%d} ",
251 bounds
.x
, bounds
.y
, bounds
.width
, bounds
.height
);
253 (!mData
->mOverflowAreas
.VisualOverflow().IsEqualEdges(bounds
) ||
254 !mData
->mOverflowAreas
.ScrollableOverflow().IsEqualEdges(bounds
))) {
255 str
+= nsPrintfCString("vis-overflow=%d,%d,%d,%d scr-overflow=%d,%d,%d,%d ",
256 mData
->mOverflowAreas
.VisualOverflow().x
,
257 mData
->mOverflowAreas
.VisualOverflow().y
,
258 mData
->mOverflowAreas
.VisualOverflow().width
,
259 mData
->mOverflowAreas
.VisualOverflow().height
,
260 mData
->mOverflowAreas
.ScrollableOverflow().x
,
261 mData
->mOverflowAreas
.ScrollableOverflow().y
,
262 mData
->mOverflowAreas
.ScrollableOverflow().width
,
263 mData
->mOverflowAreas
.ScrollableOverflow().height
);
265 fprintf_stderr(out
, "%s<\n", str
.get());
267 nsIFrame
* frame
= mFirstChild
;
268 int32_t n
= GetChildCount();
269 nsCString
pfx(aPrefix
);
272 frame
->List(out
, pfx
.get(), aFlags
);
273 frame
= frame
->GetNextSibling();
277 fprintf_stderr(out
, "%s> floats <\n", aPrefix
);
278 ListFloats(out
, pfx
.get(), mInlineData
->mFloats
);
280 fprintf_stderr(out
, "%s>\n", aPrefix
);
286 nsLineBox::LastChild() const
288 nsIFrame
* frame
= mFirstChild
;
289 int32_t n
= GetChildCount() - 1;
291 frame
= frame
->GetNextSibling();
298 nsLineBox::IndexOf(nsIFrame
* aFrame
) const
300 int32_t i
, n
= GetChildCount();
301 nsIFrame
* frame
= mFirstChild
;
302 for (i
= 0; i
< n
; i
++) {
303 if (frame
== aFrame
) {
306 frame
= frame
->GetNextSibling();
312 nsLineBox::IsEmpty() const
315 return mFirstChild
->IsEmpty();
319 for (n
= GetChildCount(), kid
= mFirstChild
;
321 --n
, kid
= kid
->GetNextSibling())
333 nsLineBox::CachedIsEmpty()
339 if (mFlags
.mEmptyCacheValid
) {
340 return mFlags
.mEmptyCacheState
;
345 result
= mFirstChild
->CachedIsEmpty();
350 for (n
= GetChildCount(), kid
= mFirstChild
;
352 --n
, kid
= kid
->GetNextSibling())
354 if (!kid
->CachedIsEmpty()) {
364 mFlags
.mEmptyCacheValid
= true;
365 mFlags
.mEmptyCacheState
= result
;
370 nsLineBox::DeleteLineList(nsPresContext
* aPresContext
, nsLineList
& aLines
,
371 nsIFrame
* aDestructRoot
, nsFrameList
* aFrames
)
373 nsIPresShell
* shell
= aPresContext
->PresShell();
375 // Keep our line list and frame list up to date as we
376 // remove frames, in case something wants to traverse the
377 // frame tree while we're destroying.
378 while (!aLines
.empty()) {
379 nsLineBox
* line
= aLines
.front();
380 if (MOZ_UNLIKELY(line
->mFlags
.mHasHashedFrames
)) {
381 line
->SwitchToCounter(); // Avoid expensive has table removals.
383 while (line
->GetChildCount() > 0) {
384 nsIFrame
* child
= aFrames
->RemoveFirstChild();
385 MOZ_ASSERT(child
== line
->mFirstChild
, "Lines out of sync");
386 line
->mFirstChild
= aFrames
->FirstChild();
387 line
->NoteFrameRemoved(child
);
388 child
->DestroyFrom(aDestructRoot
);
392 line
->Destroy(shell
);
397 nsLineBox::RFindLineContaining(nsIFrame
* aFrame
,
398 const nsLineList::iterator
& aBegin
,
399 nsLineList::iterator
& aEnd
,
400 nsIFrame
* aLastFrameBeforeEnd
,
401 int32_t* aFrameIndexInLine
)
403 NS_PRECONDITION(aFrame
, "null ptr");
405 nsIFrame
* curFrame
= aLastFrameBeforeEnd
;
406 while (aBegin
!= aEnd
) {
408 NS_ASSERTION(aEnd
->LastChild() == curFrame
, "Unexpected curFrame");
409 if (MOZ_UNLIKELY(aEnd
->mFlags
.mHasHashedFrames
) &&
410 !aEnd
->Contains(aFrame
)) {
411 if (aEnd
->mFirstChild
) {
412 curFrame
= aEnd
->mFirstChild
->GetPrevSibling();
416 // i is the index of curFrame in aEnd
417 int32_t i
= aEnd
->GetChildCount() - 1;
419 if (curFrame
== aFrame
) {
420 *aFrameIndexInLine
= i
;
424 curFrame
= curFrame
->GetPrevSibling();
426 MOZ_ASSERT(!aEnd
->mFlags
.mHasHashedFrames
, "Contains lied to us!");
428 *aFrameIndexInLine
= -1;
433 nsLineBox::GetCarriedOutBEndMargin() const
435 NS_ASSERTION(IsBlock(),
436 "GetCarriedOutBEndMargin called on non-block line.");
437 return (IsBlock() && mBlockData
)
438 ? mBlockData
->mCarriedOutBEndMargin
439 : nsCollapsingMargin();
443 nsLineBox::SetCarriedOutBEndMargin(nsCollapsingMargin aValue
)
445 bool changed
= false;
447 if (!aValue
.IsZero()) {
449 mBlockData
= new ExtraBlockData(GetPhysicalBounds());
451 changed
= aValue
!= mBlockData
->mCarriedOutBEndMargin
;
452 mBlockData
->mCarriedOutBEndMargin
= aValue
;
454 else if (mBlockData
) {
455 changed
= aValue
!= mBlockData
->mCarriedOutBEndMargin
;
456 mBlockData
->mCarriedOutBEndMargin
= aValue
;
464 nsLineBox::MaybeFreeData()
466 nsRect bounds
= GetPhysicalBounds();
467 if (mData
&& mData
->mOverflowAreas
== nsOverflowAreas(bounds
, bounds
)) {
469 if (mInlineData
->mFloats
.IsEmpty()) {
471 mInlineData
= nullptr;
474 else if (mBlockData
->mCarriedOutBEndMargin
.IsZero()) {
476 mBlockData
= nullptr;
481 // XXX get rid of this???
483 nsLineBox::GetFirstFloat()
485 NS_ABORT_IF_FALSE(IsInline(), "block line can't have floats");
486 return mInlineData
? mInlineData
->mFloats
.Head() : nullptr;
489 // XXX this might be too eager to free memory
491 nsLineBox::FreeFloats(nsFloatCacheFreeList
& aFreeList
)
493 NS_ABORT_IF_FALSE(IsInline(), "block line can't have floats");
494 if (IsInline() && mInlineData
) {
495 if (mInlineData
->mFloats
.NotEmpty()) {
496 aFreeList
.Append(mInlineData
->mFloats
);
503 nsLineBox::AppendFloats(nsFloatCacheFreeList
& aFreeList
)
505 NS_ABORT_IF_FALSE(IsInline(), "block line can't have floats");
507 if (aFreeList
.NotEmpty()) {
509 mInlineData
= new ExtraInlineData(GetPhysicalBounds());
511 mInlineData
->mFloats
.Append(aFreeList
);
517 nsLineBox::RemoveFloat(nsIFrame
* aFrame
)
519 NS_ABORT_IF_FALSE(IsInline(), "block line can't have floats");
520 if (IsInline() && mInlineData
) {
521 nsFloatCache
* fc
= mInlineData
->mFloats
.Find(aFrame
);
523 // Note: the placeholder is part of the line's child list
524 // and will be removed later.
525 mInlineData
->mFloats
.Remove(fc
);
535 nsLineBox::SetOverflowAreas(const nsOverflowAreas
& aOverflowAreas
)
537 NS_FOR_FRAME_OVERFLOW_TYPES(otype
) {
538 NS_ASSERTION(aOverflowAreas
.Overflow(otype
).width
>= 0,
539 "illegal width for combined area");
540 NS_ASSERTION(aOverflowAreas
.Overflow(otype
).height
>= 0,
541 "illegal height for combined area");
543 nsRect bounds
= GetPhysicalBounds();
544 if (!aOverflowAreas
.VisualOverflow().IsEqualInterior(bounds
) ||
545 !aOverflowAreas
.ScrollableOverflow().IsEqualEdges(bounds
)) {
548 mInlineData
= new ExtraInlineData(bounds
);
551 mBlockData
= new ExtraBlockData(bounds
);
554 mData
->mOverflowAreas
= aOverflowAreas
;
557 // Store away new value so that MaybeFreeData compares against
559 mData
->mOverflowAreas
= aOverflowAreas
;
564 //----------------------------------------------------------------------
567 static nsLineBox
* gDummyLines
[1];
569 nsLineIterator::nsLineIterator()
571 mLines
= gDummyLines
;
574 mRightToLeft
= false;
577 nsLineIterator::~nsLineIterator()
579 if (mLines
!= gDummyLines
) {
585 nsLineIterator::DisposeLineIterator()
591 nsLineIterator::Init(nsLineList
& aLines
, bool aRightToLeft
)
593 mRightToLeft
= aRightToLeft
;
596 int32_t numLines
= aLines
.size();
598 // Use gDummyLines so that we don't need null pointer checks in
599 // the accessor methods
600 mLines
= gDummyLines
;
604 // Make a linear array of the lines
605 mLines
= new nsLineBox
*[numLines
];
607 // Use gDummyLines so that we don't need null pointer checks in
608 // the accessor methods
609 mLines
= gDummyLines
;
610 return NS_ERROR_OUT_OF_MEMORY
;
612 nsLineBox
** lp
= mLines
;
613 for (nsLineList::iterator line
= aLines
.begin(), line_end
= aLines
.end() ;
619 mNumLines
= numLines
;
624 nsLineIterator::GetNumLines()
630 nsLineIterator::GetDirection()
636 nsLineIterator::GetLine(int32_t aLineNumber
,
637 nsIFrame
** aFirstFrameOnLine
,
638 int32_t* aNumFramesOnLine
,
640 uint32_t* aLineFlags
)
642 NS_ENSURE_ARG_POINTER(aFirstFrameOnLine
);
643 NS_ENSURE_ARG_POINTER(aNumFramesOnLine
);
644 NS_ENSURE_ARG_POINTER(aLineFlags
);
646 if ((aLineNumber
< 0) || (aLineNumber
>= mNumLines
)) {
647 *aFirstFrameOnLine
= nullptr;
648 *aNumFramesOnLine
= 0;
649 aLineBounds
.SetRect(0, 0, 0, 0);
652 nsLineBox
* line
= mLines
[aLineNumber
];
653 *aFirstFrameOnLine
= line
->mFirstChild
;
654 *aNumFramesOnLine
= line
->GetChildCount();
655 aLineBounds
= line
->GetPhysicalBounds();
658 if (line
->IsBlock()) {
659 flags
|= NS_LINE_FLAG_IS_BLOCK
;
662 if (line
->HasBreakAfter())
663 flags
|= NS_LINE_FLAG_ENDS_IN_BREAK
;
671 nsLineIterator::FindLineContaining(nsIFrame
* aFrame
, int32_t aStartLine
)
673 NS_PRECONDITION(aStartLine
<= mNumLines
, "Bogus line numbers");
674 int32_t lineNumber
= aStartLine
;
675 while (lineNumber
!= mNumLines
) {
676 nsLineBox
* line
= mLines
[lineNumber
];
677 if (line
->Contains(aFrame
)) {
686 nsLineIterator::CheckLineOrder(int32_t aLine
,
688 nsIFrame
**aFirstVisual
,
689 nsIFrame
**aLastVisual
)
691 NS_ASSERTION (aLine
>= 0 && aLine
< mNumLines
, "aLine out of range!");
692 nsLineBox
* line
= mLines
[aLine
];
694 if (!line
->mFirstChild
) { // empty line
695 *aIsReordered
= false;
696 *aFirstVisual
= nullptr;
697 *aLastVisual
= nullptr;
701 nsIFrame
* leftmostFrame
;
702 nsIFrame
* rightmostFrame
;
703 *aIsReordered
= nsBidiPresUtils::CheckLineOrder(line
->mFirstChild
, line
->GetChildCount(), &leftmostFrame
, &rightmostFrame
);
705 // map leftmost/rightmost to first/last according to paragraph direction
706 *aFirstVisual
= mRightToLeft
? rightmostFrame
: leftmostFrame
;
707 *aLastVisual
= mRightToLeft
? leftmostFrame
: rightmostFrame
;
713 nsLineIterator::FindFrameAt(int32_t aLineNumber
,
715 nsIFrame
** aFrameFound
,
716 bool* aXIsBeforeFirstFrame
,
717 bool* aXIsAfterLastFrame
)
719 NS_PRECONDITION(aFrameFound
&& aXIsBeforeFirstFrame
&& aXIsAfterLastFrame
,
721 if (!aFrameFound
|| !aXIsBeforeFirstFrame
|| !aXIsAfterLastFrame
) {
722 return NS_ERROR_NULL_POINTER
;
724 if ((aLineNumber
< 0) || (aLineNumber
>= mNumLines
)) {
725 return NS_ERROR_INVALID_ARG
;
728 nsLineBox
* line
= mLines
[aLineNumber
];
730 *aFrameFound
= nullptr;
731 *aXIsBeforeFirstFrame
= true;
732 *aXIsAfterLastFrame
= false;
736 if (line
->ISize() == 0 && line
->BSize() == 0)
737 return NS_ERROR_FAILURE
;
739 nsIFrame
* frame
= line
->mFirstChild
;
740 nsIFrame
* closestFromLeft
= nullptr;
741 nsIFrame
* closestFromRight
= nullptr;
742 int32_t n
= line
->GetChildCount();
744 nsRect rect
= frame
->GetRect();
745 if (rect
.width
> 0) {
746 // If aX is inside this frame - this is it
747 if (rect
.x
<= aX
&& rect
.XMost() > aX
) {
748 closestFromLeft
= closestFromRight
= frame
;
752 if (!closestFromLeft
||
753 rect
.XMost() > closestFromLeft
->GetRect().XMost())
754 closestFromLeft
= frame
;
757 if (!closestFromRight
||
758 rect
.x
< closestFromRight
->GetRect().x
)
759 closestFromRight
= frame
;
762 frame
= frame
->GetNextSibling();
764 if (!closestFromLeft
&& !closestFromRight
) {
765 // All frames were zero-width. Just take the first one.
766 closestFromLeft
= closestFromRight
= line
->mFirstChild
;
768 *aXIsBeforeFirstFrame
= mRightToLeft
? !closestFromRight
: !closestFromLeft
;
769 *aXIsAfterLastFrame
= mRightToLeft
? !closestFromLeft
: !closestFromRight
;
770 if (closestFromLeft
== closestFromRight
) {
771 *aFrameFound
= closestFromLeft
;
773 else if (!closestFromLeft
) {
774 *aFrameFound
= closestFromRight
;
776 else if (!closestFromRight
) {
777 *aFrameFound
= closestFromLeft
;
779 else { // we're between two frames
780 nscoord delta
= closestFromRight
->GetRect().x
- closestFromLeft
->GetRect().XMost();
781 if (aX
< closestFromLeft
->GetRect().XMost() + delta
/2)
782 *aFrameFound
= closestFromLeft
;
784 *aFrameFound
= closestFromRight
;
790 nsLineIterator::GetNextSiblingOnLine(nsIFrame
*& aFrame
, int32_t aLineNumber
)
792 aFrame
= aFrame
->GetNextSibling();
796 //----------------------------------------------------------------------
798 #ifdef NS_BUILD_REFCNT_LOGGING
799 nsFloatCacheList::nsFloatCacheList() :
802 MOZ_COUNT_CTOR(nsFloatCacheList
);
806 nsFloatCacheList::~nsFloatCacheList()
809 MOZ_COUNT_DTOR(nsFloatCacheList
);
813 nsFloatCacheList::DeleteAll()
815 nsFloatCache
* c
= mHead
;
817 nsFloatCache
* next
= c
->Next();
825 nsFloatCacheList::Tail() const
827 nsFloatCache
* fc
= mHead
;
838 nsFloatCacheList::Append(nsFloatCacheFreeList
& aList
)
840 NS_PRECONDITION(aList
.NotEmpty(), "Appending empty list will fail");
842 nsFloatCache
* tail
= Tail();
844 NS_ASSERTION(!tail
->mNext
, "Bogus!");
845 tail
->mNext
= aList
.mHead
;
848 NS_ASSERTION(!mHead
, "Bogus!");
851 aList
.mHead
= nullptr;
852 aList
.mTail
= nullptr;
856 nsFloatCacheList::Find(nsIFrame
* aOutOfFlowFrame
)
858 nsFloatCache
* fc
= mHead
;
860 if (fc
->mFloat
== aOutOfFlowFrame
) {
869 nsFloatCacheList::RemoveAndReturnPrev(nsFloatCache
* aElement
)
871 nsFloatCache
* fc
= mHead
;
872 nsFloatCache
* prev
= nullptr;
874 if (fc
== aElement
) {
876 prev
->mNext
= fc
->mNext
;
888 //----------------------------------------------------------------------
890 #ifdef NS_BUILD_REFCNT_LOGGING
891 nsFloatCacheFreeList::nsFloatCacheFreeList() :
894 MOZ_COUNT_CTOR(nsFloatCacheFreeList
);
897 nsFloatCacheFreeList::~nsFloatCacheFreeList()
899 MOZ_COUNT_DTOR(nsFloatCacheFreeList
);
904 nsFloatCacheFreeList::Append(nsFloatCacheList
& aList
)
906 NS_PRECONDITION(aList
.NotEmpty(), "Appending empty list will fail");
909 NS_ASSERTION(!mTail
->mNext
, "Bogus");
910 mTail
->mNext
= aList
.mHead
;
913 NS_ASSERTION(!mHead
, "Bogus");
916 mTail
= aList
.Tail();
917 aList
.mHead
= nullptr;
921 nsFloatCacheFreeList::Remove(nsFloatCache
* aElement
)
923 nsFloatCache
* prev
= nsFloatCacheList::RemoveAndReturnPrev(aElement
);
924 if (mTail
== aElement
) {
930 nsFloatCacheFreeList::DeleteAll()
932 nsFloatCacheList::DeleteAll();
937 nsFloatCacheFreeList::Alloc(nsIFrame
* aFloat
)
939 NS_PRECONDITION(aFloat
->GetStateBits() & NS_FRAME_OUT_OF_FLOW
,
940 "This is a float cache, why isn't the frame out-of-flow?");
941 nsFloatCache
* fc
= mHead
;
943 if (mHead
== mTail
) {
944 mHead
= mTail
= nullptr;
952 fc
= new nsFloatCache();
959 nsFloatCacheFreeList::Append(nsFloatCache
* aFloat
)
961 NS_ASSERTION(!aFloat
->mNext
, "Bogus!");
962 aFloat
->mNext
= nullptr;
964 NS_ASSERTION(!mTail
->mNext
, "Bogus!");
965 mTail
->mNext
= aFloat
;
969 NS_ASSERTION(!mHead
, "Bogus!");
970 mHead
= mTail
= aFloat
;
974 //----------------------------------------------------------------------
976 nsFloatCache::nsFloatCache()
980 MOZ_COUNT_CTOR(nsFloatCache
);
983 #ifdef NS_BUILD_REFCNT_LOGGING
984 nsFloatCache::~nsFloatCache()
986 MOZ_COUNT_DTOR(nsFloatCache
);