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 |