1 /*
2  * Copyright (C) 2011 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_GRID_H_
27 #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_GRID_H_
28 
29 #include <memory>
30 #include "third_party/blink/renderer/core/layout/grid.h"
31 #include "third_party/blink/renderer/core/layout/grid_layout_utils.h"
32 #include "third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.h"
33 #include "third_party/blink/renderer/core/layout/layout_block.h"
34 #include "third_party/blink/renderer/core/layout/order_iterator.h"
35 #include "third_party/blink/renderer/core/style/grid_positions_resolver.h"
36 
37 namespace blink {
38 
39 struct GridArea;
40 struct GridSpan;
41 
42 struct ContentAlignmentData {
43  public:
44   ContentAlignmentData() = default;
45   ContentAlignmentData(const ContentAlignmentData&) = delete;
46   ContentAlignmentData& operator=(const ContentAlignmentData&) = delete;
IsValidContentAlignmentData47   bool IsValid() { return position_offset >= 0 && distribution_offset >= 0; }
48 
49   LayoutUnit position_offset = LayoutUnit(-1);
50   LayoutUnit distribution_offset = LayoutUnit(-1);
51 };
52 
53 enum GridAxisPosition { kGridAxisStart, kGridAxisEnd, kGridAxisCenter };
54 
55 class LayoutGrid final : public LayoutBlock {
56  public:
57   explicit LayoutGrid(Element*);
58   ~LayoutGrid() override;
59 
60   static LayoutGrid* CreateAnonymous(Document*);
GetName()61   const char* GetName() const override {
62     NOT_DESTROYED();
63     return "LayoutGrid";
64   }
65 
66   void UpdateBlockLayout(bool relayout_children) override;
67 
68   void DirtyGrid();
69 
70   Vector<LayoutUnit> TrackSizesForComputedStyle(GridTrackSizingDirection) const;
71 
ColumnPositions()72   const Vector<LayoutUnit>& ColumnPositions() const {
73     NOT_DESTROYED();
74     DCHECK(!grid_->NeedsItemsPlacement());
75     return column_positions_;
76   }
77 
RowPositions()78   const Vector<LayoutUnit>& RowPositions() const {
79     NOT_DESTROYED();
80     DCHECK(!grid_->NeedsItemsPlacement());
81     return row_positions_;
82   }
83 
84   // TODO(svillar): rename this method as this does not return a
85   // GridCell but its contents.
GetGridCell(int row,int column)86   const GridItemList& GetGridCell(int row, int column) const {
87     NOT_DESTROYED();
88     SECURITY_DCHECK(!grid_->NeedsItemsPlacement());
89     return grid_->Cell(row, column);
90   }
91 
AutoRepeatCountForDirection(GridTrackSizingDirection direction)92   size_t AutoRepeatCountForDirection(GridTrackSizingDirection direction) const {
93     return grid_->AutoRepeatTracks(direction);
94   }
95 
ExplicitGridStartForDirection(GridTrackSizingDirection direction)96   size_t ExplicitGridStartForDirection(
97       GridTrackSizingDirection direction) const {
98     return grid_->ExplicitGridStart(direction);
99   }
100 
101   LayoutUnit TranslateRTLCoordinate(LayoutUnit) const;
102 
103   LayoutUnit TranslateOutOfFlowRTLCoordinate(const LayoutBox&,
104                                              LayoutUnit) const;
105 
106   // TODO(svillar): We need these for the GridTrackSizingAlgorithm. Let's figure
107   // it out how to remove this dependency.
108   LayoutUnit GuttersSize(const Grid&,
109                          GridTrackSizingDirection,
110                          size_t start_line,
111                          size_t span,
112                          base::Optional<LayoutUnit> available_size) const;
113   bool CachedHasDefiniteLogicalHeight() const;
114   bool IsBaselineAlignmentForChild(const LayoutBox& child) const;
115   bool IsBaselineAlignmentForChild(const LayoutBox& child, GridAxis) const;
116 
117   StyleSelfAlignmentData SelfAlignmentForChild(
118       GridAxis,
119       const LayoutBox& child,
120       const ComputedStyle* = nullptr) const;
121 
122   LayoutUnit GridGap(GridTrackSizingDirection) const;
123   LayoutUnit GridItemOffset(GridTrackSizingDirection) const;
124 
125   void UpdateGridAreaLogicalSize(LayoutBox&, LayoutSize) const;
126 
127   StyleContentAlignmentData ContentAlignment(GridTrackSizingDirection) const;
128 
129   size_t ExplicitGridEndForDirection(GridTrackSizingDirection) const;
130 
131   // Exposed for testing *ONLY*.
InternalGrid()132   Grid* InternalGrid() const {
133     NOT_DESTROYED();
134     return grid_.get();
135   }
136 
137  protected:
138   ItemPosition SelfAlignmentNormalBehavior(
139       const LayoutBox* child = nullptr) const override {
140     NOT_DESTROYED();
141     DCHECK(child);
142     return child->IsLayoutReplaced() ? ItemPosition::kStart
143                                      : ItemPosition::kStretch;
144   }
145 
146  private:
IsOfType(LayoutObjectType type)147   bool IsOfType(LayoutObjectType type) const override {
148     NOT_DESTROYED();
149     return type == kLayoutObjectGrid || LayoutBlock::IsOfType(type);
150   }
151   MinMaxSizes ComputeIntrinsicLogicalWidths() const override;
152 
153   void AddChild(LayoutObject* new_child,
154                 LayoutObject* before_child = nullptr) override;
155   void RemoveChild(LayoutObject*) override;
156 
157   bool SelfAlignmentChangedSize(GridAxis,
158                                 const ComputedStyle& old_style,
159                                 const ComputedStyle& new_style,
160                                 const LayoutBox&) const;
161   bool DefaultAlignmentChangedSize(GridAxis,
162                                    const ComputedStyle& old_style,
163                                    const ComputedStyle& new_style) const;
164   void StyleDidChange(StyleDifference, const ComputedStyle*) override;
165 
166   bool ExplicitGridDidResize(const ComputedStyle&) const;
167   bool NamedGridLinesDefinitionDidChange(const ComputedStyle&) const;
168 
169   size_t ComputeAutoRepeatTracksCount(
170       GridTrackSizingDirection,
171       base::Optional<LayoutUnit> available_size) const;
172   size_t ClampAutoRepeatTracks(GridTrackSizingDirection,
173                                size_t auto_repeat_tracks) const;
174 
175   std::unique_ptr<OrderedTrackIndexSet> ComputeEmptyTracksForAutoRepeat(
176       Grid&,
177       GridTrackSizingDirection) const;
178 
179   void PerformGridItemsPreLayout(const GridTrackSizingAlgorithm&) const;
180 
181   void PlaceItemsOnGrid(
182       GridTrackSizingAlgorithm&,
183       base::Optional<LayoutUnit> available_logical_width) const;
184   void PopulateExplicitGridAndOrderIterator(Grid&) const;
185   std::unique_ptr<GridArea> CreateEmptyGridAreaAtSpecifiedPositionsOutsideGrid(
186       const Grid&,
187       const LayoutBox&,
188       GridTrackSizingDirection,
189       const GridSpan& specified_positions) const;
190   void PlaceSpecifiedMajorAxisItemsOnGrid(Grid&,
191                                           const Vector<LayoutBox*>&) const;
192   void PlaceAutoMajorAxisItemsOnGrid(Grid&, const Vector<LayoutBox*>&) const;
193   void PlaceAutoMajorAxisItemOnGrid(
194       Grid&,
195       LayoutBox&,
196       std::pair<size_t, size_t>& auto_placement_cursor) const;
197   GridTrackSizingDirection AutoPlacementMajorAxisDirection() const;
198   GridTrackSizingDirection AutoPlacementMinorAxisDirection() const;
199 
200   base::Optional<LayoutUnit> OverrideIntrinsicContentLogicalSize(
201       GridTrackSizingDirection) const;
202 
203   void ComputeTrackSizesForIndefiniteSize(GridTrackSizingAlgorithm&,
204                                           GridTrackSizingDirection) const;
205   void ComputeTrackSizesForDefiniteSize(GridTrackSizingDirection,
206                                         LayoutUnit free_space);
207 
208   void RepeatTracksSizingIfNeeded(LayoutUnit available_space_for_columns,
209                                   LayoutUnit available_space_for_rows);
210 
211   void LayoutGridItems();
212   void PrepareChildForPositionedLayout(LayoutBox&);
213   bool HasStaticPositionForChild(const LayoutBox&,
214                                  GridTrackSizingDirection) const;
215   void LayoutPositionedObjects(
216       bool relayout_children,
217       PositionedLayoutBehavior = kDefaultLayout) override;
218   void PopulateGridPositionsForDirection(GridTrackSizingDirection);
219 
220   LayoutUnit ResolveAutoStartGridPosition(GridTrackSizingDirection) const;
221   LayoutUnit ResolveAutoEndGridPosition(GridTrackSizingDirection) const;
222   LayoutUnit LogicalOffsetForOutOfFlowChild(const LayoutBox&,
223                                             GridTrackSizingDirection,
224                                             LayoutUnit) const;
225   LayoutUnit GridAreaBreadthForOutOfFlowChild(const LayoutBox&,
226                                               GridTrackSizingDirection);
227   void GridAreaPositionForOutOfFlowChild(const LayoutBox&,
228                                          GridTrackSizingDirection,
229                                          LayoutUnit& start,
230                                          LayoutUnit& end) const;
231   void GridAreaPositionForInFlowChild(const LayoutBox&,
232                                       GridTrackSizingDirection,
233                                       LayoutUnit& start,
234                                       LayoutUnit& end) const;
235   void GridAreaPositionForChild(const LayoutBox&,
236                                 GridTrackSizingDirection,
237                                 LayoutUnit& start,
238                                 LayoutUnit& end) const;
239 
240   GridAxisPosition ColumnAxisPositionForChild(const LayoutBox&) const;
241   GridAxisPosition RowAxisPositionForChild(const LayoutBox&) const;
242   LayoutUnit RowAxisOffsetForChild(const LayoutBox&) const;
243   LayoutUnit ColumnAxisOffsetForChild(const LayoutBox&) const;
244   void ComputeContentPositionAndDistributionOffset(
245       GridTrackSizingDirection,
246       const LayoutUnit& available_free_space,
247       unsigned number_of_grid_tracks);
248   LayoutPoint GridAreaLogicalPosition(const GridArea&) const;
249   void SetLogicalPositionForChild(LayoutBox&) const;
250   void SetLogicalOffsetForChild(LayoutBox&, GridTrackSizingDirection) const;
251   LayoutUnit LogicalOffsetForChild(const LayoutBox&,
252                                    GridTrackSizingDirection) const;
253 
254   LayoutUnit GridAreaBreadthForChildIncludingAlignmentOffsets(
255       const LayoutBox&,
256       GridTrackSizingDirection) const;
257 
258   void PaintChildren(const PaintInfo&,
259                      const PhysicalOffset& paint_offset) const override;
260 
261   LayoutUnit AvailableAlignmentSpaceForChildBeforeStretching(
262       LayoutUnit grid_area_breadth_for_child,
263       const LayoutBox&) const;
264   StyleSelfAlignmentData JustifySelfForChild(
265       const LayoutBox&,
266       const ComputedStyle* = nullptr) const;
267   StyleSelfAlignmentData AlignSelfForChild(
268       const LayoutBox&,
269       const ComputedStyle* = nullptr) const;
270   StyleSelfAlignmentData DefaultAlignment(GridAxis, const ComputedStyle&) const;
271   bool DefaultAlignmentIsStretchOrNormal(GridAxis, const ComputedStyle&) const;
272   void ApplyStretchAlignmentToChildIfNeeded(LayoutBox&);
273   bool HasAutoSizeInColumnAxis(const LayoutBox& child) const;
274   bool HasAutoSizeInRowAxis(const LayoutBox& child) const;
AllowedToStretchChildAlongColumnAxis(const LayoutBox & child)275   bool AllowedToStretchChildAlongColumnAxis(const LayoutBox& child) const {
276     NOT_DESTROYED();
277     return AlignSelfForChild(child).GetPosition() == ItemPosition::kStretch &&
278            HasAutoSizeInColumnAxis(child) && !HasAutoMarginsInColumnAxis(child);
279   }
AllowedToStretchChildAlongRowAxis(const LayoutBox & child)280   bool AllowedToStretchChildAlongRowAxis(const LayoutBox& child) const {
281     NOT_DESTROYED();
282     return JustifySelfForChild(child).GetPosition() == ItemPosition::kStretch &&
283            HasAutoSizeInRowAxis(child) && !HasAutoMarginsInRowAxis(child);
284   }
285   bool HasAutoMarginsInColumnAxis(const LayoutBox&) const;
286   bool HasAutoMarginsInRowAxis(const LayoutBox&) const;
287   void UpdateAutoMarginsInColumnAxisIfNeeded(LayoutBox&);
288   void UpdateAutoMarginsInRowAxisIfNeeded(LayoutBox&);
289 
290   LayoutUnit BaselinePosition(
291       FontBaseline,
292       bool first_line,
293       LineDirectionMode,
294       LinePositionMode = kPositionOnContainingLine) const override;
295   LayoutUnit FirstLineBoxBaseline() const override;
296   LayoutUnit InlineBlockBaseline(LineDirectionMode) const override;
297 
298   LayoutUnit ColumnAxisBaselineOffsetForChild(const LayoutBox&) const;
299   LayoutUnit RowAxisBaselineOffsetForChild(const LayoutBox&) const;
300 
301   LayoutUnit GridGap(GridTrackSizingDirection,
302                      base::Optional<LayoutUnit> available_size) const;
303 
304   size_t GridItemSpan(const LayoutBox&, GridTrackSizingDirection);
305 
306   size_t NonCollapsedTracks(GridTrackSizingDirection) const;
307   size_t NumTracks(GridTrackSizingDirection, const Grid&) const;
308 
309   static LayoutUnit OverrideContainingBlockContentSizeForChild(
310       const LayoutBox& child,
311       GridTrackSizingDirection);
312   static LayoutUnit SynthesizedBaselineFromBorderBox(const LayoutBox&,
313                                                      LineDirectionMode);
314   static const StyleContentAlignmentData& ContentAlignmentNormalBehavior();
315 
316   std::unique_ptr<Grid> grid_;
317   GridTrackSizingAlgorithm track_sizing_algorithm_;
318 
319   Vector<LayoutUnit> row_positions_;
320   Vector<LayoutUnit> column_positions_;
321   ContentAlignmentData offset_between_columns_;
322   ContentAlignmentData offset_between_rows_;
323 
324   typedef HashMap<const LayoutBox*, base::Optional<size_t>>
325       OutOfFlowPositionsMap;
326   OutOfFlowPositionsMap column_of_positioned_item_;
327   OutOfFlowPositionsMap row_of_positioned_item_;
328 
329   bool has_any_orthogonal_item_{false};
330   bool baseline_items_cached_{false};
331   base::Optional<bool> has_definite_logical_height_;
332 };
333 
334 DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutGrid, IsLayoutGrid());
335 
336 }  // namespace blink
337 
338 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_GRID_H_
339