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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 if (row.logicalTop() + row.logicalHeight() > blockOffset) | 82 if (row.logicalTop() + row.logicalHeight() > blockOffset) |
83 return row; | 83 return row; |
84 } | 84 } |
85 return m_fragmentainerGroups.last(); | 85 return m_fragmentainerGroups.last(); |
86 } | 86 } |
87 | 87 |
88 LayoutUnit LayoutMultiColumnSet::pageLogicalHeightForOffset( | 88 LayoutUnit LayoutMultiColumnSet::pageLogicalHeightForOffset( |
89 LayoutUnit offsetInFlowThread) const { | 89 LayoutUnit offsetInFlowThread) const { |
90 const MultiColumnFragmentainerGroup& lastRow = lastFragmentainerGroup(); | 90 const MultiColumnFragmentainerGroup& lastRow = lastFragmentainerGroup(); |
91 if (!lastRow.logicalHeight()) { | 91 if (!lastRow.logicalHeight()) { |
92 // In the first layout pass of an auto-height multicol container, height isn
't set. No need | 92 // In the first layout pass of an auto-height multicol container, height |
93 // to perform the series of complicated dance steps below to figure out that
we should | 93 // isn't set. No need to perform the series of complicated dance steps below |
94 // simply return 0. Bail now. | 94 // to figure out that we should simply return 0. Bail now. |
95 ASSERT(m_fragmentainerGroups.size() == 1); | 95 ASSERT(m_fragmentainerGroups.size() == 1); |
96 return LayoutUnit(); | 96 return LayoutUnit(); |
97 } | 97 } |
98 if (offsetInFlowThread >= | 98 if (offsetInFlowThread >= |
99 lastRow.logicalTopInFlowThread() + fragmentainerGroupCapacity(lastRow)) { | 99 lastRow.logicalTopInFlowThread() + fragmentainerGroupCapacity(lastRow)) { |
100 // The offset is outside the bounds of the fragmentainer groups that we have
established at | 100 // The offset is outside the bounds of the fragmentainer groups that we have |
101 // this point. If we're nested inside another fragmentation context, we need
to calculate | 101 // established at this point. If we're nested inside another fragmentation |
102 // the height on our own. | 102 // context, we need to calculate the height on our own. |
103 const LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread(); | 103 const LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread(); |
104 if (FragmentationContext* enclosingFragmentationContext = | 104 if (FragmentationContext* enclosingFragmentationContext = |
105 flowThread->enclosingFragmentationContext()) { | 105 flowThread->enclosingFragmentationContext()) { |
106 // We'd ideally like to translate |offsetInFlowThread| to an offset in the
coordinate | 106 // We'd ideally like to translate |offsetInFlowThread| to an offset in the |
107 // space of the enclosing fragmentation context here, but that's hard, sin
ce the offset | 107 // coordinate space of the enclosing fragmentation context here, but |
108 // is out of bounds. So just use the bottom we have found so far. | 108 // that's hard, since the offset is out of bounds. So just use the bottom |
| 109 // we have found so far. |
109 LayoutUnit enclosingContextBottom = | 110 LayoutUnit enclosingContextBottom = |
110 lastRow.blockOffsetInEnclosingFragmentationContext() + | 111 lastRow.blockOffsetInEnclosingFragmentationContext() + |
111 lastRow.logicalHeight(); | 112 lastRow.logicalHeight(); |
112 LayoutUnit enclosingFragmentainerHeight = | 113 LayoutUnit enclosingFragmentainerHeight = |
113 enclosingFragmentationContext->fragmentainerLogicalHeightAt( | 114 enclosingFragmentationContext->fragmentainerLogicalHeightAt( |
114 enclosingContextBottom); | 115 enclosingContextBottom); |
115 // Constrain against specified height / max-height. | 116 // Constrain against specified height / max-height. |
116 LayoutUnit currentMulticolHeight = logicalTopFromMulticolContentEdge() + | 117 LayoutUnit currentMulticolHeight = logicalTopFromMulticolContentEdge() + |
117 lastRow.logicalTop() + | 118 lastRow.logicalTop() + |
118 lastRow.logicalHeight(); | 119 lastRow.logicalHeight(); |
(...skipping 10 matching lines...) Expand all Loading... |
129 .logicalHeight(); | 130 .logicalHeight(); |
130 } | 131 } |
131 | 132 |
132 LayoutUnit LayoutMultiColumnSet::pageRemainingLogicalHeightForOffset( | 133 LayoutUnit LayoutMultiColumnSet::pageRemainingLogicalHeightForOffset( |
133 LayoutUnit offsetInFlowThread, | 134 LayoutUnit offsetInFlowThread, |
134 PageBoundaryRule pageBoundaryRule) const { | 135 PageBoundaryRule pageBoundaryRule) const { |
135 const MultiColumnFragmentainerGroup& row = | 136 const MultiColumnFragmentainerGroup& row = |
136 fragmentainerGroupAtFlowThreadOffset(offsetInFlowThread, | 137 fragmentainerGroupAtFlowThreadOffset(offsetInFlowThread, |
137 pageBoundaryRule); | 138 pageBoundaryRule); |
138 LayoutUnit pageLogicalHeight = row.logicalHeight(); | 139 LayoutUnit pageLogicalHeight = row.logicalHeight(); |
139 ASSERT( | 140 // It's not allowed to call this method if the height is unknown. |
140 pageLogicalHeight); // It's not allowed to call this method if the height
is unknown. | 141 DCHECK(pageLogicalHeight); |
141 LayoutUnit pageLogicalBottom = | 142 LayoutUnit pageLogicalBottom = |
142 row.columnLogicalTopForOffset(offsetInFlowThread) + pageLogicalHeight; | 143 row.columnLogicalTopForOffset(offsetInFlowThread) + pageLogicalHeight; |
143 LayoutUnit remainingLogicalHeight = pageLogicalBottom - offsetInFlowThread; | 144 LayoutUnit remainingLogicalHeight = pageLogicalBottom - offsetInFlowThread; |
144 | 145 |
145 if (pageBoundaryRule == AssociateWithFormerPage) { | 146 if (pageBoundaryRule == AssociateWithFormerPage) { |
146 // An offset exactly at a column boundary will act as being part of the form
er column in | 147 // An offset exactly at a column boundary will act as being part of the |
147 // question (i.e. no remaining space), rather than being part of the latter
(i.e. one whole | 148 // former column in question (i.e. no remaining space), rather than being |
148 // column length of remaining space). | 149 // part of the latter (i.e. one whole column length of remaining space). |
149 remainingLogicalHeight = intMod(remainingLogicalHeight, pageLogicalHeight); | 150 remainingLogicalHeight = intMod(remainingLogicalHeight, pageLogicalHeight); |
150 } else if (!remainingLogicalHeight) { | 151 } else if (!remainingLogicalHeight) { |
151 // When pageBoundaryRule is AssociateWithLatterPage, we should never return
0, because if | 152 // When pageBoundaryRule is AssociateWithLatterPage, we should never return |
152 // there's no space left, it means that we should be at a column boundary, i
n which case we | 153 // 0, because if there's no space left, it means that we should be at a |
153 // should return the amount of space remaining in the *next* column. But thi
s is not true if | 154 // column boundary, in which case we should return the amount of space |
154 // the offset is "infinite" (saturated), so allow this to happen in that cas
e. | 155 // remaining in the *next* column. But this is not true if the offset is |
| 156 // "infinite" (saturated), so allow this to happen in that case. |
155 ASSERT(offsetInFlowThread.mightBeSaturated()); | 157 ASSERT(offsetInFlowThread.mightBeSaturated()); |
156 remainingLogicalHeight = pageLogicalHeight; | 158 remainingLogicalHeight = pageLogicalHeight; |
157 } | 159 } |
158 return remainingLogicalHeight; | 160 return remainingLogicalHeight; |
159 } | 161 } |
160 | 162 |
161 bool LayoutMultiColumnSet::isPageLogicalHeightKnown() const { | 163 bool LayoutMultiColumnSet::isPageLogicalHeightKnown() const { |
162 return firstFragmentainerGroup().logicalHeight(); | 164 return firstFragmentainerGroup().logicalHeight(); |
163 } | 165 } |
164 | 166 |
165 LayoutUnit LayoutMultiColumnSet::nextLogicalTopForUnbreakableContent( | 167 LayoutUnit LayoutMultiColumnSet::nextLogicalTopForUnbreakableContent( |
166 LayoutUnit flowThreadOffset, | 168 LayoutUnit flowThreadOffset, |
167 LayoutUnit contentLogicalHeight) const { | 169 LayoutUnit contentLogicalHeight) const { |
168 ASSERT(flowThreadOffset.mightBeSaturated() || | 170 ASSERT(flowThreadOffset.mightBeSaturated() || |
169 pageLogicalTopForOffset(flowThreadOffset) == flowThreadOffset); | 171 pageLogicalTopForOffset(flowThreadOffset) == flowThreadOffset); |
170 FragmentationContext* enclosingFragmentationContext = | 172 FragmentationContext* enclosingFragmentationContext = |
171 multiColumnFlowThread()->enclosingFragmentationContext(); | 173 multiColumnFlowThread()->enclosingFragmentationContext(); |
172 if (!enclosingFragmentationContext) { | 174 if (!enclosingFragmentationContext) { |
173 // If there's no enclosing fragmentation context, there'll ever be only one
row, and all | 175 // If there's no enclosing fragmentation context, there'll ever be only one |
174 // columns there will have the same height. | 176 // row, and all columns there will have the same height. |
175 return flowThreadOffset; | 177 return flowThreadOffset; |
176 } | 178 } |
177 | 179 |
178 // Assert the problematic situation. If we have no problem with the column hei
ght, why are we | 180 // Assert the problematic situation. If we have no problem with the column |
179 // even here? | 181 // height, why are we even here? |
180 ASSERT(pageLogicalHeightForOffset(flowThreadOffset) < contentLogicalHeight); | 182 ASSERT(pageLogicalHeightForOffset(flowThreadOffset) < contentLogicalHeight); |
181 | 183 |
182 // There's a likelihood for subsequent rows to be taller than the first one. | 184 // There's a likelihood for subsequent rows to be taller than the first one. |
183 // TODO(mstensho): if we're doubly nested (e.g. multicol in multicol in multic
ol), we need to | 185 // TODO(mstensho): if we're doubly nested (e.g. multicol in multicol in |
184 // look beyond the first row here. | 186 // multicol), we need to look beyond the first row here. |
185 const MultiColumnFragmentainerGroup& firstRow = firstFragmentainerGroup(); | 187 const MultiColumnFragmentainerGroup& firstRow = firstFragmentainerGroup(); |
186 LayoutUnit firstRowLogicalBottomInFlowThread = | 188 LayoutUnit firstRowLogicalBottomInFlowThread = |
187 firstRow.logicalTopInFlowThread() + fragmentainerGroupCapacity(firstRow); | 189 firstRow.logicalTopInFlowThread() + fragmentainerGroupCapacity(firstRow); |
188 if (flowThreadOffset >= firstRowLogicalBottomInFlowThread) | 190 if (flowThreadOffset >= firstRowLogicalBottomInFlowThread) |
189 return flowThreadOffset; // We're not in the first row. Give up. | 191 return flowThreadOffset; // We're not in the first row. Give up. |
190 LayoutUnit newLogicalHeight = | 192 LayoutUnit newLogicalHeight = |
191 enclosingFragmentationContext->fragmentainerLogicalHeightAt( | 193 enclosingFragmentationContext->fragmentainerLogicalHeightAt( |
192 firstRow.blockOffsetInEnclosingFragmentationContext() + | 194 firstRow.blockOffsetInEnclosingFragmentationContext() + |
193 firstRow.logicalHeight()); | 195 firstRow.logicalHeight()); |
194 if (contentLogicalHeight > newLogicalHeight) { | 196 if (contentLogicalHeight > newLogicalHeight) { |
195 // The next outer column or page doesn't have enough space either. Give up a
nd stay where | 197 // The next outer column or page doesn't have enough space either. Give up |
196 // we are. | 198 // and stay where we are. |
197 return flowThreadOffset; | 199 return flowThreadOffset; |
198 } | 200 } |
199 return firstRowLogicalBottomInFlowThread; | 201 return firstRowLogicalBottomInFlowThread; |
200 } | 202 } |
201 | 203 |
202 LayoutMultiColumnSet* LayoutMultiColumnSet::nextSiblingMultiColumnSet() const { | 204 LayoutMultiColumnSet* LayoutMultiColumnSet::nextSiblingMultiColumnSet() const { |
203 for (LayoutObject* sibling = nextSibling(); sibling; | 205 for (LayoutObject* sibling = nextSibling(); sibling; |
204 sibling = sibling->nextSibling()) { | 206 sibling = sibling->nextSibling()) { |
205 if (sibling->isLayoutMultiColumnSet()) | 207 if (sibling->isLayoutMultiColumnSet()) |
206 return toLayoutMultiColumnSet(sibling); | 208 return toLayoutMultiColumnSet(sibling); |
(...skipping 18 matching lines...) Expand all Loading... |
225 LayoutUnit maxLogicalBottomInFlowThread = | 227 LayoutUnit maxLogicalBottomInFlowThread = |
226 lastRow.logicalTopInFlowThread() + fragmentainerGroupCapacity(lastRow); | 228 lastRow.logicalTopInFlowThread() + fragmentainerGroupCapacity(lastRow); |
227 if (pageBoundaryRule == AssociateWithFormerPage) | 229 if (pageBoundaryRule == AssociateWithFormerPage) |
228 return offsetInFlowThread <= maxLogicalBottomInFlowThread; | 230 return offsetInFlowThread <= maxLogicalBottomInFlowThread; |
229 return offsetInFlowThread < maxLogicalBottomInFlowThread; | 231 return offsetInFlowThread < maxLogicalBottomInFlowThread; |
230 } | 232 } |
231 | 233 |
232 MultiColumnFragmentainerGroup& | 234 MultiColumnFragmentainerGroup& |
233 LayoutMultiColumnSet::appendNewFragmentainerGroup() { | 235 LayoutMultiColumnSet::appendNewFragmentainerGroup() { |
234 MultiColumnFragmentainerGroup newGroup(*this); | 236 MultiColumnFragmentainerGroup newGroup(*this); |
235 { // Extra scope here for previousGroup; it's potentially invalid once we mod
ify the m_fragmentainerGroups Vector. | 237 { // Extra scope here for previousGroup; it's potentially invalid once we |
| 238 // modify the m_fragmentainerGroups Vector. |
236 MultiColumnFragmentainerGroup& previousGroup = m_fragmentainerGroups.last(); | 239 MultiColumnFragmentainerGroup& previousGroup = m_fragmentainerGroups.last(); |
237 | 240 |
238 // This is the flow thread block offset where |previousGroup| ends and |newG
roup| takes over. | 241 // This is the flow thread block offset where |previousGroup| ends and |
| 242 // |newGroup| takes over. |
239 LayoutUnit blockOffsetInFlowThread = | 243 LayoutUnit blockOffsetInFlowThread = |
240 previousGroup.logicalTopInFlowThread() + | 244 previousGroup.logicalTopInFlowThread() + |
241 fragmentainerGroupCapacity(previousGroup); | 245 fragmentainerGroupCapacity(previousGroup); |
242 previousGroup.setLogicalBottomInFlowThread(blockOffsetInFlowThread); | 246 previousGroup.setLogicalBottomInFlowThread(blockOffsetInFlowThread); |
243 newGroup.setLogicalTopInFlowThread(blockOffsetInFlowThread); | 247 newGroup.setLogicalTopInFlowThread(blockOffsetInFlowThread); |
244 newGroup.setLogicalTop(previousGroup.logicalTop() + | 248 newGroup.setLogicalTop(previousGroup.logicalTop() + |
245 previousGroup.logicalHeight()); | 249 previousGroup.logicalHeight()); |
246 newGroup.resetColumnHeight(); | 250 newGroup.resetColumnHeight(); |
247 } | 251 } |
248 m_fragmentainerGroups.append(newGroup); | 252 m_fragmentainerGroups.append(newGroup); |
249 return m_fragmentainerGroups.last(); | 253 return m_fragmentainerGroups.last(); |
250 } | 254 } |
251 | 255 |
252 LayoutUnit LayoutMultiColumnSet::logicalTopFromMulticolContentEdge() const { | 256 LayoutUnit LayoutMultiColumnSet::logicalTopFromMulticolContentEdge() const { |
253 // We subtract the position of the first column set or spanner placeholder, ra
ther than the | 257 // We subtract the position of the first column set or spanner placeholder, |
254 // "before" border+padding of the multicol container. This distinction doesn't
matter after | 258 // rather than the "before" border+padding of the multicol container. This |
255 // layout, but during layout it does: The flow thread (i.e. the multicol conte
nts) is laid out | 259 // distinction doesn't matter after layout, but during layout it does: |
256 // before the column sets and spanner placeholders, which means that compesati
ng for a top | 260 // The flow thread (i.e. the multicol contents) is laid out before the column |
257 // border+padding that hasn't yet been baked into the offset will produce the
wrong results in | 261 // sets and spanner placeholders, which means that compesating for a top |
258 // the first layout pass, and we'd end up performing a wasted layout pass in m
any cases. | 262 // border+padding that hasn't yet been baked into the offset will produce the |
| 263 // wrong results in the first layout pass, and we'd end up performing a wasted |
| 264 // layout pass in many cases. |
259 const LayoutBox& firstColumnBox = | 265 const LayoutBox& firstColumnBox = |
260 *multiColumnFlowThread()->firstMultiColumnBox(); | 266 *multiColumnFlowThread()->firstMultiColumnBox(); |
261 // The top margin edge of the first column set or spanner placeholder is flush
with the top | 267 // The top margin edge of the first column set or spanner placeholder is flush |
262 // content edge of the multicol container. The margin here never collapses wit
h other margins, | 268 // with the top content edge of the multicol container. The margin here never |
263 // so we can just subtract it. Column sets never have margins, but spanner pla
ceholders may. | 269 // collapses with other margins, so we can just subtract it. Column sets never |
| 270 // have margins, but spanner placeholders may. |
264 LayoutUnit firstColumnBoxMarginEdge = | 271 LayoutUnit firstColumnBoxMarginEdge = |
265 firstColumnBox.logicalTop() - | 272 firstColumnBox.logicalTop() - |
266 multiColumnBlockFlow()->marginBeforeForChild(firstColumnBox); | 273 multiColumnBlockFlow()->marginBeforeForChild(firstColumnBox); |
267 return logicalTop() - firstColumnBoxMarginEdge; | 274 return logicalTop() - firstColumnBoxMarginEdge; |
268 } | 275 } |
269 | 276 |
270 LayoutUnit LayoutMultiColumnSet::logicalTopInFlowThread() const { | 277 LayoutUnit LayoutMultiColumnSet::logicalTopInFlowThread() const { |
271 return firstFragmentainerGroup().logicalTopInFlowThread(); | 278 return firstFragmentainerGroup().logicalTopInFlowThread(); |
272 } | 279 } |
273 | 280 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 std::max(flowThreadPortionRect.y(), (flowThreadOverflow.maxY())); | 322 std::max(flowThreadPortionRect.y(), (flowThreadOverflow.maxY())); |
316 clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY); | 323 clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY); |
317 } | 324 } |
318 | 325 |
319 return clipRect; | 326 return clipRect; |
320 } | 327 } |
321 | 328 |
322 bool LayoutMultiColumnSet::heightIsAuto() const { | 329 bool LayoutMultiColumnSet::heightIsAuto() const { |
323 LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread(); | 330 LayoutMultiColumnFlowThread* flowThread = multiColumnFlowThread(); |
324 if (!flowThread->isLayoutPagedFlowThread()) { | 331 if (!flowThread->isLayoutPagedFlowThread()) { |
325 // If support for the column-fill property isn't enabled, we want to behave
as if | 332 // If support for the column-fill property isn't enabled, we want to behave |
326 // column-fill were auto, so that multicol containers with specified height
don't get their | 333 // as if column-fill were auto, so that multicol containers with specified |
327 // columns balanced (auto-height multicol containers will still get their co
lumns balanced, | 334 // height don't get their columns balanced (auto-height multicol containers |
328 // even if column-fill isn't 'balance' - in accordance with the spec). Prete
nding that | 335 // will still get their columns balanced, even if column-fill isn't |
329 // column-fill is auto also matches the old multicol implementation, which h
as no support | 336 // 'balance' - in accordance with the spec). |
330 // for this property. | 337 // Pretending that column-fill is auto also matches the old multicol |
| 338 // implementation, which has no support for this property. |
331 if (multiColumnBlockFlow()->style()->getColumnFill() == ColumnFillBalance) | 339 if (multiColumnBlockFlow()->style()->getColumnFill() == ColumnFillBalance) |
332 return true; | 340 return true; |
333 if (LayoutBox* next = nextSiblingBox()) { | 341 if (LayoutBox* next = nextSiblingBox()) { |
334 if (next->isLayoutMultiColumnSpannerPlaceholder()) { | 342 if (next->isLayoutMultiColumnSpannerPlaceholder()) { |
335 // If we're followed by a spanner, we need to balance. | 343 // If we're followed by a spanner, we need to balance. |
336 return true; | 344 return true; |
337 } | 345 } |
338 } | 346 } |
339 } | 347 } |
340 return !flowThread->columnHeightAvailable(); | 348 return !flowThread->columnHeightAvailable(); |
(...skipping 17 matching lines...) Expand all Loading... |
358 | 366 |
359 LayoutUnit LayoutMultiColumnSet::pageLogicalTopForOffset( | 367 LayoutUnit LayoutMultiColumnSet::pageLogicalTopForOffset( |
360 LayoutUnit offset) const { | 368 LayoutUnit offset) const { |
361 return fragmentainerGroupAtFlowThreadOffset(offset, AssociateWithLatterPage) | 369 return fragmentainerGroupAtFlowThreadOffset(offset, AssociateWithLatterPage) |
362 .columnLogicalTopForOffset(offset); | 370 .columnLogicalTopForOffset(offset); |
363 } | 371 } |
364 | 372 |
365 bool LayoutMultiColumnSet::recalculateColumnHeight() { | 373 bool LayoutMultiColumnSet::recalculateColumnHeight() { |
366 if (m_oldLogicalTop != logicalTop() && | 374 if (m_oldLogicalTop != logicalTop() && |
367 multiColumnFlowThread()->enclosingFragmentationContext()) { | 375 multiColumnFlowThread()->enclosingFragmentationContext()) { |
368 // Preceding spanners or column sets have been moved or resized. This means
that the | 376 // Preceding spanners or column sets have been moved or resized. This means |
369 // fragmentainer groups that we have inserted need to be re-inserted. Restar
t column | 377 // that the fragmentainer groups that we have inserted need to be |
370 // balancing. | 378 // re-inserted. Restart column balancing. |
371 resetColumnHeight(); | 379 resetColumnHeight(); |
372 return true; | 380 return true; |
373 } | 381 } |
374 | 382 |
375 bool changed = false; | 383 bool changed = false; |
376 for (auto& group : m_fragmentainerGroups) | 384 for (auto& group : m_fragmentainerGroups) |
377 changed = group.recalculateColumnHeight(*this) || changed; | 385 changed = group.recalculateColumnHeight(*this) || changed; |
378 m_initialHeightCalculated = true; | 386 m_initialHeightCalculated = true; |
379 return changed; | 387 return changed; |
380 } | 388 } |
381 | 389 |
382 void LayoutMultiColumnSet::resetColumnHeight() { | 390 void LayoutMultiColumnSet::resetColumnHeight() { |
383 m_fragmentainerGroups.deleteExtraGroups(); | 391 m_fragmentainerGroups.deleteExtraGroups(); |
384 m_fragmentainerGroups.first().resetColumnHeight(); | 392 m_fragmentainerGroups.first().resetColumnHeight(); |
385 m_tallestUnbreakableLogicalHeight = LayoutUnit(); | 393 m_tallestUnbreakableLogicalHeight = LayoutUnit(); |
386 m_initialHeightCalculated = false; | 394 m_initialHeightCalculated = false; |
387 } | 395 } |
388 | 396 |
389 void LayoutMultiColumnSet::beginFlow(LayoutUnit offsetInFlowThread) { | 397 void LayoutMultiColumnSet::beginFlow(LayoutUnit offsetInFlowThread) { |
390 // At this point layout is exactly at the beginning of this set. Store block o
ffset from flow | 398 // At this point layout is exactly at the beginning of this set. Store block |
391 // thread start. | 399 // offset from flow thread start. |
392 m_fragmentainerGroups.first().setLogicalTopInFlowThread(offsetInFlowThread); | 400 m_fragmentainerGroups.first().setLogicalTopInFlowThread(offsetInFlowThread); |
393 } | 401 } |
394 | 402 |
395 void LayoutMultiColumnSet::endFlow(LayoutUnit offsetInFlowThread) { | 403 void LayoutMultiColumnSet::endFlow(LayoutUnit offsetInFlowThread) { |
396 // At this point layout is exactly at the end of this set. Store block offset
from flow thread | 404 // At this point layout is exactly at the end of this set. Store block offset |
397 // start. This set is now considered "flowed", although we may have to revisit
it later (with | 405 // from flow thread start. This set is now considered "flowed", although we |
398 // beginFlow()), e.g. if a subtree in the flow thread has to be laid out over
again because the | 406 // may have to revisit it later (with beginFlow()), e.g. if a subtree in the |
399 // initial margin collapsing estimates were wrong. | 407 // flow thread has to be laid out over again because the initial margin |
| 408 // collapsing estimates were wrong. |
400 m_fragmentainerGroups.last().setLogicalBottomInFlowThread(offsetInFlowThread); | 409 m_fragmentainerGroups.last().setLogicalBottomInFlowThread(offsetInFlowThread); |
401 } | 410 } |
402 | 411 |
403 void LayoutMultiColumnSet::styleDidChange(StyleDifference diff, | 412 void LayoutMultiColumnSet::styleDidChange(StyleDifference diff, |
404 const ComputedStyle* oldStyle) { | 413 const ComputedStyle* oldStyle) { |
405 LayoutBlockFlow::styleDidChange(diff, oldStyle); | 414 LayoutBlockFlow::styleDidChange(diff, oldStyle); |
406 | 415 |
407 // column-rule is specified on the parent (the multicol container) of this obj
ect, but it's the | 416 // column-rule is specified on the parent (the multicol container) of this |
408 // column sets that are in charge of painting them. A column rule is pretty mu
ch like any other | 417 // object, but it's the column sets that are in charge of painting them. |
409 // box decoration, like borders. We need to say that we have box decorations h
ere, so that the | 418 // A column rule is pretty much like any other box decoration, like borders. |
410 // columnn set is invalidated when it gets laid out. We cannot check here whet
her the multicol | 419 // We need to say that we have box decorations here, so that the columnn set |
411 // container actually has a visible column rule or not, because we may not hav
e been inserted | 420 // is invalidated when it gets laid out. We cannot check here whether the |
412 // into the tree yet. Painting a column set is cheap anyway, because the only
thing it can | 421 // multicol container actually has a visible column rule or not, because we |
413 // paint is the column rule, while actual multicol content is handled by the f
low thread. | 422 // may not have been inserted into the tree yet. Painting a column set is |
| 423 // cheap anyway, because the only thing it can paint is the column rule, while |
| 424 // actual multicol content is handled by the flow thread. |
414 setHasBoxDecorationBackground(true); | 425 setHasBoxDecorationBackground(true); |
415 } | 426 } |
416 | 427 |
417 void LayoutMultiColumnSet::layout() { | 428 void LayoutMultiColumnSet::layout() { |
418 if (recalculateColumnHeight()) | 429 if (recalculateColumnHeight()) |
419 multiColumnFlowThread()->setColumnHeightsChanged(); | 430 multiColumnFlowThread()->setColumnHeightsChanged(); |
420 LayoutBlockFlow::layout(); | 431 LayoutBlockFlow::layout(); |
421 } | 432 } |
422 | 433 |
423 void LayoutMultiColumnSet::computeIntrinsicLogicalWidths( | 434 void LayoutMultiColumnSet::computeIntrinsicLogicalWidths( |
(...skipping 20 matching lines...) Expand all Loading... |
444 const MultiColumnFragmentainerGroup& row = | 455 const MultiColumnFragmentainerGroup& row = |
445 fragmentainerGroupAtVisualPoint(point); | 456 fragmentainerGroupAtVisualPoint(point); |
446 LayoutPoint flowThreadPoint = | 457 LayoutPoint flowThreadPoint = |
447 row.visualPointToFlowThreadPoint(point + row.offsetFromColumnSet()); | 458 row.visualPointToFlowThreadPoint(point + row.offsetFromColumnSet()); |
448 // Then drill into the flow thread, where we'll find the actual content. | 459 // Then drill into the flow thread, where we'll find the actual content. |
449 return flowThread()->positionForPoint(flowThreadPoint); | 460 return flowThread()->positionForPoint(flowThreadPoint); |
450 } | 461 } |
451 | 462 |
452 LayoutUnit LayoutMultiColumnSet::columnGap() const { | 463 LayoutUnit LayoutMultiColumnSet::columnGap() const { |
453 LayoutBlockFlow* parentBlock = multiColumnBlockFlow(); | 464 LayoutBlockFlow* parentBlock = multiColumnBlockFlow(); |
454 if (parentBlock->style()->hasNormalColumnGap()) | 465 |
| 466 if (parentBlock->style()->hasNormalColumnGap()) { |
| 467 // "1em" is recommended as the normal gap setting. Matches <p> margins. |
455 return LayoutUnit( | 468 return LayoutUnit( |
456 parentBlock->style() | 469 parentBlock->style()->getFontDescription().computedPixelSize()); |
457 ->getFontDescription() | 470 } |
458 .computedPixelSize()); // "1em" is recommended as the normal gap se
tting. Matches <p> margins. | |
459 return LayoutUnit(parentBlock->style()->columnGap()); | 471 return LayoutUnit(parentBlock->style()->columnGap()); |
460 } | 472 } |
461 | 473 |
462 unsigned LayoutMultiColumnSet::actualColumnCount() const { | 474 unsigned LayoutMultiColumnSet::actualColumnCount() const { |
463 // FIXME: remove this method. It's a meaningless question to ask the set "how
many columns do | 475 // FIXME: remove this method. It's a meaningless question to ask the set "how |
464 // you actually have?", since that may vary for each row. | 476 // many columns do you actually have?", since that may vary for each row. |
465 return firstFragmentainerGroup().actualColumnCount(); | 477 return firstFragmentainerGroup().actualColumnCount(); |
466 } | 478 } |
467 | 479 |
468 void LayoutMultiColumnSet::paintObject(const PaintInfo& paintInfo, | 480 void LayoutMultiColumnSet::paintObject(const PaintInfo& paintInfo, |
469 const LayoutPoint& paintOffset) const { | 481 const LayoutPoint& paintOffset) const { |
470 MultiColumnSetPainter(*this).paintObject(paintInfo, paintOffset); | 482 MultiColumnSetPainter(*this).paintObject(paintInfo, paintOffset); |
471 } | 483 } |
472 | 484 |
473 LayoutRect LayoutMultiColumnSet::fragmentsBoundingBox( | 485 LayoutRect LayoutMultiColumnSet::fragmentsBoundingBox( |
474 const LayoutRect& boundingBoxInFlowThread) const { | 486 const LayoutRect& boundingBoxInFlowThread) const { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
595 // Now add in column rule bounds, if present. | 607 // Now add in column rule bounds, if present. |
596 Vector<LayoutRect> columnRuleBounds; | 608 Vector<LayoutRect> columnRuleBounds; |
597 if (computeColumnRuleBounds(LayoutPoint(), columnRuleBounds)) { | 609 if (computeColumnRuleBounds(LayoutPoint(), columnRuleBounds)) { |
598 for (auto& bound : columnRuleBounds) | 610 for (auto& bound : columnRuleBounds) |
599 blockFlowBounds.unite(bound); | 611 blockFlowBounds.unite(bound); |
600 } | 612 } |
601 return blockFlowBounds; | 613 return blockFlowBounds; |
602 } | 614 } |
603 | 615 |
604 } // namespace blink | 616 } // namespace blink |
OLD | NEW |