Index: Source/core/rendering/OrderIterator.cpp |
diff --git a/Source/core/rendering/OrderIterator.cpp b/Source/core/rendering/OrderIterator.cpp |
index 4d19918af38086bd604155b6e83958c720fa03b2..d55779cc4cf8de6523a7a428241a3f9b5530328a 100644 |
--- a/Source/core/rendering/OrderIterator.cpp |
+++ b/Source/core/rendering/OrderIterator.cpp |
@@ -38,8 +38,7 @@ namespace WebCore { |
OrderIterator::OrderIterator(const RenderBox* containerBox) |
: m_containerBox(containerBox) |
, m_currentChild(0) |
- , m_currentOrderIndex(0) |
- , m_currentChildIndex(0) |
+ , m_orderValuesIterator(0) |
{ |
} |
@@ -51,60 +50,73 @@ RenderBox* OrderIterator::first() |
RenderBox* OrderIterator::next() |
{ |
- for (; m_currentOrderIndex < m_orderValues.size(); ++m_currentOrderIndex) { |
- const Vector<RenderBox*>& currentOrderChildren = m_orderedValues.get(m_orderValues[m_currentOrderIndex]); |
- ASSERT(!currentOrderChildren.isEmpty()); |
- for (; m_currentChildIndex < currentOrderChildren.size(); ++m_currentChildIndex) { |
- m_currentChild = currentOrderChildren[m_currentChildIndex]; |
- ++m_currentChildIndex; |
- return m_currentChild; |
+ do { |
+ if (!m_currentChild) { |
+ if (m_orderValuesIterator == m_orderValues.end()) |
+ return 0; |
+ if (m_orderValuesIterator) { |
+ ++m_orderValuesIterator; |
+ if (m_orderValuesIterator == m_orderValues.end()) |
+ return 0; |
+ } else { |
+ m_orderValuesIterator = m_orderValues.begin(); |
+ } |
+ |
+ m_currentChild = m_containerBox->firstChildBox(); |
+ } else { |
+ m_currentChild = m_currentChild->nextSiblingBox(); |
} |
+ } while (!m_currentChild || m_currentChild->style()->order() != *m_orderValuesIterator); |
- m_currentChildIndex = 0; |
- } |
- |
- m_currentChild = 0; |
return m_currentChild; |
} |
void OrderIterator::reset() |
{ |
- m_currentOrderIndex = 0; |
- m_currentChildIndex = 0; |
m_currentChild = 0; |
-} |
- |
-void OrderIterator::invalidate() |
-{ |
- // Note that we don't release the memory here, we only invalidate the size. |
- // This avoids unneeded reallocation if the size ends up not changing. |
- m_orderValues.shrink(0); |
- m_orderedValues.clear(); |
- |
- reset(); |
+ m_orderValuesIterator = 0; |
} |
OrderIteratorPopulator::~OrderIteratorPopulator() |
{ |
m_iterator.reset(); |
- std::sort(m_iterator.m_orderValues.begin(), m_iterator.m_orderValues.end()); |
+ if (m_anyChildHasDefaultOrderValue) |
+ m_iterator.m_orderValues.append(0); |
+ |
+ if (m_iterator.m_orderValues.size() > 1) |
+ removeDuplicatedOrderValues(); |
// Ensure that we release any extra memory we hold onto. |
m_iterator.m_orderValues.shrinkToFit(); |
} |
-void OrderIteratorPopulator::collectChild(RenderBox* child) |
+void OrderIteratorPopulator::removeDuplicatedOrderValues() |
+{ |
+ OrderIterator::OrderValues& orderValues = m_iterator.m_orderValues; |
+ |
+ std::sort(orderValues.begin(), orderValues.end()); |
+ |
+ int previous = orderValues[0]; |
+ size_t uniqueItemIndex = 0; |
+ for (size_t i = 1; i < orderValues.size(); ++i) { |
+ int current = orderValues[i]; |
+ if (current == previous) |
+ continue; |
+ ++uniqueItemIndex; |
+ std::swap(orderValues[i], orderValues[uniqueItemIndex]); |
+ previous = current; |
+ } |
+ orderValues.shrink(uniqueItemIndex + 1); |
+} |
+ |
+void OrderIteratorPopulator::collectChild(const RenderBox* child) |
{ |
- int order = child->style()->order(); |
- |
- // FIXME: Ideally we would want to avoid inserting into the HashMap for the common case where there are only items |
- // with the default 'order' 0. The current API is designed to blend into a single iteration which makes having a |
- // slower fallback difficult without having to store the children (grid items may not be contiguous in DOM order). |
- OrderIterator::OrderedValuesMap::AddResult result = m_iterator.m_orderedValues.add(order, Vector<RenderBox*>()); |
- result.iterator->value.append(child); |
- if (result.isNewEntry) |
+ // Avoid growing the vector for the common-case default value of 0. |
+ if (int order = child->style()->order()) |
m_iterator.m_orderValues.append(order); |
+ else |
+ m_anyChildHasDefaultOrderValue = true; |
} |
} // namespace WebCore |