| 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 |