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/GridResolvedPosition.h"
     35 #include "wtf/HashMap.h"
     36 #include "wtf/PassOwnPtr.h"
     37 #include "wtf/text/WTFString.h"
     38 
     39 namespace blink {
     40 
     41 // A span in a single direction (either rows or columns). Note that |resolvedInitialPosition|
     42 // and |resolvedFinalPosition| are grid areas' indexes, NOT grid lines'. Iterating over the
     43 // span should include both |resolvedInitialPosition| and |resolvedFinalPosition| to be correct.
     44 struct GridSpan {
     45     static PassOwnPtr<GridSpan> create(const GridResolvedPosition& resolvedInitialPosition, const GridResolvedPosition& resolvedFinalPosition)
     46     {
     47         return adoptPtr(new GridSpan(resolvedInitialPosition, resolvedFinalPosition));
     48     }
     49 
     50     static PassOwnPtr<GridSpan> createWithSpanAgainstOpposite(const GridResolvedPosition& 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             GridResolvedPosition initialResolvedPosition = GridResolvedPosition(std::max<int>(0, resolvedOppositePosition.toInt() - positionOffset));
     57             return GridSpan::create(initialResolvedPosition, resolvedOppositePosition);
     58         }
     59 
     60         return GridSpan::create(resolvedOppositePosition, GridResolvedPosition(resolvedOppositePosition.toInt() + positionOffset));
     61     }
     62 
     63     static PassOwnPtr<GridSpan> createWithNamedSpanAgainstOpposite(const GridResolvedPosition& 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(const GridResolvedPosition& 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.toInt());
     77         if (firstLineBeforeOppositePosition != gridLines.end()) {
     78             if (*firstLineBeforeOppositePosition > resolvedOppositePosition.toInt() && firstLineBeforeOppositePosition != gridLines.begin())
     79                 --firstLineBeforeOppositePosition;
     80 
     81             firstLineBeforeOppositePositionIndex = firstLineBeforeOppositePosition - gridLines.begin();
     82         }
     83 
     84         size_t gridLineIndex = std::max<int>(0, firstLineBeforeOppositePositionIndex - position.spanPosition() + 1);
     85         GridResolvedPosition resolvedGridLinePosition = GridResolvedPosition(gridLines[gridLineIndex]);
     86         if (resolvedGridLinePosition > resolvedOppositePosition)
     87             resolvedGridLinePosition = resolvedOppositePosition;
     88         return GridSpan::create(resolvedGridLinePosition, resolvedOppositePosition);
     89     }
     90 
     91     static PassOwnPtr<GridSpan> createWithFinalNamedSpanAgainstOpposite(const GridResolvedPosition& resolvedOppositePosition, const GridPosition& position, const Vector<size_t>& gridLines)
     92     {
     93         size_t firstLineAfterOppositePositionIndex = gridLines.size() - 1;
     94         const size_t* firstLineAfterOppositePosition = std::upper_bound(gridLines.begin(), gridLines.end(), resolvedOppositePosition.toInt());
     95         if (firstLineAfterOppositePosition != gridLines.end())
     96             firstLineAfterOppositePositionIndex = firstLineAfterOppositePosition - gridLines.begin();
     97 
     98         size_t gridLineIndex = std::min(gridLines.size() - 1, firstLineAfterOppositePositionIndex + position.spanPosition() - 1);
     99         GridResolvedPosition resolvedGridLinePosition = GridResolvedPosition::adjustGridPositionForAfterEndSide(gridLines[gridLineIndex]);
    100         if (resolvedGridLinePosition < resolvedOppositePosition)
    101             resolvedGridLinePosition = resolvedOppositePosition;
    102         return GridSpan::create(resolvedOppositePosition, resolvedGridLinePosition);
    103     }
    104 
    105     GridSpan(const GridResolvedPosition& resolvedInitialPosition, const GridResolvedPosition& resolvedFinalPosition)
    106         : resolvedInitialPosition(resolvedInitialPosition)
    107         , resolvedFinalPosition(resolvedFinalPosition)
    108     {
    109         ASSERT(resolvedInitialPosition <= resolvedFinalPosition);
    110     }
    111 
    112     bool operator==(const GridSpan& o) const
    113     {
    114         return resolvedInitialPosition == o.resolvedInitialPosition && resolvedFinalPosition == o.resolvedFinalPosition;
    115     }
    116 
    117     size_t integerSpan() const
    118     {
    119         return resolvedFinalPosition.toInt() - resolvedInitialPosition.toInt() + 1;
    120     }
    121 
    122     GridResolvedPosition resolvedInitialPosition;
    123     GridResolvedPosition resolvedFinalPosition;
    124 
    125     typedef GridResolvedPosition iterator;
    126 
    127     iterator begin() const
    128     {
    129         return resolvedInitialPosition;
    130     }
    131 
    132     iterator end() const
    133     {
    134         return resolvedFinalPosition.next();
    135     }
    136 };
    137 
    138 // This represents a grid area that spans in both rows' and columns' direction.
    139 struct GridCoordinate {
    140     // HashMap requires a default constuctor.
    141     GridCoordinate()
    142         : columns(0, 0)
    143         , rows(0, 0)
    144     {
    145     }
    146 
    147     GridCoordinate(const GridSpan& r, const GridSpan& c)
    148         : columns(c)
    149         , rows(r)
    150     {
    151     }
    152 
    153     bool operator==(const GridCoordinate& o) const
    154     {
    155         return columns == o.columns && rows == o.rows;
    156     }
    157 
    158     bool operator!=(const GridCoordinate& o) const
    159     {
    160         return !(*this == o);
    161     }
    162 
    163     GridResolvedPosition positionForSide(GridPositionSide side) const
    164     {
    165         switch (side) {
    166         case ColumnStartSide:
    167             return columns.resolvedInitialPosition;
    168         case ColumnEndSide:
    169             return columns.resolvedFinalPosition;
    170         case RowStartSide:
    171             return rows.resolvedInitialPosition;
    172         case RowEndSide:
    173             return rows.resolvedFinalPosition;
    174         }
    175         ASSERT_NOT_REACHED();
    176         return 0;
    177     }
    178 
    179     GridSpan columns;
    180     GridSpan rows;
    181 };
    182 
    183 typedef HashMap<String, GridCoordinate> NamedGridAreaMap;
    184 
    185 } // namespace blink
    186 
    187 #endif // GridCoordinate_h
    188