1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsLineBox.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1736 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +// vim:cindent:ts=2:et:sw=2: 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +/* representation of one line within a block frame, a CSS line box */ 1.11 + 1.12 +#ifndef nsLineBox_h___ 1.13 +#define nsLineBox_h___ 1.14 + 1.15 +#include "mozilla/Attributes.h" 1.16 +#include "mozilla/Likely.h" 1.17 + 1.18 +#include "nsILineIterator.h" 1.19 +#include "nsIFrame.h" 1.20 +#include <algorithm> 1.21 + 1.22 +class nsLineBox; 1.23 +class nsFloatCache; 1.24 +class nsFloatCacheList; 1.25 +class nsFloatCacheFreeList; 1.26 + 1.27 +// State cached after reflowing a float. This state is used during 1.28 +// incremental reflow when we avoid reflowing a float. 1.29 +class nsFloatCache { 1.30 +public: 1.31 + nsFloatCache(); 1.32 +#ifdef NS_BUILD_REFCNT_LOGGING 1.33 + ~nsFloatCache(); 1.34 +#else 1.35 + ~nsFloatCache() { } 1.36 +#endif 1.37 + 1.38 + nsFloatCache* Next() const { return mNext; } 1.39 + 1.40 + nsIFrame* mFloat; // floating frame 1.41 + 1.42 +protected: 1.43 + nsFloatCache* mNext; 1.44 + 1.45 + friend class nsFloatCacheList; 1.46 + friend class nsFloatCacheFreeList; 1.47 +}; 1.48 + 1.49 +//---------------------------------------- 1.50 + 1.51 +class nsFloatCacheList { 1.52 +public: 1.53 +#ifdef NS_BUILD_REFCNT_LOGGING 1.54 + nsFloatCacheList(); 1.55 +#else 1.56 + nsFloatCacheList() : mHead(nullptr) { } 1.57 +#endif 1.58 + ~nsFloatCacheList(); 1.59 + 1.60 + bool IsEmpty() const { 1.61 + return nullptr == mHead; 1.62 + } 1.63 + 1.64 + bool NotEmpty() const { 1.65 + return nullptr != mHead; 1.66 + } 1.67 + 1.68 + nsFloatCache* Head() const { 1.69 + return mHead; 1.70 + } 1.71 + 1.72 + nsFloatCache* Tail() const; 1.73 + 1.74 + void DeleteAll(); 1.75 + 1.76 + nsFloatCache* Find(nsIFrame* aOutOfFlowFrame); 1.77 + 1.78 + // Remove a nsFloatCache from this list. Deleting this nsFloatCache 1.79 + // becomes the caller's responsibility. 1.80 + void Remove(nsFloatCache* aElement) { RemoveAndReturnPrev(aElement); } 1.81 + 1.82 + // Steal away aList's nsFloatCache objects and put them in this 1.83 + // list. aList must not be empty. 1.84 + void Append(nsFloatCacheFreeList& aList); 1.85 + 1.86 +protected: 1.87 + nsFloatCache* mHead; 1.88 + 1.89 + // Remove a nsFloatCache from this list. Deleting this nsFloatCache 1.90 + // becomes the caller's responsibility. Returns the nsFloatCache that was 1.91 + // before aElement, or nullptr if aElement was the first. 1.92 + nsFloatCache* RemoveAndReturnPrev(nsFloatCache* aElement); 1.93 + 1.94 + friend class nsFloatCacheFreeList; 1.95 +}; 1.96 + 1.97 +//--------------------------------------- 1.98 +// Like nsFloatCacheList, but with fast access to the tail 1.99 + 1.100 +class nsFloatCacheFreeList : private nsFloatCacheList { 1.101 +public: 1.102 +#ifdef NS_BUILD_REFCNT_LOGGING 1.103 + nsFloatCacheFreeList(); 1.104 + ~nsFloatCacheFreeList(); 1.105 +#else 1.106 + nsFloatCacheFreeList() : mTail(nullptr) { } 1.107 + ~nsFloatCacheFreeList() { } 1.108 +#endif 1.109 + 1.110 + // Reimplement trivial functions 1.111 + bool IsEmpty() const { 1.112 + return nullptr == mHead; 1.113 + } 1.114 + 1.115 + nsFloatCache* Head() const { 1.116 + return mHead; 1.117 + } 1.118 + 1.119 + nsFloatCache* Tail() const { 1.120 + return mTail; 1.121 + } 1.122 + 1.123 + bool NotEmpty() const { 1.124 + return nullptr != mHead; 1.125 + } 1.126 + 1.127 + void DeleteAll(); 1.128 + 1.129 + // Steal away aList's nsFloatCache objects and put them on this 1.130 + // free-list. aList must not be empty. 1.131 + void Append(nsFloatCacheList& aList); 1.132 + 1.133 + void Append(nsFloatCache* aFloatCache); 1.134 + 1.135 + void Remove(nsFloatCache* aElement); 1.136 + 1.137 + // Remove an nsFloatCache object from this list and return it, or create 1.138 + // a new one if this one is empty; Set its mFloat to aFloat. 1.139 + nsFloatCache* Alloc(nsIFrame* aFloat); 1.140 + 1.141 +protected: 1.142 + nsFloatCache* mTail; 1.143 + 1.144 + friend class nsFloatCacheList; 1.145 +}; 1.146 + 1.147 +//---------------------------------------------------------------------- 1.148 + 1.149 +#define LINE_MAX_BREAK_TYPE ((1 << 4) - 1) 1.150 +#define LINE_MAX_CHILD_COUNT INT32_MAX 1.151 + 1.152 +/** 1.153 + * Function to create a line box and initialize it with a single frame. 1.154 + * The allocation is infallible. 1.155 + * If the frame was moved from another line then you're responsible 1.156 + * for notifying that line using NoteFrameRemoved(). Alternatively, 1.157 + * it's better to use the next function that does that for you in an 1.158 + * optimal way. 1.159 + */ 1.160 +nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame, 1.161 + bool aIsBlock); 1.162 +/** 1.163 + * Function to create a line box and initialize it with aCount frames 1.164 + * that are currently on aFromLine. The allocation is infallible. 1.165 + */ 1.166 +nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine, 1.167 + nsIFrame* aFrame, int32_t aCount); 1.168 + 1.169 +class nsLineList; 1.170 + 1.171 +// don't use the following names outside of this file. Instead, use 1.172 +// nsLineList::iterator, etc. These are just here to allow them to 1.173 +// be specified as parameters to methods of nsLineBox. 1.174 +class nsLineList_iterator; 1.175 +class nsLineList_const_iterator; 1.176 +class nsLineList_reverse_iterator; 1.177 +class nsLineList_const_reverse_iterator; 1.178 + 1.179 +/** 1.180 + * Users must have the class that is to be part of the list inherit 1.181 + * from nsLineLink. If they want to be efficient, it should be the 1.182 + * first base class. (This was originally nsCLink in a templatized 1.183 + * nsCList, but it's still useful separately.) 1.184 + */ 1.185 + 1.186 +class nsLineLink { 1.187 + 1.188 + public: 1.189 + friend class nsLineList; 1.190 + friend class nsLineList_iterator; 1.191 + friend class nsLineList_reverse_iterator; 1.192 + friend class nsLineList_const_iterator; 1.193 + friend class nsLineList_const_reverse_iterator; 1.194 + 1.195 + private: 1.196 + nsLineLink *_mNext; // or head 1.197 + nsLineLink *_mPrev; // or tail 1.198 + 1.199 +}; 1.200 + 1.201 + 1.202 +/** 1.203 + * The nsLineBox class represents a horizontal line of frames. It contains 1.204 + * enough state to support incremental reflow of the frames, event handling 1.205 + * for the frames, and rendering of the frames. 1.206 + */ 1.207 +class nsLineBox MOZ_FINAL : public nsLineLink { 1.208 +private: 1.209 + nsLineBox(nsIFrame* aFrame, int32_t aCount, bool aIsBlock); 1.210 + ~nsLineBox(); 1.211 + 1.212 + // Overloaded new operator. Uses an arena (which comes from the presShell) 1.213 + // to perform the allocation. 1.214 + void* operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW; 1.215 + void operator delete(void* aPtr, size_t sz) MOZ_DELETE; 1.216 + 1.217 +public: 1.218 + // Use these functions to allocate and destroy line boxes 1.219 + friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsIFrame* aFrame, 1.220 + bool aIsBlock); 1.221 + friend nsLineBox* NS_NewLineBox(nsIPresShell* aPresShell, nsLineBox* aFromLine, 1.222 + nsIFrame* aFrame, int32_t aCount); 1.223 + void Destroy(nsIPresShell* aPresShell); 1.224 + 1.225 + // mBlock bit 1.226 + bool IsBlock() const { 1.227 + return mFlags.mBlock; 1.228 + } 1.229 + bool IsInline() const { 1.230 + return 0 == mFlags.mBlock; 1.231 + } 1.232 + 1.233 + // mDirty bit 1.234 + void MarkDirty() { 1.235 + mFlags.mDirty = 1; 1.236 + } 1.237 + void ClearDirty() { 1.238 + mFlags.mDirty = 0; 1.239 + } 1.240 + bool IsDirty() const { 1.241 + return mFlags.mDirty; 1.242 + } 1.243 + 1.244 + // mPreviousMarginDirty bit 1.245 + void MarkPreviousMarginDirty() { 1.246 + mFlags.mPreviousMarginDirty = 1; 1.247 + } 1.248 + void ClearPreviousMarginDirty() { 1.249 + mFlags.mPreviousMarginDirty = 0; 1.250 + } 1.251 + bool IsPreviousMarginDirty() const { 1.252 + return mFlags.mPreviousMarginDirty; 1.253 + } 1.254 + 1.255 + // mHasClearance bit 1.256 + void SetHasClearance() { 1.257 + mFlags.mHasClearance = 1; 1.258 + } 1.259 + void ClearHasClearance() { 1.260 + mFlags.mHasClearance = 0; 1.261 + } 1.262 + bool HasClearance() const { 1.263 + return mFlags.mHasClearance; 1.264 + } 1.265 + 1.266 + // mImpactedByFloat bit 1.267 + void SetLineIsImpactedByFloat(bool aValue) { 1.268 + mFlags.mImpactedByFloat = aValue; 1.269 + } 1.270 + bool IsImpactedByFloat() const { 1.271 + return mFlags.mImpactedByFloat; 1.272 + } 1.273 + 1.274 + // mLineWrapped bit 1.275 + void SetLineWrapped(bool aOn) { 1.276 + mFlags.mLineWrapped = aOn; 1.277 + } 1.278 + bool IsLineWrapped() const { 1.279 + return mFlags.mLineWrapped; 1.280 + } 1.281 + 1.282 + // mInvalidateTextRuns bit 1.283 + void SetInvalidateTextRuns(bool aOn) { 1.284 + mFlags.mInvalidateTextRuns = aOn; 1.285 + } 1.286 + bool GetInvalidateTextRuns() const { 1.287 + return mFlags.mInvalidateTextRuns; 1.288 + } 1.289 + 1.290 + // mResizeReflowOptimizationDisabled bit 1.291 + void DisableResizeReflowOptimization() { 1.292 + mFlags.mResizeReflowOptimizationDisabled = true; 1.293 + } 1.294 + void EnableResizeReflowOptimization() { 1.295 + mFlags.mResizeReflowOptimizationDisabled = false; 1.296 + } 1.297 + bool ResizeReflowOptimizationDisabled() const { 1.298 + return mFlags.mResizeReflowOptimizationDisabled; 1.299 + } 1.300 + 1.301 + // mHasBullet bit 1.302 + void SetHasBullet() { 1.303 + mFlags.mHasBullet = true; 1.304 + InvalidateCachedIsEmpty(); 1.305 + } 1.306 + void ClearHasBullet() { 1.307 + mFlags.mHasBullet = false; 1.308 + InvalidateCachedIsEmpty(); 1.309 + } 1.310 + bool HasBullet() const { 1.311 + return mFlags.mHasBullet; 1.312 + } 1.313 + 1.314 + // mHadFloatPushed bit 1.315 + void SetHadFloatPushed() { 1.316 + mFlags.mHadFloatPushed = true; 1.317 + } 1.318 + void ClearHadFloatPushed() { 1.319 + mFlags.mHadFloatPushed = false; 1.320 + } 1.321 + bool HadFloatPushed() const { 1.322 + return mFlags.mHadFloatPushed; 1.323 + } 1.324 + 1.325 +private: 1.326 + // Add a hash table for fast lookup when the line has more frames than this. 1.327 + static const uint32_t kMinChildCountForHashtable = 200; 1.328 + 1.329 + /** 1.330 + * Take ownership of aFromLine's hash table and remove the frames that 1.331 + * stay on aFromLine from it, i.e. aFromLineNewCount frames starting with 1.332 + * mFirstChild. This method is used to optimize moving a large number 1.333 + * of frames from one line to the next. 1.334 + */ 1.335 + void StealHashTableFrom(nsLineBox* aFromLine, uint32_t aFromLineNewCount); 1.336 + 1.337 + /** 1.338 + * Does the equivalent of this->NoteFrameAdded and aFromLine->NoteFrameRemoved 1.339 + * for each frame on this line, but in a optimized way. 1.340 + */ 1.341 + void NoteFramesMovedFrom(nsLineBox* aFromLine); 1.342 + 1.343 + void SwitchToHashtable() 1.344 + { 1.345 + MOZ_ASSERT(!mFlags.mHasHashedFrames); 1.346 + uint32_t count = GetChildCount(); 1.347 + mFlags.mHasHashedFrames = 1; 1.348 + uint32_t minSize = 1.349 + std::max(kMinChildCountForHashtable, uint32_t(PL_DHASH_MIN_SIZE)); 1.350 + mFrames = new nsTHashtable< nsPtrHashKey<nsIFrame> >(std::max(count, minSize)); 1.351 + for (nsIFrame* f = mFirstChild; count-- > 0; f = f->GetNextSibling()) { 1.352 + mFrames->PutEntry(f); 1.353 + } 1.354 + } 1.355 + void SwitchToCounter() { 1.356 + MOZ_ASSERT(mFlags.mHasHashedFrames); 1.357 + uint32_t count = GetChildCount(); 1.358 + delete mFrames; 1.359 + mFlags.mHasHashedFrames = 0; 1.360 + mChildCount = count; 1.361 + } 1.362 + 1.363 +public: 1.364 + int32_t GetChildCount() const { 1.365 + return MOZ_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Count() : mChildCount; 1.366 + } 1.367 + 1.368 + /** 1.369 + * Register that aFrame is now on this line. 1.370 + */ 1.371 + void NoteFrameAdded(nsIFrame* aFrame) { 1.372 + if (MOZ_UNLIKELY(mFlags.mHasHashedFrames)) { 1.373 + mFrames->PutEntry(aFrame); 1.374 + } else { 1.375 + if (++mChildCount >= kMinChildCountForHashtable) { 1.376 + SwitchToHashtable(); 1.377 + } 1.378 + } 1.379 + } 1.380 + 1.381 + /** 1.382 + * Register that aFrame is not on this line anymore. 1.383 + */ 1.384 + void NoteFrameRemoved(nsIFrame* aFrame) { 1.385 + MOZ_ASSERT(GetChildCount() > 0); 1.386 + if (MOZ_UNLIKELY(mFlags.mHasHashedFrames)) { 1.387 + mFrames->RemoveEntry(aFrame); 1.388 + if (mFrames->Count() < kMinChildCountForHashtable) { 1.389 + SwitchToCounter(); 1.390 + } 1.391 + } else { 1.392 + --mChildCount; 1.393 + } 1.394 + } 1.395 + 1.396 + // mBreakType value 1.397 + // Break information is applied *before* the line if the line is a block, 1.398 + // or *after* the line if the line is an inline. Confusing, I know, but 1.399 + // using different names should help. 1.400 + bool HasBreakBefore() const { 1.401 + return IsBlock() && NS_STYLE_CLEAR_NONE != mFlags.mBreakType; 1.402 + } 1.403 + void SetBreakTypeBefore(uint8_t aBreakType) { 1.404 + NS_ASSERTION(IsBlock(), "Only blocks have break-before"); 1.405 + NS_ASSERTION(aBreakType == NS_STYLE_CLEAR_NONE || 1.406 + aBreakType == NS_STYLE_CLEAR_LEFT || 1.407 + aBreakType == NS_STYLE_CLEAR_RIGHT || 1.408 + aBreakType == NS_STYLE_CLEAR_BOTH, 1.409 + "Only float break types are allowed before a line"); 1.410 + mFlags.mBreakType = aBreakType; 1.411 + } 1.412 + uint8_t GetBreakTypeBefore() const { 1.413 + return IsBlock() ? mFlags.mBreakType : NS_STYLE_CLEAR_NONE; 1.414 + } 1.415 + 1.416 + bool HasBreakAfter() const { 1.417 + return !IsBlock() && NS_STYLE_CLEAR_NONE != mFlags.mBreakType; 1.418 + } 1.419 + void SetBreakTypeAfter(uint8_t aBreakType) { 1.420 + NS_ASSERTION(!IsBlock(), "Only inlines have break-after"); 1.421 + NS_ASSERTION(aBreakType <= LINE_MAX_BREAK_TYPE, "bad break type"); 1.422 + mFlags.mBreakType = aBreakType; 1.423 + } 1.424 + bool HasFloatBreakAfter() const { 1.425 + return !IsBlock() && (NS_STYLE_CLEAR_LEFT == mFlags.mBreakType || 1.426 + NS_STYLE_CLEAR_RIGHT == mFlags.mBreakType || 1.427 + NS_STYLE_CLEAR_BOTH == mFlags.mBreakType); 1.428 + } 1.429 + uint8_t GetBreakTypeAfter() const { 1.430 + return !IsBlock() ? mFlags.mBreakType : NS_STYLE_CLEAR_NONE; 1.431 + } 1.432 + 1.433 + // mCarriedOutBottomMargin value 1.434 + nsCollapsingMargin GetCarriedOutBottomMargin() const; 1.435 + // Returns true if the margin changed 1.436 + bool SetCarriedOutBottomMargin(nsCollapsingMargin aValue); 1.437 + 1.438 + // mFloats 1.439 + bool HasFloats() const { 1.440 + return (IsInline() && mInlineData) && mInlineData->mFloats.NotEmpty(); 1.441 + } 1.442 + nsFloatCache* GetFirstFloat(); 1.443 + void FreeFloats(nsFloatCacheFreeList& aFreeList); 1.444 + void AppendFloats(nsFloatCacheFreeList& aFreeList); 1.445 + bool RemoveFloat(nsIFrame* aFrame); 1.446 + 1.447 + // Combined area is the area of the line that should influence the 1.448 + // overflow area of its parent block. The combined area should be 1.449 + // used for painting-related things, but should never be used for 1.450 + // layout (except for handling of 'overflow'). 1.451 + void SetOverflowAreas(const nsOverflowAreas& aOverflowAreas); 1.452 + nsRect GetOverflowArea(nsOverflowType aType) { 1.453 + return mData ? mData->mOverflowAreas.Overflow(aType) : GetPhysicalBounds(); 1.454 + } 1.455 + nsOverflowAreas GetOverflowAreas() { 1.456 + if (mData) { 1.457 + return mData->mOverflowAreas; 1.458 + } 1.459 + nsRect bounds = GetPhysicalBounds(); 1.460 + return nsOverflowAreas(bounds, bounds); 1.461 + } 1.462 + nsRect GetVisualOverflowArea() 1.463 + { return GetOverflowArea(eVisualOverflow); } 1.464 + nsRect GetScrollableOverflowArea() 1.465 + { return GetOverflowArea(eScrollableOverflow); } 1.466 + 1.467 + void SlideBy(nscoord aDBCoord, nscoord aContainerWidth) { 1.468 + NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1, 1.469 + "container width doesn't match"); 1.470 + mContainerWidth = aContainerWidth; 1.471 + mBounds.BStart(mWritingMode) += aDBCoord; 1.472 + if (mData) { 1.473 + NS_FOR_FRAME_OVERFLOW_TYPES(otype) { 1.474 + mData->mOverflowAreas.Overflow(otype).y += aDBCoord; 1.475 + } 1.476 + } 1.477 + } 1.478 + 1.479 + void IndentBy(nscoord aDICoord, nscoord aContainerWidth) { 1.480 + NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1, 1.481 + "container width doesn't match"); 1.482 + mContainerWidth = aContainerWidth; 1.483 + mBounds.IStart(mWritingMode) += aDICoord; 1.484 + } 1.485 + 1.486 + void ExpandBy(nscoord aDISize, nscoord aContainerWidth) { 1.487 + NS_ASSERTION(aContainerWidth == mContainerWidth || mContainerWidth == -1, 1.488 + "container width doesn't match"); 1.489 + mContainerWidth = aContainerWidth; 1.490 + mBounds.ISize(mWritingMode) += aDISize; 1.491 + } 1.492 + 1.493 + /** 1.494 + * The ascent (distance from top to baseline) of the linebox is the 1.495 + * ascent of the anonymous inline box (for which we don't actually 1.496 + * create a frame) that wraps all the consecutive inline children of a 1.497 + * block. 1.498 + * 1.499 + * This is currently unused for block lines. 1.500 + */ 1.501 + nscoord GetAscent() const { return mAscent; } 1.502 + void SetAscent(nscoord aAscent) { mAscent = aAscent; } 1.503 + 1.504 + nscoord BStart() const { 1.505 + return mBounds.BStart(mWritingMode); 1.506 + } 1.507 + nscoord BSize() const { 1.508 + return mBounds.BSize(mWritingMode); 1.509 + } 1.510 + nscoord BEnd() const { 1.511 + return mBounds.BEnd(mWritingMode); 1.512 + } 1.513 + nscoord IStart() const { 1.514 + return mBounds.IStart(mWritingMode); 1.515 + } 1.516 + nscoord ISize() const { 1.517 + return mBounds.ISize(mWritingMode); 1.518 + } 1.519 + nscoord IEnd() const { 1.520 + return mBounds.IEnd(mWritingMode); 1.521 + } 1.522 + void SetBoundsEmpty() { 1.523 + mBounds.IStart(mWritingMode) = 0; 1.524 + mBounds.ISize(mWritingMode) = 0; 1.525 + mBounds.BStart(mWritingMode) = 0; 1.526 + mBounds.BSize(mWritingMode) = 0; 1.527 + } 1.528 + 1.529 + static void DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines, 1.530 + nsIFrame* aDestructRoot, nsFrameList* aFrames); 1.531 + 1.532 + // search from end to beginning of [aBegin, aEnd) 1.533 + // Returns true if it found the line and false if not. 1.534 + // Moves aEnd as it searches so that aEnd points to the resulting line. 1.535 + // aLastFrameBeforeEnd is the last frame before aEnd (so if aEnd is 1.536 + // the end of the line list, it's just the last frame in the frame 1.537 + // list). 1.538 + static bool RFindLineContaining(nsIFrame* aFrame, 1.539 + const nsLineList_iterator& aBegin, 1.540 + nsLineList_iterator& aEnd, 1.541 + nsIFrame* aLastFrameBeforeEnd, 1.542 + int32_t* aFrameIndexInLine); 1.543 + 1.544 +#ifdef DEBUG_FRAME_DUMP 1.545 + char* StateToString(char* aBuf, int32_t aBufSize) const; 1.546 + 1.547 + void List(FILE* out, int32_t aIndent, uint32_t aFlags = 0) const; 1.548 + void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const; 1.549 + nsIFrame* LastChild() const; 1.550 +#endif 1.551 + 1.552 +private: 1.553 + int32_t IndexOf(nsIFrame* aFrame) const; 1.554 +public: 1.555 + 1.556 + bool Contains(nsIFrame* aFrame) const { 1.557 + return MOZ_UNLIKELY(mFlags.mHasHashedFrames) ? mFrames->Contains(aFrame) 1.558 + : IndexOf(aFrame) >= 0; 1.559 + } 1.560 + 1.561 + // whether the line box is "logically" empty (just like nsIFrame::IsEmpty) 1.562 + bool IsEmpty() const; 1.563 + 1.564 + // Call this only while in Reflow() for the block the line belongs 1.565 + // to, only between reflowing the line (or sliding it, if we skip 1.566 + // reflowing it) and the end of reflowing the block. 1.567 + bool CachedIsEmpty(); 1.568 + 1.569 + void InvalidateCachedIsEmpty() { 1.570 + mFlags.mEmptyCacheValid = false; 1.571 + } 1.572 + 1.573 + // For debugging purposes 1.574 + bool IsValidCachedIsEmpty() { 1.575 + return mFlags.mEmptyCacheValid; 1.576 + } 1.577 + 1.578 +#ifdef DEBUG 1.579 + static int32_t GetCtorCount(); 1.580 +#endif 1.581 + 1.582 + nsIFrame* mFirstChild; 1.583 + 1.584 + mozilla::WritingMode mWritingMode; 1.585 + nscoord mContainerWidth; 1.586 + private: 1.587 + mozilla::LogicalRect mBounds; 1.588 + public: 1.589 + const mozilla::LogicalRect& GetBounds() { return mBounds; } 1.590 + nsRect GetPhysicalBounds() const 1.591 + { 1.592 + if (mBounds.IsEmpty()) { 1.593 + return nsRect(0, 0, 0, 0); 1.594 + } 1.595 + 1.596 + NS_ASSERTION(mContainerWidth != -1, "mContainerWidth not initialized"); 1.597 + return mBounds.GetPhysicalRect(mWritingMode, mContainerWidth); 1.598 + } 1.599 + void SetBounds(mozilla::WritingMode aWritingMode, 1.600 + nscoord aIStart, nscoord aBStart, 1.601 + nscoord aISize, nscoord aBSize, 1.602 + nscoord aContainerWidth) 1.603 + { 1.604 + mWritingMode = aWritingMode; 1.605 + mContainerWidth = aContainerWidth; 1.606 + mBounds = mozilla::LogicalRect(aWritingMode, aIStart, aBStart, 1.607 + aISize, aBSize); 1.608 + } 1.609 + void SetBounds(mozilla::WritingMode aWritingMode, 1.610 + nsRect aRect, nscoord aContainerWidth) 1.611 + { 1.612 + mWritingMode = aWritingMode; 1.613 + mContainerWidth = aContainerWidth; 1.614 + mBounds = mozilla::LogicalRect(aWritingMode, aRect, aContainerWidth); 1.615 + } 1.616 + 1.617 + // mFlags.mHasHashedFrames says which one to use 1.618 + union { 1.619 + nsTHashtable< nsPtrHashKey<nsIFrame> >* mFrames; 1.620 + uint32_t mChildCount; 1.621 + }; 1.622 + 1.623 + struct FlagBits { 1.624 + uint32_t mDirty : 1; 1.625 + uint32_t mPreviousMarginDirty : 1; 1.626 + uint32_t mHasClearance : 1; 1.627 + uint32_t mBlock : 1; 1.628 + uint32_t mImpactedByFloat : 1; 1.629 + uint32_t mLineWrapped: 1; 1.630 + uint32_t mInvalidateTextRuns : 1; 1.631 + 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 1.632 + uint32_t mEmptyCacheValid: 1; 1.633 + uint32_t mEmptyCacheState: 1; 1.634 + // mHasBullet indicates that this is an inline line whose block's 1.635 + // bullet is adjacent to this line and non-empty. 1.636 + uint32_t mHasBullet : 1; 1.637 + // Indicates that this line *may* have a placeholder for a float 1.638 + // that was pushed to a later column or page. 1.639 + uint32_t mHadFloatPushed : 1; 1.640 + uint32_t mHasHashedFrames: 1; 1.641 + uint32_t mBreakType : 4; 1.642 + }; 1.643 + 1.644 + struct ExtraData { 1.645 + ExtraData(const nsRect& aBounds) : mOverflowAreas(aBounds, aBounds) { 1.646 + } 1.647 + nsOverflowAreas mOverflowAreas; 1.648 + }; 1.649 + 1.650 + struct ExtraBlockData : public ExtraData { 1.651 + ExtraBlockData(const nsRect& aBounds) 1.652 + : ExtraData(aBounds), 1.653 + mCarriedOutBottomMargin() 1.654 + { 1.655 + } 1.656 + nsCollapsingMargin mCarriedOutBottomMargin; 1.657 + }; 1.658 + 1.659 + struct ExtraInlineData : public ExtraData { 1.660 + ExtraInlineData(const nsRect& aBounds) : ExtraData(aBounds) { 1.661 + } 1.662 + nsFloatCacheList mFloats; 1.663 + }; 1.664 + 1.665 +protected: 1.666 + nscoord mAscent; // see |SetAscent| / |GetAscent| 1.667 + union { 1.668 + uint32_t mAllFlags; 1.669 + FlagBits mFlags; 1.670 + }; 1.671 + 1.672 + union { 1.673 + ExtraData* mData; 1.674 + ExtraBlockData* mBlockData; 1.675 + ExtraInlineData* mInlineData; 1.676 + }; 1.677 + 1.678 + void Cleanup(); 1.679 + void MaybeFreeData(); 1.680 +}; 1.681 + 1.682 +/** 1.683 + * A linked list type where the items in the list must inherit from 1.684 + * a link type to fuse allocations. 1.685 + * 1.686 + * API heavily based on the |list| class in the C++ standard. 1.687 + */ 1.688 + 1.689 +class nsLineList_iterator { 1.690 + public: 1.691 + friend class nsLineList; 1.692 + friend class nsLineList_reverse_iterator; 1.693 + friend class nsLineList_const_iterator; 1.694 + friend class nsLineList_const_reverse_iterator; 1.695 + 1.696 + typedef nsLineList_iterator iterator_self_type; 1.697 + typedef nsLineList_reverse_iterator iterator_reverse_type; 1.698 + 1.699 + typedef nsLineBox& reference; 1.700 + typedef const nsLineBox& const_reference; 1.701 + 1.702 + typedef nsLineBox* pointer; 1.703 + typedef const nsLineBox* const_pointer; 1.704 + 1.705 + typedef uint32_t size_type; 1.706 + typedef int32_t difference_type; 1.707 + 1.708 + typedef nsLineLink link_type; 1.709 + 1.710 +#ifdef DEBUG 1.711 + nsLineList_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); } 1.712 +#else 1.713 + // Auto generated default constructor OK. 1.714 +#endif 1.715 + // Auto generated copy-constructor OK. 1.716 + 1.717 + inline iterator_self_type& 1.718 + operator=(const iterator_self_type& aOther); 1.719 + inline iterator_self_type& 1.720 + operator=(const iterator_reverse_type& aOther); 1.721 + 1.722 + iterator_self_type& operator++() 1.723 + { 1.724 + mCurrent = mCurrent->_mNext; 1.725 + return *this; 1.726 + } 1.727 + 1.728 + iterator_self_type operator++(int) 1.729 + { 1.730 + iterator_self_type rv(*this); 1.731 + mCurrent = mCurrent->_mNext; 1.732 + return rv; 1.733 + } 1.734 + 1.735 + iterator_self_type& operator--() 1.736 + { 1.737 + mCurrent = mCurrent->_mPrev; 1.738 + return *this; 1.739 + } 1.740 + 1.741 + iterator_self_type operator--(int) 1.742 + { 1.743 + iterator_self_type rv(*this); 1.744 + mCurrent = mCurrent->_mPrev; 1.745 + return rv; 1.746 + } 1.747 + 1.748 + reference operator*() 1.749 + { 1.750 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.751 + return *static_cast<pointer>(mCurrent); 1.752 + } 1.753 + 1.754 + pointer operator->() 1.755 + { 1.756 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.757 + return static_cast<pointer>(mCurrent); 1.758 + } 1.759 + 1.760 + pointer get() 1.761 + { 1.762 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.763 + return static_cast<pointer>(mCurrent); 1.764 + } 1.765 + 1.766 + operator pointer() 1.767 + { 1.768 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.769 + return static_cast<pointer>(mCurrent); 1.770 + } 1.771 + 1.772 + const_reference operator*() const 1.773 + { 1.774 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.775 + return *static_cast<const_pointer>(mCurrent); 1.776 + } 1.777 + 1.778 + const_pointer operator->() const 1.779 + { 1.780 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.781 + return static_cast<const_pointer>(mCurrent); 1.782 + } 1.783 + 1.784 +#ifndef __MWERKS__ 1.785 + operator const_pointer() const 1.786 + { 1.787 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.788 + return static_cast<const_pointer>(mCurrent); 1.789 + } 1.790 +#endif /* !__MWERKS__ */ 1.791 + 1.792 + iterator_self_type next() 1.793 + { 1.794 + iterator_self_type copy(*this); 1.795 + return ++copy; 1.796 + } 1.797 + 1.798 + const iterator_self_type next() const 1.799 + { 1.800 + iterator_self_type copy(*this); 1.801 + return ++copy; 1.802 + } 1.803 + 1.804 + iterator_self_type prev() 1.805 + { 1.806 + iterator_self_type copy(*this); 1.807 + return --copy; 1.808 + } 1.809 + 1.810 + const iterator_self_type prev() const 1.811 + { 1.812 + iterator_self_type copy(*this); 1.813 + return --copy; 1.814 + } 1.815 + 1.816 + // Passing by value rather than by reference and reference to const 1.817 + // to keep AIX happy. 1.818 + bool operator==(const iterator_self_type aOther) const 1.819 + { 1.820 + NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.821 + return mCurrent == aOther.mCurrent; 1.822 + } 1.823 + bool operator!=(const iterator_self_type aOther) const 1.824 + { 1.825 + NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.826 + return mCurrent != aOther.mCurrent; 1.827 + } 1.828 + bool operator==(const iterator_self_type aOther) 1.829 + { 1.830 + NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.831 + return mCurrent == aOther.mCurrent; 1.832 + } 1.833 + bool operator!=(const iterator_self_type aOther) 1.834 + { 1.835 + NS_ABORT_IF_FALSE(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.836 + return mCurrent != aOther.mCurrent; 1.837 + } 1.838 + 1.839 + private: 1.840 + link_type *mCurrent; 1.841 +#ifdef DEBUG 1.842 + link_type *mListLink; // the list's link, i.e., the end 1.843 +#endif 1.844 +}; 1.845 + 1.846 +class nsLineList_reverse_iterator { 1.847 + 1.848 + public: 1.849 + 1.850 + friend class nsLineList; 1.851 + friend class nsLineList_iterator; 1.852 + friend class nsLineList_const_iterator; 1.853 + friend class nsLineList_const_reverse_iterator; 1.854 + 1.855 + typedef nsLineList_reverse_iterator iterator_self_type; 1.856 + typedef nsLineList_iterator iterator_reverse_type; 1.857 + 1.858 + typedef nsLineBox& reference; 1.859 + typedef const nsLineBox& const_reference; 1.860 + 1.861 + typedef nsLineBox* pointer; 1.862 + typedef const nsLineBox* const_pointer; 1.863 + 1.864 + typedef uint32_t size_type; 1.865 + typedef int32_t difference_type; 1.866 + 1.867 + typedef nsLineLink link_type; 1.868 + 1.869 +#ifdef DEBUG 1.870 + nsLineList_reverse_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); } 1.871 +#else 1.872 + // Auto generated default constructor OK. 1.873 +#endif 1.874 + // Auto generated copy-constructor OK. 1.875 + 1.876 + inline iterator_self_type& 1.877 + operator=(const iterator_reverse_type& aOther); 1.878 + inline iterator_self_type& 1.879 + operator=(const iterator_self_type& aOther); 1.880 + 1.881 + iterator_self_type& operator++() 1.882 + { 1.883 + mCurrent = mCurrent->_mPrev; 1.884 + return *this; 1.885 + } 1.886 + 1.887 + iterator_self_type operator++(int) 1.888 + { 1.889 + iterator_self_type rv(*this); 1.890 + mCurrent = mCurrent->_mPrev; 1.891 + return rv; 1.892 + } 1.893 + 1.894 + iterator_self_type& operator--() 1.895 + { 1.896 + mCurrent = mCurrent->_mNext; 1.897 + return *this; 1.898 + } 1.899 + 1.900 + iterator_self_type operator--(int) 1.901 + { 1.902 + iterator_self_type rv(*this); 1.903 + mCurrent = mCurrent->_mNext; 1.904 + return rv; 1.905 + } 1.906 + 1.907 + reference operator*() 1.908 + { 1.909 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.910 + return *static_cast<pointer>(mCurrent); 1.911 + } 1.912 + 1.913 + pointer operator->() 1.914 + { 1.915 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.916 + return static_cast<pointer>(mCurrent); 1.917 + } 1.918 + 1.919 + pointer get() 1.920 + { 1.921 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.922 + return static_cast<pointer>(mCurrent); 1.923 + } 1.924 + 1.925 + operator pointer() 1.926 + { 1.927 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.928 + return static_cast<pointer>(mCurrent); 1.929 + } 1.930 + 1.931 + const_reference operator*() const 1.932 + { 1.933 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.934 + return *static_cast<const_pointer>(mCurrent); 1.935 + } 1.936 + 1.937 + const_pointer operator->() const 1.938 + { 1.939 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.940 + return static_cast<const_pointer>(mCurrent); 1.941 + } 1.942 + 1.943 +#ifndef __MWERKS__ 1.944 + operator const_pointer() const 1.945 + { 1.946 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.947 + return static_cast<const_pointer>(mCurrent); 1.948 + } 1.949 +#endif /* !__MWERKS__ */ 1.950 + 1.951 + // Passing by value rather than by reference and reference to const 1.952 + // to keep AIX happy. 1.953 + bool operator==(const iterator_self_type aOther) const 1.954 + { 1.955 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.956 + return mCurrent == aOther.mCurrent; 1.957 + } 1.958 + bool operator!=(const iterator_self_type aOther) const 1.959 + { 1.960 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.961 + return mCurrent != aOther.mCurrent; 1.962 + } 1.963 + bool operator==(const iterator_self_type aOther) 1.964 + { 1.965 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.966 + return mCurrent == aOther.mCurrent; 1.967 + } 1.968 + bool operator!=(const iterator_self_type aOther) 1.969 + { 1.970 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.971 + return mCurrent != aOther.mCurrent; 1.972 + } 1.973 + 1.974 + private: 1.975 + link_type *mCurrent; 1.976 +#ifdef DEBUG 1.977 + link_type *mListLink; // the list's link, i.e., the end 1.978 +#endif 1.979 +}; 1.980 + 1.981 +class nsLineList_const_iterator { 1.982 + public: 1.983 + 1.984 + friend class nsLineList; 1.985 + friend class nsLineList_iterator; 1.986 + friend class nsLineList_reverse_iterator; 1.987 + friend class nsLineList_const_reverse_iterator; 1.988 + 1.989 + typedef nsLineList_const_iterator iterator_self_type; 1.990 + typedef nsLineList_const_reverse_iterator iterator_reverse_type; 1.991 + typedef nsLineList_iterator iterator_nonconst_type; 1.992 + typedef nsLineList_reverse_iterator iterator_nonconst_reverse_type; 1.993 + 1.994 + typedef nsLineBox& reference; 1.995 + typedef const nsLineBox& const_reference; 1.996 + 1.997 + typedef nsLineBox* pointer; 1.998 + typedef const nsLineBox* const_pointer; 1.999 + 1.1000 + typedef uint32_t size_type; 1.1001 + typedef int32_t difference_type; 1.1002 + 1.1003 + typedef nsLineLink link_type; 1.1004 + 1.1005 +#ifdef DEBUG 1.1006 + nsLineList_const_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); } 1.1007 +#else 1.1008 + // Auto generated default constructor OK. 1.1009 +#endif 1.1010 + // Auto generated copy-constructor OK. 1.1011 + 1.1012 + inline iterator_self_type& 1.1013 + operator=(const iterator_nonconst_type& aOther); 1.1014 + inline iterator_self_type& 1.1015 + operator=(const iterator_nonconst_reverse_type& aOther); 1.1016 + inline iterator_self_type& 1.1017 + operator=(const iterator_self_type& aOther); 1.1018 + inline iterator_self_type& 1.1019 + operator=(const iterator_reverse_type& aOther); 1.1020 + 1.1021 + iterator_self_type& operator++() 1.1022 + { 1.1023 + mCurrent = mCurrent->_mNext; 1.1024 + return *this; 1.1025 + } 1.1026 + 1.1027 + iterator_self_type operator++(int) 1.1028 + { 1.1029 + iterator_self_type rv(*this); 1.1030 + mCurrent = mCurrent->_mNext; 1.1031 + return rv; 1.1032 + } 1.1033 + 1.1034 + iterator_self_type& operator--() 1.1035 + { 1.1036 + mCurrent = mCurrent->_mPrev; 1.1037 + return *this; 1.1038 + } 1.1039 + 1.1040 + iterator_self_type operator--(int) 1.1041 + { 1.1042 + iterator_self_type rv(*this); 1.1043 + mCurrent = mCurrent->_mPrev; 1.1044 + return rv; 1.1045 + } 1.1046 + 1.1047 + const_reference operator*() const 1.1048 + { 1.1049 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.1050 + return *static_cast<const_pointer>(mCurrent); 1.1051 + } 1.1052 + 1.1053 + const_pointer operator->() const 1.1054 + { 1.1055 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.1056 + return static_cast<const_pointer>(mCurrent); 1.1057 + } 1.1058 + 1.1059 + const_pointer get() const 1.1060 + { 1.1061 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.1062 + return static_cast<const_pointer>(mCurrent); 1.1063 + } 1.1064 + 1.1065 +#ifndef __MWERKS__ 1.1066 + operator const_pointer() const 1.1067 + { 1.1068 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.1069 + return static_cast<const_pointer>(mCurrent); 1.1070 + } 1.1071 +#endif /* !__MWERKS__ */ 1.1072 + 1.1073 + const iterator_self_type next() const 1.1074 + { 1.1075 + iterator_self_type copy(*this); 1.1076 + return ++copy; 1.1077 + } 1.1078 + 1.1079 + const iterator_self_type prev() const 1.1080 + { 1.1081 + iterator_self_type copy(*this); 1.1082 + return --copy; 1.1083 + } 1.1084 + 1.1085 + // Passing by value rather than by reference and reference to const 1.1086 + // to keep AIX happy. 1.1087 + bool operator==(const iterator_self_type aOther) const 1.1088 + { 1.1089 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.1090 + return mCurrent == aOther.mCurrent; 1.1091 + } 1.1092 + bool operator!=(const iterator_self_type aOther) const 1.1093 + { 1.1094 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.1095 + return mCurrent != aOther.mCurrent; 1.1096 + } 1.1097 + bool operator==(const iterator_self_type aOther) 1.1098 + { 1.1099 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.1100 + return mCurrent == aOther.mCurrent; 1.1101 + } 1.1102 + bool operator!=(const iterator_self_type aOther) 1.1103 + { 1.1104 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.1105 + return mCurrent != aOther.mCurrent; 1.1106 + } 1.1107 + 1.1108 + private: 1.1109 + const link_type *mCurrent; 1.1110 +#ifdef DEBUG 1.1111 + const link_type *mListLink; // the list's link, i.e., the end 1.1112 +#endif 1.1113 +}; 1.1114 + 1.1115 +class nsLineList_const_reverse_iterator { 1.1116 + public: 1.1117 + 1.1118 + friend class nsLineList; 1.1119 + friend class nsLineList_iterator; 1.1120 + friend class nsLineList_reverse_iterator; 1.1121 + friend class nsLineList_const_iterator; 1.1122 + 1.1123 + typedef nsLineList_const_reverse_iterator iterator_self_type; 1.1124 + typedef nsLineList_const_iterator iterator_reverse_type; 1.1125 + typedef nsLineList_iterator iterator_nonconst_reverse_type; 1.1126 + typedef nsLineList_reverse_iterator iterator_nonconst_type; 1.1127 + 1.1128 + typedef nsLineBox& reference; 1.1129 + typedef const nsLineBox& const_reference; 1.1130 + 1.1131 + typedef nsLineBox* pointer; 1.1132 + typedef const nsLineBox* const_pointer; 1.1133 + 1.1134 + typedef uint32_t size_type; 1.1135 + typedef int32_t difference_type; 1.1136 + 1.1137 + typedef nsLineLink link_type; 1.1138 + 1.1139 +#ifdef DEBUG 1.1140 + nsLineList_const_reverse_iterator() { memset(&mCurrent, 0xcd, sizeof(mCurrent)); } 1.1141 +#else 1.1142 + // Auto generated default constructor OK. 1.1143 +#endif 1.1144 + // Auto generated copy-constructor OK. 1.1145 + 1.1146 + inline iterator_self_type& 1.1147 + operator=(const iterator_nonconst_type& aOther); 1.1148 + inline iterator_self_type& 1.1149 + operator=(const iterator_nonconst_reverse_type& aOther); 1.1150 + inline iterator_self_type& 1.1151 + operator=(const iterator_self_type& aOther); 1.1152 + inline iterator_self_type& 1.1153 + operator=(const iterator_reverse_type& aOther); 1.1154 + 1.1155 + iterator_self_type& operator++() 1.1156 + { 1.1157 + mCurrent = mCurrent->_mPrev; 1.1158 + return *this; 1.1159 + } 1.1160 + 1.1161 + iterator_self_type operator++(int) 1.1162 + { 1.1163 + iterator_self_type rv(*this); 1.1164 + mCurrent = mCurrent->_mPrev; 1.1165 + return rv; 1.1166 + } 1.1167 + 1.1168 + iterator_self_type& operator--() 1.1169 + { 1.1170 + mCurrent = mCurrent->_mNext; 1.1171 + return *this; 1.1172 + } 1.1173 + 1.1174 + iterator_self_type operator--(int) 1.1175 + { 1.1176 + iterator_self_type rv(*this); 1.1177 + mCurrent = mCurrent->_mNext; 1.1178 + return rv; 1.1179 + } 1.1180 + 1.1181 + const_reference operator*() const 1.1182 + { 1.1183 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.1184 + return *static_cast<const_pointer>(mCurrent); 1.1185 + } 1.1186 + 1.1187 + const_pointer operator->() const 1.1188 + { 1.1189 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.1190 + return static_cast<const_pointer>(mCurrent); 1.1191 + } 1.1192 + 1.1193 + const_pointer get() const 1.1194 + { 1.1195 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.1196 + return static_cast<const_pointer>(mCurrent); 1.1197 + } 1.1198 + 1.1199 +#ifndef __MWERKS__ 1.1200 + operator const_pointer() const 1.1201 + { 1.1202 + NS_ABORT_IF_FALSE(mCurrent != mListLink, "running past end"); 1.1203 + return static_cast<const_pointer>(mCurrent); 1.1204 + } 1.1205 +#endif /* !__MWERKS__ */ 1.1206 + 1.1207 + // Passing by value rather than by reference and reference to const 1.1208 + // to keep AIX happy. 1.1209 + bool operator==(const iterator_self_type aOther) const 1.1210 + { 1.1211 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.1212 + return mCurrent == aOther.mCurrent; 1.1213 + } 1.1214 + bool operator!=(const iterator_self_type aOther) const 1.1215 + { 1.1216 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.1217 + return mCurrent != aOther.mCurrent; 1.1218 + } 1.1219 + bool operator==(const iterator_self_type aOther) 1.1220 + { 1.1221 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.1222 + return mCurrent == aOther.mCurrent; 1.1223 + } 1.1224 + bool operator!=(const iterator_self_type aOther) 1.1225 + { 1.1226 + NS_ASSERTION(mListLink == aOther.mListLink, "comparing iterators over different lists"); 1.1227 + return mCurrent != aOther.mCurrent; 1.1228 + } 1.1229 + 1.1230 +//private: 1.1231 + const link_type *mCurrent; 1.1232 +#ifdef DEBUG 1.1233 + const link_type *mListLink; // the list's link, i.e., the end 1.1234 +#endif 1.1235 +}; 1.1236 + 1.1237 +class nsLineList { 1.1238 + 1.1239 + public: 1.1240 + 1.1241 + friend class nsLineList_iterator; 1.1242 + friend class nsLineList_reverse_iterator; 1.1243 + friend class nsLineList_const_iterator; 1.1244 + friend class nsLineList_const_reverse_iterator; 1.1245 + 1.1246 + typedef uint32_t size_type; 1.1247 + typedef int32_t difference_type; 1.1248 + 1.1249 + typedef nsLineLink link_type; 1.1250 + 1.1251 + private: 1.1252 + link_type mLink; 1.1253 + 1.1254 + public: 1.1255 + typedef nsLineList self_type; 1.1256 + 1.1257 + typedef nsLineBox& reference; 1.1258 + typedef const nsLineBox& const_reference; 1.1259 + 1.1260 + typedef nsLineBox* pointer; 1.1261 + typedef const nsLineBox* const_pointer; 1.1262 + 1.1263 + typedef nsLineList_iterator iterator; 1.1264 + typedef nsLineList_reverse_iterator reverse_iterator; 1.1265 + typedef nsLineList_const_iterator const_iterator; 1.1266 + typedef nsLineList_const_reverse_iterator const_reverse_iterator; 1.1267 + 1.1268 + nsLineList() 1.1269 + { 1.1270 + MOZ_COUNT_CTOR(nsLineList); 1.1271 + clear(); 1.1272 + } 1.1273 + 1.1274 + ~nsLineList() 1.1275 + { 1.1276 + MOZ_COUNT_DTOR(nsLineList); 1.1277 + } 1.1278 + 1.1279 + const_iterator begin() const 1.1280 + { 1.1281 + const_iterator rv; 1.1282 + rv.mCurrent = mLink._mNext; 1.1283 +#ifdef DEBUG 1.1284 + rv.mListLink = &mLink; 1.1285 +#endif 1.1286 + return rv; 1.1287 + } 1.1288 + 1.1289 + iterator begin() 1.1290 + { 1.1291 + iterator rv; 1.1292 + rv.mCurrent = mLink._mNext; 1.1293 +#ifdef DEBUG 1.1294 + rv.mListLink = &mLink; 1.1295 +#endif 1.1296 + return rv; 1.1297 + } 1.1298 + 1.1299 + iterator begin(nsLineBox* aLine) 1.1300 + { 1.1301 + iterator rv; 1.1302 + rv.mCurrent = aLine; 1.1303 +#ifdef DEBUG 1.1304 + rv.mListLink = &mLink; 1.1305 +#endif 1.1306 + return rv; 1.1307 + } 1.1308 + 1.1309 + const_iterator end() const 1.1310 + { 1.1311 + const_iterator rv; 1.1312 + rv.mCurrent = &mLink; 1.1313 +#ifdef DEBUG 1.1314 + rv.mListLink = &mLink; 1.1315 +#endif 1.1316 + return rv; 1.1317 + } 1.1318 + 1.1319 + iterator end() 1.1320 + { 1.1321 + iterator rv; 1.1322 + rv.mCurrent = &mLink; 1.1323 +#ifdef DEBUG 1.1324 + rv.mListLink = &mLink; 1.1325 +#endif 1.1326 + return rv; 1.1327 + } 1.1328 + 1.1329 + const_reverse_iterator rbegin() const 1.1330 + { 1.1331 + const_reverse_iterator rv; 1.1332 + rv.mCurrent = mLink._mPrev; 1.1333 +#ifdef DEBUG 1.1334 + rv.mListLink = &mLink; 1.1335 +#endif 1.1336 + return rv; 1.1337 + } 1.1338 + 1.1339 + reverse_iterator rbegin() 1.1340 + { 1.1341 + reverse_iterator rv; 1.1342 + rv.mCurrent = mLink._mPrev; 1.1343 +#ifdef DEBUG 1.1344 + rv.mListLink = &mLink; 1.1345 +#endif 1.1346 + return rv; 1.1347 + } 1.1348 + 1.1349 + reverse_iterator rbegin(nsLineBox* aLine) 1.1350 + { 1.1351 + reverse_iterator rv; 1.1352 + rv.mCurrent = aLine; 1.1353 +#ifdef DEBUG 1.1354 + rv.mListLink = &mLink; 1.1355 +#endif 1.1356 + return rv; 1.1357 + } 1.1358 + 1.1359 + const_reverse_iterator rend() const 1.1360 + { 1.1361 + const_reverse_iterator rv; 1.1362 + rv.mCurrent = &mLink; 1.1363 +#ifdef DEBUG 1.1364 + rv.mListLink = &mLink; 1.1365 +#endif 1.1366 + return rv; 1.1367 + } 1.1368 + 1.1369 + reverse_iterator rend() 1.1370 + { 1.1371 + reverse_iterator rv; 1.1372 + rv.mCurrent = &mLink; 1.1373 +#ifdef DEBUG 1.1374 + rv.mListLink = &mLink; 1.1375 +#endif 1.1376 + return rv; 1.1377 + } 1.1378 + 1.1379 + bool empty() const 1.1380 + { 1.1381 + return mLink._mNext == &mLink; 1.1382 + } 1.1383 + 1.1384 + // NOTE: O(N). 1.1385 + size_type size() const 1.1386 + { 1.1387 + size_type count = 0; 1.1388 + for (const link_type *cur = mLink._mNext; 1.1389 + cur != &mLink; 1.1390 + cur = cur->_mNext) 1.1391 + { 1.1392 + ++count; 1.1393 + } 1.1394 + return count; 1.1395 + } 1.1396 + 1.1397 + pointer front() 1.1398 + { 1.1399 + NS_ASSERTION(!empty(), "no element to return"); 1.1400 + return static_cast<pointer>(mLink._mNext); 1.1401 + } 1.1402 + 1.1403 + const_pointer front() const 1.1404 + { 1.1405 + NS_ASSERTION(!empty(), "no element to return"); 1.1406 + return static_cast<const_pointer>(mLink._mNext); 1.1407 + } 1.1408 + 1.1409 + pointer back() 1.1410 + { 1.1411 + NS_ASSERTION(!empty(), "no element to return"); 1.1412 + return static_cast<pointer>(mLink._mPrev); 1.1413 + } 1.1414 + 1.1415 + const_pointer back() const 1.1416 + { 1.1417 + NS_ASSERTION(!empty(), "no element to return"); 1.1418 + return static_cast<const_pointer>(mLink._mPrev); 1.1419 + } 1.1420 + 1.1421 + void push_front(pointer aNew) 1.1422 + { 1.1423 + aNew->_mNext = mLink._mNext; 1.1424 + mLink._mNext->_mPrev = aNew; 1.1425 + aNew->_mPrev = &mLink; 1.1426 + mLink._mNext = aNew; 1.1427 + } 1.1428 + 1.1429 + void pop_front() 1.1430 + // NOTE: leaves dangling next/prev pointers 1.1431 + { 1.1432 + NS_ASSERTION(!empty(), "no element to pop"); 1.1433 + link_type *newFirst = mLink._mNext->_mNext; 1.1434 + newFirst->_mPrev = &mLink; 1.1435 + // mLink._mNext->_mNext = nullptr; 1.1436 + // mLink._mNext->_mPrev = nullptr; 1.1437 + mLink._mNext = newFirst; 1.1438 + } 1.1439 + 1.1440 + void push_back(pointer aNew) 1.1441 + { 1.1442 + aNew->_mPrev = mLink._mPrev; 1.1443 + mLink._mPrev->_mNext = aNew; 1.1444 + aNew->_mNext = &mLink; 1.1445 + mLink._mPrev = aNew; 1.1446 + } 1.1447 + 1.1448 + void pop_back() 1.1449 + // NOTE: leaves dangling next/prev pointers 1.1450 + { 1.1451 + NS_ASSERTION(!empty(), "no element to pop"); 1.1452 + link_type *newLast = mLink._mPrev->_mPrev; 1.1453 + newLast->_mNext = &mLink; 1.1454 + // mLink._mPrev->_mPrev = nullptr; 1.1455 + // mLink._mPrev->_mNext = nullptr; 1.1456 + mLink._mPrev = newLast; 1.1457 + } 1.1458 + 1.1459 + // inserts x before position 1.1460 + iterator before_insert(iterator position, pointer x) 1.1461 + { 1.1462 + // use |mCurrent| to prevent DEBUG_PASS_END assertions 1.1463 + x->_mPrev = position.mCurrent->_mPrev; 1.1464 + x->_mNext = position.mCurrent; 1.1465 + position.mCurrent->_mPrev->_mNext = x; 1.1466 + position.mCurrent->_mPrev = x; 1.1467 + return --position; 1.1468 + } 1.1469 + 1.1470 + // inserts x after position 1.1471 + iterator after_insert(iterator position, pointer x) 1.1472 + { 1.1473 + // use |mCurrent| to prevent DEBUG_PASS_END assertions 1.1474 + x->_mNext = position.mCurrent->_mNext; 1.1475 + x->_mPrev = position.mCurrent; 1.1476 + position.mCurrent->_mNext->_mPrev = x; 1.1477 + position.mCurrent->_mNext = x; 1.1478 + return ++position; 1.1479 + } 1.1480 + 1.1481 + // returns iterator pointing to after the element 1.1482 + iterator erase(iterator position) 1.1483 + // NOTE: leaves dangling next/prev pointers 1.1484 + { 1.1485 + position->_mPrev->_mNext = position->_mNext; 1.1486 + position->_mNext->_mPrev = position->_mPrev; 1.1487 + return ++position; 1.1488 + } 1.1489 + 1.1490 + void swap(self_type& y) 1.1491 + { 1.1492 + link_type tmp(y.mLink); 1.1493 + y.mLink = mLink; 1.1494 + mLink = tmp; 1.1495 + 1.1496 + if (!empty()) { 1.1497 + mLink._mNext->_mPrev = &mLink; 1.1498 + mLink._mPrev->_mNext = &mLink; 1.1499 + } 1.1500 + 1.1501 + if (!y.empty()) { 1.1502 + y.mLink._mNext->_mPrev = &y.mLink; 1.1503 + y.mLink._mPrev->_mNext = &y.mLink; 1.1504 + } 1.1505 + } 1.1506 + 1.1507 + void clear() 1.1508 + // NOTE: leaves dangling next/prev pointers 1.1509 + { 1.1510 + mLink._mNext = &mLink; 1.1511 + mLink._mPrev = &mLink; 1.1512 + } 1.1513 + 1.1514 + // inserts the conts of x before position and makes x empty 1.1515 + void splice(iterator position, self_type& x) 1.1516 + { 1.1517 + // use |mCurrent| to prevent DEBUG_PASS_END assertions 1.1518 + position.mCurrent->_mPrev->_mNext = x.mLink._mNext; 1.1519 + x.mLink._mNext->_mPrev = position.mCurrent->_mPrev; 1.1520 + x.mLink._mPrev->_mNext = position.mCurrent; 1.1521 + position.mCurrent->_mPrev = x.mLink._mPrev; 1.1522 + x.clear(); 1.1523 + } 1.1524 + 1.1525 + // Inserts element *i from list x before position and removes 1.1526 + // it from x. 1.1527 + void splice(iterator position, self_type& x, iterator i) 1.1528 + { 1.1529 + NS_ASSERTION(!x.empty(), "Can't insert from empty list."); 1.1530 + NS_ASSERTION(position != i && position.mCurrent != i->_mNext, 1.1531 + "We don't check for this case."); 1.1532 + 1.1533 + // remove from |x| 1.1534 + i->_mPrev->_mNext = i->_mNext; 1.1535 + i->_mNext->_mPrev = i->_mPrev; 1.1536 + 1.1537 + // use |mCurrent| to prevent DEBUG_PASS_END assertions 1.1538 + // link into |this|, before-side 1.1539 + i->_mPrev = position.mCurrent->_mPrev; 1.1540 + position.mCurrent->_mPrev->_mNext = i.get(); 1.1541 + 1.1542 + // link into |this|, after-side 1.1543 + i->_mNext = position.mCurrent; 1.1544 + position.mCurrent->_mPrev = i.get(); 1.1545 + } 1.1546 + 1.1547 + // Inserts elements in [|first|, |last|), which are in |x|, 1.1548 + // into |this| before |position| and removes them from |x|. 1.1549 + void splice(iterator position, self_type& x, iterator first, 1.1550 + iterator last) 1.1551 + { 1.1552 + NS_ASSERTION(!x.empty(), "Can't insert from empty list."); 1.1553 + 1.1554 + if (first == last) 1.1555 + return; 1.1556 + 1.1557 + --last; // so we now want to move [first, last] 1.1558 + // remove from |x| 1.1559 + first->_mPrev->_mNext = last->_mNext; 1.1560 + last->_mNext->_mPrev = first->_mPrev; 1.1561 + 1.1562 + // use |mCurrent| to prevent DEBUG_PASS_END assertions 1.1563 + // link into |this|, before-side 1.1564 + first->_mPrev = position.mCurrent->_mPrev; 1.1565 + position.mCurrent->_mPrev->_mNext = first.get(); 1.1566 + 1.1567 + // link into |this|, after-side 1.1568 + last->_mNext = position.mCurrent; 1.1569 + position.mCurrent->_mPrev = last.get(); 1.1570 + } 1.1571 + 1.1572 +}; 1.1573 + 1.1574 + 1.1575 +// Many of these implementations of operator= don't work yet. I don't 1.1576 +// know why. 1.1577 + 1.1578 +#ifdef DEBUG 1.1579 + 1.1580 + // NOTE: ASSIGN_FROM is meant to be used *only* as the entire body 1.1581 + // of a function and therefore lacks PR_{BEGIN,END}_MACRO 1.1582 +#define ASSIGN_FROM(other_) \ 1.1583 + mCurrent = other_.mCurrent; \ 1.1584 + mListLink = other_.mListLink; \ 1.1585 + return *this; 1.1586 + 1.1587 +#else /* !NS_LINELIST_DEBUG_PASS_END */ 1.1588 + 1.1589 +#define ASSIGN_FROM(other_) \ 1.1590 + mCurrent = other_.mCurrent; \ 1.1591 + return *this; 1.1592 + 1.1593 +#endif /* !NS_LINELIST_DEBUG_PASS_END */ 1.1594 + 1.1595 +inline 1.1596 +nsLineList_iterator& 1.1597 +nsLineList_iterator::operator=(const nsLineList_iterator& aOther) 1.1598 +{ 1.1599 + ASSIGN_FROM(aOther) 1.1600 +} 1.1601 + 1.1602 +inline 1.1603 +nsLineList_iterator& 1.1604 +nsLineList_iterator::operator=(const nsLineList_reverse_iterator& aOther) 1.1605 +{ 1.1606 + ASSIGN_FROM(aOther) 1.1607 +} 1.1608 + 1.1609 +inline 1.1610 +nsLineList_reverse_iterator& 1.1611 +nsLineList_reverse_iterator::operator=(const nsLineList_iterator& aOther) 1.1612 +{ 1.1613 + ASSIGN_FROM(aOther) 1.1614 +} 1.1615 + 1.1616 +inline 1.1617 +nsLineList_reverse_iterator& 1.1618 +nsLineList_reverse_iterator::operator=(const nsLineList_reverse_iterator& aOther) 1.1619 +{ 1.1620 + ASSIGN_FROM(aOther) 1.1621 +} 1.1622 + 1.1623 +inline 1.1624 +nsLineList_const_iterator& 1.1625 +nsLineList_const_iterator::operator=(const nsLineList_iterator& aOther) 1.1626 +{ 1.1627 + ASSIGN_FROM(aOther) 1.1628 +} 1.1629 + 1.1630 +inline 1.1631 +nsLineList_const_iterator& 1.1632 +nsLineList_const_iterator::operator=(const nsLineList_reverse_iterator& aOther) 1.1633 +{ 1.1634 + ASSIGN_FROM(aOther) 1.1635 +} 1.1636 + 1.1637 +inline 1.1638 +nsLineList_const_iterator& 1.1639 +nsLineList_const_iterator::operator=(const nsLineList_const_iterator& aOther) 1.1640 +{ 1.1641 + ASSIGN_FROM(aOther) 1.1642 +} 1.1643 + 1.1644 +inline 1.1645 +nsLineList_const_iterator& 1.1646 +nsLineList_const_iterator::operator=(const nsLineList_const_reverse_iterator& aOther) 1.1647 +{ 1.1648 + ASSIGN_FROM(aOther) 1.1649 +} 1.1650 + 1.1651 +inline 1.1652 +nsLineList_const_reverse_iterator& 1.1653 +nsLineList_const_reverse_iterator::operator=(const nsLineList_iterator& aOther) 1.1654 +{ 1.1655 + ASSIGN_FROM(aOther) 1.1656 +} 1.1657 + 1.1658 +inline 1.1659 +nsLineList_const_reverse_iterator& 1.1660 +nsLineList_const_reverse_iterator::operator=(const nsLineList_reverse_iterator& aOther) 1.1661 +{ 1.1662 + ASSIGN_FROM(aOther) 1.1663 +} 1.1664 + 1.1665 +inline 1.1666 +nsLineList_const_reverse_iterator& 1.1667 +nsLineList_const_reverse_iterator::operator=(const nsLineList_const_iterator& aOther) 1.1668 +{ 1.1669 + ASSIGN_FROM(aOther) 1.1670 +} 1.1671 + 1.1672 +inline 1.1673 +nsLineList_const_reverse_iterator& 1.1674 +nsLineList_const_reverse_iterator::operator=(const nsLineList_const_reverse_iterator& aOther) 1.1675 +{ 1.1676 + ASSIGN_FROM(aOther) 1.1677 +} 1.1678 + 1.1679 + 1.1680 +//---------------------------------------------------------------------- 1.1681 + 1.1682 +class nsLineIterator MOZ_FINAL : public nsILineIterator 1.1683 +{ 1.1684 +public: 1.1685 + nsLineIterator(); 1.1686 + ~nsLineIterator(); 1.1687 + 1.1688 + virtual void DisposeLineIterator() MOZ_OVERRIDE; 1.1689 + 1.1690 + virtual int32_t GetNumLines() MOZ_OVERRIDE; 1.1691 + virtual bool GetDirection() MOZ_OVERRIDE; 1.1692 + NS_IMETHOD GetLine(int32_t aLineNumber, 1.1693 + nsIFrame** aFirstFrameOnLine, 1.1694 + int32_t* aNumFramesOnLine, 1.1695 + nsRect& aLineBounds, 1.1696 + uint32_t* aLineFlags) MOZ_OVERRIDE; 1.1697 + virtual int32_t FindLineContaining(nsIFrame* aFrame, int32_t aStartLine = 0) MOZ_OVERRIDE; 1.1698 + NS_IMETHOD FindFrameAt(int32_t aLineNumber, 1.1699 + nscoord aX, 1.1700 + nsIFrame** aFrameFound, 1.1701 + bool* aXIsBeforeFirstFrame, 1.1702 + bool* aXIsAfterLastFrame) MOZ_OVERRIDE; 1.1703 + 1.1704 + NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, int32_t aLineNumber) MOZ_OVERRIDE; 1.1705 + NS_IMETHOD CheckLineOrder(int32_t aLine, 1.1706 + bool *aIsReordered, 1.1707 + nsIFrame **aFirstVisual, 1.1708 + nsIFrame **aLastVisual) MOZ_OVERRIDE; 1.1709 + nsresult Init(nsLineList& aLines, bool aRightToLeft); 1.1710 + 1.1711 +private: 1.1712 + nsLineBox* PrevLine() { 1.1713 + if (0 == mIndex) { 1.1714 + return nullptr; 1.1715 + } 1.1716 + return mLines[--mIndex]; 1.1717 + } 1.1718 + 1.1719 + nsLineBox* NextLine() { 1.1720 + if (mIndex >= mNumLines - 1) { 1.1721 + return nullptr; 1.1722 + } 1.1723 + return mLines[++mIndex]; 1.1724 + } 1.1725 + 1.1726 + nsLineBox* LineAt(int32_t aIndex) { 1.1727 + if ((aIndex < 0) || (aIndex >= mNumLines)) { 1.1728 + return nullptr; 1.1729 + } 1.1730 + return mLines[aIndex]; 1.1731 + } 1.1732 + 1.1733 + nsLineBox** mLines; 1.1734 + int32_t mIndex; 1.1735 + int32_t mNumLines; 1.1736 + bool mRightToLeft; 1.1737 +}; 1.1738 + 1.1739 +#endif /* nsLineBox_h___ */