DepthOrderedFrameList.cpp (2683B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "DepthOrderedFrameList.h" 8 9 #include "nsContainerFrame.h" 10 #include "nsIFrame.h" 11 12 namespace mozilla { 13 14 void DepthOrderedFrameList::Add(nsIFrame* aFrame) { 15 MOZ_ASSERT(aFrame); 16 17 if (auto p = mFrames.lookupForAdd(aFrame)) { 18 // We don't expect the depth of a frame in the list to change. 19 MOZ_ASSERT(p->value() == aFrame->GetDepthInFrameTree()); 20 } else { 21 if (!mFrames.add(p, aFrame, aFrame->GetDepthInFrameTree())) { 22 NS_WARNING("failed to add frame to DepthOrderedFrameList"); 23 } 24 if (mFrames.count() == 1) { 25 // We just added the first frame, so can directly set up mSortedFrames. 26 // (Lists that only contain a single frame are common.) 27 MOZ_ASSERT(mSortedFrames.IsEmpty()); 28 mSortedFrames.AppendElement(FrameAndDepth{aFrame, p->value()}); 29 } else { 30 // Clear mSortedFrames, so that we'll rebuild it when needed. 31 mSortedFrames.ClearAndRetainStorage(); 32 } 33 } 34 } 35 36 nsIFrame* DepthOrderedFrameList::PopShallowestRoot() { 37 MOZ_ASSERT(!mFrames.empty(), "no frames in list!"); 38 39 EnsureSortedList(); 40 41 // List is sorted in order of decreasing depth, so there are no shallower 42 // frames than the last one. 43 const FrameAndDepth& lastFAD = mSortedFrames.PopLastElement(); 44 nsIFrame* frame = lastFAD.mFrame; 45 // We don't expect frame to change depths. 46 MOZ_ASSERT(frame->GetDepthInFrameTree() == lastFAD.mDepth); 47 // Keep the hashtable in sync with the sorted list. 48 mFrames.remove(frame); 49 return frame; 50 } 51 52 bool DepthOrderedFrameList::FrameIsAncestorOfAnyElement( 53 nsIFrame* aFrame) const { 54 MOZ_ASSERT(aFrame); 55 56 // Look for a path from any element to aFrame, following GetParent(). This 57 // check mirrors what FrameNeedsReflow() would have done if the reflow root 58 // didn't get in the way. 59 for (auto iter = mFrames.iter(); !iter.done(); iter.next()) { 60 nsIFrame* f = iter.get().key(); 61 do { 62 if (f == aFrame) { 63 return true; 64 } 65 f = f->GetParent(); 66 } while (f); 67 } 68 69 return false; 70 } 71 72 void DepthOrderedFrameList::BuildSortedList() const { 73 MOZ_ASSERT(mSortedFrames.IsEmpty()); 74 75 mSortedFrames.SetCapacity(mFrames.count()); 76 for (auto iter = mFrames.iter(); !iter.done(); iter.next()) { 77 mSortedFrames.AppendElement( 78 FrameAndDepth{iter.get().key(), iter.get().value()}); 79 } 80 mSortedFrames.Sort(); 81 } 82 83 } // namespace mozilla