layout/generic/nsLineBox.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 */
     9 #ifndef nsLineBox_h___
    10 #define nsLineBox_h___
    12 #include "mozilla/Attributes.h"
    13 #include "mozilla/Likely.h"
    15 #include "nsILineIterator.h"
    16 #include "nsIFrame.h"
    17 #include <algorithm>
    19 class nsLineBox;
    20 class nsFloatCache;
    21 class nsFloatCacheList;
    22 class nsFloatCacheFreeList;
    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
    35   nsFloatCache* Next() const { return mNext; }
    37   nsIFrame* mFloat;                     // floating frame
    39 protected:
    40   nsFloatCache* mNext;
    42   friend class nsFloatCacheList;
    43   friend class nsFloatCacheFreeList;
    44 };
    46 //----------------------------------------
    48 class nsFloatCacheList {
    49 public:
    50 #ifdef NS_BUILD_REFCNT_LOGGING
    51   nsFloatCacheList();
    52 #else
    53   nsFloatCacheList() : mHead(nullptr) { }
    54 #endif
    55   ~nsFloatCacheList();
    57   bool IsEmpty() const {
    58     return nullptr == mHead;
    59   }
    61   bool NotEmpty() const {
    62     return nullptr != mHead;
    63   }
    65   nsFloatCache* Head() const {
    66     return mHead;
    67   }
    69   nsFloatCache* Tail() const;
    71   void DeleteAll();
    73   nsFloatCache* Find(nsIFrame* aOutOfFlowFrame);
    75   // Remove a nsFloatCache from this list.  Deleting this nsFloatCache
    76   // becomes the caller's responsibility.
    77   void Remove(nsFloatCache* aElement) { RemoveAndReturnPrev(aElement); }
    79   // Steal away aList's nsFloatCache objects and put them in this
    80   // list.  aList must not be empty.
    81   void Append(nsFloatCacheFreeList& aList);
    83 protected:
    84   nsFloatCache* mHead;
    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);
    91   friend class nsFloatCacheFreeList;
    92 };
    94 //---------------------------------------
    95 // Like nsFloatCacheList, but with fast access to the tail
    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
   107   // Reimplement trivial functions
   108   bool IsEmpty() const {
   109     return nullptr == mHead;
   110   }
   112   nsFloatCache* Head() const {
   113     return mHead;
   114   }
   116   nsFloatCache* Tail() const {
   117     return mTail;
   118   }
   120   bool NotEmpty() const {
   121     return nullptr != mHead;
   122   }
   124   void DeleteAll();
   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);
   130   void Append(nsFloatCache* aFloatCache);
   132   void Remove(nsFloatCache* aElement);
   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);
   138 protected:
   139   nsFloatCache* mTail;
   141   friend class nsFloatCacheList;
   142 };
   144 //----------------------------------------------------------------------
   146 #define LINE_MAX_BREAK_TYPE  ((1 << 4) - 1)
   147 #define LINE_MAX_CHILD_COUNT INT32_MAX
   149 /**
   150  * Function to create a line box and initialize it with a single frame.
   151  * The allocation is infallible.
   152  * If the frame was moved from another line then you're responsible
   153  * for notifying that line using NoteFrameRemoved().  Alternatively,
   154  * it's better to use the next function that does that for you in an
   155  * optimal way.
   156  */
   157 nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
   158                          bool aIsBlock);
   159 /**
   160  * Function to create a line box and initialize it with aCount frames
   161  * that are currently on aFromLine.  The allocation is infallible.
   162  */
   163 nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
   164                          nsIFrame* aFrame, int32_t aCount);
   166 class nsLineList;
   168 // don't use the following names outside of this file.  Instead, use
   169 // nsLineList::iterator, etc.  These are just here to allow them to
   170 // be specified as parameters to methods of nsLineBox.
   171 class nsLineList_iterator;
   172 class nsLineList_const_iterator;
   173 class nsLineList_reverse_iterator;
   174 class nsLineList_const_reverse_iterator;
   176 /**
   177  * Users must have the class that is to be part of the list inherit
   178  * from nsLineLink.  If they want to be efficient, it should be the
   179  * first base class.  (This was originally nsCLink in a templatized
   180  * nsCList, but it's still useful separately.)
   181  */
   183 class nsLineLink {
   185   public:
   186     friend class nsLineList;
   187     friend class nsLineList_iterator;
   188     friend class nsLineList_reverse_iterator;
   189     friend class nsLineList_const_iterator;
   190     friend class nsLineList_const_reverse_iterator;
   192   private:
   193     nsLineLink *_mNext; // or head
   194     nsLineLink *_mPrev; // or tail
   196 };
   199 /**
   200  * The nsLineBox class represents a horizontal line of frames. It contains
   201  * enough state to support incremental reflow of the frames, event handling
   202  * for the frames, and rendering of the frames.
   203  */
   204 class nsLineBox MOZ_FINAL : public nsLineLink {
   205 private:
   206   nsLineBox(nsIFrame* aFrame, int32_t aCount, bool aIsBlock);
   207   ~nsLineBox();
   209   // Overloaded new operator. Uses an arena (which comes from the presShell)
   210   // to perform the allocation.
   211   void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW;
   212   void operator delete(void* aPtr, size_t sz) MOZ_DELETE;
   214 public:
   215   // Use these functions to allocate and destroy line boxes
   216   friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame,
   217                                   bool aIsBlock);
   218   friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine,
   219                                   nsIFrame* aFrame, int32_t aCount);
   220   void Destroy(nsIPresShell* aPresShell);
   222   // mBlock bit
   223   bool IsBlock() const {
   224     return mFlags.mBlock;
   225   }
   226   bool IsInline() const {
   227     return 0 == mFlags.mBlock;
   228   }
   230   // mDirty bit
   231   void MarkDirty() {
   232     mFlags.mDirty = 1;
   233   }
   234   void ClearDirty() {
   235     mFlags.mDirty = 0;
   236   }
   237   bool IsDirty() const {
   238     return mFlags.mDirty;
   239   }
   241   // mPreviousMarginDirty bit
   242   void MarkPreviousMarginDirty() {
   243     mFlags.mPreviousMarginDirty = 1;
   244   }
   245   void ClearPreviousMarginDirty() {
   246     mFlags.mPreviousMarginDirty = 0;
   247   }
   248   bool IsPreviousMarginDirty() const {
   249     return mFlags.mPreviousMarginDirty;
   250   }
   252   // mHasClearance bit
   253   void SetHasClearance() {
   254     mFlags.mHasClearance = 1;
   255   }
   256   void ClearHasClearance() {
   257     mFlags.mHasClearance = 0;
   258   }
   259   bool HasClearance() const {
   260     return mFlags.mHasClearance;
   261   }
   263   // mImpactedByFloat bit
   264   void SetLineIsImpactedByFloat(bool aValue) {
   265     mFlags.mImpactedByFloat = aValue;
   266   }
   267   bool IsImpactedByFloat() const {
   268     return mFlags.mImpactedByFloat;
   269   }
   271   // mLineWrapped bit
   272   void SetLineWrapped(bool aOn) {
   273     mFlags.mLineWrapped = aOn;
   274   }
   275   bool IsLineWrapped() const {
   276     return mFlags.mLineWrapped;
   277   }
   279   // mInvalidateTextRuns bit
   280   void SetInvalidateTextRuns(bool aOn) {
   281     mFlags.mInvalidateTextRuns = aOn;
   282   }
   283   bool GetInvalidateTextRuns() const {
   284     return mFlags.mInvalidateTextRuns;
   285   }
   287   // mResizeReflowOptimizationDisabled bit
   288   void DisableResizeReflowOptimization() {
   289     mFlags.mResizeReflowOptimizationDisabled = true;
   290   }
   291   void EnableResizeReflowOptimization() {
   292     mFlags.mResizeReflowOptimizationDisabled = false;
   293   }
   294   bool ResizeReflowOptimizationDisabled() const {
   295     return mFlags.mResizeReflowOptimizationDisabled;
   296   }
   298   // mHasBullet bit
   299   void SetHasBullet() {
   300     mFlags.mHasBullet = true;
   301     InvalidateCachedIsEmpty();
   302   }
   303   void ClearHasBullet() {
   304     mFlags.mHasBullet = false;
   305     InvalidateCachedIsEmpty();
   306   }
   307   bool HasBullet() const {
   308     return mFlags.mHasBullet;
   309   }
   311   // mHadFloatPushed bit
   312   void SetHadFloatPushed() {
   313     mFlags.mHadFloatPushed = true;
   314   }
   315   void ClearHadFloatPushed() {
   316     mFlags.mHadFloatPushed = false;
   317   }
   318   bool HadFloatPushed() const {
   319     return mFlags.mHadFloatPushed;
   320   }
   322 private:
   323   // Add a hash table for fast lookup when the line has more frames than this.
   324   static const uint32_t kMinChildCountForHashtable = 200;
   326   /**
   327    * Take ownership of aFromLine's hash table and remove the frames that
   328    * stay on aFromLine from it, i.e. aFromLineNewCount frames starting with
   329    * mFirstChild.  This method is used to optimize moving a large number
   330    * of frames from one line to the next.
   331    */
   332   void StealHashTableFrom(nsLineBox* aFromLine, uint32_t aFromLineNewCount);
   334   /**
   335    * Does the equivalent of this->NoteFrameAdded and aFromLine->NoteFrameRemoved
   336    * for each frame on this line, but in a optimized way.
   337    */
   338   void NoteFramesMovedFrom(nsLineBox* aFromLine);
   340   void SwitchToHashtable()
   341   {
   342     MOZ_ASSERT(!mFlags.mHasHashedFrames);
   343     uint32_t count = GetChildCount();
   344     mFlags.mHasHashedFrames = 1;
   345     uint32_t minSize =
   346       std::max(kMinChildCountForHashtable, uint32_t(PL_DHASH_MIN_SIZE));
   347     mFrames = new nsTHashtable< nsPtrHashKey<nsIFrame> >(std::max(count, minSize));
   348     for (nsIFrame* f = mFirstChild; count-- > 0; f = f->GetNextSibling()) {
   349       mFrames->PutEntry(f);
   350     }
   351   }
   352   void SwitchToCounter() {
   353     MOZ_ASSERT(mFlags.mHasHashedFrames);
   354     uint32_t count = GetChildCount();
   355     delete mFrames;
   356     mFlags.mHasHashedFrames = 0;
   357     mChildCount = count;
   358   }
   360 public:
   361   int32_t GetChildCount() const {
   362     return MOZ_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Count() : mChildCount;
   363   }
   365   /**
   366    * Register that aFrame is now on this line.
   367    */
   368   void NoteFrameAdded(nsIFrame* aFrame) {
   369     if (MOZ_UNLIKELY(mFlags.mHasHashedFrames)) {
   370       mFrames->PutEntry(aFrame);
   371     } else {
   372       if (++mChildCount >= kMinChildCountForHashtable) {
   373         SwitchToHashtable();
   374       }
   375     }
   376   }
   378   /**
   379    * Register that aFrame is not on this line anymore.
   380    */
   381   void NoteFrameRemoved(nsIFrame* aFrame) {
   382     MOZ_ASSERT(GetChildCount() > 0);
   383     if (MOZ_UNLIKELY(mFlags.mHasHashedFrames)) {
   384       mFrames->RemoveEntry(aFrame);
   385       if (mFrames->Count() < kMinChildCountForHashtable) {
   386         SwitchToCounter();
   387       }
   388     } else {
   389       --mChildCount;
   390     }
   391   }
   393   // mBreakType value
   394   // Break information is applied *before* the line if the line is a block,
   395   // or *after* the line if the line is an inline. Confusing, I know, but
   396   // using different names should help.
   397   bool HasBreakBefore() const {
   398     return IsBlock() && NS_STYLE_CLEAR_NONE != mFlags.mBreakType;
   399   }
   400   void SetBreakTypeBefore(uint8_t aBreakType) {
   401     NS_ASSERTION(IsBlock(), "Only blocks have break-before");
   402     NS_ASSERTION(aBreakType == NS_STYLE_CLEAR_NONE ||
   403                  aBreakType == NS_STYLE_CLEAR_LEFT ||
   404                  aBreakType == NS_STYLE_CLEAR_RIGHT ||
   405                  aBreakType == NS_STYLE_CLEAR_BOTH,
   406                  "Only float break types are allowed before a line");
   407     mFlags.mBreakType = aBreakType;
   408   }
   409   uint8_t GetBreakTypeBefore() const {
   410     return IsBlock() ? mFlags.mBreakType : NS_STYLE_CLEAR_NONE;
   411   }
   413   bool HasBreakAfter() const {
   414     return !IsBlock() && NS_STYLE_CLEAR_NONE != mFlags.mBreakType;
   415   }
   416   void SetBreakTypeAfter(uint8_t aBreakType) {
   417     NS_ASSERTION(!IsBlock(), "Only inlines have break-after");
   418     NS_ASSERTION(aBreakType <= LINE_MAX_BREAK_TYPE, "bad break type");
   419     mFlags.mBreakType = aBreakType;
   420   }
   421   bool HasFloatBreakAfter() const {
   422     return !IsBlock() && (NS_STYLE_CLEAR_LEFT == mFlags.mBreakType ||
   423                           NS_STYLE_CLEAR_RIGHT == mFlags.mBreakType ||
   424                           NS_STYLE_CLEAR_BOTH == mFlags.mBreakType);
   425   }
   426   uint8_t GetBreakTypeAfter() const {
   427     return !IsBlock() ? mFlags.mBreakType : NS_STYLE_CLEAR_NONE;
   428   }
   430   // mCarriedOutBottomMargin value
   431   nsCollapsingMargin GetCarriedOutBottomMargin() const;
   432   // Returns true if the margin changed
   433   bool SetCarriedOutBottomMargin(nsCollapsingMargin aValue);
   435   // mFloats
   436   bool HasFloats() const {
   437     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);
   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   nsRect GetOverflowArea(nsOverflowType aType) {
   450     return mData ? mData->mOverflowAreas.Overflow(aType) : GetPhysicalBounds();
   451   }
   452   nsOverflowAreas GetOverflowAreas() {
   453     if (mData) {
   454       return mData->mOverflowAreas;
   455     }
   456     nsRect bounds = GetPhysicalBounds();
   457     return nsOverflowAreas(bounds, bounds);
   458   }
   459   nsRect GetVisualOverflowArea()
   460     { return GetOverflowArea(eVisualOverflow); }
   461   nsRect GetScrollableOverflowArea()
   462     { return GetOverflowArea(eScrollableOverflow); }
   464   void SlideBy(nscoord aDBCoord, nscoord aContainerWidth) {
   465     NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1,
   466                  "container width doesn't match");
   467     mContainerWidth = aContainerWidth;
   468     mBounds.BStart(mWritingMode) += aDBCoord;
   469     if (mData) {
   470       NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
   471         mData->mOverflowAreas.Overflow(otype).y += aDBCoord;
   472       }
   473     }
   474   }
   476   void IndentBy(nscoord aDICoord, nscoord aContainerWidth) {
   477     NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1,
   478                  "container width doesn't match");
   479     mContainerWidth = aContainerWidth;
   480     mBounds.IStart(mWritingMode) += aDICoord;
   481   }
   483   void ExpandBy(nscoord aDISize, nscoord aContainerWidth) {
   484     NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1,
   485                  "container width doesn't match");
   486     mContainerWidth = aContainerWidth;
   487     mBounds.ISize(mWritingMode) += aDISize;
   488   }
   490   /**
   491    * The ascent (distance from top to baseline) of the linebox is the
   492    * ascent of the anonymous inline box (for which we don't actually
   493    * create a frame) that wraps all the consecutive inline children of a
   494    * block.
   495    *
   496    * This is currently unused for block lines.
   497    */
   498   nscoord GetAscent() const { return mAscent; }
   499   void SetAscent(nscoord aAscent) { mAscent = aAscent; }
   501   nscoord BStart() const {
   502     return mBounds.BStart(mWritingMode);
   503   }
   504   nscoord BSize() const {
   505     return mBounds.BSize(mWritingMode);
   506   }
   507   nscoord BEnd() const {
   508     return mBounds.BEnd(mWritingMode);
   509   }
   510   nscoord IStart() const {
   511     return mBounds.IStart(mWritingMode);
   512   }
   513   nscoord ISize() const {
   514     return mBounds.ISize(mWritingMode);
   515   }
   516   nscoord IEnd() const {
   517     return mBounds.IEnd(mWritingMode);
   518   }
   519   void SetBoundsEmpty() {
   520     mBounds.IStart(mWritingMode) = 0;
   521     mBounds.ISize(mWritingMode) = 0;
   522     mBounds.BStart(mWritingMode) = 0;
   523     mBounds.BSize(mWritingMode) = 0;
   524   }
   526   static void DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines,
   527                              nsIFrame* aDestructRoot, nsFrameList* aFrames);
   529   // search from end to beginning of [aBegin, aEnd)
   530   // Returns true if it found the line and false if not.
   531   // Moves aEnd as it searches so that aEnd points to the resulting line.
   532   // aLastFrameBeforeEnd is the last frame before aEnd (so if aEnd is
   533   // the end of the line list, it's just the last frame in the frame
   534   // list).
   535   static bool RFindLineContaining(nsIFrame* aFrame,
   536                                     const nsLineList_iterator& aBegin,
   537                                     nsLineList_iterator& aEnd,
   538                                     nsIFrame* aLastFrameBeforeEnd,
   539                                     int32_t* aFrameIndexInLine);
   541 #ifdef DEBUG_FRAME_DUMP
   542   char* StateToString(char* aBuf, int32_t aBufSize) const;
   544   void List(FILE* out, int32_t aIndent, uint32_t aFlags = 0) const;
   545   void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const;
   546   nsIFrame* LastChild() const;
   547 #endif
   549 private:
   550   int32_t IndexOf(nsIFrame* aFrame) const;
   551 public:
   553   bool Contains(nsIFrame* aFrame) const {
   554     return MOZ_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Contains(aFrame)
   555                                                 : IndexOf(aFrame) >= 0;
   556   }
   558   // whether the line box is "logically" empty (just like nsIFrame::IsEmpty)
   559   bool IsEmpty() const;
   561   // Call this only while in Reflow() for the block the line belongs
   562   // to, only between reflowing the line (or sliding it, if we skip
   563   // reflowing it) and the end of reflowing the block.
   564   bool CachedIsEmpty();
   566   void InvalidateCachedIsEmpty() {
   567     mFlags.mEmptyCacheValid = false;
   568   }
   570   // For debugging purposes
   571   bool IsValidCachedIsEmpty() {
   572     return mFlags.mEmptyCacheValid;
   573   }
   575 #ifdef DEBUG
   576   static int32_t GetCtorCount();
   577 #endif
   579   nsIFrame* mFirstChild;
   581   mozilla::WritingMode mWritingMode;
   582   nscoord mContainerWidth;
   583  private:
   584   mozilla::LogicalRect mBounds;
   585  public:
   586   const mozilla::LogicalRect& GetBounds() { return mBounds; }
   587   nsRect GetPhysicalBounds() const
   588   {
   589     if (mBounds.IsEmpty()) {
   590       return nsRect(0, 0, 0, 0);
   591     }
   593     NS_ASSERTION(mContainerWidth != -1, "mContainerWidth not initialized");
   594     return mBounds.GetPhysicalRect(mWritingMode, mContainerWidth);
   595   }
   596   void SetBounds(mozilla::WritingMode aWritingMode,
   597                  nscoord aIStart, nscoord aBStart,
   598                  nscoord aISize, nscoord aBSize,
   599                  nscoord aContainerWidth)
   600   {
   601     mWritingMode = aWritingMode;
   602     mContainerWidth = aContainerWidth;
   603     mBounds = mozilla::LogicalRect(aWritingMode, aIStart, aBStart,
   604                                    aISize, aBSize);
   605   }
   606   void SetBounds(mozilla::WritingMode aWritingMode,
   607                  nsRect aRect, nscoord aContainerWidth)
   608   {
   609     mWritingMode = aWritingMode;
   610     mContainerWidth = aContainerWidth;
   611     mBounds = mozilla::LogicalRect(aWritingMode, aRect, aContainerWidth);
   612   }
   614   // mFlags.mHasHashedFrames says which one to use
   615   union {
   616     nsTHashtable< nsPtrHashKey<nsIFrame> >* mFrames;
   617     uint32_t mChildCount;
   618   };
   620   struct FlagBits {
   621     uint32_t mDirty : 1;
   622     uint32_t mPreviousMarginDirty : 1;
   623     uint32_t mHasClearance : 1;
   624     uint32_t mBlock : 1;
   625     uint32_t mImpactedByFloat : 1;
   626     uint32_t mLineWrapped: 1;
   627     uint32_t mInvalidateTextRuns : 1;
   628     uint32_t mResizeReflowOptimizationDisabled: 1;  // default 0 = means that the opt potentially applies to this line. 1 = never skip reflowing this line for a resize reflow
   629     uint32_t mEmptyCacheValid: 1;
   630     uint32_t mEmptyCacheState: 1;
   631     // mHasBullet indicates that this is an inline line whose block's
   632     // bullet is adjacent to this line and non-empty.
   633     uint32_t mHasBullet : 1;
   634     // Indicates that this line *may* have a placeholder for a float
   635     // that was pushed to a later column or page.
   636     uint32_t mHadFloatPushed : 1;
   637     uint32_t mHasHashedFrames: 1;
   638     uint32_t mBreakType : 4;
   639   };
   641   struct ExtraData {
   642     ExtraData(const nsRect& aBounds) : mOverflowAreas(aBounds, aBounds) {
   643     }
   644     nsOverflowAreas mOverflowAreas;
   645   };
   647   struct ExtraBlockData : public ExtraData {
   648     ExtraBlockData(const nsRect& aBounds)
   649       : ExtraData(aBounds),
   650         mCarriedOutBottomMargin()
   651     {
   652     }
   653     nsCollapsingMargin mCarriedOutBottomMargin;
   654   };
   656   struct ExtraInlineData : public ExtraData {
   657     ExtraInlineData(const nsRect& aBounds) : ExtraData(aBounds) {
   658     }
   659     nsFloatCacheList mFloats;
   660   };
   662 protected:
   663   nscoord mAscent;           // see |SetAscent| / |GetAscent|
   664   union {
   665     uint32_t mAllFlags;
   666     FlagBits mFlags;
   667   };
   669   union {
   670     ExtraData* mData;
   671     ExtraBlockData* mBlockData;
   672     ExtraInlineData* mInlineData;
   673   };
   675   void Cleanup();
   676   void MaybeFreeData();
   677 };
   679 /**
   680  * A linked list type where the items in the list must inherit from
   681  * a link type to fuse allocations.
   682  *
   683  * API heavily based on the |list| class in the C++ standard.
   684  */
   686 class nsLineList_iterator {
   687   public:
   688     friend class nsLineList;
   689     friend class nsLineList_reverse_iterator;
   690     friend class nsLineList_const_iterator;
   691     friend class nsLineList_const_reverse_iterator;
   693     typedef nsLineList_iterator         iterator_self_type;
   694     typedef nsLineList_reverse_iterator iterator_reverse_type;
   696     typedef nsLineBox&                  reference;
   697     typedef const nsLineBox&            const_reference;
   699     typedef nsLineBox*                  pointer;
   700     typedef const nsLineBox*            const_pointer;
   702     typedef uint32_t                    size_type;
   703     typedef int32_t                     difference_type;
   705     typedef nsLineLink                  link_type;
   707 #ifdef DEBUG
   708     nsLineList_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
   709 #else
   710     // Auto generated default constructor OK.
   711 #endif
   712     // Auto generated copy-constructor OK.
   714     inline iterator_self_type&
   715         operator=(const iterator_self_type& aOther);
   716     inline iterator_self_type&
   717         operator=(const iterator_reverse_type& aOther);
   719     iterator_self_type& operator++()
   720     {
   721       mCurrent = mCurrent->_mNext;
   722       return *this;
   723     }
   725     iterator_self_type operator++(int)
   726     {
   727       iterator_self_type rv(*this);
   728       mCurrent = mCurrent->_mNext;
   729       return rv;
   730     }
   732     iterator_self_type& operator--()
   733     {
   734       mCurrent = mCurrent->_mPrev;
   735       return *this;
   736     }
   738     iterator_self_type operator--(int)
   739     {
   740       iterator_self_type rv(*this);
   741       mCurrent = mCurrent->_mPrev;
   742       return rv;
   743     }
   745     reference operator*()
   746     {
   747       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   748       return *static_cast<pointer>(mCurrent);
   749     }
   751     pointer operator->()
   752     {
   753       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   754       return static_cast<pointer>(mCurrent);
   755     }
   757     pointer get()
   758     {
   759       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   760       return static_cast<pointer>(mCurrent);
   761     }
   763     operator pointer()
   764     {
   765       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   766       return static_cast<pointer>(mCurrent);
   767     }
   769     const_reference operator*() const
   770     {
   771       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   772       return *static_cast<const_pointer>(mCurrent);
   773     }
   775     const_pointer operator->() const
   776     {
   777       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   778       return static_cast<const_pointer>(mCurrent);
   779     }
   781 #ifndef __MWERKS__
   782     operator const_pointer() const
   783     {
   784       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   785       return static_cast<const_pointer>(mCurrent);
   786     }
   787 #endif /* !__MWERKS__ */
   789     iterator_self_type next()
   790     {
   791       iterator_self_type copy(*this);
   792       return ++copy;
   793     }
   795     const iterator_self_type next() const
   796     {
   797       iterator_self_type copy(*this);
   798       return ++copy;
   799     }
   801     iterator_self_type prev()
   802     {
   803       iterator_self_type copy(*this);
   804       return --copy;
   805     }
   807     const iterator_self_type prev() const
   808     {
   809       iterator_self_type copy(*this);
   810       return --copy;
   811     }
   813     // Passing by value rather than by reference and reference to const
   814     // to keep AIX happy.
   815     bool operator==(const iterator_self_type aOther) const
   816     {
   817       NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
   818       return mCurrent == aOther.mCurrent;
   819     }
   820     bool operator!=(const iterator_self_type aOther) const
   821     {
   822       NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
   823       return mCurrent != aOther.mCurrent;
   824     }
   825     bool operator==(const iterator_self_type aOther)
   826     {
   827       NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
   828       return mCurrent == aOther.mCurrent;
   829     }
   830     bool operator!=(const iterator_self_type aOther)
   831     {
   832       NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists");
   833       return mCurrent != aOther.mCurrent;
   834     }
   836   private:
   837     link_type *mCurrent;
   838 #ifdef DEBUG
   839     link_type *mListLink; // the list's link, i.e., the end
   840 #endif
   841 };
   843 class nsLineList_reverse_iterator {
   845   public:
   847     friend class nsLineList;
   848     friend class nsLineList_iterator;
   849     friend class nsLineList_const_iterator;
   850     friend class nsLineList_const_reverse_iterator;
   852     typedef nsLineList_reverse_iterator iterator_self_type;
   853     typedef nsLineList_iterator         iterator_reverse_type;
   855     typedef nsLineBox&                  reference;
   856     typedef const nsLineBox&            const_reference;
   858     typedef nsLineBox*                  pointer;
   859     typedef const nsLineBox*            const_pointer;
   861     typedef uint32_t                    size_type;
   862     typedef int32_t                     difference_type;
   864     typedef nsLineLink                  link_type;
   866 #ifdef DEBUG
   867     nsLineList_reverse_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
   868 #else
   869     // Auto generated default constructor OK.
   870 #endif
   871     // Auto generated copy-constructor OK.
   873     inline iterator_self_type&
   874         operator=(const iterator_reverse_type& aOther);
   875     inline iterator_self_type&
   876         operator=(const iterator_self_type& aOther);
   878     iterator_self_type& operator++()
   879     {
   880       mCurrent = mCurrent->_mPrev;
   881       return *this;
   882     }
   884     iterator_self_type operator++(int)
   885     {
   886       iterator_self_type rv(*this);
   887       mCurrent = mCurrent->_mPrev;
   888       return rv;
   889     }
   891     iterator_self_type& operator--()
   892     {
   893       mCurrent = mCurrent->_mNext;
   894       return *this;
   895     }
   897     iterator_self_type operator--(int)
   898     {
   899       iterator_self_type rv(*this);
   900       mCurrent = mCurrent->_mNext;
   901       return rv;
   902     }
   904     reference operator*()
   905     {
   906       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   907       return *static_cast<pointer>(mCurrent);
   908     }
   910     pointer operator->()
   911     {
   912       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   913       return static_cast<pointer>(mCurrent);
   914     }
   916     pointer get()
   917     {
   918       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   919       return static_cast<pointer>(mCurrent);
   920     }
   922     operator pointer()
   923     {
   924       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   925       return static_cast<pointer>(mCurrent);
   926     }
   928     const_reference operator*() const
   929     {
   930       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   931       return *static_cast<const_pointer>(mCurrent);
   932     }
   934     const_pointer operator->() const
   935     {
   936       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   937       return static_cast<const_pointer>(mCurrent);
   938     }
   940 #ifndef __MWERKS__
   941     operator const_pointer() const
   942     {
   943       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
   944       return static_cast<const_pointer>(mCurrent);
   945     }
   946 #endif /* !__MWERKS__ */
   948     // Passing by value rather than by reference and reference to const
   949     // to keep AIX happy.
   950     bool operator==(const iterator_self_type aOther) const
   951     {
   952       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
   953       return mCurrent == aOther.mCurrent;
   954     }
   955     bool operator!=(const iterator_self_type aOther) const
   956     {
   957       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
   958       return mCurrent != aOther.mCurrent;
   959     }
   960     bool operator==(const iterator_self_type aOther)
   961     {
   962       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
   963       return mCurrent == aOther.mCurrent;
   964     }
   965     bool operator!=(const iterator_self_type aOther)
   966     {
   967       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
   968       return mCurrent != aOther.mCurrent;
   969     }
   971   private:
   972     link_type *mCurrent;
   973 #ifdef DEBUG
   974     link_type *mListLink; // the list's link, i.e., the end
   975 #endif
   976 };
   978 class nsLineList_const_iterator {
   979   public:
   981     friend class nsLineList;
   982     friend class nsLineList_iterator;
   983     friend class nsLineList_reverse_iterator;
   984     friend class nsLineList_const_reverse_iterator;
   986     typedef nsLineList_const_iterator           iterator_self_type;
   987     typedef nsLineList_const_reverse_iterator   iterator_reverse_type;
   988     typedef nsLineList_iterator                 iterator_nonconst_type;
   989     typedef nsLineList_reverse_iterator         iterator_nonconst_reverse_type;
   991     typedef nsLineBox&                  reference;
   992     typedef const nsLineBox&            const_reference;
   994     typedef nsLineBox*                  pointer;
   995     typedef const nsLineBox*            const_pointer;
   997     typedef uint32_t                    size_type;
   998     typedef int32_t                     difference_type;
  1000     typedef nsLineLink                  link_type;
  1002 #ifdef DEBUG
  1003     nsLineList_const_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
  1004 #else
  1005     // Auto generated default constructor OK.
  1006 #endif
  1007     // Auto generated copy-constructor OK.
  1009     inline iterator_self_type&
  1010         operator=(const iterator_nonconst_type& aOther);
  1011     inline iterator_self_type&
  1012         operator=(const iterator_nonconst_reverse_type& aOther);
  1013     inline iterator_self_type&
  1014         operator=(const iterator_self_type& aOther);
  1015     inline iterator_self_type&
  1016         operator=(const iterator_reverse_type& aOther);
  1018     iterator_self_type& operator++()
  1020       mCurrent = mCurrent->_mNext;
  1021       return *this;
  1024     iterator_self_type operator++(int)
  1026       iterator_self_type rv(*this);
  1027       mCurrent = mCurrent->_mNext;
  1028       return rv;
  1031     iterator_self_type& operator--()
  1033       mCurrent = mCurrent->_mPrev;
  1034       return *this;
  1037     iterator_self_type operator--(int)
  1039       iterator_self_type rv(*this);
  1040       mCurrent = mCurrent->_mPrev;
  1041       return rv;
  1044     const_reference operator*() const
  1046       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
  1047       return *static_cast<const_pointer>(mCurrent);
  1050     const_pointer operator->() const
  1052       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
  1053       return static_cast<const_pointer>(mCurrent);
  1056     const_pointer get() const
  1058       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
  1059       return static_cast<const_pointer>(mCurrent);
  1062 #ifndef __MWERKS__
  1063     operator const_pointer() const
  1065       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
  1066       return static_cast<const_pointer>(mCurrent);
  1068 #endif /* !__MWERKS__ */
  1070     const iterator_self_type next() const
  1072       iterator_self_type copy(*this);
  1073       return ++copy;
  1076     const iterator_self_type prev() const
  1078       iterator_self_type copy(*this);
  1079       return --copy;
  1082     // Passing by value rather than by reference and reference to const
  1083     // to keep AIX happy.
  1084     bool operator==(const iterator_self_type aOther) const
  1086       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
  1087       return mCurrent == aOther.mCurrent;
  1089     bool operator!=(const iterator_self_type aOther) const
  1091       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
  1092       return mCurrent != aOther.mCurrent;
  1094     bool operator==(const iterator_self_type aOther)
  1096       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
  1097       return mCurrent == aOther.mCurrent;
  1099     bool operator!=(const iterator_self_type aOther)
  1101       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
  1102       return mCurrent != aOther.mCurrent;
  1105   private:
  1106     const link_type *mCurrent;
  1107 #ifdef DEBUG
  1108     const link_type *mListLink; // the list's link, i.e., the end
  1109 #endif
  1110 };
  1112 class nsLineList_const_reverse_iterator {
  1113   public:
  1115     friend class nsLineList;
  1116     friend class nsLineList_iterator;
  1117     friend class nsLineList_reverse_iterator;
  1118     friend class nsLineList_const_iterator;
  1120     typedef nsLineList_const_reverse_iterator   iterator_self_type;
  1121     typedef nsLineList_const_iterator           iterator_reverse_type;
  1122     typedef nsLineList_iterator                 iterator_nonconst_reverse_type;
  1123     typedef nsLineList_reverse_iterator         iterator_nonconst_type;
  1125     typedef nsLineBox&                  reference;
  1126     typedef const nsLineBox&            const_reference;
  1128     typedef nsLineBox*                  pointer;
  1129     typedef const nsLineBox*            const_pointer;
  1131     typedef uint32_t                    size_type;
  1132     typedef int32_t                     difference_type;
  1134     typedef nsLineLink                  link_type;
  1136 #ifdef DEBUG
  1137     nsLineList_const_reverse_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); }
  1138 #else
  1139     // Auto generated default constructor OK.
  1140 #endif
  1141     // Auto generated copy-constructor OK.
  1143     inline iterator_self_type&
  1144         operator=(const iterator_nonconst_type& aOther);
  1145     inline iterator_self_type&
  1146         operator=(const iterator_nonconst_reverse_type& aOther);
  1147     inline iterator_self_type&
  1148         operator=(const iterator_self_type& aOther);
  1149     inline iterator_self_type&
  1150         operator=(const iterator_reverse_type& aOther);
  1152     iterator_self_type& operator++()
  1154       mCurrent = mCurrent->_mPrev;
  1155       return *this;
  1158     iterator_self_type operator++(int)
  1160       iterator_self_type rv(*this);
  1161       mCurrent = mCurrent->_mPrev;
  1162       return rv;
  1165     iterator_self_type& operator--()
  1167       mCurrent = mCurrent->_mNext;
  1168       return *this;
  1171     iterator_self_type operator--(int)
  1173       iterator_self_type rv(*this);
  1174       mCurrent = mCurrent->_mNext;
  1175       return rv;
  1178     const_reference operator*() const
  1180       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
  1181       return *static_cast<const_pointer>(mCurrent);
  1184     const_pointer operator->() const
  1186       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
  1187       return static_cast<const_pointer>(mCurrent);
  1190     const_pointer get() const
  1192       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
  1193       return static_cast<const_pointer>(mCurrent);
  1196 #ifndef __MWERKS__
  1197     operator const_pointer() const
  1199       NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end");
  1200       return static_cast<const_pointer>(mCurrent);
  1202 #endif /* !__MWERKS__ */
  1204     // Passing by value rather than by reference and reference to const
  1205     // to keep AIX happy.
  1206     bool operator==(const iterator_self_type aOther) const
  1208       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
  1209       return mCurrent == aOther.mCurrent;
  1211     bool operator!=(const iterator_self_type aOther) const
  1213       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
  1214       return mCurrent != aOther.mCurrent;
  1216     bool operator==(const iterator_self_type aOther)
  1218       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
  1219       return mCurrent == aOther.mCurrent;
  1221     bool operator!=(const iterator_self_type aOther)
  1223       NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists");
  1224       return mCurrent != aOther.mCurrent;
  1227 //private:
  1228     const link_type *mCurrent;
  1229 #ifdef DEBUG
  1230     const link_type *mListLink; // the list's link, i.e., the end
  1231 #endif
  1232 };
  1234 class nsLineList {
  1236   public:
  1238   friend class nsLineList_iterator;
  1239   friend class nsLineList_reverse_iterator;
  1240   friend class nsLineList_const_iterator;
  1241   friend class nsLineList_const_reverse_iterator;
  1243   typedef uint32_t                    size_type;
  1244   typedef int32_t                     difference_type;
  1246   typedef nsLineLink                  link_type;
  1248   private:
  1249     link_type mLink;
  1251   public:
  1252     typedef nsLineList                  self_type;
  1254     typedef nsLineBox&                  reference;
  1255     typedef const nsLineBox&            const_reference;
  1257     typedef nsLineBox*                  pointer;
  1258     typedef const nsLineBox*            const_pointer;
  1260     typedef nsLineList_iterator         iterator;
  1261     typedef nsLineList_reverse_iterator reverse_iterator;
  1262     typedef nsLineList_const_iterator   const_iterator;
  1263     typedef nsLineList_const_reverse_iterator const_reverse_iterator;
  1265     nsLineList()
  1267       MOZ_COUNT_CTOR(nsLineList);
  1268       clear();
  1271     ~nsLineList()
  1273       MOZ_COUNT_DTOR(nsLineList);
  1276     const_iterator begin() const
  1278       const_iterator rv;
  1279       rv.mCurrent = mLink._mNext;
  1280 #ifdef DEBUG
  1281       rv.mListLink = &mLink;
  1282 #endif
  1283       return rv;
  1286     iterator begin()
  1288       iterator rv;
  1289       rv.mCurrent = mLink._mNext;
  1290 #ifdef DEBUG
  1291       rv.mListLink = &mLink;
  1292 #endif
  1293       return rv;
  1296     iterator begin(nsLineBox* aLine)
  1298       iterator rv;
  1299       rv.mCurrent = aLine;
  1300 #ifdef DEBUG
  1301       rv.mListLink = &mLink;
  1302 #endif
  1303       return rv;
  1306     const_iterator end() const
  1308       const_iterator rv;
  1309       rv.mCurrent = &mLink;
  1310 #ifdef DEBUG
  1311       rv.mListLink = &mLink;
  1312 #endif
  1313       return rv;
  1316     iterator end()
  1318       iterator rv;
  1319       rv.mCurrent = &mLink;
  1320 #ifdef DEBUG
  1321       rv.mListLink = &mLink;
  1322 #endif
  1323       return rv;
  1326     const_reverse_iterator rbegin() const
  1328       const_reverse_iterator rv;
  1329       rv.mCurrent = mLink._mPrev;
  1330 #ifdef DEBUG
  1331       rv.mListLink = &mLink;
  1332 #endif
  1333       return rv;
  1336     reverse_iterator rbegin()
  1338       reverse_iterator rv;
  1339       rv.mCurrent = mLink._mPrev;
  1340 #ifdef DEBUG
  1341       rv.mListLink = &mLink;
  1342 #endif
  1343       return rv;
  1346     reverse_iterator rbegin(nsLineBox* aLine)
  1348       reverse_iterator rv;
  1349       rv.mCurrent = aLine;
  1350 #ifdef DEBUG
  1351       rv.mListLink = &mLink;
  1352 #endif
  1353       return rv;
  1356     const_reverse_iterator rend() const
  1358       const_reverse_iterator rv;
  1359       rv.mCurrent = &mLink;
  1360 #ifdef DEBUG
  1361       rv.mListLink = &mLink;
  1362 #endif
  1363       return rv;
  1366     reverse_iterator rend()
  1368       reverse_iterator rv;
  1369       rv.mCurrent = &mLink;
  1370 #ifdef DEBUG
  1371       rv.mListLink = &mLink;
  1372 #endif
  1373       return rv;
  1376     bool empty() const
  1378       return mLink._mNext == &mLink;
  1381     // NOTE: O(N).
  1382     size_type size() const
  1384       size_type count = 0;
  1385       for (const link_type *cur = mLink._mNext;
  1386            cur != &mLink;
  1387            cur = cur->_mNext)
  1389         ++count;
  1391       return count;
  1394     pointer front()
  1396       NS_ASSERTION(!empty(), "no element to return");
  1397       return static_cast<pointer>(mLink._mNext);
  1400     const_pointer front() const
  1402       NS_ASSERTION(!empty(), "no element to return");
  1403       return static_cast<const_pointer>(mLink._mNext);
  1406     pointer back()
  1408       NS_ASSERTION(!empty(), "no element to return");
  1409       return static_cast<pointer>(mLink._mPrev);
  1412     const_pointer back() const
  1414       NS_ASSERTION(!empty(), "no element to return");
  1415       return static_cast<const_pointer>(mLink._mPrev);
  1418     void push_front(pointer aNew)
  1420       aNew->_mNext = mLink._mNext;
  1421       mLink._mNext->_mPrev = aNew;
  1422       aNew->_mPrev = &mLink;
  1423       mLink._mNext = aNew;
  1426     void pop_front()
  1427         // NOTE: leaves dangling next/prev pointers
  1429       NS_ASSERTION(!empty(), "no element to pop");
  1430       link_type *newFirst = mLink._mNext->_mNext;
  1431       newFirst->_mPrev = &mLink;
  1432       // mLink._mNext->_mNext = nullptr;
  1433       // mLink._mNext->_mPrev = nullptr;
  1434       mLink._mNext = newFirst;
  1437     void push_back(pointer aNew)
  1439       aNew->_mPrev = mLink._mPrev;
  1440       mLink._mPrev->_mNext = aNew;
  1441       aNew->_mNext = &mLink;
  1442       mLink._mPrev = aNew;
  1445     void pop_back()
  1446         // NOTE: leaves dangling next/prev pointers
  1448       NS_ASSERTION(!empty(), "no element to pop");
  1449       link_type *newLast = mLink._mPrev->_mPrev;
  1450       newLast->_mNext = &mLink;
  1451       // mLink._mPrev->_mPrev = nullptr;
  1452       // mLink._mPrev->_mNext = nullptr;
  1453       mLink._mPrev = newLast;
  1456     // inserts x before position
  1457     iterator before_insert(iterator position, pointer x)
  1459       // use |mCurrent| to prevent DEBUG_PASS_END assertions
  1460       x->_mPrev = position.mCurrent->_mPrev;
  1461       x->_mNext = position.mCurrent;
  1462       position.mCurrent->_mPrev->_mNext = x;
  1463       position.mCurrent->_mPrev = x;
  1464       return --position;
  1467     // inserts x after position
  1468     iterator after_insert(iterator position, pointer x)
  1470       // use |mCurrent| to prevent DEBUG_PASS_END assertions
  1471       x->_mNext = position.mCurrent->_mNext;
  1472       x->_mPrev = position.mCurrent;
  1473       position.mCurrent->_mNext->_mPrev = x;
  1474       position.mCurrent->_mNext = x;
  1475       return ++position;
  1478     // returns iterator pointing to after the element
  1479     iterator erase(iterator position)
  1480         // NOTE: leaves dangling next/prev pointers
  1482       position->_mPrev->_mNext = position->_mNext;
  1483       position->_mNext->_mPrev = position->_mPrev;
  1484       return ++position;
  1487     void swap(self_type& y)
  1489       link_type tmp(y.mLink);
  1490       y.mLink = mLink;
  1491       mLink = tmp;
  1493       if (!empty()) {
  1494         mLink._mNext->_mPrev = &mLink;
  1495         mLink._mPrev->_mNext = &mLink;
  1498       if (!y.empty()) {
  1499         y.mLink._mNext->_mPrev = &y.mLink;
  1500         y.mLink._mPrev->_mNext = &y.mLink;
  1504     void clear()
  1505         // NOTE:  leaves dangling next/prev pointers
  1507       mLink._mNext = &mLink;
  1508       mLink._mPrev = &mLink;
  1511     // inserts the conts of x before position and makes x empty
  1512     void splice(iterator position, self_type& x)
  1514       // use |mCurrent| to prevent DEBUG_PASS_END assertions
  1515       position.mCurrent->_mPrev->_mNext = x.mLink._mNext;
  1516       x.mLink._mNext->_mPrev = position.mCurrent->_mPrev;
  1517       x.mLink._mPrev->_mNext = position.mCurrent;
  1518       position.mCurrent->_mPrev = x.mLink._mPrev;
  1519       x.clear();
  1522     // Inserts element *i from list x before position and removes
  1523     // it from x.
  1524     void splice(iterator position, self_type& x, iterator i)
  1526       NS_ASSERTION(!x.empty(), "Can't insert from empty list.");
  1527       NS_ASSERTION(position != i && position.mCurrent != i->_mNext,
  1528                    "We don't check for this case.");
  1530       // remove from |x|
  1531       i->_mPrev->_mNext = i->_mNext;
  1532       i->_mNext->_mPrev = i->_mPrev;
  1534       // use |mCurrent| to prevent DEBUG_PASS_END assertions
  1535       // link into |this|, before-side
  1536       i->_mPrev = position.mCurrent->_mPrev;
  1537       position.mCurrent->_mPrev->_mNext = i.get();
  1539       // link into |this|, after-side
  1540       i->_mNext = position.mCurrent;
  1541       position.mCurrent->_mPrev = i.get();
  1544     // Inserts elements in [|first|, |last|), which are in |x|,
  1545     // into |this| before |position| and removes them from |x|.
  1546     void splice(iterator position, self_type& x, iterator first,
  1547                 iterator last)
  1549       NS_ASSERTION(!x.empty(), "Can't insert from empty list.");
  1551       if (first == last)
  1552         return;
  1554       --last; // so we now want to move [first, last]
  1555       // remove from |x|
  1556       first->_mPrev->_mNext = last->_mNext;
  1557       last->_mNext->_mPrev = first->_mPrev;
  1559       // use |mCurrent| to prevent DEBUG_PASS_END assertions
  1560       // link into |this|, before-side
  1561       first->_mPrev = position.mCurrent->_mPrev;
  1562       position.mCurrent->_mPrev->_mNext = first.get();
  1564       // link into |this|, after-side
  1565       last->_mNext = position.mCurrent;
  1566       position.mCurrent->_mPrev = last.get();
  1569 };
  1572 // Many of these implementations of operator= don't work yet.  I don't
  1573 // know why.
  1575 #ifdef DEBUG
  1577   // NOTE: ASSIGN_FROM is meant to be used *only* as the entire body
  1578   // of a function and therefore lacks PR_{BEGIN,END}_MACRO
  1579 #define ASSIGN_FROM(other_)          \
  1580   mCurrent = other_.mCurrent;        \
  1581   mListLink = other_.mListLink;      \
  1582   return *this;
  1584 #else /* !NS_LINELIST_DEBUG_PASS_END */
  1586 #define ASSIGN_FROM(other_)          \
  1587   mCurrent = other_.mCurrent;        \
  1588   return *this;
  1590 #endif /* !NS_LINELIST_DEBUG_PASS_END */
  1592 inline
  1593 nsLineList_iterator&
  1594 nsLineList_iterator::operator=(const nsLineList_iterator& aOther)
  1596   ASSIGN_FROM(aOther)
  1599 inline
  1600 nsLineList_iterator&
  1601 nsLineList_iterator::operator=(const nsLineList_reverse_iterator& aOther)
  1603   ASSIGN_FROM(aOther)
  1606 inline
  1607 nsLineList_reverse_iterator&
  1608 nsLineList_reverse_iterator::operator=(const nsLineList_iterator& aOther)
  1610   ASSIGN_FROM(aOther)
  1613 inline
  1614 nsLineList_reverse_iterator&
  1615 nsLineList_reverse_iterator::operator=(const nsLineList_reverse_iterator& aOther)
  1617   ASSIGN_FROM(aOther)
  1620 inline
  1621 nsLineList_const_iterator&
  1622 nsLineList_const_iterator::operator=(const nsLineList_iterator& aOther)
  1624   ASSIGN_FROM(aOther)
  1627 inline
  1628 nsLineList_const_iterator&
  1629 nsLineList_const_iterator::operator=(const nsLineList_reverse_iterator& aOther)
  1631   ASSIGN_FROM(aOther)
  1634 inline
  1635 nsLineList_const_iterator&
  1636 nsLineList_const_iterator::operator=(const nsLineList_const_iterator& aOther)
  1638   ASSIGN_FROM(aOther)
  1641 inline
  1642 nsLineList_const_iterator&
  1643 nsLineList_const_iterator::operator=(const nsLineList_const_reverse_iterator& aOther)
  1645   ASSIGN_FROM(aOther)
  1648 inline
  1649 nsLineList_const_reverse_iterator&
  1650 nsLineList_const_reverse_iterator::operator=(const nsLineList_iterator& aOther)
  1652   ASSIGN_FROM(aOther)
  1655 inline
  1656 nsLineList_const_reverse_iterator&
  1657 nsLineList_const_reverse_iterator::operator=(const nsLineList_reverse_iterator& aOther)
  1659   ASSIGN_FROM(aOther)
  1662 inline
  1663 nsLineList_const_reverse_iterator&
  1664 nsLineList_const_reverse_iterator::operator=(const nsLineList_const_iterator& aOther)
  1666   ASSIGN_FROM(aOther)
  1669 inline
  1670 nsLineList_const_reverse_iterator&
  1671 nsLineList_const_reverse_iterator::operator=(const nsLineList_const_reverse_iterator& aOther)
  1673   ASSIGN_FROM(aOther)
  1677 //----------------------------------------------------------------------
  1679 class nsLineIterator MOZ_FINAL : public nsILineIterator
  1681 public:
  1682   nsLineIterator();
  1683   ~nsLineIterator();
  1685   virtual void DisposeLineIterator() MOZ_OVERRIDE;
  1687   virtual int32_t GetNumLines() MOZ_OVERRIDE;
  1688   virtual bool GetDirection() MOZ_OVERRIDE;
  1689   NS_IMETHOD GetLine(int32_t aLineNumber,
  1690                      nsIFrame** aFirstFrameOnLine,
  1691                      int32_t* aNumFramesOnLine,
  1692                      nsRect& aLineBounds,
  1693                      uint32_t* aLineFlags) MOZ_OVERRIDE;
  1694   virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) MOZ_OVERRIDE;
  1695   NS_IMETHOD FindFrameAt(int32_t aLineNumber,
  1696                          nscoord aX,
  1697                          nsIFrame** aFrameFound,
  1698                          bool* aXIsBeforeFirstFrame,
  1699                          bool* aXIsAfterLastFrame) MOZ_OVERRIDE;
  1701   NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, int32_t aLineNumber) MOZ_OVERRIDE;
  1702   NS_IMETHOD CheckLineOrder(int32_t                  aLine,
  1703                             bool                     *aIsReordered,
  1704                             nsIFrame                 **aFirstVisual,
  1705                             nsIFrame                 **aLastVisual) MOZ_OVERRIDE;
  1706   nsresult Init(nsLineList& aLines, bool aRightToLeft);
  1708 private:
  1709   nsLineBox* PrevLine() {
  1710     if (0 == mIndex) {
  1711       return nullptr;
  1713     return mLines[--mIndex];
  1716   nsLineBox* NextLine() {
  1717     if (mIndex >= mNumLines - 1) {
  1718       return nullptr;
  1720     return mLines[++mIndex];
  1723   nsLineBox* LineAt(int32_t aIndex) {
  1724     if ((aIndex < 0) || (aIndex >= mNumLines)) {
  1725       return nullptr;
  1727     return mLines[aIndex];
  1730   nsLineBox** mLines;
  1731   int32_t mIndex;
  1732   int32_t mNumLines;
  1733   bool mRightToLeft;
  1734 };
  1736 #endif /* nsLineBox_h___ */

mercurial