LCOV - code coverage report
Current view: top level - layout/generic - nsLineBox.h (source / functions) Hit Total Coverage
Test: output.info Lines: 255 444 57.4 %
Date: 2017-07-14 16:53:18 Functions: 84 132 63.6 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : /* representation of one line within a block frame, a CSS line box */
       8             : 
       9             : #ifndef nsLineBox_h___
      10             : #define nsLineBox_h___
      11             : 
      12             : #include "mozilla/Attributes.h"
      13             : #include "mozilla/Likely.h"
      14             : 
      15             : #include "nsILineIterator.h"
      16             : #include "nsIFrame.h"
      17             : #include <algorithm>
      18             : 
      19             : class nsLineBox;
      20             : class nsFloatCache;
      21             : class nsFloatCacheList;
      22             : class nsFloatCacheFreeList;
      23             : 
      24             : // State cached after reflowing a float. This state is used during
      25             : // incremental reflow when we avoid reflowing a float.
      26             : class nsFloatCache {
      27             : public:
      28             :   nsFloatCache();
      29             : #ifdef NS_BUILD_REFCNT_LOGGING
      30             :   ~nsFloatCache();
      31             : #else
      32             :   ~nsFloatCache() { }
      33             : #endif
      34             : 
      35           0 :   nsFloatCache* Next() const { return mNext; }
      36             : 
      37             :   nsIFrame* mFloat;                     // floating frame
      38             : 
      39             : protected:
      40             :   nsFloatCache* mNext;
      41             : 
      42             :   friend class nsFloatCacheList;
      43             :   friend class nsFloatCacheFreeList;
      44             : };
      45             : 
      46             : //----------------------------------------
      47             : 
      48             : class nsFloatCacheList {
      49             : public:
      50             : #ifdef NS_BUILD_REFCNT_LOGGING
      51             :   nsFloatCacheList();
      52             : #else
      53             :   nsFloatCacheList() : mHead(nullptr) { }
      54             : #endif
      55             :   ~nsFloatCacheList();
      56             : 
      57           0 :   bool IsEmpty() const {
      58           0 :     return nullptr == mHead;
      59             :   }
      60             : 
      61         158 :   bool NotEmpty() const {
      62         158 :     return nullptr != mHead;
      63             :   }
      64             : 
      65           0 :   nsFloatCache* Head() const {
      66           0 :     return mHead;
      67             :   }
      68             : 
      69             :   nsFloatCache* Tail() const;
      70             : 
      71             :   void DeleteAll();
      72             : 
      73             :   nsFloatCache* Find(nsIFrame* aOutOfFlowFrame);
      74             : 
      75             :   // Remove a nsFloatCache from this list.  Deleting this nsFloatCache
      76             :   // becomes the caller's responsibility.
      77           0 :   void Remove(nsFloatCache* aElement) { RemoveAndReturnPrev(aElement); }
      78             : 
      79             :   // Steal away aList's nsFloatCache objects and put them in this
      80             :   // list.  aList must not be empty.
      81             :   void Append(nsFloatCacheFreeList& aList);
      82             : 
      83             : protected:
      84             :   nsFloatCache* mHead;
      85             : 
      86             :   // Remove a nsFloatCache from this list.  Deleting this nsFloatCache
      87             :   // becomes the caller's responsibility. Returns the nsFloatCache that was
      88             :   // before aElement, or nullptr if aElement was the first.
      89             :   nsFloatCache* RemoveAndReturnPrev(nsFloatCache* aElement);
      90             : 
      91             :   friend class nsFloatCacheFreeList;
      92             : };
      93             : 
      94             : //---------------------------------------
      95             : // Like nsFloatCacheList, but with fast access to the tail
      96             : 
      97             : class nsFloatCacheFreeList : private nsFloatCacheList {
      98             : public:
      99             : #ifdef NS_BUILD_REFCNT_LOGGING
     100             :   nsFloatCacheFreeList();
     101             :   ~nsFloatCacheFreeList();
     102             : #else
     103             :   nsFloatCacheFreeList() : mTail(nullptr) { }
     104             :   ~nsFloatCacheFreeList() { }
     105             : #endif
     106             : 
     107             :   // Reimplement trivial functions
     108           0 :   bool IsEmpty() const {
     109           0 :     return nullptr == mHead;
     110             :   }
     111             : 
     112           0 :   nsFloatCache* Head() const {
     113           0 :     return mHead;
     114             :   }
     115             : 
     116           0 :   nsFloatCache* Tail() const {
     117           0 :     return mTail;
     118             :   }
     119             : 
     120         150 :   bool NotEmpty() const {
     121         150 :     return nullptr != mHead;
     122             :   }
     123             : 
     124             :   void DeleteAll();
     125             : 
     126             :   // Steal away aList's nsFloatCache objects and put them on this
     127             :   // free-list.  aList must not be empty.
     128             :   void Append(nsFloatCacheList& aList);
     129             : 
     130             :   void Append(nsFloatCache* aFloatCache);
     131             : 
     132             :   void Remove(nsFloatCache* aElement);
     133             : 
     134             :   // Remove an nsFloatCache object from this list and return it, or create
     135             :   // a new one if this one is empty; Set its mFloat to aFloat.
     136             :   nsFloatCache* Alloc(nsIFrame* aFloat);
     137             : 
     138             : protected:
     139             :   nsFloatCache* mTail;
     140             : 
     141             :   friend class nsFloatCacheList;
     142             : };
     143             : 
     144             : //----------------------------------------------------------------------
     145             : 
     146             : #define LINE_MAX_CHILD_COUNT INT32_MAX
     147             : 
     148             : /**
     149             :  * Function to create a line box and initialize it with a single frame.
     150             :  * The allocation is infallible.
     151             :  * If the frame was moved from another line then you're responsible
     152             :  * for notifying that line using NoteFrameRemoved().  Alternatively,
     153             :  * it's better to use the next function that does that for you in an
     154             :  * optimal way.
     155             :  */
     156             : nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
     157             :                          bool aIsBlock);
     158             : /**
     159             :  * Function to create a line box and initialize it with aCount frames
     160             :  * that are currently on aFromLine.  The allocation is infallible.
     161             :  */
     162             : nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
     163             :                          nsIFrame* aFrame, int32_t aCount);
     164             : 
     165             : class nsLineList;
     166             : 
     167             : // don't use the following names outside of this file.  Instead, use
     168             : // nsLineList::iterator, etc.  These are just here to allow them to
     169             : // be specified as parameters to methods of nsLineBox.
     170             : class nsLineList_iterator;
     171             : class nsLineList_const_iterator;
     172             : class nsLineList_reverse_iterator;
     173             : class nsLineList_const_reverse_iterator;
     174             : 
     175             : /**
     176             :  * Users must have the class that is to be part of the list inherit
     177             :  * from nsLineLink.  If they want to be efficient, it should be the
     178             :  * first base class.  (This was originally nsCLink in a templatized
     179             :  * nsCList, but it's still useful separately.)
     180             :  */
     181             : 
     182          33 : class nsLineLink {
     183             : 
     184             :   public:
     185             :     friend class nsLineList;
     186             :     friend class nsLineList_iterator;
     187             :     friend class nsLineList_reverse_iterator;
     188             :     friend class nsLineList_const_iterator;
     189             :     friend class nsLineList_const_reverse_iterator;
     190             : 
     191             :   private:
     192             :     nsLineLink *_mNext; // or head
     193             :     nsLineLink *_mPrev; // or tail
     194             : 
     195             : };
     196             : 
     197             : 
     198             : /**
     199             :  * The nsLineBox class represents a horizontal line of frames. It contains
     200             :  * enough state to support incremental reflow of the frames, event handling
     201             :  * for the frames, and rendering of the frames.
     202             :  */
     203             : class nsLineBox final : public nsLineLink {
     204             : private:
     205             :   nsLineBox(nsIFrame* aFrame, int32_t aCount, bool aIsBlock);
     206             :   ~nsLineBox();
     207             : 
     208             :   // Infallible overloaded new operator. Uses an arena (which comes from the
     209             :   // presShell) to perform the allocation.
     210             :   void* operator new(size_t sz, nsIPresShell* aPresShell);
     211             :   void operator delete(void* aPtr, size_t sz) = delete;
     212             : 
     213             : public:
     214             :   // Use these functions to allocate and destroy line boxes
     215             :   friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
     216             :                                   bool aIsBlock);
     217             :   friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
     218             :                                   nsIFrame* aFrame, int32_t aCount);
     219             :   void Destroy(nsIPresShell* aPresShell);
     220             : 
     221             :   // mBlock bit
     222        1654 :   bool IsBlock() const {
     223        1654 :     return mFlags.mBlock;
     224             :   }
     225        1077 :   bool IsInline() const {
     226        1077 :     return !mFlags.mBlock;
     227             :   }
     228             : 
     229             :   // mDirty bit
     230         149 :   void MarkDirty() {
     231         149 :     mFlags.mDirty = 1;
     232         149 :   }
     233          85 :   void ClearDirty() {
     234          85 :     mFlags.mDirty = 0;
     235          85 :   }
     236         972 :   bool IsDirty() const {
     237         972 :     return mFlags.mDirty;
     238             :   }
     239             : 
     240             :   // mPreviousMarginDirty bit
     241           0 :   void MarkPreviousMarginDirty() {
     242           0 :     mFlags.mPreviousMarginDirty = 1;
     243           0 :   }
     244           0 :   void ClearPreviousMarginDirty() {
     245           0 :     mFlags.mPreviousMarginDirty = 0;
     246           0 :   }
     247         151 :   bool IsPreviousMarginDirty() const {
     248         151 :     return mFlags.mPreviousMarginDirty;
     249             :   }
     250             : 
     251             :   // mHasClearance bit
     252           0 :   void SetHasClearance() {
     253           0 :     mFlags.mHasClearance = 1;
     254           0 :   }
     255          10 :   void ClearHasClearance() {
     256          10 :     mFlags.mHasClearance = 0;
     257          10 :   }
     258          11 :   bool HasClearance() const {
     259          11 :     return mFlags.mHasClearance;
     260             :   }
     261             : 
     262             :   // mImpactedByFloat bit
     263          85 :   void SetLineIsImpactedByFloat(bool aValue) {
     264          85 :     mFlags.mImpactedByFloat = aValue;
     265          85 :   }
     266           0 :   bool IsImpactedByFloat() const {
     267           0 :     return mFlags.mImpactedByFloat;
     268             :   }
     269             : 
     270             :   // mLineWrapped bit
     271          75 :   void SetLineWrapped(bool aOn) {
     272          75 :     mFlags.mLineWrapped = aOn;
     273          75 :   }
     274          75 :   bool IsLineWrapped() const {
     275          75 :     return mFlags.mLineWrapped;
     276             :   }
     277             : 
     278             :   // mInvalidateTextRuns bit
     279          33 :   void SetInvalidateTextRuns(bool aOn) {
     280          33 :     mFlags.mInvalidateTextRuns = aOn;
     281          33 :   }
     282          41 :   bool GetInvalidateTextRuns() const {
     283          41 :     return mFlags.mInvalidateTextRuns;
     284             :   }
     285             : 
     286             :   // mResizeReflowOptimizationDisabled bit
     287           4 :   void DisableResizeReflowOptimization() {
     288           4 :     mFlags.mResizeReflowOptimizationDisabled = true;
     289           4 :   }
     290          75 :   void EnableResizeReflowOptimization() {
     291          75 :     mFlags.mResizeReflowOptimizationDisabled = false;
     292          75 :   }
     293           0 :   bool ResizeReflowOptimizationDisabled() const {
     294           0 :     return mFlags.mResizeReflowOptimizationDisabled;
     295             :   }
     296             : 
     297             :   // mHasBullet bit
     298           0 :   void SetHasBullet() {
     299           0 :     mFlags.mHasBullet = true;
     300           0 :     InvalidateCachedIsEmpty();
     301           0 :   }
     302          75 :   void ClearHasBullet() {
     303          75 :     mFlags.mHasBullet = false;
     304          75 :     InvalidateCachedIsEmpty();
     305          75 :   }
     306         140 :   bool HasBullet() const {
     307         140 :     return mFlags.mHasBullet;
     308             :   }
     309             : 
     310             :   // mHadFloatPushed bit
     311           0 :   void SetHadFloatPushed() {
     312           0 :     mFlags.mHadFloatPushed = true;
     313           0 :   }
     314          85 :   void ClearHadFloatPushed() {
     315          85 :     mFlags.mHadFloatPushed = false;
     316          85 :   }
     317           0 :   bool HadFloatPushed() const {
     318           0 :     return mFlags.mHadFloatPushed;
     319             :   }
     320             : 
     321             : private:
     322             :   // Add a hash table for fast lookup when the line has more frames than this.
     323             :   static const uint32_t kMinChildCountForHashtable = 200;
     324             : 
     325             :   /**
     326             :    * Take ownership of aFromLine's hash table and remove the frames that
     327             :    * stay on aFromLine from it, i.e. aFromLineNewCount frames starting with
     328             :    * mFirstChild.  This method is used to optimize moving a large number
     329             :    * of frames from one line to the next.
     330             :    */
     331             :   void StealHashTableFrom(nsLineBox* aFromLine, uint32_t aFromLineNewCount);
     332             : 
     333             :   /**
     334             :    * Does the equivalent of this->NoteFrameAdded and aFromLine->NoteFrameRemoved
     335             :    * for each frame on this line, but in a optimized way.
     336             :    */
     337             :   void NoteFramesMovedFrom(nsLineBox* aFromLine);
     338             : 
     339           0 :   void SwitchToHashtable()
     340             :   {
     341           0 :     MOZ_ASSERT(!mFlags.mHasHashedFrames);
     342           0 :     uint32_t count = GetChildCount();
     343           0 :     mFlags.mHasHashedFrames = 1;
     344           0 :     uint32_t minLength = std::max(kMinChildCountForHashtable,
     345           0 :                                   uint32_t(PLDHashTable::kDefaultInitialLength));
     346           0 :     mFrames = new nsTHashtable< nsPtrHashKey<nsIFrame> >(std::max(count, minLength));
     347           0 :     for (nsIFrame* f = mFirstChild; count-- > 0; f = f->GetNextSibling()) {
     348           0 :       mFrames->PutEntry(f);
     349             :     }
     350           0 :   }
     351           0 :   void SwitchToCounter() {
     352           0 :     MOZ_ASSERT(mFlags.mHasHashedFrames);
     353           0 :     uint32_t count = GetChildCount();
     354           0 :     delete mFrames;
     355           0 :     mFlags.mHasHashedFrames = 0;
     356           0 :     mChildCount = count;
     357           0 :   }
     358             : 
     359             : public:
     360         721 :   int32_t GetChildCount() const {
     361         721 :     return MOZ_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Count() : mChildCount;
     362             :   }
     363             : 
     364             :   /**
     365             :    * Register that aFrame is now on this line.
     366             :    */
     367           0 :   void NoteFrameAdded(nsIFrame* aFrame) {
     368           0 :     if (MOZ_UNLIKELY(mFlags.mHasHashedFrames)) {
     369           0 :       mFrames->PutEntry(aFrame);
     370             :     } else {
     371           0 :       if (++mChildCount >= kMinChildCountForHashtable) {
     372           0 :         SwitchToHashtable();
     373             :       }
     374             :     }
     375           0 :   }
     376             : 
     377             :   /**
     378             :    * Register that aFrame is not on this line anymore.
     379             :    */
     380          12 :   void NoteFrameRemoved(nsIFrame* aFrame) {
     381          12 :     MOZ_ASSERT(GetChildCount() > 0);
     382          12 :     if (MOZ_UNLIKELY(mFlags.mHasHashedFrames)) {
     383           0 :       mFrames->RemoveEntry(aFrame);
     384           0 :       if (mFrames->Count() < kMinChildCountForHashtable) {
     385           0 :         SwitchToCounter();
     386             :       }
     387             :     } else {
     388          12 :       --mChildCount;
     389             :     }
     390          12 :   }
     391             : 
     392             :   // mBreakType value
     393             :   // Break information is applied *before* the line if the line is a block,
     394             :   // or *after* the line if the line is an inline. Confusing, I know, but
     395             :   // using different names should help.
     396             :   using StyleClear = mozilla::StyleClear;
     397             :   bool HasBreakBefore() const {
     398             :     return IsBlock() && StyleClear::None != BreakType();
     399             :   }
     400          10 :   void SetBreakTypeBefore(StyleClear aBreakType) {
     401          10 :     MOZ_ASSERT(IsBlock(), "Only blocks have break-before");
     402          10 :     MOZ_ASSERT(aBreakType == StyleClear::None ||
     403             :                aBreakType == StyleClear::Left ||
     404             :                aBreakType == StyleClear::Right ||
     405             :                aBreakType == StyleClear::Both,
     406             :                "Only float break types are allowed before a line");
     407          10 :     mFlags.mBreakType = aBreakType;
     408          10 :   }
     409          76 :   StyleClear GetBreakTypeBefore() const {
     410          76 :     return IsBlock() ? BreakType() : StyleClear::None;
     411             :   }
     412             : 
     413           0 :   bool HasBreakAfter() const {
     414           0 :     return !IsBlock() && StyleClear::None != BreakType();
     415             :   }
     416          84 :   void SetBreakTypeAfter(StyleClear aBreakType) {
     417          84 :     MOZ_ASSERT(!IsBlock(), "Only inlines have break-after");
     418          84 :     mFlags.mBreakType = aBreakType;
     419          84 :   }
     420         367 :   bool HasFloatBreakAfter() const {
     421         724 :     return !IsBlock() &&
     422         714 :            (StyleClear::Left == BreakType() ||
     423         714 :             StyleClear::Right == BreakType() ||
     424         724 :             StyleClear::Both == BreakType());
     425             :   }
     426           0 :   StyleClear GetBreakTypeAfter() const {
     427           0 :     return !IsBlock() ? BreakType() : StyleClear::None;
     428             :   }
     429             : 
     430             :   // mCarriedOutBEndMargin value
     431             :   nsCollapsingMargin GetCarriedOutBEndMargin() const;
     432             :   // Returns true if the margin changed
     433             :   bool SetCarriedOutBEndMargin(nsCollapsingMargin aValue);
     434             : 
     435             :   // mFloats
     436         485 :   bool HasFloats() const {
     437         485 :     return (IsInline() && mInlineData) && mInlineData->mFloats.NotEmpty();
     438             :   }
     439             :   nsFloatCache* GetFirstFloat();
     440             :   void FreeFloats(nsFloatCacheFreeList& aFreeList);
     441             :   void AppendFloats(nsFloatCacheFreeList& aFreeList);
     442             :   bool RemoveFloat(nsIFrame* aFrame);
     443             : 
     444             :   // Combined area is the area of the line that should influence the
     445             :   // overflow area of its parent block.  The combined area should be
     446             :   // used for painting-related things, but should never be used for
     447             :   // layout (except for handling of 'overflow').
     448             :   void SetOverflowAreas(const nsOverflowAreas& aOverflowAreas);
     449           0 :   mozilla::LogicalRect GetOverflowArea(nsOverflowType aType,
     450             :                                        mozilla::WritingMode aWM,
     451             :                                        const nsSize& aContainerSize)
     452             :   {
     453           0 :     return mozilla::LogicalRect(aWM, GetOverflowArea(aType), aContainerSize);
     454             :   }
     455         197 :   nsRect GetOverflowArea(nsOverflowType aType) {
     456         197 :     return mData ? mData->mOverflowAreas.Overflow(aType) : GetPhysicalBounds();
     457             :   }
     458         151 :   nsOverflowAreas GetOverflowAreas() {
     459         151 :     if (mData) {
     460          62 :       return mData->mOverflowAreas;
     461             :     }
     462         178 :     nsRect bounds = GetPhysicalBounds();
     463          89 :     return nsOverflowAreas(bounds, bounds);
     464             :   }
     465         197 :   nsRect GetVisualOverflowArea()
     466         197 :     { return GetOverflowArea(eVisualOverflow); }
     467           0 :   nsRect GetScrollableOverflowArea()
     468           0 :     { return GetOverflowArea(eScrollableOverflow); }
     469             : 
     470           0 :   void SlideBy(nscoord aDBCoord, const nsSize& aContainerSize) {
     471           0 :     NS_ASSERTION(aContainerSize == mContainerSize ||
     472             :                  mContainerSize == nsSize(-1, -1),
     473             :                  "container size doesn't match");
     474           0 :     mContainerSize = aContainerSize;
     475           0 :     mBounds.BStart(mWritingMode) += aDBCoord;
     476           0 :     if (mData) {
     477             :       // Use a null containerSize to convert vector from logical to physical.
     478           0 :       const nsSize nullContainerSize;
     479             :       nsPoint physicalDelta =
     480           0 :         mozilla::LogicalPoint(mWritingMode, 0, aDBCoord).
     481           0 :           GetPhysicalPoint(mWritingMode, nullContainerSize);
     482           0 :       NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
     483           0 :         mData->mOverflowAreas.Overflow(otype) += physicalDelta;
     484             :       }
     485             :     }
     486           0 :   }
     487             : 
     488             :   // Container-size for the line is changing (and therefore if writing mode
     489             :   // was vertical-rl, the line will move physically; this is like SlideBy,
     490             :   // but it is the container size instead of the line's own logical coord
     491             :   // that is changing.
     492           0 :   nsSize UpdateContainerSize(const nsSize aNewContainerSize)
     493             :   {
     494           0 :     NS_ASSERTION(mContainerSize != nsSize(-1, -1), "container size not set");
     495           0 :     nsSize delta = mContainerSize - aNewContainerSize;
     496           0 :     mContainerSize = aNewContainerSize;
     497             :     // this has a physical-coordinate effect only in vertical-rl mode
     498           0 :     if (mWritingMode.IsVerticalRL() && mData) {
     499           0 :       nsPoint physicalDelta(-delta.width, 0);
     500           0 :       NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
     501           0 :         mData->mOverflowAreas.Overflow(otype) += physicalDelta;
     502             :       }
     503             :     }
     504           0 :     return delta;
     505             :   }
     506             : 
     507           0 :   void IndentBy(nscoord aDICoord, const nsSize& aContainerSize) {
     508           0 :     NS_ASSERTION(aContainerSize == mContainerSize ||
     509             :                  mContainerSize == nsSize(-1, -1),
     510             :                  "container size doesn't match");
     511           0 :     mContainerSize = aContainerSize;
     512           0 :     mBounds.IStart(mWritingMode) += aDICoord;
     513           0 :   }
     514             : 
     515           0 :   void ExpandBy(nscoord aDISize, const nsSize& aContainerSize) {
     516           0 :     NS_ASSERTION(aContainerSize == mContainerSize ||
     517             :                  mContainerSize == nsSize(-1, -1),
     518             :                  "container size doesn't match");
     519           0 :     mContainerSize = aContainerSize;
     520           0 :     mBounds.ISize(mWritingMode) += aDISize;
     521           0 :   }
     522             : 
     523             :   /**
     524             :    * The logical ascent (distance from block-start to baseline) of the
     525             :    * linebox is the logical ascent of the anonymous inline box (for
     526             :    * which we don't actually create a frame) that wraps all the
     527             :    * consecutive inline children of a block.
     528             :    *
     529             :    * This is currently unused for block lines.
     530             :    */
     531           5 :   nscoord GetLogicalAscent() const { return mAscent; }
     532          75 :   void SetLogicalAscent(nscoord aAscent) { mAscent = aAscent; }
     533             : 
     534         454 :   nscoord BStart() const {
     535         454 :     return mBounds.BStart(mWritingMode);
     536             :   }
     537         192 :   nscoord BSize() const {
     538         192 :     return mBounds.BSize(mWritingMode);
     539             :   }
     540         451 :   nscoord BEnd() const {
     541         451 :     return mBounds.BEnd(mWritingMode);
     542             :   }
     543          85 :   nscoord IStart() const {
     544          85 :     return mBounds.IStart(mWritingMode);
     545             :   }
     546         129 :   nscoord ISize() const {
     547         129 :     return mBounds.ISize(mWritingMode);
     548             :   }
     549           0 :   nscoord IEnd() const {
     550           0 :     return mBounds.IEnd(mWritingMode);
     551             :   }
     552           0 :   void SetBoundsEmpty() {
     553           0 :     mBounds.IStart(mWritingMode) = 0;
     554           0 :     mBounds.ISize(mWritingMode) = 0;
     555           0 :     mBounds.BStart(mWritingMode) = 0;
     556           0 :     mBounds.BSize(mWritingMode) = 0;
     557           0 :   }
     558             : 
     559             :   static void DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines,
     560             :                              nsIFrame* aDestructRoot, nsFrameList* aFrames);
     561             : 
     562             :   // search from end to beginning of [aBegin, aEnd)
     563             :   // Returns true if it found the line and false if not.
     564             :   // Moves aEnd as it searches so that aEnd points to the resulting line.
     565             :   // aLastFrameBeforeEnd is the last frame before aEnd (so if aEnd is
     566             :   // the end of the line list, it's just the last frame in the frame
     567             :   // list).
     568             :   static bool RFindLineContaining(nsIFrame* aFrame,
     569             :                                     const nsLineList_iterator& aBegin,
     570             :                                     nsLineList_iterator& aEnd,
     571             :                                     nsIFrame* aLastFrameBeforeEnd,
     572             :                                     int32_t* aFrameIndexInLine);
     573             : 
     574             : #ifdef DEBUG_FRAME_DUMP
     575             :   const char* BreakTypeToString(StyleClear aBreakType) const;
     576             :   char* StateToString(char* aBuf, int32_t aBufSize) const;
     577             : 
     578             :   void List(FILE* out, int32_t aIndent, uint32_t aFlags = 0) const;
     579             :   void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const;
     580             :   nsIFrame* LastChild() const;
     581             : #endif
     582             : 
     583             : private:
     584             :   int32_t IndexOf(nsIFrame* aFrame) const;
     585             : public:
     586             : 
     587          12 :   bool Contains(nsIFrame* aFrame) const {
     588          24 :     return MOZ_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Contains(aFrame)
     589          24 :                                                 : IndexOf(aFrame) >= 0;
     590             :   }
     591             : 
     592             :   // whether the line box is "logically" empty (just like nsIFrame::IsEmpty)
     593             :   bool IsEmpty() const;
     594             : 
     595             :   // Call this only while in Reflow() for the block the line belongs
     596             :   // to, only between reflowing the line (or sliding it, if we skip
     597             :   // reflowing it) and the end of reflowing the block.
     598             :   bool CachedIsEmpty();
     599             : 
     600         160 :   void InvalidateCachedIsEmpty() {
     601         160 :     mFlags.mEmptyCacheValid = false;
     602         160 :   }
     603             : 
     604             :   // For debugging purposes
     605             :   bool IsValidCachedIsEmpty() {
     606             :     return mFlags.mEmptyCacheValid;
     607             :   }
     608             : 
     609             : #ifdef DEBUG
     610             :   static int32_t GetCtorCount();
     611             : #endif
     612             : 
     613             :   nsIFrame* mFirstChild;
     614             : 
     615             :   mozilla::WritingMode mWritingMode;
     616             : 
     617             :   // Physical size. Use only for physical <-> logical coordinate conversion.
     618             :   nsSize mContainerSize;
     619             : 
     620             :  private:
     621             :   mozilla::LogicalRect mBounds;
     622             : 
     623             :  public:
     624           0 :   const mozilla::LogicalRect& GetBounds() { return mBounds; }
     625         323 :   nsRect GetPhysicalBounds() const
     626             :   {
     627         323 :     if (mBounds.IsAllZero()) {
     628          47 :       return nsRect(0, 0, 0, 0);
     629             :     }
     630             : 
     631         276 :     NS_ASSERTION(mContainerSize != nsSize(-1, -1),
     632             :                  "mContainerSize not initialized");
     633         276 :     return mBounds.GetPhysicalRect(mWritingMode, mContainerSize);
     634             :   }
     635          85 :   void SetBounds(mozilla::WritingMode aWritingMode,
     636             :                  nscoord aIStart, nscoord aBStart,
     637             :                  nscoord aISize, nscoord aBSize,
     638             :                  const nsSize& aContainerSize)
     639             :   {
     640          85 :     mWritingMode = aWritingMode;
     641          85 :     mContainerSize = aContainerSize;
     642          85 :     mBounds = mozilla::LogicalRect(aWritingMode, aIStart, aBStart,
     643             :                                    aISize, aBSize);
     644          85 :   }
     645             :   void SetBounds(mozilla::WritingMode aWritingMode,
     646             :                  nsRect aRect, const nsSize& aContainerSize)
     647             :   {
     648             :     mWritingMode = aWritingMode;
     649             :     mContainerSize = aContainerSize;
     650             :     mBounds = mozilla::LogicalRect(aWritingMode, aRect, aContainerSize);
     651             :   }
     652             : 
     653             :   // mFlags.mHasHashedFrames says which one to use
     654             :   union {
     655             :     nsTHashtable< nsPtrHashKey<nsIFrame> >* mFrames;
     656             :     uint32_t mChildCount;
     657             :   };
     658             : 
     659             :   struct FlagBits {
     660             :     bool mDirty : 1;
     661             :     bool mPreviousMarginDirty : 1;
     662             :     bool mHasClearance : 1;
     663             :     bool mBlock : 1;
     664             :     bool mImpactedByFloat : 1;
     665             :     bool mLineWrapped: 1;
     666             :     bool mInvalidateTextRuns : 1;
     667             :     // default 0 = means that the opt potentially applies to this line.
     668             :     // 1 = never skip reflowing this line for a resize reflow
     669             :     bool mResizeReflowOptimizationDisabled: 1;
     670             :     bool mEmptyCacheValid: 1;
     671             :     bool mEmptyCacheState: 1;
     672             :     // mHasBullet indicates that this is an inline line whose block's
     673             :     // bullet is adjacent to this line and non-empty.
     674             :     bool mHasBullet : 1;
     675             :     // Indicates that this line *may* have a placeholder for a float
     676             :     // that was pushed to a later column or page.
     677             :     bool mHadFloatPushed : 1;
     678             :     bool mHasHashedFrames: 1;
     679             :     StyleClear mBreakType;
     680             :   };
     681             : 
     682           5 :   struct ExtraData {
     683          11 :     explicit ExtraData(const nsRect& aBounds) : mOverflowAreas(aBounds, aBounds) {
     684          11 :     }
     685             :     nsOverflowAreas mOverflowAreas;
     686             :   };
     687             : 
     688           0 :   struct ExtraBlockData : public ExtraData {
     689           2 :     explicit ExtraBlockData(const nsRect& aBounds)
     690           2 :       : ExtraData(aBounds),
     691           2 :         mCarriedOutBEndMargin()
     692             :     {
     693           2 :     }
     694             :     nsCollapsingMargin mCarriedOutBEndMargin;
     695             :   };
     696             : 
     697           5 :   struct ExtraInlineData : public ExtraData {
     698           9 :     explicit ExtraInlineData(const nsRect& aBounds)
     699           9 :       : ExtraData(aBounds)
     700             :       , mFloatEdgeIStart(nscoord_MIN)
     701           9 :       , mFloatEdgeIEnd(nscoord_MIN)
     702           9 :     {}
     703             :     nscoord mFloatEdgeIStart;
     704             :     nscoord mFloatEdgeIEnd;
     705             :     nsFloatCacheList mFloats;
     706             :   };
     707             : 
     708           0 :   bool GetFloatEdges(nscoord* aStart, nscoord* aEnd) const {
     709           0 :     MOZ_ASSERT(IsInline(), "block line can't have float edges");
     710           0 :     if (mInlineData && mInlineData->mFloatEdgeIStart != nscoord_MIN) {
     711           0 :       *aStart = mInlineData->mFloatEdgeIStart;
     712           0 :       *aEnd = mInlineData->mFloatEdgeIEnd;
     713           0 :       return true;
     714             :     }
     715           0 :     return false;
     716             :   }
     717             :   void SetFloatEdges(nscoord aStart, nscoord aEnd);
     718             :   void ClearFloatEdges();
     719             : 
     720             : protected:
     721             :   nscoord mAscent;           // see |SetAscent| / |GetAscent|
     722             :   static_assert(sizeof(FlagBits) <= sizeof(uint32_t),
     723             :                 "size of FlagBits should not be larger than size of uint32_t");
     724             :   union {
     725             :     uint32_t mAllFlags;
     726             :     FlagBits mFlags;
     727             :   };
     728             : 
     729        1081 :   StyleClear BreakType() const {
     730        1081 :     return mFlags.mBreakType;
     731             :   };
     732             : 
     733             :   union {
     734             :     ExtraData* mData;
     735             :     ExtraBlockData* mBlockData;
     736             :     ExtraInlineData* mInlineData;
     737             :   };
     738             : 
     739             :   void Cleanup();
     740             :   void MaybeFreeData();
     741             : };
     742             : 
     743             : /**
     744             :  * A linked list type where the items in the list must inherit from
     745             :  * a link type to fuse allocations.
     746             :  *
     747             :  * API heavily based on the |list| class in the C++ standard.
     748             :  */
     749             : 
     750             : class nsLineList_iterator {
     751             :   public:
     752             :     friend class nsLineList;
     753             :     friend class nsLineList_reverse_iterator;
     754             :     friend class nsLineList_const_iterator;
     755             :     friend class nsLineList_const_reverse_iterator;
     756             : 
     757             :     typedef nsLineList_iterator         iterator_self_type;
     758             :     typedef nsLineList_reverse_iterator iterator_reverse_type;
     759             : 
     760             :     typedef nsLineBox&                  reference;
     761             :     typedef const nsLineBox&            const_reference;
     762             : 
     763             :     typedef nsLineBox*                  pointer;
     764             :     typedef const nsLineBox*            const_pointer;
     765             : 
     766             :     typedef uint32_t                    size_type;
     767             :     typedef int32_t                     difference_type;
     768             : 
     769             :     typedef nsLineLink                  link_type;
     770             : 
     771             : #ifdef DEBUG
     772        2823 :     nsLineList_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
     773             : #else
     774             :     // Auto generated default constructor OK.
     775             : #endif
     776             :     // Auto generated copy-constructor OK.
     777             : 
     778             :     inline iterator_self_type&
     779             :         operator=(const iterator_self_type& aOther);
     780             :     inline iterator_self_type&
     781             :         operator=(const iterator_reverse_type& aOther);
     782             : 
     783         967 :     iterator_self_type& operator++()
     784             :     {
     785         967 :       mCurrent = mCurrent->_mNext;
     786         967 :       return *this;
     787             :     }
     788             : 
     789           0 :     iterator_self_type operator++(int)
     790             :     {
     791           0 :       iterator_self_type rv(*this);
     792           0 :       mCurrent = mCurrent->_mNext;
     793           0 :       return rv;
     794             :     }
     795             : 
     796          82 :     iterator_self_type& operator--()
     797             :     {
     798          82 :       mCurrent = mCurrent->_mPrev;
     799          82 :       return *this;
     800             :     }
     801             : 
     802           0 :     iterator_self_type operator--(int)
     803             :     {
     804           0 :       iterator_self_type rv(*this);
     805           0 :       mCurrent = mCurrent->_mPrev;
     806           0 :       return rv;
     807             :     }
     808             : 
     809             :     reference operator*()
     810             :     {
     811             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     812             :       return *static_cast<pointer>(mCurrent);
     813             :     }
     814             : 
     815        7259 :     pointer operator->()
     816             :     {
     817        7259 :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     818        7259 :       return static_cast<pointer>(mCurrent);
     819             :     }
     820             : 
     821         414 :     pointer get()
     822             :     {
     823         414 :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     824         414 :       return static_cast<pointer>(mCurrent);
     825             :     }
     826             : 
     827         718 :     operator pointer()
     828             :     {
     829         718 :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     830         718 :       return static_cast<pointer>(mCurrent);
     831             :     }
     832             : 
     833             :     const_reference operator*() const
     834             :     {
     835             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     836             :       return *static_cast<const_pointer>(mCurrent);
     837             :     }
     838             : 
     839          41 :     const_pointer operator->() const
     840             :     {
     841          41 :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     842          41 :       return static_cast<const_pointer>(mCurrent);
     843             :     }
     844             : 
     845             : #ifndef __MWERKS__
     846             :     operator const_pointer() const
     847             :     {
     848             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     849             :       return static_cast<const_pointer>(mCurrent);
     850             :     }
     851             : #endif /* !__MWERKS__ */
     852             : 
     853         163 :     iterator_self_type next()
     854             :     {
     855         163 :       iterator_self_type copy(*this);
     856         163 :       return ++copy;
     857             :     }
     858             : 
     859             :     const iterator_self_type next() const
     860             :     {
     861             :       iterator_self_type copy(*this);
     862             :       return ++copy;
     863             :     }
     864             : 
     865           0 :     iterator_self_type prev()
     866             :     {
     867           0 :       iterator_self_type copy(*this);
     868           0 :       return --copy;
     869             :     }
     870             : 
     871             :     const iterator_self_type prev() const
     872             :     {
     873             :       iterator_self_type copy(*this);
     874             :       return --copy;
     875             :     }
     876             : 
     877             :     // Passing by value rather than by reference and reference to const
     878             :     // to keep AIX happy.
     879             :     bool operator==(const iterator_self_type aOther) const
     880             :     {
     881             :       MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists");
     882             :       return mCurrent == aOther.mCurrent;
     883             :     }
     884           0 :     bool operator!=(const iterator_self_type aOther) const
     885             :     {
     886           0 :       MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists");
     887           0 :       return mCurrent != aOther.mCurrent;
     888             :     }
     889         282 :     bool operator==(const iterator_self_type aOther)
     890             :     {
     891         282 :       MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists");
     892         282 :       return mCurrent == aOther.mCurrent;
     893             :     }
     894        1878 :     bool operator!=(const iterator_self_type aOther)
     895             :     {
     896        1878 :       MOZ_ASSERT(mListLink == aOther.mListLink, "comparing iterators over different lists");
     897        1878 :       return mCurrent != aOther.mCurrent;
     898             :     }
     899             : 
     900             :   private:
     901             :     link_type *mCurrent;
     902             : #ifdef DEBUG
     903             :     link_type *mListLink; // the list's link, i.e., the end
     904             : #endif
     905             : };
     906             : 
     907             : class nsLineList_reverse_iterator {
     908             : 
     909             :   public:
     910             : 
     911             :     friend class nsLineList;
     912             :     friend class nsLineList_iterator;
     913             :     friend class nsLineList_const_iterator;
     914             :     friend class nsLineList_const_reverse_iterator;
     915             : 
     916             :     typedef nsLineList_reverse_iterator iterator_self_type;
     917             :     typedef nsLineList_iterator         iterator_reverse_type;
     918             : 
     919             :     typedef nsLineBox&                  reference;
     920             :     typedef const nsLineBox&            const_reference;
     921             : 
     922             :     typedef nsLineBox*                  pointer;
     923             :     typedef const nsLineBox*            const_pointer;
     924             : 
     925             :     typedef uint32_t                    size_type;
     926             :     typedef int32_t                     difference_type;
     927             : 
     928             :     typedef nsLineLink                  link_type;
     929             : 
     930             : #ifdef DEBUG
     931           0 :     nsLineList_reverse_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
     932             : #else
     933             :     // Auto generated default constructor OK.
     934             : #endif
     935             :     // Auto generated copy-constructor OK.
     936             : 
     937             :     inline iterator_self_type&
     938             :         operator=(const iterator_reverse_type& aOther);
     939             :     inline iterator_self_type&
     940             :         operator=(const iterator_self_type& aOther);
     941             : 
     942           0 :     iterator_self_type& operator++()
     943             :     {
     944           0 :       mCurrent = mCurrent->_mPrev;
     945           0 :       return *this;
     946             :     }
     947             : 
     948             :     iterator_self_type operator++(int)
     949             :     {
     950             :       iterator_self_type rv(*this);
     951             :       mCurrent = mCurrent->_mPrev;
     952             :       return rv;
     953             :     }
     954             : 
     955             :     iterator_self_type& operator--()
     956             :     {
     957             :       mCurrent = mCurrent->_mNext;
     958             :       return *this;
     959             :     }
     960             : 
     961             :     iterator_self_type operator--(int)
     962             :     {
     963             :       iterator_self_type rv(*this);
     964             :       mCurrent = mCurrent->_mNext;
     965             :       return rv;
     966             :     }
     967             : 
     968             :     reference operator*()
     969             :     {
     970             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     971             :       return *static_cast<pointer>(mCurrent);
     972             :     }
     973             : 
     974           0 :     pointer operator->()
     975             :     {
     976           0 :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     977           0 :       return static_cast<pointer>(mCurrent);
     978             :     }
     979             : 
     980             :     pointer get()
     981             :     {
     982             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     983             :       return static_cast<pointer>(mCurrent);
     984             :     }
     985             : 
     986             :     operator pointer()
     987             :     {
     988             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     989             :       return static_cast<pointer>(mCurrent);
     990             :     }
     991             : 
     992             :     const_reference operator*() const
     993             :     {
     994             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
     995             :       return *static_cast<const_pointer>(mCurrent);
     996             :     }
     997             : 
     998             :     const_pointer operator->() const
     999             :     {
    1000             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
    1001             :       return static_cast<const_pointer>(mCurrent);
    1002             :     }
    1003             : 
    1004             : #ifndef __MWERKS__
    1005             :     operator const_pointer() const
    1006             :     {
    1007             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
    1008             :       return static_cast<const_pointer>(mCurrent);
    1009             :     }
    1010             : #endif /* !__MWERKS__ */
    1011             : 
    1012             :     // Passing by value rather than by reference and reference to const
    1013             :     // to keep AIX happy.
    1014             :     bool operator==(const iterator_self_type aOther) const
    1015             :     {
    1016             :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1017             :       return mCurrent == aOther.mCurrent;
    1018             :     }
    1019             :     bool operator!=(const iterator_self_type aOther) const
    1020             :     {
    1021             :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1022             :       return mCurrent != aOther.mCurrent;
    1023             :     }
    1024             :     bool operator==(const iterator_self_type aOther)
    1025             :     {
    1026             :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1027             :       return mCurrent == aOther.mCurrent;
    1028             :     }
    1029           0 :     bool operator!=(const iterator_self_type aOther)
    1030             :     {
    1031           0 :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1032           0 :       return mCurrent != aOther.mCurrent;
    1033             :     }
    1034             : 
    1035             :   private:
    1036             :     link_type *mCurrent;
    1037             : #ifdef DEBUG
    1038             :     link_type *mListLink; // the list's link, i.e., the end
    1039             : #endif
    1040             : };
    1041             : 
    1042             : class nsLineList_const_iterator {
    1043             :   public:
    1044             : 
    1045             :     friend class nsLineList;
    1046             :     friend class nsLineList_iterator;
    1047             :     friend class nsLineList_reverse_iterator;
    1048             :     friend class nsLineList_const_reverse_iterator;
    1049             : 
    1050             :     typedef nsLineList_const_iterator           iterator_self_type;
    1051             :     typedef nsLineList_const_reverse_iterator   iterator_reverse_type;
    1052             :     typedef nsLineList_iterator                 iterator_nonconst_type;
    1053             :     typedef nsLineList_reverse_iterator         iterator_nonconst_reverse_type;
    1054             : 
    1055             :     typedef nsLineBox&                  reference;
    1056             :     typedef const nsLineBox&            const_reference;
    1057             : 
    1058             :     typedef nsLineBox*                  pointer;
    1059             :     typedef const nsLineBox*            const_pointer;
    1060             : 
    1061             :     typedef uint32_t                    size_type;
    1062             :     typedef int32_t                     difference_type;
    1063             : 
    1064             :     typedef nsLineLink                  link_type;
    1065             : 
    1066             : #ifdef DEBUG
    1067          70 :     nsLineList_const_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
    1068             : #else
    1069             :     // Auto generated default constructor OK.
    1070             : #endif
    1071             :     // Auto generated copy-constructor OK.
    1072             : 
    1073             :     inline iterator_self_type&
    1074             :         operator=(const iterator_nonconst_type& aOther);
    1075             :     inline iterator_self_type&
    1076             :         operator=(const iterator_nonconst_reverse_type& aOther);
    1077             :     inline iterator_self_type&
    1078             :         operator=(const iterator_self_type& aOther);
    1079             :     inline iterator_self_type&
    1080             :         operator=(const iterator_reverse_type& aOther);
    1081             : 
    1082          30 :     iterator_self_type& operator++()
    1083             :     {
    1084          30 :       mCurrent = mCurrent->_mNext;
    1085          30 :       return *this;
    1086             :     }
    1087             : 
    1088             :     iterator_self_type operator++(int)
    1089             :     {
    1090             :       iterator_self_type rv(*this);
    1091             :       mCurrent = mCurrent->_mNext;
    1092             :       return rv;
    1093             :     }
    1094             : 
    1095             :     iterator_self_type& operator--()
    1096             :     {
    1097             :       mCurrent = mCurrent->_mPrev;
    1098             :       return *this;
    1099             :     }
    1100             : 
    1101             :     iterator_self_type operator--(int)
    1102             :     {
    1103             :       iterator_self_type rv(*this);
    1104             :       mCurrent = mCurrent->_mPrev;
    1105             :       return rv;
    1106             :     }
    1107             : 
    1108             :     const_reference operator*() const
    1109             :     {
    1110             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
    1111             :       return *static_cast<const_pointer>(mCurrent);
    1112             :     }
    1113             : 
    1114         115 :     const_pointer operator->() const
    1115             :     {
    1116         115 :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
    1117         115 :       return static_cast<const_pointer>(mCurrent);
    1118             :     }
    1119             : 
    1120             :     const_pointer get() const
    1121             :     {
    1122             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
    1123             :       return static_cast<const_pointer>(mCurrent);
    1124             :     }
    1125             : 
    1126             : #ifndef __MWERKS__
    1127           0 :     operator const_pointer() const
    1128             :     {
    1129           0 :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
    1130           0 :       return static_cast<const_pointer>(mCurrent);
    1131             :     }
    1132             : #endif /* !__MWERKS__ */
    1133             : 
    1134             :     const iterator_self_type next() const
    1135             :     {
    1136             :       iterator_self_type copy(*this);
    1137             :       return ++copy;
    1138             :     }
    1139             : 
    1140             :     const iterator_self_type prev() const
    1141             :     {
    1142             :       iterator_self_type copy(*this);
    1143             :       return --copy;
    1144             :     }
    1145             : 
    1146             :     // Passing by value rather than by reference and reference to const
    1147             :     // to keep AIX happy.
    1148             :     bool operator==(const iterator_self_type aOther) const
    1149             :     {
    1150             :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1151             :       return mCurrent == aOther.mCurrent;
    1152             :     }
    1153             :     bool operator!=(const iterator_self_type aOther) const
    1154             :     {
    1155             :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1156             :       return mCurrent != aOther.mCurrent;
    1157             :     }
    1158             :     bool operator==(const iterator_self_type aOther)
    1159             :     {
    1160             :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1161             :       return mCurrent == aOther.mCurrent;
    1162             :     }
    1163          65 :     bool operator!=(const iterator_self_type aOther)
    1164             :     {
    1165          65 :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1166          65 :       return mCurrent != aOther.mCurrent;
    1167             :     }
    1168             : 
    1169             :   private:
    1170             :     const link_type *mCurrent;
    1171             : #ifdef DEBUG
    1172             :     const link_type *mListLink; // the list's link, i.e., the end
    1173             : #endif
    1174             : };
    1175             : 
    1176             : class nsLineList_const_reverse_iterator {
    1177             :   public:
    1178             : 
    1179             :     friend class nsLineList;
    1180             :     friend class nsLineList_iterator;
    1181             :     friend class nsLineList_reverse_iterator;
    1182             :     friend class nsLineList_const_iterator;
    1183             : 
    1184             :     typedef nsLineList_const_reverse_iterator   iterator_self_type;
    1185             :     typedef nsLineList_const_iterator           iterator_reverse_type;
    1186             :     typedef nsLineList_iterator                 iterator_nonconst_reverse_type;
    1187             :     typedef nsLineList_reverse_iterator         iterator_nonconst_type;
    1188             : 
    1189             :     typedef nsLineBox&                  reference;
    1190             :     typedef const nsLineBox&            const_reference;
    1191             : 
    1192             :     typedef nsLineBox*                  pointer;
    1193             :     typedef const nsLineBox*            const_pointer;
    1194             : 
    1195             :     typedef uint32_t                    size_type;
    1196             :     typedef int32_t                     difference_type;
    1197             : 
    1198             :     typedef nsLineLink                  link_type;
    1199             : 
    1200             : #ifdef DEBUG
    1201          60 :     nsLineList_const_reverse_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
    1202             : #else
    1203             :     // Auto generated default constructor OK.
    1204             : #endif
    1205             :     // Auto generated copy-constructor OK.
    1206             : 
    1207             :     inline iterator_self_type&
    1208             :         operator=(const iterator_nonconst_type& aOther);
    1209             :     inline iterator_self_type&
    1210             :         operator=(const iterator_nonconst_reverse_type& aOther);
    1211             :     inline iterator_self_type&
    1212             :         operator=(const iterator_self_type& aOther);
    1213             :     inline iterator_self_type&
    1214             :         operator=(const iterator_reverse_type& aOther);
    1215             : 
    1216          30 :     iterator_self_type& operator++()
    1217             :     {
    1218          30 :       mCurrent = mCurrent->_mPrev;
    1219          30 :       return *this;
    1220             :     }
    1221             : 
    1222             :     iterator_self_type operator++(int)
    1223             :     {
    1224             :       iterator_self_type rv(*this);
    1225             :       mCurrent = mCurrent->_mPrev;
    1226             :       return rv;
    1227             :     }
    1228             : 
    1229             :     iterator_self_type& operator--()
    1230             :     {
    1231             :       mCurrent = mCurrent->_mNext;
    1232             :       return *this;
    1233             :     }
    1234             : 
    1235             :     iterator_self_type operator--(int)
    1236             :     {
    1237             :       iterator_self_type rv(*this);
    1238             :       mCurrent = mCurrent->_mNext;
    1239             :       return rv;
    1240             :     }
    1241             : 
    1242             :     const_reference operator*() const
    1243             :     {
    1244             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
    1245             :       return *static_cast<const_pointer>(mCurrent);
    1246             :     }
    1247             : 
    1248          90 :     const_pointer operator->() const
    1249             :     {
    1250          90 :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
    1251          90 :       return static_cast<const_pointer>(mCurrent);
    1252             :     }
    1253             : 
    1254             :     const_pointer get() const
    1255             :     {
    1256             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
    1257             :       return static_cast<const_pointer>(mCurrent);
    1258             :     }
    1259             : 
    1260             : #ifndef __MWERKS__
    1261             :     operator const_pointer() const
    1262             :     {
    1263             :       MOZ_ASSERT(mCurrent != mListLink, "running past end");
    1264             :       return static_cast<const_pointer>(mCurrent);
    1265             :     }
    1266             : #endif /* !__MWERKS__ */
    1267             : 
    1268             :     // Passing by value rather than by reference and reference to const
    1269             :     // to keep AIX happy.
    1270             :     bool operator==(const iterator_self_type aOther) const
    1271             :     {
    1272             :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1273             :       return mCurrent == aOther.mCurrent;
    1274             :     }
    1275             :     bool operator!=(const iterator_self_type aOther) const
    1276             :     {
    1277             :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1278             :       return mCurrent != aOther.mCurrent;
    1279             :     }
    1280             :     bool operator==(const iterator_self_type aOther)
    1281             :     {
    1282             :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1283             :       return mCurrent == aOther.mCurrent;
    1284             :     }
    1285          60 :     bool operator!=(const iterator_self_type aOther)
    1286             :     {
    1287          60 :       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
    1288          60 :       return mCurrent != aOther.mCurrent;
    1289             :     }
    1290             : 
    1291             : //private:
    1292             :     const link_type *mCurrent;
    1293             : #ifdef DEBUG
    1294             :     const link_type *mListLink; // the list's link, i.e., the end
    1295             : #endif
    1296             : };
    1297             : 
    1298             : class nsLineList {
    1299             : 
    1300             :   public:
    1301             : 
    1302             :   friend class nsLineList_iterator;
    1303             :   friend class nsLineList_reverse_iterator;
    1304             :   friend class nsLineList_const_iterator;
    1305             :   friend class nsLineList_const_reverse_iterator;
    1306             : 
    1307             :   typedef uint32_t                    size_type;
    1308             :   typedef int32_t                     difference_type;
    1309             : 
    1310             :   typedef nsLineLink                  link_type;
    1311             : 
    1312             :   private:
    1313             :     link_type mLink;
    1314             : 
    1315             :   public:
    1316             :     typedef nsLineList                  self_type;
    1317             : 
    1318             :     typedef nsLineBox&                  reference;
    1319             :     typedef const nsLineBox&            const_reference;
    1320             : 
    1321             :     typedef nsLineBox*                  pointer;
    1322             :     typedef const nsLineBox*            const_pointer;
    1323             : 
    1324             :     typedef nsLineList_iterator         iterator;
    1325             :     typedef nsLineList_reverse_iterator reverse_iterator;
    1326             :     typedef nsLineList_const_iterator   const_iterator;
    1327             :     typedef nsLineList_const_reverse_iterator const_reverse_iterator;
    1328             : 
    1329          34 :     nsLineList()
    1330          34 :     {
    1331          34 :       MOZ_COUNT_CTOR(nsLineList);
    1332          34 :       clear();
    1333          34 :     }
    1334             : 
    1335          10 :     ~nsLineList()
    1336          10 :     {
    1337          10 :       MOZ_COUNT_DTOR(nsLineList);
    1338          10 :     }
    1339             : 
    1340          35 :     const_iterator begin() const
    1341             :     {
    1342          35 :       const_iterator rv;
    1343          35 :       rv.mCurrent = mLink._mNext;
    1344             : #ifdef DEBUG
    1345          35 :       rv.mListLink = &mLink;
    1346             : #endif
    1347          35 :       return rv;
    1348             :     }
    1349             : 
    1350        1064 :     iterator begin()
    1351             :     {
    1352        1064 :       iterator rv;
    1353        1064 :       rv.mCurrent = mLink._mNext;
    1354             : #ifdef DEBUG
    1355        1064 :       rv.mListLink = &mLink;
    1356             : #endif
    1357        1064 :       return rv;
    1358             :     }
    1359             : 
    1360           0 :     iterator begin(nsLineBox* aLine)
    1361             :     {
    1362           0 :       iterator rv;
    1363           0 :       rv.mCurrent = aLine;
    1364             : #ifdef DEBUG
    1365           0 :       rv.mListLink = &mLink;
    1366             : #endif
    1367           0 :       return rv;
    1368             :     }
    1369             : 
    1370          35 :     const_iterator end() const
    1371             :     {
    1372          35 :       const_iterator rv;
    1373          35 :       rv.mCurrent = &mLink;
    1374             : #ifdef DEBUG
    1375          35 :       rv.mListLink = &mLink;
    1376             : #endif
    1377          35 :       return rv;
    1378             :     }
    1379             : 
    1380        1295 :     iterator end()
    1381             :     {
    1382        1295 :       iterator rv;
    1383        1295 :       rv.mCurrent = &mLink;
    1384             : #ifdef DEBUG
    1385        1295 :       rv.mListLink = &mLink;
    1386             : #endif
    1387        1295 :       return rv;
    1388             :     }
    1389             : 
    1390          30 :     const_reverse_iterator rbegin() const
    1391             :     {
    1392          30 :       const_reverse_iterator rv;
    1393          30 :       rv.mCurrent = mLink._mPrev;
    1394             : #ifdef DEBUG
    1395          30 :       rv.mListLink = &mLink;
    1396             : #endif
    1397          30 :       return rv;
    1398             :     }
    1399             : 
    1400             :     reverse_iterator rbegin()
    1401             :     {
    1402             :       reverse_iterator rv;
    1403             :       rv.mCurrent = mLink._mPrev;
    1404             : #ifdef DEBUG
    1405             :       rv.mListLink = &mLink;
    1406             : #endif
    1407             :       return rv;
    1408             :     }
    1409             : 
    1410           0 :     reverse_iterator rbegin(nsLineBox* aLine)
    1411             :     {
    1412           0 :       reverse_iterator rv;
    1413           0 :       rv.mCurrent = aLine;
    1414             : #ifdef DEBUG
    1415           0 :       rv.mListLink = &mLink;
    1416             : #endif
    1417           0 :       return rv;
    1418             :     }
    1419             : 
    1420          30 :     const_reverse_iterator rend() const
    1421             :     {
    1422          30 :       const_reverse_iterator rv;
    1423          30 :       rv.mCurrent = &mLink;
    1424             : #ifdef DEBUG
    1425          30 :       rv.mListLink = &mLink;
    1426             : #endif
    1427          30 :       return rv;
    1428             :     }
    1429             : 
    1430           0 :     reverse_iterator rend()
    1431             :     {
    1432           0 :       reverse_iterator rv;
    1433           0 :       rv.mCurrent = &mLink;
    1434             : #ifdef DEBUG
    1435           0 :       rv.mListLink = &mLink;
    1436             : #endif
    1437           0 :       return rv;
    1438             :     }
    1439             : 
    1440         230 :     bool empty() const
    1441             :     {
    1442         230 :       return mLink._mNext == &mLink;
    1443             :     }
    1444             : 
    1445             :     // NOTE: O(N).
    1446          12 :     size_type size() const
    1447             :     {
    1448          12 :       size_type count = 0;
    1449          24 :       for (const link_type *cur = mLink._mNext;
    1450          24 :            cur != &mLink;
    1451          12 :            cur = cur->_mNext)
    1452             :       {
    1453          12 :         ++count;
    1454             :       }
    1455          12 :       return count;
    1456             :     }
    1457             : 
    1458          81 :     pointer front()
    1459             :     {
    1460          81 :       NS_ASSERTION(!empty(), "no element to return");
    1461          81 :       return static_cast<pointer>(mLink._mNext);
    1462             :     }
    1463             : 
    1464           6 :     const_pointer front() const
    1465             :     {
    1466           6 :       NS_ASSERTION(!empty(), "no element to return");
    1467           6 :       return static_cast<const_pointer>(mLink._mNext);
    1468             :     }
    1469             : 
    1470          88 :     pointer back()
    1471             :     {
    1472          88 :       NS_ASSERTION(!empty(), "no element to return");
    1473          88 :       return static_cast<pointer>(mLink._mPrev);
    1474             :     }
    1475             : 
    1476             :     const_pointer back() const
    1477             :     {
    1478             :       NS_ASSERTION(!empty(), "no element to return");
    1479             :       return static_cast<const_pointer>(mLink._mPrev);
    1480             :     }
    1481             : 
    1482          33 :     void push_front(pointer aNew)
    1483             :     {
    1484          33 :       aNew->_mNext = mLink._mNext;
    1485          33 :       mLink._mNext->_mPrev = aNew;
    1486          33 :       aNew->_mPrev = &mLink;
    1487          33 :       mLink._mNext = aNew;
    1488          33 :     }
    1489             : 
    1490           6 :     void pop_front()
    1491             :         // NOTE: leaves dangling next/prev pointers
    1492             :     {
    1493           6 :       NS_ASSERTION(!empty(), "no element to pop");
    1494           6 :       link_type *newFirst = mLink._mNext->_mNext;
    1495           6 :       newFirst->_mPrev = &mLink;
    1496             :       // mLink._mNext->_mNext = nullptr;
    1497             :       // mLink._mNext->_mPrev = nullptr;
    1498           6 :       mLink._mNext = newFirst;
    1499           6 :     }
    1500             : 
    1501             :     void push_back(pointer aNew)
    1502             :     {
    1503             :       aNew->_mPrev = mLink._mPrev;
    1504             :       mLink._mPrev->_mNext = aNew;
    1505             :       aNew->_mNext = &mLink;
    1506             :       mLink._mPrev = aNew;
    1507             :     }
    1508             : 
    1509             :     void pop_back()
    1510             :         // NOTE: leaves dangling next/prev pointers
    1511             :     {
    1512             :       NS_ASSERTION(!empty(), "no element to pop");
    1513             :       link_type *newLast = mLink._mPrev->_mPrev;
    1514             :       newLast->_mNext = &mLink;
    1515             :       // mLink._mPrev->_mPrev = nullptr;
    1516             :       // mLink._mPrev->_mNext = nullptr;
    1517             :       mLink._mPrev = newLast;
    1518             :     }
    1519             : 
    1520             :     // inserts x before position
    1521           0 :     iterator before_insert(iterator position, pointer x)
    1522             :     {
    1523             :       // use |mCurrent| to prevent DEBUG_PASS_END assertions
    1524           0 :       x->_mPrev = position.mCurrent->_mPrev;
    1525           0 :       x->_mNext = position.mCurrent;
    1526           0 :       position.mCurrent->_mPrev->_mNext = x;
    1527           0 :       position.mCurrent->_mPrev = x;
    1528           0 :       return --position;
    1529             :     }
    1530             : 
    1531             :     // inserts x after position
    1532           0 :     iterator after_insert(iterator position, pointer x)
    1533             :     {
    1534             :       // use |mCurrent| to prevent DEBUG_PASS_END assertions
    1535           0 :       x->_mNext = position.mCurrent->_mNext;
    1536           0 :       x->_mPrev = position.mCurrent;
    1537           0 :       position.mCurrent->_mNext->_mPrev = x;
    1538           0 :       position.mCurrent->_mNext = x;
    1539           0 :       return ++position;
    1540             :     }
    1541             : 
    1542             :     // returns iterator pointing to after the element
    1543           6 :     iterator erase(iterator position)
    1544             :         // NOTE: leaves dangling next/prev pointers
    1545             :     {
    1546           6 :       position->_mPrev->_mNext = position->_mNext;
    1547           6 :       position->_mNext->_mPrev = position->_mPrev;
    1548           6 :       return ++position;
    1549             :     }
    1550             : 
    1551             :     void swap(self_type& y)
    1552             :     {
    1553             :       link_type tmp(y.mLink);
    1554             :       y.mLink = mLink;
    1555             :       mLink = tmp;
    1556             : 
    1557             :       if (!empty()) {
    1558             :         mLink._mNext->_mPrev = &mLink;
    1559             :         mLink._mPrev->_mNext = &mLink;
    1560             :       }
    1561             : 
    1562             :       if (!y.empty()) {
    1563             :         y.mLink._mNext->_mPrev = &y.mLink;
    1564             :         y.mLink._mPrev->_mNext = &y.mLink;
    1565             :       }
    1566             :     }
    1567             : 
    1568          34 :     void clear()
    1569             :         // NOTE:  leaves dangling next/prev pointers
    1570             :     {
    1571          34 :       mLink._mNext = &mLink;
    1572          34 :       mLink._mPrev = &mLink;
    1573          34 :     }
    1574             : 
    1575             :     // inserts the conts of x before position and makes x empty
    1576           0 :     void splice(iterator position, self_type& x)
    1577             :     {
    1578             :       // use |mCurrent| to prevent DEBUG_PASS_END assertions
    1579           0 :       position.mCurrent->_mPrev->_mNext = x.mLink._mNext;
    1580           0 :       x.mLink._mNext->_mPrev = position.mCurrent->_mPrev;
    1581           0 :       x.mLink._mPrev->_mNext = position.mCurrent;
    1582           0 :       position.mCurrent->_mPrev = x.mLink._mPrev;
    1583           0 :       x.clear();
    1584           0 :     }
    1585             : 
    1586             :     // Inserts element *i from list x before position and removes
    1587             :     // it from x.
    1588             :     void splice(iterator position, self_type& x, iterator i)
    1589             :     {
    1590             :       NS_ASSERTION(!x.empty(), "Can't insert from empty list.");
    1591             :       NS_ASSERTION(position != i && position.mCurrent != i->_mNext,
    1592             :                    "We don't check for this case.");
    1593             : 
    1594             :       // remove from |x|
    1595             :       i->_mPrev->_mNext = i->_mNext;
    1596             :       i->_mNext->_mPrev = i->_mPrev;
    1597             : 
    1598             :       // use |mCurrent| to prevent DEBUG_PASS_END assertions
    1599             :       // link into |this|, before-side
    1600             :       i->_mPrev = position.mCurrent->_mPrev;
    1601             :       position.mCurrent->_mPrev->_mNext = i.get();
    1602             : 
    1603             :       // link into |this|, after-side
    1604             :       i->_mNext = position.mCurrent;
    1605             :       position.mCurrent->_mPrev = i.get();
    1606             :     }
    1607             : 
    1608             :     // Inserts elements in [|first|, |last|), which are in |x|,
    1609             :     // into |this| before |position| and removes them from |x|.
    1610           0 :     void splice(iterator position, self_type& x, iterator first,
    1611             :                 iterator last)
    1612             :     {
    1613           0 :       NS_ASSERTION(!x.empty(), "Can't insert from empty list.");
    1614             : 
    1615           0 :       if (first == last)
    1616           0 :         return;
    1617             : 
    1618           0 :       --last; // so we now want to move [first, last]
    1619             :       // remove from |x|
    1620           0 :       first->_mPrev->_mNext = last->_mNext;
    1621           0 :       last->_mNext->_mPrev = first->_mPrev;
    1622             : 
    1623             :       // use |mCurrent| to prevent DEBUG_PASS_END assertions
    1624             :       // link into |this|, before-side
    1625           0 :       first->_mPrev = position.mCurrent->_mPrev;
    1626           0 :       position.mCurrent->_mPrev->_mNext = first.get();
    1627             : 
    1628             :       // link into |this|, after-side
    1629           0 :       last->_mNext = position.mCurrent;
    1630           0 :       position.mCurrent->_mPrev = last.get();
    1631             :     }
    1632             : 
    1633             : };
    1634             : 
    1635             : 
    1636             : // Many of these implementations of operator= don't work yet.  I don't
    1637             : // know why.
    1638             : 
    1639             : #ifdef DEBUG
    1640             : 
    1641             :   // NOTE: ASSIGN_FROM is meant to be used *only* as the entire body
    1642             :   // of a function and therefore lacks PR_{BEGIN,END}_MACRO
    1643             : #define ASSIGN_FROM(other_)          \
    1644             :   mCurrent = other_.mCurrent;        \
    1645             :   mListLink = other_.mListLink;      \
    1646             :   return *this;
    1647             : 
    1648             : #else /* !NS_LINELIST_DEBUG_PASS_END */
    1649             : 
    1650             : #define ASSIGN_FROM(other_)          \
    1651             :   mCurrent = other_.mCurrent;        \
    1652             :   return *this;
    1653             : 
    1654             : #endif /* !NS_LINELIST_DEBUG_PASS_END */
    1655             : 
    1656             : inline
    1657             : nsLineList_iterator&
    1658         516 : nsLineList_iterator::operator=(const nsLineList_iterator& aOther)
    1659             : {
    1660         516 :   ASSIGN_FROM(aOther)
    1661             : }
    1662             : 
    1663             : inline
    1664             : nsLineList_iterator&
    1665           0 : nsLineList_iterator::operator=(const nsLineList_reverse_iterator& aOther)
    1666             : {
    1667           0 :   ASSIGN_FROM(aOther)
    1668             : }
    1669             : 
    1670             : inline
    1671             : nsLineList_reverse_iterator&
    1672             : nsLineList_reverse_iterator::operator=(const nsLineList_iterator& aOther)
    1673             : {
    1674             :   ASSIGN_FROM(aOther)
    1675             : }
    1676             : 
    1677             : inline
    1678             : nsLineList_reverse_iterator&
    1679             : nsLineList_reverse_iterator::operator=(const nsLineList_reverse_iterator& aOther)
    1680             : {
    1681             :   ASSIGN_FROM(aOther)
    1682             : }
    1683             : 
    1684             : inline
    1685             : nsLineList_const_iterator&
    1686             : nsLineList_const_iterator::operator=(const nsLineList_iterator& aOther)
    1687             : {
    1688             :   ASSIGN_FROM(aOther)
    1689             : }
    1690             : 
    1691             : inline
    1692             : nsLineList_const_iterator&
    1693             : nsLineList_const_iterator::operator=(const nsLineList_reverse_iterator& aOther)
    1694             : {
    1695             :   ASSIGN_FROM(aOther)
    1696             : }
    1697             : 
    1698             : inline
    1699             : nsLineList_const_iterator&
    1700             : nsLineList_const_iterator::operator=(const nsLineList_const_iterator& aOther)
    1701             : {
    1702             :   ASSIGN_FROM(aOther)
    1703             : }
    1704             : 
    1705             : inline
    1706             : nsLineList_const_iterator&
    1707             : nsLineList_const_iterator::operator=(const nsLineList_const_reverse_iterator& aOther)
    1708             : {
    1709             :   ASSIGN_FROM(aOther)
    1710             : }
    1711             : 
    1712             : inline
    1713             : nsLineList_const_reverse_iterator&
    1714             : nsLineList_const_reverse_iterator::operator=(const nsLineList_iterator& aOther)
    1715             : {
    1716             :   ASSIGN_FROM(aOther)
    1717             : }
    1718             : 
    1719             : inline
    1720             : nsLineList_const_reverse_iterator&
    1721             : nsLineList_const_reverse_iterator::operator=(const nsLineList_reverse_iterator& aOther)
    1722             : {
    1723             :   ASSIGN_FROM(aOther)
    1724             : }
    1725             : 
    1726             : inline
    1727             : nsLineList_const_reverse_iterator&
    1728             : nsLineList_const_reverse_iterator::operator=(const nsLineList_const_iterator& aOther)
    1729             : {
    1730             :   ASSIGN_FROM(aOther)
    1731             : }
    1732             : 
    1733             : inline
    1734             : nsLineList_const_reverse_iterator&
    1735             : nsLineList_const_reverse_iterator::operator=(const nsLineList_const_reverse_iterator& aOther)
    1736             : {
    1737             :   ASSIGN_FROM(aOther)
    1738             : }
    1739             : 
    1740             : 
    1741             : //----------------------------------------------------------------------
    1742             : 
    1743             : class nsLineIterator final : public nsILineIterator
    1744             : {
    1745             : public:
    1746             :   nsLineIterator();
    1747             :   ~nsLineIterator();
    1748             : 
    1749             :   virtual void DisposeLineIterator() override;
    1750             : 
    1751             :   virtual int32_t GetNumLines() override;
    1752             :   virtual bool GetDirection() override;
    1753             :   NS_IMETHOD GetLine(int32_t aLineNumber,
    1754             :                      nsIFrame** aFirstFrameOnLine,
    1755             :                      int32_t* aNumFramesOnLine,
    1756             :                      nsRect& aLineBounds) override;
    1757             :   virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) override;
    1758             :   NS_IMETHOD FindFrameAt(int32_t aLineNumber,
    1759             :                          nsPoint aPos,
    1760             :                          nsIFrame** aFrameFound,
    1761             :                          bool* aPosIsBeforeFirstFrame,
    1762             :                          bool* aPosIsAfterLastFrame) override;
    1763             : 
    1764             :   NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, int32_t aLineNumber) override;
    1765             :   NS_IMETHOD CheckLineOrder(int32_t                  aLine,
    1766             :                             bool                     *aIsReordered,
    1767             :                             nsIFrame                 **aFirstVisual,
    1768             :                             nsIFrame                 **aLastVisual) override;
    1769             :   nsresult Init(nsLineList& aLines, bool aRightToLeft);
    1770             : 
    1771             : private:
    1772             :   nsLineBox* PrevLine() {
    1773             :     if (0 == mIndex) {
    1774             :       return nullptr;
    1775             :     }
    1776             :     return mLines[--mIndex];
    1777             :   }
    1778             : 
    1779             :   nsLineBox* NextLine() {
    1780             :     if (mIndex >= mNumLines - 1) {
    1781             :       return nullptr;
    1782             :     }
    1783             :     return mLines[++mIndex];
    1784             :   }
    1785             : 
    1786             :   nsLineBox* LineAt(int32_t aIndex) {
    1787             :     if ((aIndex < 0) || (aIndex >= mNumLines)) {
    1788             :       return nullptr;
    1789             :     }
    1790             :     return mLines[aIndex];
    1791             :   }
    1792             : 
    1793             :   nsLineBox** mLines;
    1794             :   int32_t mIndex;
    1795             :   int32_t mNumLines;
    1796             :   bool mRightToLeft;
    1797             : };
    1798             : 
    1799             : #endif /* nsLineBox_h___ */

Generated by: LCOV version 1.13