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"
14 #include "nsBidiPresUtils.h"
16 #include "nsIFrameInlines.h"
17 #include "mozilla/Assertions.h"
18 #include "mozilla/Likely.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 nsLineBox::nsLineBox(nsIFrame
* aFrame
, int32_t aCount
, bool aIsBlock
)
32 // NOTE: memory is already zeroed since we allocate with AllocateByObjectID.
34 MOZ_COUNT_CTOR(nsLineBox
);
37 NS_ASSERTION(!aIsBlock
|| aCount
== 1, "Blocks must have exactly one child");
39 for (int32_t n
= aCount
; n
> 0; f
= f
->GetNextSibling(), --n
) {
40 NS_ASSERTION(aIsBlock
== f
->IsBlockOutside(),
41 "wrong kind of child frame");
45 static_assert(NS_STYLE_CLEAR_LAST_VALUE
<= 15,
46 "FlagBits needs more bits to store the full range of "
47 "break type ('clear') values");
48 #if NS_STYLE_CLEAR_NONE > 0
49 mFlags
.mBreakType
= NS_STYLE_CLEAR_NONE
;
53 mFlags
.mBlock
= aIsBlock
;
56 nsLineBox::~nsLineBox()
58 MOZ_COUNT_DTOR(nsLineBox
);
59 if (MOZ_UNLIKELY(mFlags
.mHasHashedFrames
)) {
66 NS_NewLineBox(nsIPresShell
* aPresShell
, nsIFrame
* aFrame
, bool aIsBlock
)
68 return new (aPresShell
) nsLineBox(aFrame
, 1, aIsBlock
);
72 NS_NewLineBox(nsIPresShell
* aPresShell
, nsLineBox
* aFromLine
,
73 nsIFrame
* aFrame
, int32_t aCount
)
75 nsLineBox
* newLine
= new (aPresShell
) nsLineBox(aFrame
, aCount
, false);
76 newLine
->NoteFramesMovedFrom(aFromLine
);
81 nsLineBox::StealHashTableFrom(nsLineBox
* aFromLine
, uint32_t aFromLineNewCount
)
83 MOZ_ASSERT(!mFlags
.mHasHashedFrames
);
84 MOZ_ASSERT(GetChildCount() >= int32_t(aFromLineNewCount
));
85 mFrames
= aFromLine
->mFrames
;
86 mFlags
.mHasHashedFrames
= 1;
87 aFromLine
->mFlags
.mHasHashedFrames
= 0;
88 aFromLine
->mChildCount
= aFromLineNewCount
;
89 // remove aFromLine's frames that aren't on this line
90 nsIFrame
* f
= aFromLine
->mFirstChild
;
91 for (uint32_t i
= 0; i
< aFromLineNewCount
; f
= f
->GetNextSibling(), ++i
) {
92 mFrames
->RemoveEntry(f
);
97 nsLineBox::NoteFramesMovedFrom(nsLineBox
* aFromLine
)
99 uint32_t fromCount
= aFromLine
->GetChildCount();
100 uint32_t toCount
= GetChildCount();
101 MOZ_ASSERT(toCount
<= fromCount
, "moved more frames than aFromLine has");
102 uint32_t fromNewCount
= fromCount
- toCount
;
103 if (MOZ_LIKELY(!aFromLine
->mFlags
.mHasHashedFrames
)) {
104 aFromLine
->mChildCount
= fromNewCount
;
105 MOZ_ASSERT(toCount
< kMinChildCountForHashtable
);
106 } else if (fromNewCount
< kMinChildCountForHashtable
) {
107 // aFromLine has a hash table but will not have it after moving the frames
108 // so this line can steal the hash table if it needs it.
109 if (toCount
>= kMinChildCountForHashtable
) {
110 StealHashTableFrom(aFromLine
, fromNewCount
);
112 delete aFromLine
->mFrames
;
113 aFromLine
->mFlags
.mHasHashedFrames
= 0;
114 aFromLine
->mChildCount
= fromNewCount
;
117 // aFromLine still needs a hash table.
118 if (toCount
< kMinChildCountForHashtable
) {
119 // remove the moved frames from it
120 nsIFrame
* f
= mFirstChild
;
121 for (uint32_t i
= 0; i
< toCount
; f
= f
->GetNextSibling(), ++i
) {
122 aFromLine
->mFrames
->RemoveEntry(f
);
124 } else if (toCount
<= fromNewCount
) {
125 // This line needs a hash table, allocate a hash table for it since that
126 // means fewer hash ops.
127 nsIFrame
* f
= mFirstChild
;
128 for (uint32_t i
= 0; i
< toCount
; f
= f
->GetNextSibling(), ++i
) {
129 aFromLine
->mFrames
->RemoveEntry(f
); // toCount RemoveEntry
131 SwitchToHashtable(); // toCount PutEntry
133 // This line needs a hash table, but it's fewer hash ops to steal
134 // aFromLine's hash table and allocate a new hash table for that line.
135 StealHashTableFrom(aFromLine
, fromNewCount
); // fromNewCount RemoveEntry
136 aFromLine
->SwitchToHashtable(); // fromNewCount PutEntry
141 // Overloaded new operator. Uses an arena (which comes from the presShell)
142 // to perform the allocation.
144 nsLineBox::operator new(size_t sz
, nsIPresShell
* aPresShell
) CPP_THROW_NEW
146 return aPresShell
->AllocateByObjectID(nsPresArena::nsLineBox_id
, sz
);
150 nsLineBox::Destroy(nsIPresShell
* aPresShell
)
152 this->nsLineBox::~nsLineBox();
153 aPresShell
->FreeByObjectID(nsPresArena::nsLineBox_id
, this);
172 ListFloats(FILE* out
, int32_t aIndent
, const nsFloatCacheList
& aFloats
)
174 nsFloatCache
* fc
= aFloats
.Head();
176 nsFrame::IndentBy(out
, aIndent
);
177 nsIFrame
* frame
= fc
->mFloat
;
178 fprintf(out
, "floatframe@%p ", static_cast<void*>(frame
));
180 nsAutoString frameName
;
181 frame
->GetFrameName(frameName
);
182 fputs(NS_LossyConvertUTF16toASCII(frameName
).get(), out
);
185 fputs("\n###!!! NULL out-of-flow frame", out
);
195 BreakTypeToString(uint8_t aBreakType
)
197 switch (aBreakType
) {
198 case NS_STYLE_CLEAR_NONE
: return "nobr";
199 case NS_STYLE_CLEAR_LEFT
: return "leftbr";
200 case NS_STYLE_CLEAR_RIGHT
: return "rightbr";
201 case NS_STYLE_CLEAR_LEFT_AND_RIGHT
: return "leftbr+rightbr";
202 case NS_STYLE_CLEAR_LINE
: return "linebr";
210 nsLineBox::StateToString(char* aBuf
, int32_t aBufSize
) const
212 PR_snprintf(aBuf
, aBufSize
, "%s,%s,%s,%s,%s,before:%s,after:%s[0x%x]",
213 IsBlock() ? "block" : "inline",
214 IsDirty() ? "dirty" : "clean",
215 IsPreviousMarginDirty() ? "prevmargindirty" : "prevmarginclean",
216 IsImpactedByFloat() ? "impacted" : "not impacted",
217 IsLineWrapped() ? "wrapped" : "not wrapped",
218 BreakTypeToString(GetBreakTypeBefore()),
219 BreakTypeToString(GetBreakTypeAfter()),
225 nsLineBox::List(FILE* out
, int32_t aIndent
, uint32_t aFlags
) const
227 nsFrame::IndentBy(out
, aIndent
);
229 fprintf(out
, "line %p: count=%d state=%s ",
230 static_cast<const void*>(this), GetChildCount(),
231 StateToString(cbuf
, sizeof(cbuf
)));
232 if (IsBlock() && !GetCarriedOutBottomMargin().IsZero()) {
233 fprintf(out
, "bm=%d ", GetCarriedOutBottomMargin().get());
235 fprintf(out
, "{%d,%d,%d,%d} ",
236 mBounds
.x
, mBounds
.y
, mBounds
.width
, mBounds
.height
);
238 (!mData
->mOverflowAreas
.VisualOverflow().IsEqualEdges(mBounds
) ||
239 !mData
->mOverflowAreas
.ScrollableOverflow().IsEqualEdges(mBounds
))) {
240 fprintf(out
, "vis-overflow=%d,%d,%d,%d scr-overflow=%d,%d,%d,%d ",
241 mData
->mOverflowAreas
.VisualOverflow().x
,
242 mData
->mOverflowAreas
.VisualOverflow().y
,
243 mData
->mOverflowAreas
.VisualOverflow().width
,
244 mData
->mOverflowAreas
.VisualOverflow().height
,
245 mData
->mOverflowAreas
.ScrollableOverflow().x
,
246 mData
->mOverflowAreas
.ScrollableOverflow().y
,
247 mData
->mOverflowAreas
.ScrollableOverflow().width
,
248 mData
->mOverflowAreas
.ScrollableOverflow().height
);
252 nsIFrame
* frame
= mFirstChild
;
253 int32_t n
= GetChildCount();
255 frame
->List(out
, aIndent
+ 1, aFlags
);
256 frame
= frame
->GetNextSibling();
260 nsFrame::IndentBy(out
, aIndent
);
261 fputs("> floats <\n", out
);
262 ListFloats(out
, aIndent
+ 1, mInlineData
->mFloats
);
264 nsFrame::IndentBy(out
, aIndent
);
271 nsLineBox::LastChild() const
273 nsIFrame
* frame
= mFirstChild
;
274 int32_t n
= GetChildCount() - 1;
276 frame
= frame
->GetNextSibling();
283 nsLineBox::IndexOf(nsIFrame
* aFrame
) const
285 int32_t i
, n
= GetChildCount();
286 nsIFrame
* frame
= mFirstChild
;
287 for (i
= 0; i
< n
; i
++) {
288 if (frame
== aFrame
) {
291 frame
= frame
->GetNextSibling();
297 nsLineBox::IsEmpty() const
300 return mFirstChild
->IsEmpty();
304 for (n
= GetChildCount(), kid
= mFirstChild
;
306 --n
, kid
= kid
->GetNextSibling())
318 nsLineBox::CachedIsEmpty()
324 if (mFlags
.mEmptyCacheValid
) {
325 return mFlags
.mEmptyCacheState
;
330 result
= mFirstChild
->CachedIsEmpty();
335 for (n
= GetChildCount(), kid
= mFirstChild
;
337 --n
, kid
= kid
->GetNextSibling())
339 if (!kid
->CachedIsEmpty()) {
349 mFlags
.mEmptyCacheValid
= true;
350 mFlags
.mEmptyCacheState
= result
;
355 nsLineBox::DeleteLineList(nsPresContext
* aPresContext
, nsLineList
& aLines
,
356 nsIFrame
* aDestructRoot
, nsFrameList
* aFrames
)
358 nsIPresShell
* shell
= aPresContext
->PresShell();
360 // Keep our line list and frame list up to date as we
361 // remove frames, in case something wants to traverse the
362 // frame tree while we're destroying.
363 while (!aLines
.empty()) {
364 nsLineBox
* line
= aLines
.front();
365 if (MOZ_UNLIKELY(line
->mFlags
.mHasHashedFrames
)) {
366 line
->SwitchToCounter(); // Avoid expensive has table removals.
368 while (line
->GetChildCount() > 0) {
369 nsIFrame
* child
= aFrames
->RemoveFirstChild();
370 MOZ_ASSERT(child
== line
->mFirstChild
, "Lines out of sync");
371 line
->mFirstChild
= aFrames
->FirstChild();
372 line
->NoteFrameRemoved(child
);
373 child
->DestroyFrom(aDestructRoot
);
377 line
->Destroy(shell
);
382 nsLineBox::RFindLineContaining(nsIFrame
* aFrame
,
383 const nsLineList::iterator
& aBegin
,
384 nsLineList::iterator
& aEnd
,
385 nsIFrame
* aLastFrameBeforeEnd
,
386 int32_t* aFrameIndexInLine
)
388 NS_PRECONDITION(aFrame
, "null ptr");
390 nsIFrame
* curFrame
= aLastFrameBeforeEnd
;
391 while (aBegin
!= aEnd
) {
393 NS_ASSERTION(aEnd
->LastChild() == curFrame
, "Unexpected curFrame");
394 if (MOZ_UNLIKELY(aEnd
->mFlags
.mHasHashedFrames
) &&
395 !aEnd
->Contains(aFrame
)) {
396 if (aEnd
->mFirstChild
) {
397 curFrame
= aEnd
->mFirstChild
->GetPrevSibling();
401 // i is the index of curFrame in aEnd
402 int32_t i
= aEnd
->GetChildCount() - 1;
404 if (curFrame
== aFrame
) {
405 *aFrameIndexInLine
= i
;
409 curFrame
= curFrame
->GetPrevSibling();
411 MOZ_ASSERT(!aEnd
->mFlags
.mHasHashedFrames
, "Contains lied to us!");
413 *aFrameIndexInLine
= -1;
418 nsLineBox::GetCarriedOutBottomMargin() const
420 NS_ASSERTION(IsBlock(),
421 "GetCarriedOutBottomMargin called on non-block line.");
422 return (IsBlock() && mBlockData
)
423 ? mBlockData
->mCarriedOutBottomMargin
424 : nsCollapsingMargin();
428 nsLineBox::SetCarriedOutBottomMargin(nsCollapsingMargin aValue
)
430 bool changed
= false;
432 if (!aValue
.IsZero()) {
434 mBlockData
= new ExtraBlockData(mBounds
);
436 changed
= aValue
!= mBlockData
->mCarriedOutBottomMargin
;
437 mBlockData
->mCarriedOutBottomMargin
= aValue
;
439 else if (mBlockData
) {
440 changed
= aValue
!= mBlockData
->mCarriedOutBottomMargin
;
441 mBlockData
->mCarriedOutBottomMargin
= aValue
;
449 nsLineBox::MaybeFreeData()
451 if (mData
&& mData
->mOverflowAreas
== nsOverflowAreas(mBounds
, mBounds
)) {
453 if (mInlineData
->mFloats
.IsEmpty()) {
455 mInlineData
= nullptr;
458 else if (mBlockData
->mCarriedOutBottomMargin
.IsZero()) {
460 mBlockData
= nullptr;
465 // XXX get rid of this???
467 nsLineBox::GetFirstFloat()
469 NS_ABORT_IF_FALSE(IsInline(), "block line can't have floats");
470 return mInlineData
? mInlineData
->mFloats
.Head() : nullptr;
473 // XXX this might be too eager to free memory
475 nsLineBox::FreeFloats(nsFloatCacheFreeList
& aFreeList
)
477 NS_ABORT_IF_FALSE(IsInline(), "block line can't have floats");
478 if (IsInline() && mInlineData
) {
479 if (mInlineData
->mFloats
.NotEmpty()) {
480 aFreeList
.Append(mInlineData
->mFloats
);
487 nsLineBox::AppendFloats(nsFloatCacheFreeList
& aFreeList
)
489 NS_ABORT_IF_FALSE(IsInline(), "block line can't have floats");
491 if (aFreeList
.NotEmpty()) {
493 mInlineData
= new ExtraInlineData(mBounds
);
495 mInlineData
->mFloats
.Append(aFreeList
);
501 nsLineBox::RemoveFloat(nsIFrame
* aFrame
)
503 NS_ABORT_IF_FALSE(IsInline(), "block line can't have floats");
504 if (IsInline() && mInlineData
) {
505 nsFloatCache
* fc
= mInlineData
->mFloats
.Find(aFrame
);
507 // Note: the placeholder is part of the line's child list
508 // and will be removed later.
509 mInlineData
->mFloats
.Remove(fc
);
519 nsLineBox::SetOverflowAreas(const nsOverflowAreas
& aOverflowAreas
)
521 NS_FOR_FRAME_OVERFLOW_TYPES(otype
) {
522 NS_ASSERTION(aOverflowAreas
.Overflow(otype
).width
>= 0,
523 "illegal width for combined area");
524 NS_ASSERTION(aOverflowAreas
.Overflow(otype
).height
>= 0,
525 "illegal height for combined area");
527 if (!aOverflowAreas
.VisualOverflow().IsEqualInterior(mBounds
) ||
528 !aOverflowAreas
.ScrollableOverflow().IsEqualEdges(mBounds
)) {
531 mInlineData
= new ExtraInlineData(mBounds
);
534 mBlockData
= new ExtraBlockData(mBounds
);
537 mData
->mOverflowAreas
= aOverflowAreas
;
540 // Store away new value so that MaybeFreeData compares against
542 mData
->mOverflowAreas
= aOverflowAreas
;
547 //----------------------------------------------------------------------
550 static nsLineBox
* gDummyLines
[1];
552 nsLineIterator::nsLineIterator()
554 mLines
= gDummyLines
;
557 mRightToLeft
= false;
560 nsLineIterator::~nsLineIterator()
562 if (mLines
!= gDummyLines
) {
568 nsLineIterator::DisposeLineIterator()
574 nsLineIterator::Init(nsLineList
& aLines
, bool aRightToLeft
)
576 mRightToLeft
= aRightToLeft
;
579 int32_t numLines
= aLines
.size();
581 // Use gDummyLines so that we don't need null pointer checks in
582 // the accessor methods
583 mLines
= gDummyLines
;
587 // Make a linear array of the lines
588 mLines
= new nsLineBox
*[numLines
];
590 // Use gDummyLines so that we don't need null pointer checks in
591 // the accessor methods
592 mLines
= gDummyLines
;
593 return NS_ERROR_OUT_OF_MEMORY
;
595 nsLineBox
** lp
= mLines
;
596 for (nsLineList::iterator line
= aLines
.begin(), line_end
= aLines
.end() ;
602 mNumLines
= numLines
;
607 nsLineIterator::GetNumLines()
613 nsLineIterator::GetDirection()
619 nsLineIterator::GetLine(int32_t aLineNumber
,
620 nsIFrame
** aFirstFrameOnLine
,
621 int32_t* aNumFramesOnLine
,
623 uint32_t* aLineFlags
)
625 NS_ENSURE_ARG_POINTER(aFirstFrameOnLine
);
626 NS_ENSURE_ARG_POINTER(aNumFramesOnLine
);
627 NS_ENSURE_ARG_POINTER(aLineFlags
);
629 if ((aLineNumber
< 0) || (aLineNumber
>= mNumLines
)) {
630 *aFirstFrameOnLine
= nullptr;
631 *aNumFramesOnLine
= 0;
632 aLineBounds
.SetRect(0, 0, 0, 0);
635 nsLineBox
* line
= mLines
[aLineNumber
];
636 *aFirstFrameOnLine
= line
->mFirstChild
;
637 *aNumFramesOnLine
= line
->GetChildCount();
638 aLineBounds
= line
->mBounds
;
641 if (line
->IsBlock()) {
642 flags
|= NS_LINE_FLAG_IS_BLOCK
;
645 if (line
->HasBreakAfter())
646 flags
|= NS_LINE_FLAG_ENDS_IN_BREAK
;
654 nsLineIterator::FindLineContaining(nsIFrame
* aFrame
, int32_t aStartLine
)
656 NS_PRECONDITION(aStartLine
<= mNumLines
, "Bogus line numbers");
657 int32_t lineNumber
= aStartLine
;
658 while (lineNumber
!= mNumLines
) {
659 nsLineBox
* line
= mLines
[lineNumber
];
660 if (line
->Contains(aFrame
)) {
670 nsLineIterator::CheckLineOrder(int32_t aLine
,
672 nsIFrame
**aFirstVisual
,
673 nsIFrame
**aLastVisual
)
675 NS_ASSERTION (aLine
>= 0 && aLine
< mNumLines
, "aLine out of range!");
676 nsLineBox
* line
= mLines
[aLine
];
678 if (!line
->mFirstChild
) { // empty line
679 *aIsReordered
= false;
680 *aFirstVisual
= nullptr;
681 *aLastVisual
= nullptr;
685 nsIFrame
* leftmostFrame
;
686 nsIFrame
* rightmostFrame
;
687 *aIsReordered
= nsBidiPresUtils::CheckLineOrder(line
->mFirstChild
, line
->GetChildCount(), &leftmostFrame
, &rightmostFrame
);
689 // map leftmost/rightmost to first/last according to paragraph direction
690 *aFirstVisual
= mRightToLeft
? rightmostFrame
: leftmostFrame
;
691 *aLastVisual
= mRightToLeft
? leftmostFrame
: rightmostFrame
;
698 nsLineIterator::FindFrameAt(int32_t aLineNumber
,
700 nsIFrame
** aFrameFound
,
701 bool* aXIsBeforeFirstFrame
,
702 bool* aXIsAfterLastFrame
)
704 NS_PRECONDITION(aFrameFound
&& aXIsBeforeFirstFrame
&& aXIsAfterLastFrame
,
706 if (!aFrameFound
|| !aXIsBeforeFirstFrame
|| !aXIsAfterLastFrame
) {
707 return NS_ERROR_NULL_POINTER
;
709 if ((aLineNumber
< 0) || (aLineNumber
>= mNumLines
)) {
710 return NS_ERROR_INVALID_ARG
;
713 nsLineBox
* line
= mLines
[aLineNumber
];
715 *aFrameFound
= nullptr;
716 *aXIsBeforeFirstFrame
= true;
717 *aXIsAfterLastFrame
= false;
721 if (line
->mBounds
.width
== 0 && line
->mBounds
.height
== 0)
722 return NS_ERROR_FAILURE
;
724 nsIFrame
* frame
= line
->mFirstChild
;
725 nsIFrame
* closestFromLeft
= nullptr;
726 nsIFrame
* closestFromRight
= nullptr;
727 int32_t n
= line
->GetChildCount();
729 nsRect rect
= frame
->GetRect();
730 if (rect
.width
> 0) {
731 // If aX is inside this frame - this is it
732 if (rect
.x
<= aX
&& rect
.XMost() > aX
) {
733 closestFromLeft
= closestFromRight
= frame
;
737 if (!closestFromLeft
||
738 rect
.XMost() > closestFromLeft
->GetRect().XMost())
739 closestFromLeft
= frame
;
742 if (!closestFromRight
||
743 rect
.x
< closestFromRight
->GetRect().x
)
744 closestFromRight
= frame
;
747 frame
= frame
->GetNextSibling();
749 if (!closestFromLeft
&& !closestFromRight
) {
750 // All frames were zero-width. Just take the first one.
751 closestFromLeft
= closestFromRight
= line
->mFirstChild
;
753 *aXIsBeforeFirstFrame
= mRightToLeft
? !closestFromRight
: !closestFromLeft
;
754 *aXIsAfterLastFrame
= mRightToLeft
? !closestFromLeft
: !closestFromRight
;
755 if (closestFromLeft
== closestFromRight
) {
756 *aFrameFound
= closestFromLeft
;
758 else if (!closestFromLeft
) {
759 *aFrameFound
= closestFromRight
;
761 else if (!closestFromRight
) {
762 *aFrameFound
= closestFromLeft
;
764 else { // we're between two frames
765 nscoord delta
= closestFromRight
->GetRect().x
- closestFromLeft
->GetRect().XMost();
766 if (aX
< closestFromLeft
->GetRect().XMost() + delta
/2)
767 *aFrameFound
= closestFromLeft
;
769 *aFrameFound
= closestFromRight
;
775 nsLineIterator::GetNextSiblingOnLine(nsIFrame
*& aFrame
, int32_t aLineNumber
)
777 aFrame
= aFrame
->GetNextSibling();
781 //----------------------------------------------------------------------
783 #ifdef NS_BUILD_REFCNT_LOGGING
784 nsFloatCacheList::nsFloatCacheList() :
787 MOZ_COUNT_CTOR(nsFloatCacheList
);
791 nsFloatCacheList::~nsFloatCacheList()
794 MOZ_COUNT_DTOR(nsFloatCacheList
);
798 nsFloatCacheList::DeleteAll()
800 nsFloatCache
* c
= mHead
;
802 nsFloatCache
* next
= c
->Next();
810 nsFloatCacheList::Tail() const
812 nsFloatCache
* fc
= mHead
;
823 nsFloatCacheList::Append(nsFloatCacheFreeList
& aList
)
825 NS_PRECONDITION(aList
.NotEmpty(), "Appending empty list will fail");
827 nsFloatCache
* tail
= Tail();
829 NS_ASSERTION(!tail
->mNext
, "Bogus!");
830 tail
->mNext
= aList
.mHead
;
833 NS_ASSERTION(!mHead
, "Bogus!");
836 aList
.mHead
= nullptr;
837 aList
.mTail
= nullptr;
841 nsFloatCacheList::Find(nsIFrame
* aOutOfFlowFrame
)
843 nsFloatCache
* fc
= mHead
;
845 if (fc
->mFloat
== aOutOfFlowFrame
) {
854 nsFloatCacheList::RemoveAndReturnPrev(nsFloatCache
* aElement
)
856 nsFloatCache
* fc
= mHead
;
857 nsFloatCache
* prev
= nullptr;
859 if (fc
== aElement
) {
861 prev
->mNext
= fc
->mNext
;
873 //----------------------------------------------------------------------
875 #ifdef NS_BUILD_REFCNT_LOGGING
876 nsFloatCacheFreeList::nsFloatCacheFreeList() :
879 MOZ_COUNT_CTOR(nsFloatCacheFreeList
);
882 nsFloatCacheFreeList::~nsFloatCacheFreeList()
884 MOZ_COUNT_DTOR(nsFloatCacheFreeList
);
889 nsFloatCacheFreeList::Append(nsFloatCacheList
& aList
)
891 NS_PRECONDITION(aList
.NotEmpty(), "Appending empty list will fail");
894 NS_ASSERTION(!mTail
->mNext
, "Bogus");
895 mTail
->mNext
= aList
.mHead
;
898 NS_ASSERTION(!mHead
, "Bogus");
901 mTail
= aList
.Tail();
902 aList
.mHead
= nullptr;
906 nsFloatCacheFreeList::Remove(nsFloatCache
* aElement
)
908 nsFloatCache
* prev
= nsFloatCacheList::RemoveAndReturnPrev(aElement
);
909 if (mTail
== aElement
) {
915 nsFloatCacheFreeList::DeleteAll()
917 nsFloatCacheList::DeleteAll();
922 nsFloatCacheFreeList::Alloc(nsIFrame
* aFloat
)
924 NS_PRECONDITION(aFloat
->GetStateBits() & NS_FRAME_OUT_OF_FLOW
,
925 "This is a float cache, why isn't the frame out-of-flow?");
926 nsFloatCache
* fc
= mHead
;
928 if (mHead
== mTail
) {
929 mHead
= mTail
= nullptr;
937 fc
= new nsFloatCache();
944 nsFloatCacheFreeList::Append(nsFloatCache
* aFloat
)
946 NS_ASSERTION(!aFloat
->mNext
, "Bogus!");
947 aFloat
->mNext
= nullptr;
949 NS_ASSERTION(!mTail
->mNext
, "Bogus!");
950 mTail
->mNext
= aFloat
;
954 NS_ASSERTION(!mHead
, "Bogus!");
955 mHead
= mTail
= aFloat
;
959 //----------------------------------------------------------------------
961 nsFloatCache::nsFloatCache()
965 MOZ_COUNT_CTOR(nsFloatCache
);
968 #ifdef NS_BUILD_REFCNT_LOGGING
969 nsFloatCache::~nsFloatCache()
971 MOZ_COUNT_DTOR(nsFloatCache
);