OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2012 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 15 matching lines...) Expand all Loading... |
26 #ifndef LayoutMultiColumnSet_h | 26 #ifndef LayoutMultiColumnSet_h |
27 #define LayoutMultiColumnSet_h | 27 #define LayoutMultiColumnSet_h |
28 | 28 |
29 #include "core/CoreExport.h" | 29 #include "core/CoreExport.h" |
30 #include "core/layout/LayoutMultiColumnFlowThread.h" | 30 #include "core/layout/LayoutMultiColumnFlowThread.h" |
31 #include "core/layout/MultiColumnFragmentainerGroup.h" | 31 #include "core/layout/MultiColumnFragmentainerGroup.h" |
32 #include "wtf/Vector.h" | 32 #include "wtf/Vector.h" |
33 | 33 |
34 namespace blink { | 34 namespace blink { |
35 | 35 |
36 // A set of columns in a multicol container. A column set is inserted as an anon
ymous child of the | 36 // A set of columns in a multicol container. A column set is inserted as an |
37 // actual multicol container (i.e. the layoutObject whose style computes to non-
auto column-count and/or | 37 // anonymous child of the actual multicol container (i.e. the layoutObject whose |
38 // column-width), next to the flow thread. There'll be one column set for each c
ontiguous run of | 38 // style computes to non-auto column-count and/or column-width), next to the |
39 // column content. The only thing that can interrupt a contiguous run of column
content is a column | 39 // flow thread. There'll be one column set for each contiguous run of column |
40 // spanner, which means that if there are no spanners, there'll only be one colu
mn set. | 40 // content. The only thing that can interrupt a contiguous run of column content |
| 41 // is a column spanner, which means that if there are no spanners, there'll |
| 42 // only be one column set. |
41 // | 43 // |
42 // Since a spanner interrupts an otherwise contiguous run of column content, ins
erting one may | 44 // Since a spanner interrupts an otherwise contiguous run of column content, |
43 // result in the creation of additional new column sets. A placeholder for the s
panning layoutObject has | 45 // inserting one may result in the creation of additional new column sets. A |
44 // to be placed in between the column sets that come before and after the spanne
r, if there's | 46 // placeholder for the spanning layoutObject has to be placed in between the |
45 // actually column content both before and after the spanner. | 47 // column sets that come before and after the spanner, if there's actually |
| 48 // column content both before and after the spanner. |
46 // | 49 // |
47 // A column set has no children on its own, but is merely used to slice a portio
n of the tall | 50 // A column set has no children on its own, but is merely used to slice a |
48 // "single-column" flow thread into actual columns visually, to convert from flo
w thread coordinates | 51 // portion of the tall "single-column" flow thread into actual columns visually, |
49 // to visual ones. It is in charge of both positioning columns correctly relativ
ely to the parent | 52 // to convert from flow thread coordinates to visual ones. It is in charge of |
50 // multicol container, and to calculate the correct translation for each column'
s contents, and to | 53 // both positioning columns correctly relatively to the parent multicol |
51 // paint any rules between them. LayoutMultiColumnSet objects are used for paint
ing, hit testing, | 54 // container, and to calculate the correct translation for each column's |
52 // and any other type of operation that requires mapping from flow thread coordi
nates to visual | 55 // contents, and to paint any rules between them. LayoutMultiColumnSet objects |
53 // coordinates. | 56 // are used for painting, hit testing, and any other type of operation that |
| 57 // requires mapping from flow thread coordinates to visual coordinates. |
54 // | 58 // |
55 // Columns are normally laid out in the inline progression direction, but if the
multicol container | 59 // Columns are normally laid out in the inline progression direction, but if the |
56 // is inside another fragmentation context (e.g. paged media, or an another mult
icol container), we | 60 // multicol container is inside another fragmentation context (e.g. paged media, |
57 // may need to group the columns, so that we get one MultiColumnFragmentainerGro
up for each outer | 61 // or an another multicol container), we may need to group the columns, so |
58 // fragmentainer (page / column) that the inner multicol container lives in. Eac
h fragmentainer | 62 // that we get one MultiColumnFragmentainerGroup for each outer fragmentainer |
59 // group has its own column height, but the column height is uniform within a gr
oup. | 63 // (page / column) that the inner multicol container lives in. Each |
| 64 // fragmentainer group has its own column height, but the column height is |
| 65 // uniform within a group. |
60 class CORE_EXPORT LayoutMultiColumnSet : public LayoutBlockFlow { | 66 class CORE_EXPORT LayoutMultiColumnSet : public LayoutBlockFlow { |
61 public: | 67 public: |
62 static LayoutMultiColumnSet* createAnonymous( | 68 static LayoutMultiColumnSet* createAnonymous( |
63 LayoutFlowThread&, | 69 LayoutFlowThread&, |
64 const ComputedStyle& parentStyle); | 70 const ComputedStyle& parentStyle); |
65 | 71 |
66 const MultiColumnFragmentainerGroup& firstFragmentainerGroup() const { | 72 const MultiColumnFragmentainerGroup& firstFragmentainerGroup() const { |
67 return m_fragmentainerGroups.first(); | 73 return m_fragmentainerGroups.first(); |
68 } | 74 } |
69 const MultiColumnFragmentainerGroup& lastFragmentainerGroup() const { | 75 const MultiColumnFragmentainerGroup& lastFragmentainerGroup() const { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 LayoutBlockFlow* multiColumnBlockFlow() const { | 124 LayoutBlockFlow* multiColumnBlockFlow() const { |
119 return toLayoutBlockFlow(parent()); | 125 return toLayoutBlockFlow(parent()); |
120 } | 126 } |
121 LayoutMultiColumnFlowThread* multiColumnFlowThread() const { | 127 LayoutMultiColumnFlowThread* multiColumnFlowThread() const { |
122 return toLayoutMultiColumnFlowThread(flowThread()); | 128 return toLayoutMultiColumnFlowThread(flowThread()); |
123 } | 129 } |
124 | 130 |
125 LayoutMultiColumnSet* nextSiblingMultiColumnSet() const; | 131 LayoutMultiColumnSet* nextSiblingMultiColumnSet() const; |
126 LayoutMultiColumnSet* previousSiblingMultiColumnSet() const; | 132 LayoutMultiColumnSet* previousSiblingMultiColumnSet() const; |
127 | 133 |
128 // Return true if we have a fragmentainer group that can hold a column at the
specified flow thread block offset. | 134 // Return true if we have a fragmentainer group that can hold a column at the |
| 135 // specified flow thread block offset. |
129 bool hasFragmentainerGroupForColumnAt(LayoutUnit bottomOffsetInFlowThread, | 136 bool hasFragmentainerGroupForColumnAt(LayoutUnit bottomOffsetInFlowThread, |
130 PageBoundaryRule) const; | 137 PageBoundaryRule) const; |
131 | 138 |
132 MultiColumnFragmentainerGroup& appendNewFragmentainerGroup(); | 139 MultiColumnFragmentainerGroup& appendNewFragmentainerGroup(); |
133 | 140 |
134 // Logical top relative to the content edge of the multicol container. | 141 // Logical top relative to the content edge of the multicol container. |
135 LayoutUnit logicalTopFromMulticolContentEdge() const; | 142 LayoutUnit logicalTopFromMulticolContentEdge() const; |
136 | 143 |
137 LayoutUnit logicalTopInFlowThread() const; | 144 LayoutUnit logicalTopInFlowThread() const; |
138 LayoutUnit logicalBottomInFlowThread() const; | 145 LayoutUnit logicalBottomInFlowThread() const; |
139 LayoutUnit logicalHeightInFlowThread() const { | 146 LayoutUnit logicalHeightInFlowThread() const { |
140 return logicalBottomInFlowThread() - logicalTopInFlowThread(); | 147 return logicalBottomInFlowThread() - logicalTopInFlowThread(); |
141 } | 148 } |
142 | 149 |
143 // Return the amount of flow thread contents that the specified fragmentainer
group can hold | 150 // Return the amount of flow thread contents that the specified fragmentainer |
144 // without overflowing. | 151 // group can hold without overflowing. |
145 LayoutUnit fragmentainerGroupCapacity( | 152 LayoutUnit fragmentainerGroupCapacity( |
146 const MultiColumnFragmentainerGroup& group) const { | 153 const MultiColumnFragmentainerGroup& group) const { |
147 return group.logicalHeight() * usedColumnCount(); | 154 return group.logicalHeight() * usedColumnCount(); |
148 } | 155 } |
149 | 156 |
150 LayoutRect flowThreadPortionRect() const; | 157 LayoutRect flowThreadPortionRect() const; |
151 LayoutRect flowThreadPortionOverflowRect() const; | 158 LayoutRect flowThreadPortionOverflowRect() const; |
152 LayoutRect overflowRectForFlowThreadPortion( | 159 LayoutRect overflowRectForFlowThreadPortion( |
153 const LayoutRect& flowThreadPortionRect, | 160 const LayoutRect& flowThreadPortionRect, |
154 bool isFirstPortion, | 161 bool isFirstPortion, |
155 bool isLastPortion) const; | 162 bool isLastPortion) const; |
156 | 163 |
157 // The used CSS value of column-count, i.e. how many columns there are room fo
r without overflowing. | 164 // The used CSS value of column-count, i.e. how many columns there are room |
| 165 // for without overflowing. |
158 unsigned usedColumnCount() const { | 166 unsigned usedColumnCount() const { |
159 return multiColumnFlowThread()->columnCount(); | 167 return multiColumnFlowThread()->columnCount(); |
160 } | 168 } |
161 | 169 |
162 bool heightIsAuto() const; | 170 bool heightIsAuto() const; |
163 | 171 |
164 // Find the column that contains the given block offset, and return the transl
ation needed to | 172 // Find the column that contains the given block offset, and return the |
165 // get from flow thread coordinates to visual coordinates. | 173 // translation needed to get from flow thread coordinates to visual |
| 174 // coordinates. |
166 LayoutSize flowThreadTranslationAtOffset(LayoutUnit, | 175 LayoutSize flowThreadTranslationAtOffset(LayoutUnit, |
167 PageBoundaryRule, | 176 PageBoundaryRule, |
168 CoordinateSpaceConversion) const; | 177 CoordinateSpaceConversion) const; |
169 | 178 |
170 LayoutPoint visualPointToFlowThreadPoint( | 179 LayoutPoint visualPointToFlowThreadPoint( |
171 const LayoutPoint& visualPoint) const; | 180 const LayoutPoint& visualPoint) const; |
172 | 181 |
173 // (Re-)calculate the column height if it's auto. This is first and foremost n
eeded by sets that | 182 // (Re-)calculate the column height if it's auto. This is first and foremost |
174 // are to balance the column height, but even when it isn't to be balanced, th
is is necessary if | 183 // needed by sets that are to balance the column height, but even when it |
175 // the multicol container's height is constrained. | 184 // isn't to be balanced, this is necessary if the multicol container's height |
| 185 // is constrained. |
176 bool recalculateColumnHeight(); | 186 bool recalculateColumnHeight(); |
177 | 187 |
178 // Reset previously calculated column height. Will mark for layout if needed. | 188 // Reset previously calculated column height. Will mark for layout if needed. |
179 void resetColumnHeight(); | 189 void resetColumnHeight(); |
180 | 190 |
181 void storeOldPosition() { m_oldLogicalTop = logicalTop(); } | 191 void storeOldPosition() { m_oldLogicalTop = logicalTop(); } |
182 bool isInitialHeightCalculated() const { return m_initialHeightCalculated; } | 192 bool isInitialHeightCalculated() const { return m_initialHeightCalculated; } |
183 | 193 |
184 // Layout of flow thread content that's to be rendered inside this column set
begins. This | 194 // Layout of flow thread content that's to be rendered inside this column set |
185 // happens at the beginning of flow thread layout, and when advancing from a p
revious column set | 195 // begins. This happens at the beginning of flow thread layout, and when |
186 // or spanner to this one. | 196 // advancing from a previous column set or spanner to this one. |
187 void beginFlow(LayoutUnit offsetInFlowThread); | 197 void beginFlow(LayoutUnit offsetInFlowThread); |
188 | 198 |
189 // Layout of flow thread content that was to be rendered inside this column se
t has | 199 // Layout of flow thread content that was to be rendered inside this column |
190 // finished. This happens at end of flow thread layout, and when advancing to
the next column | 200 // set has finished. This happens at end of flow thread layout, and when |
191 // set or spanner. | 201 // advancing to the next column set or spanner. |
192 void endFlow(LayoutUnit offsetInFlowThread); | 202 void endFlow(LayoutUnit offsetInFlowThread); |
193 | 203 |
194 void styleDidChange(StyleDifference, const ComputedStyle* oldStyle) override; | 204 void styleDidChange(StyleDifference, const ComputedStyle* oldStyle) override; |
195 void layout() override; | 205 void layout() override; |
196 | 206 |
197 void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, | 207 void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, |
198 LayoutUnit& maxLogicalWidth) const final; | 208 LayoutUnit& maxLogicalWidth) const final; |
199 | 209 |
200 void attachToFlowThread(); | 210 void attachToFlowThread(); |
201 void detachFromFlowThread(); | 211 void detachFromFlowThread(); |
202 | 212 |
203 // The top of the page nearest to the specified block offset. All in flowthrea
d coordinates. | 213 // The top of the page nearest to the specified block offset. All in |
| 214 // flowthread coordinates. |
204 LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const; | 215 LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const; |
205 | 216 |
206 LayoutRect fragmentsBoundingBox( | 217 LayoutRect fragmentsBoundingBox( |
207 const LayoutRect& boundingBoxInFlowThread) const; | 218 const LayoutRect& boundingBoxInFlowThread) const; |
208 | 219 |
209 LayoutUnit columnGap() const; | 220 LayoutUnit columnGap() const; |
210 | 221 |
211 // The "CSS actual" value of column-count. This includes overflowing columns,
if any. | 222 // The "CSS actual" value of column-count. This includes overflowing columns, |
| 223 // if any. |
212 unsigned actualColumnCount() const; | 224 unsigned actualColumnCount() const; |
213 | 225 |
214 const char* name() const override { return "LayoutMultiColumnSet"; } | 226 const char* name() const override { return "LayoutMultiColumnSet"; } |
215 | 227 |
216 // Sets |columnRuleBounds| to the bounds of each column rule rect's painted ex
tent, adjusted by paint offset, | 228 // Sets |columnRuleBounds| to the bounds of each column rule rect's painted |
217 // before pixel snapping. Returns true if column rules should be painted at al
l. | 229 // extent, adjusted by paint offset, before pixel snapping. Returns true if |
| 230 // column rules should be painted at all. |
218 bool computeColumnRuleBounds(const LayoutPoint& paintOffset, | 231 bool computeColumnRuleBounds(const LayoutPoint& paintOffset, |
219 Vector<LayoutRect>& columnRuleBounds) const; | 232 Vector<LayoutRect>& columnRuleBounds) const; |
220 | 233 |
221 LayoutRect localOverflowRectForPaintInvalidation() const override; | 234 LayoutRect localOverflowRectForPaintInvalidation() const override; |
222 | 235 |
223 protected: | 236 protected: |
224 LayoutMultiColumnSet(LayoutFlowThread*); | 237 LayoutMultiColumnSet(LayoutFlowThread*); |
225 | 238 |
226 private: | 239 private: |
227 void insertedIntoTree() final; | 240 void insertedIntoTree() final; |
228 void willBeRemovedFromTree() final; | 241 void willBeRemovedFromTree() final; |
229 | 242 |
230 bool isSelfCollapsingBlock() const override { return false; } | 243 bool isSelfCollapsingBlock() const override { return false; } |
231 | 244 |
232 void computeLogicalHeight(LayoutUnit logicalHeight, | 245 void computeLogicalHeight(LayoutUnit logicalHeight, |
233 LayoutUnit logicalTop, | 246 LayoutUnit logicalTop, |
234 LogicalExtentComputedValues&) const override; | 247 LogicalExtentComputedValues&) const override; |
235 PositionWithAffinity positionForPoint(const LayoutPoint&) override; | 248 PositionWithAffinity positionForPoint(const LayoutPoint&) override; |
236 | 249 |
237 void paintObject(const PaintInfo&, | 250 void paintObject(const PaintInfo&, |
238 const LayoutPoint& paintOffset) const override; | 251 const LayoutPoint& paintOffset) const override; |
239 | 252 |
240 void addOverflowFromChildren() override; | 253 void addOverflowFromChildren() override; |
241 | 254 |
242 MultiColumnFragmentainerGroupList m_fragmentainerGroups; | 255 MultiColumnFragmentainerGroupList m_fragmentainerGroups; |
243 LayoutFlowThread* m_flowThread; | 256 LayoutFlowThread* m_flowThread; |
244 | 257 |
245 // Height of the tallest piece of unbreakable content. This is the minimum col
umn logical height | 258 // Height of the tallest piece of unbreakable content. This is the minimum |
246 // required to avoid fragmentation where it shouldn't occur (inside unbreakabl
e content, between | 259 // column logical height required to avoid fragmentation where it shouldn't |
247 // orphans and widows, etc.). We only store this so that outer fragmentation c
ontexts (if any) | 260 // occur (inside unbreakable content, between orphans and widows, etc.). |
248 // can query this when calculating their own minimum. Note that we don't store
this value in | 261 // We only store this so that outer fragmentation contexts (if any) can query |
249 // every fragmentainer group (but rather here, in the column set), since we on
ly need the | 262 // this when calculating their own minimum. Note that we don't store this |
250 // largest one among them. | 263 // value in every fragmentainer group (but rather here, in the column set), |
| 264 // since we only need the largest one among them. |
251 LayoutUnit m_tallestUnbreakableLogicalHeight; | 265 LayoutUnit m_tallestUnbreakableLogicalHeight; |
252 | 266 |
253 // Logical top in previous layout pass. | 267 // Logical top in previous layout pass. |
254 LayoutUnit m_oldLogicalTop; | 268 LayoutUnit m_oldLogicalTop; |
255 | 269 |
256 bool m_initialHeightCalculated; | 270 bool m_initialHeightCalculated; |
257 }; | 271 }; |
258 | 272 |
259 DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutMultiColumnSet, isLayoutMultiColumnSet()); | 273 DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutMultiColumnSet, isLayoutMultiColumnSet()); |
260 | 274 |
261 } // namespace blink | 275 } // namespace blink |
262 | 276 |
263 #endif // LayoutMultiColumnSet_h | 277 #endif // LayoutMultiColumnSet_h |
OLD | NEW |