| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 | 6 |
| 7 #include "core/layout/MultiColumnFragmentainerGroup.h" | 7 #include "core/layout/MultiColumnFragmentainerGroup.h" |
| 8 | 8 |
| 9 #include "core/layout/LayoutMultiColumnSet.h" | 9 #include "core/layout/LayoutMultiColumnSet.h" |
| 10 | 10 |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 LayoutRect clippedRect(layerBoundsInFlowThread); | 207 LayoutRect clippedRect(layerBoundsInFlowThread); |
| 208 clippedRect.intersect(m_columnSet.flowThreadPortionOverflowRect()); | 208 clippedRect.intersect(m_columnSet.flowThreadPortionOverflowRect()); |
| 209 if (clippedRect.isEmpty()) | 209 if (clippedRect.isEmpty()) |
| 210 return; | 210 return; |
| 211 | 211 |
| 212 // Now we know we intersect at least one column. Let's figure out the logica
l top and logical | 212 // Now we know we intersect at least one column. Let's figure out the logica
l top and logical |
| 213 // bottom of the area we're checking. | 213 // bottom of the area we're checking. |
| 214 LayoutUnit layerLogicalTop = isHorizontalWritingMode ? layerBoundsInFlowThre
ad.y() : layerBoundsInFlowThread.x(); | 214 LayoutUnit layerLogicalTop = isHorizontalWritingMode ? layerBoundsInFlowThre
ad.y() : layerBoundsInFlowThread.x(); |
| 215 LayoutUnit layerLogicalBottom = (isHorizontalWritingMode ? layerBoundsInFlow
Thread.maxY() : layerBoundsInFlowThread.maxX()) - 1; | 215 LayoutUnit layerLogicalBottom = (isHorizontalWritingMode ? layerBoundsInFlow
Thread.maxY() : layerBoundsInFlowThread.maxX()) - 1; |
| 216 | 216 |
| 217 // Figure out the start and end columns and only check within that range so
that we don't walk the | 217 // Figure out the start and end columns for the layer and only check within
that range so that |
| 218 // entire column row. | 218 // we don't walk the entire column row. |
| 219 unsigned startColumn = columnIndexAtOffset(layerLogicalTop); | 219 unsigned startColumn = columnIndexAtOffset(layerLogicalTop); |
| 220 unsigned endColumn = columnIndexAtOffset(layerLogicalBottom); | 220 unsigned endColumn = columnIndexAtOffset(layerLogicalBottom); |
| 221 | 221 |
| 222 // Now intersect with the columns actually occupied by the dirty rect, to na
rrow it down even further. |
| 223 unsigned firstColumnInDirtyRect, lastColumnInDirtyRect; |
| 224 columnIntervalForVisualRect(dirtyRect, firstColumnInDirtyRect, lastColumnInD
irtyRect); |
| 225 if (firstColumnInDirtyRect > endColumn || lastColumnInDirtyRect < startColum
n) |
| 226 return; // The two column intervals are disjoint. There's nothing to col
lect. |
| 227 if (startColumn < firstColumnInDirtyRect) |
| 228 startColumn = firstColumnInDirtyRect; |
| 229 if (endColumn > lastColumnInDirtyRect) |
| 230 endColumn = lastColumnInDirtyRect; |
| 231 ASSERT(endColumn >= startColumn); |
| 232 |
| 222 LayoutUnit colLogicalWidth = m_columnSet.pageLogicalWidth(); | 233 LayoutUnit colLogicalWidth = m_columnSet.pageLogicalWidth(); |
| 223 LayoutUnit colGap = m_columnSet.columnGap(); | 234 LayoutUnit colGap = m_columnSet.columnGap(); |
| 224 unsigned colCount = actualColumnCount(); | 235 unsigned colCount = actualColumnCount(); |
| 225 | 236 |
| 226 bool progressionIsInline = flowThread->progressionIsInline(); | 237 bool progressionIsInline = flowThread->progressionIsInline(); |
| 227 bool leftToRight = m_columnSet.style()->isLeftToRightDirection(); | 238 bool leftToRight = m_columnSet.style()->isLeftToRightDirection(); |
| 228 | 239 |
| 229 LayoutUnit initialBlockOffset = m_columnSet.logicalTop() + logicalTop() - fl
owThread->logicalTop(); | 240 LayoutUnit initialBlockOffset = m_columnSet.logicalTop() + logicalTop() - fl
owThread->logicalTop(); |
| 230 | 241 |
| 231 for (unsigned i = startColumn; i <= endColumn; i++) { | 242 for (unsigned i = startColumn; i <= endColumn; i++) { |
| 232 // Get the portion of the flow thread that corresponds to this column. | 243 // Get the portion of the flow thread that corresponds to this column. |
| 233 LayoutRect flowThreadPortion = flowThreadPortionRectAt(i); | 244 LayoutRect flowThreadPortion = flowThreadPortionRectAt(i); |
| 234 | 245 |
| 235 // Now get the overflow rect that corresponds to the column. | 246 // Now get the overflow rect that corresponds to the column. |
| 236 LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flo
wThreadPortion, i, colCount, colGap); | 247 LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flo
wThreadPortion, i, colCount, colGap); |
| 237 | 248 |
| 238 // In order to create a fragment we must intersect the portion painted b
y this column. | |
| 239 LayoutRect clippedRect(layerBoundsInFlowThread); | |
| 240 clippedRect.intersect(flowThreadOverflowPortion); | |
| 241 if (clippedRect.isEmpty()) | |
| 242 continue; | |
| 243 | |
| 244 // We also need to intersect the dirty rect. We have to apply a translat
ion and shift based off | |
| 245 // our column index. | |
| 246 LayoutPoint translationOffset; | 249 LayoutPoint translationOffset; |
| 247 LayoutUnit inlineOffset = progressionIsInline ? i * (colLogicalWidth + c
olGap) : LayoutUnit(); | 250 LayoutUnit inlineOffset = progressionIsInline ? i * (colLogicalWidth + c
olGap) : LayoutUnit(); |
| 248 if (!leftToRight) | 251 if (!leftToRight) |
| 249 inlineOffset = -inlineOffset; | 252 inlineOffset = -inlineOffset; |
| 250 translationOffset.setX(inlineOffset); | 253 translationOffset.setX(inlineOffset); |
| 251 LayoutUnit blockOffset; | 254 LayoutUnit blockOffset; |
| 252 if (progressionIsInline) { | 255 if (progressionIsInline) { |
| 253 blockOffset = initialBlockOffset + (isHorizontalWritingMode ? -flowT
hreadPortion.y() : -flowThreadPortion.x()); | 256 blockOffset = initialBlockOffset + (isHorizontalWritingMode ? -flowT
hreadPortion.y() : -flowThreadPortion.x()); |
| 254 } else { | 257 } else { |
| 255 // Column gap can apply in the block direction for page fragmentaine
rs. | 258 // Column gap can apply in the block direction for page fragmentaine
rs. |
| 256 // There is currently no spec which calls for column-gap to apply | 259 // There is currently no spec which calls for column-gap to apply |
| 257 // for page fragmentainers at all, but it's applied here for compati
bility | 260 // for page fragmentainers at all, but it's applied here for compati
bility |
| 258 // with the old multicolumn implementation. | 261 // with the old multicolumn implementation. |
| 259 blockOffset = i * colGap; | 262 blockOffset = i * colGap; |
| 260 } | 263 } |
| 261 if (isFlippedBlocksWritingMode(m_columnSet.style()->writingMode())) | 264 if (isFlippedBlocksWritingMode(m_columnSet.style()->writingMode())) |
| 262 blockOffset = -blockOffset; | 265 blockOffset = -blockOffset; |
| 263 translationOffset.setY(blockOffset); | 266 translationOffset.setY(blockOffset); |
| 264 if (!isHorizontalWritingMode) | 267 if (!isHorizontalWritingMode) |
| 265 translationOffset = translationOffset.transposedPoint(); | 268 translationOffset = translationOffset.transposedPoint(); |
| 266 | 269 |
| 267 // Shift the dirty rect to be in flow thread coordinates with this trans
lation applied. | 270 // Make a fragment now and supply the physical translation offset and th
e clip rect for the |
| 268 LayoutRect translatedDirtyRect(dirtyRect); | 271 // column with that offset applied. |
| 269 translatedDirtyRect.moveBy(-translationOffset); | |
| 270 | |
| 271 // See if we intersect the dirty rect. | |
| 272 clippedRect = layerBoundingBox; | |
| 273 clippedRect.intersect(translatedDirtyRect); | |
| 274 if (clippedRect.isEmpty()) | |
| 275 continue; | |
| 276 | |
| 277 // Something does need to paint in this column. Make a fragment now and
supply the physical translation | |
| 278 // offset and the clip rect for the column with that offset applied. | |
| 279 DeprecatedPaintLayerFragment fragment; | 272 DeprecatedPaintLayerFragment fragment; |
| 280 fragment.paginationOffset = translationOffset; | 273 fragment.paginationOffset = translationOffset; |
| 281 | 274 |
| 282 LayoutRect flippedFlowThreadOverflowPortion(flowThreadOverflowPortion); | 275 LayoutRect flippedFlowThreadOverflowPortion(flowThreadOverflowPortion); |
| 283 // Flip it into more a physical (DeprecatedPaintLayer-style) rectangle. | 276 // Flip it into more a physical (DeprecatedPaintLayer-style) rectangle. |
| 284 flowThread->flipForWritingMode(flippedFlowThreadOverflowPortion); | 277 flowThread->flipForWritingMode(flippedFlowThreadOverflowPortion); |
| 285 fragment.paginationClip = flippedFlowThreadOverflowPortion; | 278 fragment.paginationClip = flippedFlowThreadOverflowPortion; |
| 286 fragments.append(fragment); | 279 fragments.append(fragment); |
| 287 } | 280 } |
| 288 } | 281 } |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 551 LayoutUnit columnGap = m_columnSet.columnGap(); | 544 LayoutUnit columnGap = m_columnSet.columnGap(); |
| 552 if (columnLengthInColumnProgressionDirection + columnGap <= 0) | 545 if (columnLengthInColumnProgressionDirection + columnGap <= 0) |
| 553 return 0; | 546 return 0; |
| 554 // Column boundaries are in the middle of the column gap. | 547 // Column boundaries are in the middle of the column gap. |
| 555 int index = (offsetInColumnProgressionDirection + columnGap / 2) / (columnLe
ngthInColumnProgressionDirection + columnGap); | 548 int index = (offsetInColumnProgressionDirection + columnGap / 2) / (columnLe
ngthInColumnProgressionDirection + columnGap); |
| 556 if (index < 0) | 549 if (index < 0) |
| 557 return 0; | 550 return 0; |
| 558 return std::min(unsigned(index), actualColumnCount() - 1); | 551 return std::min(unsigned(index), actualColumnCount() - 1); |
| 559 } | 552 } |
| 560 | 553 |
| 554 void MultiColumnFragmentainerGroup::columnIntervalForVisualRect(const LayoutRect
& rect, unsigned& firstColumn, unsigned& lastColumn) const |
| 555 { |
| 556 bool isColumnProgressionInline = m_columnSet.multiColumnFlowThread()->progre
ssionIsInline(); |
| 557 bool isFlippedColumnProgression = !m_columnSet.style()->isLeftToRightDirecti
on() && isColumnProgressionInline; |
| 558 if (m_columnSet.isHorizontalWritingMode() == isColumnProgressionInline) { |
| 559 if (isFlippedColumnProgression) { |
| 560 firstColumn = columnIndexAtVisualPoint(rect.maxXMinYCorner()); |
| 561 lastColumn = columnIndexAtVisualPoint(rect.minXMinYCorner()); |
| 562 } else { |
| 563 firstColumn = columnIndexAtVisualPoint(rect.minXMinYCorner()); |
| 564 lastColumn = columnIndexAtVisualPoint(rect.maxXMinYCorner()); |
| 565 } |
| 566 } else { |
| 567 if (isFlippedColumnProgression) { |
| 568 firstColumn = columnIndexAtVisualPoint(rect.minXMaxYCorner()); |
| 569 lastColumn = columnIndexAtVisualPoint(rect.minXMinYCorner()); |
| 570 } else { |
| 571 firstColumn = columnIndexAtVisualPoint(rect.minXMinYCorner()); |
| 572 lastColumn = columnIndexAtVisualPoint(rect.minXMaxYCorner()); |
| 573 } |
| 574 } |
| 575 ASSERT(firstColumn <= lastColumn); |
| 576 } |
| 577 |
| 561 MultiColumnFragmentainerGroupList::MultiColumnFragmentainerGroupList(LayoutMulti
ColumnSet& columnSet) | 578 MultiColumnFragmentainerGroupList::MultiColumnFragmentainerGroupList(LayoutMulti
ColumnSet& columnSet) |
| 562 : m_columnSet(columnSet) | 579 : m_columnSet(columnSet) |
| 563 { | 580 { |
| 564 append(MultiColumnFragmentainerGroup(m_columnSet)); | 581 append(MultiColumnFragmentainerGroup(m_columnSet)); |
| 565 } | 582 } |
| 566 | 583 |
| 567 // An explicit empty destructor of MultiColumnFragmentainerGroupList should be i
n | 584 // An explicit empty destructor of MultiColumnFragmentainerGroupList should be i
n |
| 568 // MultiColumnFragmentainerGroup.cpp, because if an implicit destructor is used, | 585 // MultiColumnFragmentainerGroup.cpp, because if an implicit destructor is used, |
| 569 // msvc 2015 tries to generate its destructor (because the class is dll-exported
class) | 586 // msvc 2015 tries to generate its destructor (because the class is dll-exported
class) |
| 570 // and causes a compile error because of lack of MultiColumnFragmentainerGroup::
operator=. | 587 // and causes a compile error because of lack of MultiColumnFragmentainerGroup::
operator=. |
| 571 // Since MultiColumnFragmentainerGroup is non-copyable, we cannot define the ope
rator=. | 588 // Since MultiColumnFragmentainerGroup is non-copyable, we cannot define the ope
rator=. |
| 572 MultiColumnFragmentainerGroupList::~MultiColumnFragmentainerGroupList() | 589 MultiColumnFragmentainerGroupList::~MultiColumnFragmentainerGroupList() |
| 573 { | 590 { |
| 574 } | 591 } |
| 575 | 592 |
| 576 MultiColumnFragmentainerGroup& MultiColumnFragmentainerGroupList::addExtraGroup(
) | 593 MultiColumnFragmentainerGroup& MultiColumnFragmentainerGroupList::addExtraGroup(
) |
| 577 { | 594 { |
| 578 append(MultiColumnFragmentainerGroup(m_columnSet)); | 595 append(MultiColumnFragmentainerGroup(m_columnSet)); |
| 579 return last(); | 596 return last(); |
| 580 } | 597 } |
| 581 | 598 |
| 582 void MultiColumnFragmentainerGroupList::deleteExtraGroups() | 599 void MultiColumnFragmentainerGroupList::deleteExtraGroups() |
| 583 { | 600 { |
| 584 shrink(1); | 601 shrink(1); |
| 585 } | 602 } |
| 586 | 603 |
| 587 } // namespace blink | 604 } // namespace blink |
| OLD | NEW |