| Index: Source/platform/graphics/paint/DisplayItems.h
|
| diff --git a/Source/platform/graphics/paint/DisplayItems.h b/Source/platform/graphics/paint/DisplayItems.h
|
| index ff125ed3d3d2a9dcbf59e36f76f7e9b05c9726ca..f790abdb7a8530d7695a0847003986e431586d97 100644
|
| --- a/Source/platform/graphics/paint/DisplayItems.h
|
| +++ b/Source/platform/graphics/paint/DisplayItems.h
|
| @@ -6,8 +6,10 @@
|
| #define DisplayItems_h
|
|
|
| #include "platform/PlatformExport.h"
|
| +#include "platform/graphics/ListContainer.h"
|
| #include "platform/graphics/paint/DisplayItem.h"
|
| #include "platform/graphics/paint/DrawingDisplayItem.h"
|
| +#include "platform/graphics/paint/Transform3DDisplayItem.h"
|
| #include "wtf/Forward.h"
|
| #include "wtf/Noncopyable.h"
|
| #include "wtf/OwnPtr.h"
|
| @@ -20,6 +22,8 @@ class SkPicture;
|
|
|
| namespace blink {
|
|
|
| +static const size_t kMaximumDisplayItemSize = sizeof(BeginTransform3DDisplayItem);
|
| +
|
| // Encapsulates logic for dealing with a simple list of display items, as
|
| // opposed to DisplayItemList, which also manages the logic required for caching
|
| // and updating them.
|
| @@ -83,62 +87,79 @@ public:
|
| // Input iterators over the display items.
|
| class Iterator : public std::iterator<std::input_iterator_tag, const ItemHandle> {
|
| public:
|
| - const ItemHandle& operator*() const { m_handle = ItemHandle(m_iterator->get()); return m_handle; }
|
| + const ItemHandle& operator*() const { m_handle = ItemHandle(*m_iterator); return m_handle; }
|
| const ItemHandle* operator->() const { return &operator*(); }
|
| Iterator& operator++() { ++m_iterator; return *this; }
|
| Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; }
|
| bool operator==(const Iterator& other) const { return m_iterator == other.m_iterator; }
|
| bool operator!=(const Iterator& other) const { return !(*this == other); }
|
| private:
|
| - using InternalIterator = Vector<OwnPtr<DisplayItem>>::iterator;
|
| - Iterator(const InternalIterator& it) : m_iterator(it) { }
|
| + using InternalIterator = Vector<DisplayItem*>::iterator;
|
| + Iterator(const InternalIterator& it, DisplayItems* owningList) : m_iterator(it), m_owningList(owningList) { }
|
| InternalIterator m_iterator;
|
| + DisplayItems* m_owningList;
|
| mutable ItemHandle m_handle;
|
| friend class DisplayItems;
|
| friend class ConstIterator;
|
| };
|
| class ConstIterator : public std::iterator<std::input_iterator_tag, const ItemHandle> {
|
| public:
|
| - ConstIterator(const Iterator& it) : m_iterator(it.m_iterator) { }
|
| - const ItemHandle& operator*() const { m_handle = ItemHandle(m_iterator->get()); return m_handle; }
|
| + ConstIterator(const Iterator& it, const DisplayItems* owningList) : m_iterator(it.m_iterator), m_owningList(owningList) { }
|
| + const ItemHandle& operator*() const { m_handle = ItemHandle(*m_iterator); return m_handle; }
|
| const ItemHandle* operator->() const { return &operator*(); }
|
| ConstIterator& operator++() { ++m_iterator; return *this; }
|
| ConstIterator operator++(int) { ConstIterator tmp(*this); operator++(); return tmp; }
|
| bool operator==(const ConstIterator& other) const { return m_iterator == other.m_iterator; }
|
| bool operator!=(const ConstIterator& other) const { return !(*this == other); }
|
| private:
|
| - using InternalIterator = Vector<OwnPtr<DisplayItem>>::const_iterator;
|
| - ConstIterator(const InternalIterator& it) : m_iterator(it) { }
|
| + using InternalIterator = Vector<DisplayItem*>::const_iterator;
|
| + ConstIterator(const InternalIterator& it, const DisplayItems* owningList) : m_iterator(it), m_owningList(owningList) { }
|
| InternalIterator m_iterator;
|
| + const DisplayItems* m_owningList;
|
| mutable ItemHandle m_handle;
|
| friend class DisplayItems;
|
| };
|
|
|
| - DisplayItems();
|
| + DisplayItems(size_t reserveCapacity)
|
| + : m_ptrs()
|
| + , m_items(reserveCapacity, kMaximumDisplayItemSize)
|
| + {
|
| + m_ptrs.reserveCapacity(reserveCapacity);
|
| + }
|
| +
|
| ~DisplayItems();
|
|
|
| - bool isEmpty() const { return m_items.isEmpty(); }
|
| - size_t size() const { return m_items.size(); }
|
| + bool isEmpty() const { return m_ptrs.isEmpty(); }
|
| + size_t size() const { return m_ptrs.size(); }
|
|
|
| // Random access may not remain O(1) in the future.
|
| - ItemHandle operator[](size_t index) const { return ItemHandle(m_items[index].get()); }
|
| - Iterator iteratorAt(size_t index) { return Iterator(m_items.begin() + index); }
|
| - ConstIterator iteratorAt(size_t index) const { return ConstIterator(m_items.begin() + index); }
|
| - size_t indexForIterator(const Iterator& it) const { return it.m_iterator - m_items.begin(); }
|
| - size_t indexForIterator(const ConstIterator& it) const { return it.m_iterator - m_items.begin(); }
|
| + ItemHandle operator[](size_t index) const { return ItemHandle(m_ptrs[index]); }
|
| + Iterator iteratorAt(size_t index) { return Iterator(m_ptrs.begin() + index, this); }
|
| + ConstIterator iteratorAt(size_t index) const { return ConstIterator(m_ptrs.begin() + index, this); }
|
| + size_t indexForIterator(const Iterator& it) const { return it.m_iterator - m_ptrs.begin(); }
|
| + size_t indexForIterator(const ConstIterator& it) const { return it.m_iterator - m_ptrs.begin(); }
|
|
|
| // Input iteration, however, should remain cheap.
|
| - Iterator begin() { return Iterator(m_items.begin()); }
|
| - Iterator end() { return Iterator(m_items.end()); }
|
| - ConstIterator begin() const { return ConstIterator(m_items.begin()); }
|
| - ConstIterator end() const { return ConstIterator(m_items.end()); }
|
| + Iterator begin() { return Iterator(m_ptrs.begin(), this); }
|
| + Iterator end() { return Iterator(m_ptrs.end(), this); }
|
| + ConstIterator begin() const { return ConstIterator(m_ptrs.begin(), this); }
|
| + ConstIterator end() const { return ConstIterator(m_ptrs.end(), this); }
|
|
|
| // Access to the end of the list should also be fast.
|
| - ItemHandle last() const { return ItemHandle(m_items.last().get()); }
|
| + ItemHandle last() const { return ItemHandle(m_ptrs.last()); }
|
| +
|
| + template<typename DisplayItemClass>
|
| + DisplayItemClass& createAndAppend()
|
| + {
|
| + static_assert(WTF::IsSubclass<DisplayItemClass, DisplayItem>::value,
|
| + "Can only emplace subclasses of DisplayItem.");
|
| + static_assert(sizeof(DisplayItemClass) <= kMaximumDisplayItemSize,
|
| + "DisplayItem subclass is larger than storage buffer.");
|
|
|
| - // TODO(jbroman): Replace this with something that doesn't first require
|
| - // heap allocation.
|
| - void append(PassOwnPtr<DisplayItem>);
|
| + DisplayItemClass& item = *m_items.allocateAndConstruct<DisplayItemClass>();
|
| + m_ptrs.append(&item);
|
| + return item;
|
| + }
|
|
|
| // Appends by moving from another list. The item in the list it's being
|
| // removed from will become "gone" in this process, but can still be safely
|
| @@ -156,7 +177,11 @@ public:
|
| void setGone(const Iterator&);
|
|
|
| private:
|
| - Vector<OwnPtr<DisplayItem>> m_items;
|
| + // Non-owning list of pointers into m_items to support both fast iteration and
|
| + // the {set,is}Gone concept.
|
| + // TODO(pdr): Remove or clairify {set,is}Gone.
|
| + Vector<DisplayItem*> m_ptrs;
|
| + ListContainer<DisplayItem> m_items;
|
| };
|
|
|
| } // namespace blink
|
|
|