layout/generic/nsFrameList.cpp

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 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsFrameList.h"
michael@0 7 #include "nsIFrame.h"
michael@0 8 #include "nsLayoutUtils.h"
michael@0 9 #include "nsPresContext.h"
michael@0 10 #include "nsIPresShell.h"
michael@0 11
michael@0 12 #include "nsGkAtoms.h"
michael@0 13 #include "nsILineIterator.h"
michael@0 14 #include "nsBidiPresUtils.h"
michael@0 15
michael@0 16 namespace mozilla {
michael@0 17 namespace layout {
michael@0 18 namespace detail {
michael@0 19 const AlignedFrameListBytes gEmptyFrameListBytes = { 0 };
michael@0 20 }
michael@0 21 }
michael@0 22 }
michael@0 23
michael@0 24 void*
michael@0 25 nsFrameList::operator new(size_t sz, nsIPresShell* aPresShell) CPP_THROW_NEW
michael@0 26 {
michael@0 27 return aPresShell->AllocateByObjectID(nsPresArena::nsFrameList_id, sz);
michael@0 28 }
michael@0 29
michael@0 30 void
michael@0 31 nsFrameList::Delete(nsIPresShell* aPresShell)
michael@0 32 {
michael@0 33 NS_PRECONDITION(this != &EmptyList(), "Shouldn't Delete() this list");
michael@0 34 NS_ASSERTION(IsEmpty(), "Shouldn't Delete() a non-empty list");
michael@0 35
michael@0 36 aPresShell->FreeByObjectID(nsPresArena::nsFrameList_id, this);
michael@0 37 }
michael@0 38
michael@0 39 void
michael@0 40 nsFrameList::DestroyFrames()
michael@0 41 {
michael@0 42 while (nsIFrame* frame = RemoveFirstChild()) {
michael@0 43 frame->Destroy();
michael@0 44 }
michael@0 45 mLastChild = nullptr;
michael@0 46 }
michael@0 47
michael@0 48 void
michael@0 49 nsFrameList::DestroyFramesFrom(nsIFrame* aDestructRoot)
michael@0 50 {
michael@0 51 NS_PRECONDITION(aDestructRoot, "Missing destruct root");
michael@0 52
michael@0 53 while (nsIFrame* frame = RemoveFirstChild()) {
michael@0 54 frame->DestroyFrom(aDestructRoot);
michael@0 55 }
michael@0 56 mLastChild = nullptr;
michael@0 57 }
michael@0 58
michael@0 59 void
michael@0 60 nsFrameList::SetFrames(nsIFrame* aFrameList)
michael@0 61 {
michael@0 62 NS_PRECONDITION(!mFirstChild, "Losing frames");
michael@0 63
michael@0 64 mFirstChild = aFrameList;
michael@0 65 mLastChild = nsLayoutUtils::GetLastSibling(mFirstChild);
michael@0 66 }
michael@0 67
michael@0 68 void
michael@0 69 nsFrameList::RemoveFrame(nsIFrame* aFrame)
michael@0 70 {
michael@0 71 NS_PRECONDITION(aFrame, "null ptr");
michael@0 72 #ifdef DEBUG_FRAME_LIST
michael@0 73 // ContainsFrame is O(N)
michael@0 74 NS_PRECONDITION(ContainsFrame(aFrame), "wrong list");
michael@0 75 #endif
michael@0 76
michael@0 77 nsIFrame* nextFrame = aFrame->GetNextSibling();
michael@0 78 if (aFrame == mFirstChild) {
michael@0 79 mFirstChild = nextFrame;
michael@0 80 aFrame->SetNextSibling(nullptr);
michael@0 81 if (!nextFrame) {
michael@0 82 mLastChild = nullptr;
michael@0 83 }
michael@0 84 }
michael@0 85 else {
michael@0 86 nsIFrame* prevSibling = aFrame->GetPrevSibling();
michael@0 87 NS_ASSERTION(prevSibling && prevSibling->GetNextSibling() == aFrame,
michael@0 88 "Broken frame linkage");
michael@0 89 prevSibling->SetNextSibling(nextFrame);
michael@0 90 aFrame->SetNextSibling(nullptr);
michael@0 91 if (!nextFrame) {
michael@0 92 mLastChild = prevSibling;
michael@0 93 }
michael@0 94 }
michael@0 95 }
michael@0 96
michael@0 97 nsFrameList
michael@0 98 nsFrameList::RemoveFramesAfter(nsIFrame* aAfterFrame)
michael@0 99 {
michael@0 100 if (!aAfterFrame) {
michael@0 101 nsFrameList result;
michael@0 102 result.InsertFrames(nullptr, nullptr, *this);
michael@0 103 return result;
michael@0 104 }
michael@0 105
michael@0 106 NS_PRECONDITION(NotEmpty(), "illegal operation on empty list");
michael@0 107 #ifdef DEBUG_FRAME_LIST
michael@0 108 NS_PRECONDITION(ContainsFrame(aAfterFrame), "wrong list");
michael@0 109 #endif
michael@0 110
michael@0 111 nsIFrame* tail = aAfterFrame->GetNextSibling();
michael@0 112 // if (!tail) return EmptyList(); -- worth optimizing this case?
michael@0 113 nsIFrame* oldLastChild = mLastChild;
michael@0 114 mLastChild = aAfterFrame;
michael@0 115 aAfterFrame->SetNextSibling(nullptr);
michael@0 116 return nsFrameList(tail, tail ? oldLastChild : nullptr);
michael@0 117 }
michael@0 118
michael@0 119 nsIFrame*
michael@0 120 nsFrameList::RemoveFirstChild()
michael@0 121 {
michael@0 122 if (mFirstChild) {
michael@0 123 nsIFrame* firstChild = mFirstChild;
michael@0 124 RemoveFrame(firstChild);
michael@0 125 return firstChild;
michael@0 126 }
michael@0 127 return nullptr;
michael@0 128 }
michael@0 129
michael@0 130 void
michael@0 131 nsFrameList::DestroyFrame(nsIFrame* aFrame)
michael@0 132 {
michael@0 133 NS_PRECONDITION(aFrame, "null ptr");
michael@0 134 RemoveFrame(aFrame);
michael@0 135 aFrame->Destroy();
michael@0 136 }
michael@0 137
michael@0 138 nsFrameList::Slice
michael@0 139 nsFrameList::InsertFrames(nsIFrame* aParent, nsIFrame* aPrevSibling,
michael@0 140 nsFrameList& aFrameList)
michael@0 141 {
michael@0 142 NS_PRECONDITION(aFrameList.NotEmpty(), "Unexpected empty list");
michael@0 143
michael@0 144 if (aParent) {
michael@0 145 aFrameList.ApplySetParent(aParent);
michael@0 146 }
michael@0 147
michael@0 148 NS_ASSERTION(IsEmpty() ||
michael@0 149 FirstChild()->GetParent() == aFrameList.FirstChild()->GetParent(),
michael@0 150 "frame to add has different parent");
michael@0 151 NS_ASSERTION(!aPrevSibling ||
michael@0 152 aPrevSibling->GetParent() == aFrameList.FirstChild()->GetParent(),
michael@0 153 "prev sibling has different parent");
michael@0 154 #ifdef DEBUG_FRAME_LIST
michael@0 155 // ContainsFrame is O(N)
michael@0 156 NS_ASSERTION(!aPrevSibling || ContainsFrame(aPrevSibling),
michael@0 157 "prev sibling is not on this list");
michael@0 158 #endif
michael@0 159
michael@0 160 nsIFrame* firstNewFrame = aFrameList.FirstChild();
michael@0 161 nsIFrame* nextSibling;
michael@0 162 if (aPrevSibling) {
michael@0 163 nextSibling = aPrevSibling->GetNextSibling();
michael@0 164 aPrevSibling->SetNextSibling(firstNewFrame);
michael@0 165 }
michael@0 166 else {
michael@0 167 nextSibling = mFirstChild;
michael@0 168 mFirstChild = firstNewFrame;
michael@0 169 }
michael@0 170
michael@0 171 nsIFrame* lastNewFrame = aFrameList.LastChild();
michael@0 172 lastNewFrame->SetNextSibling(nextSibling);
michael@0 173 if (!nextSibling) {
michael@0 174 mLastChild = lastNewFrame;
michael@0 175 }
michael@0 176
michael@0 177 VerifyList();
michael@0 178
michael@0 179 aFrameList.Clear();
michael@0 180 return Slice(*this, firstNewFrame, nextSibling);
michael@0 181 }
michael@0 182
michael@0 183 nsFrameList
michael@0 184 nsFrameList::ExtractHead(FrameLinkEnumerator& aLink)
michael@0 185 {
michael@0 186 NS_PRECONDITION(&aLink.List() == this, "Unexpected list");
michael@0 187 NS_PRECONDITION(!aLink.PrevFrame() ||
michael@0 188 aLink.PrevFrame()->GetNextSibling() ==
michael@0 189 aLink.NextFrame(),
michael@0 190 "Unexpected PrevFrame()");
michael@0 191 NS_PRECONDITION(aLink.PrevFrame() ||
michael@0 192 aLink.NextFrame() == FirstChild(),
michael@0 193 "Unexpected NextFrame()");
michael@0 194 NS_PRECONDITION(!aLink.PrevFrame() ||
michael@0 195 aLink.NextFrame() != FirstChild(),
michael@0 196 "Unexpected NextFrame()");
michael@0 197 NS_PRECONDITION(aLink.mEnd == nullptr,
michael@0 198 "Unexpected mEnd for frame link enumerator");
michael@0 199
michael@0 200 nsIFrame* prev = aLink.PrevFrame();
michael@0 201 nsIFrame* newFirstFrame = nullptr;
michael@0 202 if (prev) {
michael@0 203 // Truncate the list after |prev| and hand the first part to our new list.
michael@0 204 prev->SetNextSibling(nullptr);
michael@0 205 newFirstFrame = mFirstChild;
michael@0 206 mFirstChild = aLink.NextFrame();
michael@0 207 if (!mFirstChild) { // we handed over the whole list
michael@0 208 mLastChild = nullptr;
michael@0 209 }
michael@0 210
michael@0 211 // Now make sure aLink doesn't point to a frame we no longer have.
michael@0 212 aLink.mPrev = nullptr;
michael@0 213 }
michael@0 214 // else aLink is pointing to before our first frame. Nothing to do.
michael@0 215
michael@0 216 return nsFrameList(newFirstFrame, prev);
michael@0 217 }
michael@0 218
michael@0 219 nsFrameList
michael@0 220 nsFrameList::ExtractTail(FrameLinkEnumerator& aLink)
michael@0 221 {
michael@0 222 NS_PRECONDITION(&aLink.List() == this, "Unexpected list");
michael@0 223 NS_PRECONDITION(!aLink.PrevFrame() ||
michael@0 224 aLink.PrevFrame()->GetNextSibling() ==
michael@0 225 aLink.NextFrame(),
michael@0 226 "Unexpected PrevFrame()");
michael@0 227 NS_PRECONDITION(aLink.PrevFrame() ||
michael@0 228 aLink.NextFrame() == FirstChild(),
michael@0 229 "Unexpected NextFrame()");
michael@0 230 NS_PRECONDITION(!aLink.PrevFrame() ||
michael@0 231 aLink.NextFrame() != FirstChild(),
michael@0 232 "Unexpected NextFrame()");
michael@0 233 NS_PRECONDITION(aLink.mEnd == nullptr,
michael@0 234 "Unexpected mEnd for frame link enumerator");
michael@0 235
michael@0 236 nsIFrame* prev = aLink.PrevFrame();
michael@0 237 nsIFrame* newFirstFrame;
michael@0 238 nsIFrame* newLastFrame;
michael@0 239 if (prev) {
michael@0 240 // Truncate the list after |prev| and hand the second part to our new list
michael@0 241 prev->SetNextSibling(nullptr);
michael@0 242 newFirstFrame = aLink.NextFrame();
michael@0 243 newLastFrame = newFirstFrame ? mLastChild : nullptr;
michael@0 244 mLastChild = prev;
michael@0 245 } else {
michael@0 246 // Hand the whole list over to our new list
michael@0 247 newFirstFrame = mFirstChild;
michael@0 248 newLastFrame = mLastChild;
michael@0 249 Clear();
michael@0 250 }
michael@0 251
michael@0 252 // Now make sure aLink doesn't point to a frame we no longer have.
michael@0 253 aLink.mFrame = nullptr;
michael@0 254
michael@0 255 NS_POSTCONDITION(aLink.AtEnd(), "What's going on here?");
michael@0 256
michael@0 257 return nsFrameList(newFirstFrame, newLastFrame);
michael@0 258 }
michael@0 259
michael@0 260 nsIFrame*
michael@0 261 nsFrameList::FrameAt(int32_t aIndex) const
michael@0 262 {
michael@0 263 NS_PRECONDITION(aIndex >= 0, "invalid arg");
michael@0 264 if (aIndex < 0) return nullptr;
michael@0 265 nsIFrame* frame = mFirstChild;
michael@0 266 while ((aIndex-- > 0) && frame) {
michael@0 267 frame = frame->GetNextSibling();
michael@0 268 }
michael@0 269 return frame;
michael@0 270 }
michael@0 271
michael@0 272 int32_t
michael@0 273 nsFrameList::IndexOf(nsIFrame* aFrame) const
michael@0 274 {
michael@0 275 int32_t count = 0;
michael@0 276 for (nsIFrame* f = mFirstChild; f; f = f->GetNextSibling()) {
michael@0 277 if (f == aFrame)
michael@0 278 return count;
michael@0 279 ++count;
michael@0 280 }
michael@0 281 return -1;
michael@0 282 }
michael@0 283
michael@0 284 bool
michael@0 285 nsFrameList::ContainsFrame(const nsIFrame* aFrame) const
michael@0 286 {
michael@0 287 NS_PRECONDITION(aFrame, "null ptr");
michael@0 288
michael@0 289 nsIFrame* frame = mFirstChild;
michael@0 290 while (frame) {
michael@0 291 if (frame == aFrame) {
michael@0 292 return true;
michael@0 293 }
michael@0 294 frame = frame->GetNextSibling();
michael@0 295 }
michael@0 296 return false;
michael@0 297 }
michael@0 298
michael@0 299 int32_t
michael@0 300 nsFrameList::GetLength() const
michael@0 301 {
michael@0 302 int32_t count = 0;
michael@0 303 nsIFrame* frame = mFirstChild;
michael@0 304 while (frame) {
michael@0 305 count++;
michael@0 306 frame = frame->GetNextSibling();
michael@0 307 }
michael@0 308 return count;
michael@0 309 }
michael@0 310
michael@0 311 void
michael@0 312 nsFrameList::ApplySetParent(nsIFrame* aParent) const
michael@0 313 {
michael@0 314 NS_ASSERTION(aParent, "null ptr");
michael@0 315
michael@0 316 for (nsIFrame* f = FirstChild(); f; f = f->GetNextSibling()) {
michael@0 317 f->SetParent(aParent);
michael@0 318 }
michael@0 319 }
michael@0 320
michael@0 321 /* static */ void
michael@0 322 nsFrameList::UnhookFrameFromSiblings(nsIFrame* aFrame)
michael@0 323 {
michael@0 324 MOZ_ASSERT(aFrame->GetPrevSibling() && aFrame->GetNextSibling());
michael@0 325 nsIFrame* const nextSibling = aFrame->GetNextSibling();
michael@0 326 nsIFrame* const prevSibling = aFrame->GetPrevSibling();
michael@0 327 aFrame->SetNextSibling(nullptr);
michael@0 328 prevSibling->SetNextSibling(nextSibling);
michael@0 329 MOZ_ASSERT(!aFrame->GetPrevSibling() && !aFrame->GetNextSibling());
michael@0 330 }
michael@0 331
michael@0 332 #ifdef DEBUG_FRAME_DUMP
michael@0 333 void
michael@0 334 nsFrameList::List(FILE* out) const
michael@0 335 {
michael@0 336 fprintf_stderr(out, "<\n");
michael@0 337 for (nsIFrame* frame = mFirstChild; frame;
michael@0 338 frame = frame->GetNextSibling()) {
michael@0 339 frame->List(out, " ");
michael@0 340 }
michael@0 341 fprintf_stderr(out, ">\n");
michael@0 342 }
michael@0 343 #endif
michael@0 344
michael@0 345 nsIFrame*
michael@0 346 nsFrameList::GetPrevVisualFor(nsIFrame* aFrame) const
michael@0 347 {
michael@0 348 if (!mFirstChild)
michael@0 349 return nullptr;
michael@0 350
michael@0 351 nsIFrame* parent = mFirstChild->GetParent();
michael@0 352 if (!parent)
michael@0 353 return aFrame ? aFrame->GetPrevSibling() : LastChild();
michael@0 354
michael@0 355 nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild);
michael@0 356
michael@0 357 nsAutoLineIterator iter = parent->GetLineIterator();
michael@0 358 if (!iter) {
michael@0 359 // Parent is not a block Frame
michael@0 360 if (parent->GetType() == nsGkAtoms::lineFrame) {
michael@0 361 // Line frames are not bidi-splittable, so need to consider bidi reordering
michael@0 362 if (baseLevel == NSBIDI_LTR) {
michael@0 363 return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1);
michael@0 364 } else { // RTL
michael@0 365 return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1);
michael@0 366 }
michael@0 367 } else {
michael@0 368 // Just get the next or prev sibling, depending on block and frame direction.
michael@0 369 nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild);
michael@0 370 if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) {
michael@0 371 return aFrame ? aFrame->GetPrevSibling() : LastChild();
michael@0 372 } else {
michael@0 373 return aFrame ? aFrame->GetNextSibling() : mFirstChild;
michael@0 374 }
michael@0 375 }
michael@0 376 }
michael@0 377
michael@0 378 // Parent is a block frame, so use the LineIterator to find the previous visual
michael@0 379 // sibling on this line, or the last one on the previous line.
michael@0 380
michael@0 381 int32_t thisLine;
michael@0 382 if (aFrame) {
michael@0 383 thisLine = iter->FindLineContaining(aFrame);
michael@0 384 if (thisLine < 0)
michael@0 385 return nullptr;
michael@0 386 } else {
michael@0 387 thisLine = iter->GetNumLines();
michael@0 388 }
michael@0 389
michael@0 390 nsIFrame* frame = nullptr;
michael@0 391 nsIFrame* firstFrameOnLine;
michael@0 392 int32_t numFramesOnLine;
michael@0 393 nsRect lineBounds;
michael@0 394 uint32_t lineFlags;
michael@0 395
michael@0 396 if (aFrame) {
michael@0 397 iter->GetLine(thisLine, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
michael@0 398
michael@0 399 if (baseLevel == NSBIDI_LTR) {
michael@0 400 frame = nsBidiPresUtils::GetFrameToLeftOf(aFrame, firstFrameOnLine, numFramesOnLine);
michael@0 401 } else { // RTL
michael@0 402 frame = nsBidiPresUtils::GetFrameToRightOf(aFrame, firstFrameOnLine, numFramesOnLine);
michael@0 403 }
michael@0 404 }
michael@0 405
michael@0 406 if (!frame && thisLine > 0) {
michael@0 407 // Get the last frame of the previous line
michael@0 408 iter->GetLine(thisLine - 1, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
michael@0 409
michael@0 410 if (baseLevel == NSBIDI_LTR) {
michael@0 411 frame = nsBidiPresUtils::GetFrameToLeftOf(nullptr, firstFrameOnLine, numFramesOnLine);
michael@0 412 } else { // RTL
michael@0 413 frame = nsBidiPresUtils::GetFrameToRightOf(nullptr, firstFrameOnLine, numFramesOnLine);
michael@0 414 }
michael@0 415 }
michael@0 416 return frame;
michael@0 417 }
michael@0 418
michael@0 419 nsIFrame*
michael@0 420 nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const
michael@0 421 {
michael@0 422 if (!mFirstChild)
michael@0 423 return nullptr;
michael@0 424
michael@0 425 nsIFrame* parent = mFirstChild->GetParent();
michael@0 426 if (!parent)
michael@0 427 return aFrame ? aFrame->GetPrevSibling() : mFirstChild;
michael@0 428
michael@0 429 nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild);
michael@0 430
michael@0 431 nsAutoLineIterator iter = parent->GetLineIterator();
michael@0 432 if (!iter) {
michael@0 433 // Parent is not a block Frame
michael@0 434 if (parent->GetType() == nsGkAtoms::lineFrame) {
michael@0 435 // Line frames are not bidi-splittable, so need to consider bidi reordering
michael@0 436 if (baseLevel == NSBIDI_LTR) {
michael@0 437 return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1);
michael@0 438 } else { // RTL
michael@0 439 return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1);
michael@0 440 }
michael@0 441 } else {
michael@0 442 // Just get the next or prev sibling, depending on block and frame direction.
michael@0 443 nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild);
michael@0 444 if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) {
michael@0 445 return aFrame ? aFrame->GetNextSibling() : mFirstChild;
michael@0 446 } else {
michael@0 447 return aFrame ? aFrame->GetPrevSibling() : LastChild();
michael@0 448 }
michael@0 449 }
michael@0 450 }
michael@0 451
michael@0 452 // Parent is a block frame, so use the LineIterator to find the next visual
michael@0 453 // sibling on this line, or the first one on the next line.
michael@0 454
michael@0 455 int32_t thisLine;
michael@0 456 if (aFrame) {
michael@0 457 thisLine = iter->FindLineContaining(aFrame);
michael@0 458 if (thisLine < 0)
michael@0 459 return nullptr;
michael@0 460 } else {
michael@0 461 thisLine = -1;
michael@0 462 }
michael@0 463
michael@0 464 nsIFrame* frame = nullptr;
michael@0 465 nsIFrame* firstFrameOnLine;
michael@0 466 int32_t numFramesOnLine;
michael@0 467 nsRect lineBounds;
michael@0 468 uint32_t lineFlags;
michael@0 469
michael@0 470 if (aFrame) {
michael@0 471 iter->GetLine(thisLine, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
michael@0 472
michael@0 473 if (baseLevel == NSBIDI_LTR) {
michael@0 474 frame = nsBidiPresUtils::GetFrameToRightOf(aFrame, firstFrameOnLine, numFramesOnLine);
michael@0 475 } else { // RTL
michael@0 476 frame = nsBidiPresUtils::GetFrameToLeftOf(aFrame, firstFrameOnLine, numFramesOnLine);
michael@0 477 }
michael@0 478 }
michael@0 479
michael@0 480 int32_t numLines = iter->GetNumLines();
michael@0 481 if (!frame && thisLine < numLines - 1) {
michael@0 482 // Get the first frame of the next line
michael@0 483 iter->GetLine(thisLine + 1, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
michael@0 484
michael@0 485 if (baseLevel == NSBIDI_LTR) {
michael@0 486 frame = nsBidiPresUtils::GetFrameToRightOf(nullptr, firstFrameOnLine, numFramesOnLine);
michael@0 487 } else { // RTL
michael@0 488 frame = nsBidiPresUtils::GetFrameToLeftOf(nullptr, firstFrameOnLine, numFramesOnLine);
michael@0 489 }
michael@0 490 }
michael@0 491 return frame;
michael@0 492 }
michael@0 493
michael@0 494 #ifdef DEBUG_FRAME_LIST
michael@0 495 void
michael@0 496 nsFrameList::VerifyList() const
michael@0 497 {
michael@0 498 NS_ASSERTION((mFirstChild == nullptr) == (mLastChild == nullptr),
michael@0 499 "bad list state");
michael@0 500
michael@0 501 if (IsEmpty()) {
michael@0 502 return;
michael@0 503 }
michael@0 504
michael@0 505 // Simple algorithm to find a loop in a linked list -- advance pointers
michael@0 506 // through it at speeds of 1 and 2, and if they ever get to be equal bail
michael@0 507 NS_ASSERTION(!mFirstChild->GetPrevSibling(), "bad prev sibling pointer");
michael@0 508 nsIFrame *first = mFirstChild, *second = mFirstChild;
michael@0 509 for (;;) {
michael@0 510 first = first->GetNextSibling();
michael@0 511 second = second->GetNextSibling();
michael@0 512 if (!second) {
michael@0 513 break;
michael@0 514 }
michael@0 515 NS_ASSERTION(second->GetPrevSibling()->GetNextSibling() == second,
michael@0 516 "bad prev sibling pointer");
michael@0 517 second = second->GetNextSibling();
michael@0 518 if (first == second) {
michael@0 519 // Loop detected! Since second advances faster, they can't both be null;
michael@0 520 // we would have broken out of the loop long ago.
michael@0 521 NS_ERROR("loop in frame list. This will probably hang soon.");
michael@0 522 return;
michael@0 523 }
michael@0 524 if (!second) {
michael@0 525 break;
michael@0 526 }
michael@0 527 NS_ASSERTION(second->GetPrevSibling()->GetNextSibling() == second,
michael@0 528 "bad prev sibling pointer");
michael@0 529 }
michael@0 530
michael@0 531 NS_ASSERTION(mLastChild == nsLayoutUtils::GetLastSibling(mFirstChild),
michael@0 532 "bogus mLastChild");
michael@0 533 // XXX we should also assert that all GetParent() are either null or
michael@0 534 // the same non-null value, but nsCSSFrameConstructor::nsFrameItems
michael@0 535 // prevents that, e.g. table captions.
michael@0 536 }
michael@0 537 #endif
michael@0 538
michael@0 539 namespace mozilla {
michael@0 540 namespace layout {
michael@0 541
michael@0 542 AutoFrameListPtr::~AutoFrameListPtr()
michael@0 543 {
michael@0 544 if (mFrameList) {
michael@0 545 mFrameList->Delete(mPresContext->PresShell());
michael@0 546 }
michael@0 547 }
michael@0 548
michael@0 549 }
michael@0 550 }

mercurial