diff --git a/layout/painting/nsDisplayList.h b/layout/painting/nsDisplayList.h index 40967dc9555e..9e9468bcede7 100644 --- a/layout/painting/nsDisplayList.h +++ b/layout/painting/nsDisplayList.h @@ -3207,6 +3207,92 @@ private: bool mForceTransparentSurface; }; +class FlattenedDisplayItemIterator +{ +public: + FlattenedDisplayItemIterator(nsDisplayListBuilder* aBuilder, + nsDisplayList* aList, + const bool aResolveFlattening = true) + : mBuilder(aBuilder) + , mNext(aList->GetBottom()) + { + if (aResolveFlattening) { + // This is done conditionally in case subclass overrides + // ShouldFlattenNextItem(). + ResolveFlattening(); + } + } + + virtual ~FlattenedDisplayItemIterator() + { + MOZ_ASSERT(!HasNext()); + } + + nsDisplayItem* GetNext() + { + nsDisplayItem* next = mNext; + + // Advance mNext to the following item + if (next) { + mNext = mNext->GetAbove(); + ResolveFlattening(); + } + return next; + } + + bool HasNext() const + { + return mNext || !mStack.IsEmpty(); + } + + nsDisplayItem* PeekNext() + { + return mNext; + } + +protected: + bool AtEndOfNestedList() const + { + return !mNext && mStack.Length() > 0; + } + + virtual bool ShouldFlattenNextItem() const + { + return mNext && mNext->ShouldFlattenAway(mBuilder); + } + + void ResolveFlattening() + { + // Handle the case where we reach the end of a nested list, or the current + // item should start a new nested list. Repeat this until we find an actual + // item, or the very end of the outer list. + while (AtEndOfNestedList() || ShouldFlattenNextItem()) { + if (AtEndOfNestedList()) { + // Pop the last item off the stack. + mNext = mStack.LastElement(); + EndNested(mNext); + mStack.RemoveElementAt(mStack.Length() - 1); + // We stored the item that was flattened, so advance to the next. + mNext = mNext->GetAbove(); + } else { + // This item wants to be flattened. Store the current item on the stack, + // and use the first item in the child list instead. + mStack.AppendElement(mNext); + StartNested(mNext); + nsDisplayList* childItems = mNext->GetSameCoordinateSystemChildren(); + mNext = childItems->GetBottom(); + } + } + } + + virtual void EndNested(nsDisplayItem* aItem) {} + virtual void StartNested(nsDisplayItem* aItem) {} + + nsDisplayListBuilder* mBuilder; + nsDisplayItem* mNext; + AutoTArray mStack; +}; + /** * This is passed as a parameter to nsIFrame::BuildDisplayList. That method * will put any generated items onto the appropriate list given here. It's @@ -6778,72 +6864,6 @@ public: mutable mozilla::Maybe mIsFrameSelected; }; -class FlattenedDisplayItemIterator -{ -public: - FlattenedDisplayItemIterator(nsDisplayListBuilder* aBuilder, - nsDisplayList* aList) - : mBuilder(aBuilder) - , mNext(aList->GetBottom()) - { - ResolveFlattening(); - } - - nsDisplayItem* GetNext() - { - nsDisplayItem* next = mNext; - - // Advance mNext to the following item - if (next) { - mNext = mNext->GetAbove(); - ResolveFlattening(); - } - return next; - } - - nsDisplayItem* PeekNext() - { - return mNext; - } - -private: - bool AtEndOfNestedList() - { - return !mNext && mStack.Length() > 0; - } - - bool ShouldFlattenNextItem() - { - return mNext && mNext->ShouldFlattenAway(mBuilder); - } - - void ResolveFlattening() - { - // Handle the case where we reach the end of a nested list, or the current - // item should start a new nested list. Repeat this until we find an actual - // item, or the very end of the outer list. - while (AtEndOfNestedList() || ShouldFlattenNextItem()) { - if (AtEndOfNestedList()) { - // Pop the last item off the stack. - mNext = mStack.PopLastElement(); - // We stored the item that was flattened, so advance to the next. - mNext = mNext->GetAbove(); - } else { - // This item wants to be flattened. Store the current item on the stack, - // and use the first item in the child list instead. - mStack.AppendElement(mNext); - nsDisplayList* childItems = mNext->GetSameCoordinateSystemChildren(); - mNext = childItems->GetBottom(); - } - } - } - - - nsDisplayListBuilder* mBuilder; - nsDisplayItem* mNext; - AutoTArray mStack; -}; - /** * A display item that for webrender to handle SVG */