Home | History | Annotate | Download | only in paint
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "config.h"
      6 #include "core/paint/GridPainter.h"
      7 
      8 #include "core/rendering/PaintInfo.h"
      9 #include "core/rendering/RenderGrid.h"
     10 
     11 namespace blink {
     12 
     13 static GridSpan dirtiedGridAreas(const Vector<LayoutUnit>& coordinates, LayoutUnit start, LayoutUnit end)
     14 {
     15     // This function does a binary search over the coordinates.
     16     // This doesn't work with grid items overflowing their grid areas, but that is managed with m_gridItemsOverflowingGridArea.
     17 
     18     size_t startGridAreaIndex = std::upper_bound(coordinates.begin(), coordinates.end() - 1, start) - coordinates.begin();
     19     if (startGridAreaIndex > 0)
     20         --startGridAreaIndex;
     21 
     22     size_t endGridAreaIndex = std::upper_bound(coordinates.begin() + startGridAreaIndex, coordinates.end() - 1, end) - coordinates.begin();
     23     if (endGridAreaIndex > 0)
     24         --endGridAreaIndex;
     25 
     26     return GridSpan(startGridAreaIndex, endGridAreaIndex);
     27 }
     28 
     29 class GridItemsSorter {
     30 public:
     31     bool operator()(const std::pair<RenderBox*, size_t>& firstChild, const std::pair<RenderBox*, size_t>& secondChild) const
     32     {
     33         if (firstChild.first->style()->order() != secondChild.first->style()->order())
     34             return firstChild.first->style()->order() < secondChild.first->style()->order();
     35 
     36         return firstChild.second < secondChild.second;
     37     }
     38 };
     39 
     40 void GridPainter::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
     41 {
     42     ASSERT_WITH_SECURITY_IMPLICATION(!m_renderGrid.gridIsDirty());
     43 
     44     LayoutRect localPaintInvalidationRect = paintInfo.rect;
     45     localPaintInvalidationRect.moveBy(-paintOffset);
     46 
     47     GridSpan dirtiedColumns = dirtiedGridAreas(m_renderGrid.columnPositions(), localPaintInvalidationRect.x(), localPaintInvalidationRect.maxX());
     48     GridSpan dirtiedRows = dirtiedGridAreas(m_renderGrid.rowPositions(), localPaintInvalidationRect.y(), localPaintInvalidationRect.maxY());
     49 
     50     Vector<std::pair<RenderBox*, size_t> > gridItemsToBePainted;
     51 
     52     for (GridSpan::iterator row = dirtiedRows.begin(); row != dirtiedRows.end(); ++row) {
     53         for (GridSpan::iterator column = dirtiedColumns.begin(); column != dirtiedColumns.end(); ++column) {
     54             const Vector<RenderBox*, 1>& children = m_renderGrid.gridCell(row.toInt(), column.toInt());
     55             for (size_t j = 0; j < children.size(); ++j)
     56                 gridItemsToBePainted.append(std::make_pair(children[j], m_renderGrid.paintIndexForGridItem(children[j])));
     57         }
     58     }
     59 
     60     for (Vector<RenderBox*>::const_iterator it = m_renderGrid.itemsOverflowingGridArea().begin(); it != m_renderGrid.itemsOverflowingGridArea().end(); ++it) {
     61         if ((*it)->frameRect().intersects(localPaintInvalidationRect))
     62             gridItemsToBePainted.append(std::make_pair(*it, m_renderGrid.paintIndexForGridItem(*it)));
     63     }
     64 
     65     // Sort grid items following order-modified document order.
     66     // See http://www.w3.org/TR/css-flexbox/#order-modified-document-order
     67     std::stable_sort(gridItemsToBePainted.begin(), gridItemsToBePainted.end(), GridItemsSorter());
     68 
     69     RenderBox* previous = 0;
     70     for (Vector<std::pair<RenderBox*, size_t> >::const_iterator it = gridItemsToBePainted.begin(); it != gridItemsToBePainted.end(); ++it) {
     71         // We might have duplicates because of spanning children are included in all cells they span.
     72         // Skip them here to avoid painting items several times.
     73         RenderBox* current = it->first;
     74         if (current == previous)
     75             continue;
     76 
     77         paintChild(*current, paintInfo, paintOffset);
     78         previous = current;
     79     }
     80 }
     81 
     82 void GridPainter::paintChild(RenderBox& child, PaintInfo& paintInfo, const LayoutPoint& paintOffset)
     83 {
     84     LayoutPoint childPoint = m_renderGrid.flipForWritingModeForChild(&child, paintOffset);
     85     if (!child.hasSelfPaintingLayer() && !child.isFloating())
     86         child.paint(paintInfo, childPoint);
     87 }
     88 
     89 } // namespace blink
     90