layout/generic/nsLineBox.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial