File: MultiColumnFragmentainerGroup.h

package info (click to toggle)
chromium-browser 57.0.2987.98-1~deb8u1
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 2,637,852 kB
  • ctags: 2,544,394
  • sloc: cpp: 12,815,961; ansic: 3,676,222; python: 1,147,112; asm: 526,608; java: 523,212; xml: 286,794; perl: 92,654; sh: 86,408; objc: 73,271; makefile: 27,698; cs: 18,487; yacc: 13,031; tcl: 12,957; pascal: 4,875; ml: 4,716; lex: 3,904; sql: 3,862; ruby: 1,982; lisp: 1,508; php: 1,368; exp: 404; awk: 325; csh: 117; jsp: 39; sed: 37
file content (208 lines) | stat: -rw-r--r-- 8,332 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MultiColumnFragmentainerGroup_h
#define MultiColumnFragmentainerGroup_h

#include "core/layout/LayoutMultiColumnFlowThread.h"
#include "wtf/Allocator.h"

namespace blink {

// A group of columns, that are laid out in the inline progression direction,
// all with the same column height.
//
// When a multicol container is inside another fragmentation context, and said
// multicol container lives in multiple outer fragmentainers (pages / columns),
// we need to put these inner columns into separate groups, with one group per
// outer fragmentainer. Such a group of columns is what comprises a "row of
// column boxes" in spec lingo.
//
// Column balancing, when enabled, takes place within a column fragmentainer
// group.
//
// Each fragmentainer group may have its own actual column count (if there are
// unused columns because of forced breaks, for example). If there are multiple
// fragmentainer groups, the actual column count must not exceed the used column
// count (the one calculated based on column-count and column-width from CSS),
// or they'd overflow the outer fragmentainer in the inline direction. If we
// need more columns than what a group has room for, we'll create another group
// and put them there (and make them appear in the next outer fragmentainer).
class MultiColumnFragmentainerGroup {
  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();

 public:
  MultiColumnFragmentainerGroup(const LayoutMultiColumnSet&);

  const LayoutMultiColumnSet& columnSet() const { return m_columnSet; }

  bool isFirstGroup() const;
  bool isLastGroup() const;

  // Position within the LayoutMultiColumnSet.
  LayoutUnit logicalTop() const { return m_logicalTop; }
  void setLogicalTop(LayoutUnit logicalTop) { m_logicalTop = logicalTop; }

  LayoutUnit logicalHeight() const { return m_columnHeight; }

  LayoutSize offsetFromColumnSet() const;

  // Return the block offset from the enclosing fragmentation context, if
  // nested. In the coordinate space of the enclosing fragmentation context.
  LayoutUnit blockOffsetInEnclosingFragmentationContext() const;

  // The top of our flow thread portion
  LayoutUnit logicalTopInFlowThread() const { return m_logicalTopInFlowThread; }
  void setLogicalTopInFlowThread(LayoutUnit logicalTopInFlowThread) {
    m_logicalTopInFlowThread = logicalTopInFlowThread;
  }

  // The bottom of our flow thread portion
  LayoutUnit logicalBottomInFlowThread() const {
    return m_logicalBottomInFlowThread;
  }
  void setLogicalBottomInFlowThread(LayoutUnit logicalBottomInFlowThread) {
    ASSERT(logicalBottomInFlowThread >= m_logicalTopInFlowThread);
    m_logicalBottomInFlowThread = logicalBottomInFlowThread;
  }

  // The height of our flow thread portion
  LayoutUnit logicalHeightInFlowThread() const {
    return m_logicalBottomInFlowThread - m_logicalTopInFlowThread;
  }

  void resetColumnHeight();
  bool recalculateColumnHeight(LayoutMultiColumnSet&);

  LayoutSize flowThreadTranslationAtOffset(LayoutUnit,
                                           LayoutBox::PageBoundaryRule,
                                           CoordinateSpaceConversion) const;
  LayoutUnit columnLogicalTopForOffset(LayoutUnit offsetInFlowThread) const;

  // If SnapToColumnPolicy is SnapToColumn, visualPointToFlowThreadPoint() won't
  // return points that lie outside the bounds of the columns: Before converting
  // to a flow thread position, if the block direction coordinate is outside the
  // column, snap to the bounds of the column, and reset the inline direction
  // coordinate to the start position in the column. The effect of this is that
  // if the block position is before the column rectangle, we'll get to the
  // beginning of this column, while if the block position is after the column
  // rectangle, we'll get to the beginning of the next column. This is behavior
  // that positionForPoint() depends on.
  enum SnapToColumnPolicy { DontSnapToColumn, SnapToColumn };
  LayoutPoint visualPointToFlowThreadPoint(
      const LayoutPoint& visualPoint,
      SnapToColumnPolicy = DontSnapToColumn) const;

  LayoutRect fragmentsBoundingBox(
      const LayoutRect& boundingBoxInFlowThread) const;

  LayoutRect flowThreadPortionRectAt(unsigned columnIndex) const;
  LayoutRect flowThreadPortionOverflowRectAt(unsigned columnIndex) const;

  // Get the first and the last column intersecting the specified block range.
  // Note that |logicalBottomInFlowThread| is an exclusive endpoint.
  void columnIntervalForBlockRangeInFlowThread(
      LayoutUnit logicalTopInFlowThread,
      LayoutUnit logicalBottomInFlowThread,
      unsigned& firstColumn,
      unsigned& lastColumn) const;

  // Get the first and the last column intersecting the specified visual
  // rectangle.
  void columnIntervalForVisualRect(const LayoutRect&,
                                   unsigned& firstColumn,
                                   unsigned& lastColumn) const;

  LayoutRect calculateOverflow() const;

  unsigned columnIndexAtOffset(LayoutUnit offsetInFlowThread,
                               LayoutBox::PageBoundaryRule) const;

  // The "CSS actual" value of column-count. This includes overflowing columns,
  // if any.
  // Returns 1 or greater, never 0.
  unsigned actualColumnCount() const;

 private:
  LayoutUnit heightAdjustedForRowOffset(LayoutUnit height) const;
  LayoutUnit calculateMaxColumnHeight() const;
  void setAndConstrainColumnHeight(LayoutUnit);

  LayoutUnit rebalanceColumnHeightIfNeeded() const;

  LayoutRect columnRectAt(unsigned columnIndex) const;
  LayoutUnit logicalTopInFlowThreadAt(unsigned columnIndex) const {
    return m_logicalTopInFlowThread + columnIndex * m_columnHeight;
  }

  // Return the column that the specified visual point belongs to. Only the
  // coordinate on the column progression axis is relevant. Every point belongs
  // to a column, even if said point is not inside any of the columns.
  unsigned columnIndexAtVisualPoint(const LayoutPoint& visualPoint) const;

  const LayoutMultiColumnSet& m_columnSet;

  LayoutUnit m_logicalTop;
  LayoutUnit m_logicalTopInFlowThread;
  LayoutUnit m_logicalBottomInFlowThread;

  LayoutUnit m_columnHeight;

  LayoutUnit m_maxColumnHeight;  // Maximum column height allowed.
};

// List of all fragmentainer groups within a column set. There will always be at
// least one group. Deleting the one group is not allowed (or possible). There
// will be more than one group if the owning column set lives in multiple outer
// fragmentainers (e.g. multicol inside paged media).
class CORE_EXPORT MultiColumnFragmentainerGroupList {
  DISALLOW_NEW();

 public:
  MultiColumnFragmentainerGroupList(LayoutMultiColumnSet&);
  ~MultiColumnFragmentainerGroupList();

  // Add an additional fragmentainer group to the end of the list, and return
  // it.
  MultiColumnFragmentainerGroup& addExtraGroup();

  // Remove all fragmentainer groups but the first one.
  void deleteExtraGroups();

  MultiColumnFragmentainerGroup& first() { return m_groups.front(); }
  const MultiColumnFragmentainerGroup& first() const {
    return m_groups.front();
  }
  MultiColumnFragmentainerGroup& last() { return m_groups.back(); }
  const MultiColumnFragmentainerGroup& last() const { return m_groups.back(); }

  typedef Vector<MultiColumnFragmentainerGroup, 1>::iterator iterator;
  typedef Vector<MultiColumnFragmentainerGroup, 1>::const_iterator
      const_iterator;

  iterator begin() { return m_groups.begin(); }
  const_iterator begin() const { return m_groups.begin(); }
  iterator end() { return m_groups.end(); }
  const_iterator end() const { return m_groups.end(); }

  size_t size() const { return m_groups.size(); }
  MultiColumnFragmentainerGroup& operator[](size_t i) { return m_groups.at(i); }
  const MultiColumnFragmentainerGroup& operator[](size_t i) const {
    return m_groups.at(i);
  }

  void append(const MultiColumnFragmentainerGroup& group) {
    m_groups.push_back(group);
  }
  void shrink(size_t size) { m_groups.shrink(size); }

 private:
  LayoutMultiColumnSet& m_columnSet;

  Vector<MultiColumnFragmentainerGroup, 1> m_groups;
};

}  // namespace blink

#endif  // MultiColumnFragmentainerGroup_h