Home | History | Annotate | Download | only in style
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #ifndef GridCoordinate_h
     32 #define GridCoordinate_h
     33 
     34 #include "core/rendering/style/GridPosition.h"
     35 #include "wtf/HashMap.h"
     36 #include "wtf/PassOwnPtr.h"
     37 #include "wtf/text/WTFString.h"
     38 
     39 namespace WebCore {
     40 
     41 // A span in a single direction (either rows or columns). Note that |initialPositionIndex|
     42 // and |finalPositionIndex| are grid areas' indexes, NOT grid lines'. Iterating over the
     43 // span should include both |initialPositionIndex| and |finalPositionIndex| to be correct.
     44 struct GridSpan {
     45     static PassOwnPtr<GridSpan> create(size_t initialPosition, size_t finalPosition)
     46     {
     47         return adoptPtr(new GridSpan(initialPosition, finalPosition));
     48     }
     49 
     50     static PassOwnPtr<GridSpan> createWithSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side)
     51     {
     52         // 'span 1' is contained inside a single grid track regardless of the direction.
     53         // That's why the CSS span value is one more than the offset we apply.
     54         size_t positionOffset = position.spanPosition() - 1;
     55         if (side == ColumnStartSide || side == RowStartSide) {
     56             size_t initialResolvedPosition = std::max<int>(0, resolvedOppositePosition - positionOffset);
     57             return GridSpan::create(initialResolvedPosition, resolvedOppositePosition);
     58         }
     59 
     60         return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition + positionOffset);
     61     }
     62 
     63     static PassOwnPtr<GridSpan> createWithNamedSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side, const Vector<size_t>& gridLines)
     64     {
     65         if (side == RowStartSide || side == ColumnStartSide)
     66             return createWithInitialNamedSpanAgainstOpposite(resolvedOppositePosition, position, gridLines);
     67 
     68         return createWithFinalNamedSpanAgainstOpposite(resolvedOppositePosition, position, gridLines);
     69     }
     70 
     71     static PassOwnPtr<GridSpan> createWithInitialNamedSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines)
     72     {
     73         // The grid line inequality needs to be strict (which doesn't match the after / end case) because |resolvedOppositePosition|
     74         // is already converted to an index in our grid representation (ie one was removed from the grid line to account for the side).
     75         size_t firstLineBeforeOppositePositionIndex = 0;
     76         const size_t* firstLineBeforeOppositePosition = std::lower_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition);
     77         if (firstLineBeforeOppositePosition != gridLines.end())
     78             firstLineBeforeOppositePositionIndex = firstLineBeforeOppositePosition - gridLines.begin();
     79 
     80         size_t gridLineIndex = std::max<int>(0, firstLineBeforeOppositePositionIndex - position.spanPosition() + 1);
     81         size_t resolvedGridLinePosition = gridLines[gridLineIndex];
     82         if (resolvedGridLinePosition > resolvedOppositePosition)
     83             resolvedGridLinePosition = resolvedOppositePosition;
     84         return GridSpan::create(resolvedGridLinePosition, resolvedOppositePosition);
     85     }
     86 
     87     static PassOwnPtr<GridSpan> createWithFinalNamedSpanAgainstOpposite(size_t resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines)
     88     {
     89         size_t firstLineAfterOppositePositionIndex = gridLines.size() - 1;
     90         const size_t* firstLineAfterOppositePosition = std::upper_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition);
     91         if (firstLineAfterOppositePosition != gridLines.end())
     92             firstLineAfterOppositePositionIndex = firstLineAfterOppositePosition - gridLines.begin();
     93 
     94         size_t gridLineIndex = std::min(gridLines.size() - 1, firstLineAfterOppositePositionIndex + position.spanPosition() - 1);
     95         size_t resolvedGridLinePosition = GridPosition::adjustGridPositionForAfterEndSide(gridLines[gridLineIndex]);
     96         if (resolvedGridLinePosition < resolvedOppositePosition)
     97             resolvedGridLinePosition = resolvedOppositePosition;
     98         return GridSpan::create(resolvedOppositePosition, resolvedGridLinePosition);
     99     }
    100 
    101     GridSpan(size_t initialPosition, size_t finalPosition)
    102         : initialPositionIndex(initialPosition)
    103         , finalPositionIndex(finalPosition)
    104     {
    105         ASSERT(initialPositionIndex <= finalPositionIndex);
    106     }
    107 
    108     bool operator==(const GridSpan& o) const
    109     {
    110         return initialPositionIndex == o.initialPositionIndex && finalPositionIndex == o.finalPositionIndex;
    111     }
    112 
    113     size_t initialPositionIndex;
    114     size_t finalPositionIndex;
    115 };
    116 
    117 // This represents a grid area that spans in both rows' and columns' direction.
    118 struct GridCoordinate {
    119     // HashMap requires a default constuctor.
    120     GridCoordinate()
    121         : columns(0, 0)
    122         , rows(0, 0)
    123     {
    124     }
    125 
    126     GridCoordinate(const GridSpan& r, const GridSpan& c)
    127         : columns(c)
    128         , rows(r)
    129     {
    130     }
    131 
    132     bool operator==(const GridCoordinate& o) const
    133     {
    134         return columns == o.columns && rows == o.rows;
    135     }
    136 
    137     bool operator!=(const GridCoordinate& o) const
    138     {
    139         return !(*this == o);
    140     }
    141 
    142     GridSpan columns;
    143     GridSpan rows;
    144 };
    145 
    146 typedef HashMap<String, GridCoordinate> NamedGridAreaMap;
    147 
    148 } // namespace WebCore
    149 
    150 #endif // GridCoordinate_h
    151