| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "core/layout/FragmentainerIterator.h" | 5 #include "core/layout/FragmentainerIterator.h" |
| 6 | 6 |
| 7 #include "core/layout/LayoutMultiColumnSet.h" | 7 #include "core/layout/LayoutMultiColumnSet.h" |
| 8 | 8 |
| 9 namespace blink { | 9 namespace blink { |
| 10 | 10 |
| 11 FragmentainerIterator::FragmentainerIterator( | 11 FragmentainerIterator::FragmentainerIterator( |
| 12 const LayoutFlowThread& flowThread, | 12 const LayoutFlowThread& flowThread, |
| 13 const LayoutRect& physicalBoundingBoxInFlowThread, | 13 const LayoutRect& physicalBoundingBoxInFlowThread, |
| 14 const LayoutRect& clipRectInMulticolContainer) | 14 const LayoutRect& clipRectInMulticolContainer) |
| 15 : m_flowThread(flowThread), | 15 : m_flowThread(flowThread), |
| 16 m_clipRectInMulticolContainer(clipRectInMulticolContainer), | 16 m_clipRectInMulticolContainer(clipRectInMulticolContainer), |
| 17 m_currentFragmentainerGroupIndex(0) { | 17 m_currentFragmentainerGroupIndex(0) { |
| 18 // Put the bounds into flow thread-local coordinates by flipping it first. Thi
s is how | 18 // Put the bounds into flow thread-local coordinates by flipping it first. |
| 19 // rectangles typically are represented in layout, i.e. with the block directi
on coordinate | 19 // This is how rectangles typically are represented in layout, i.e. with the |
| 20 // flipped, if writing mode is vertical-rl. | 20 // block direction coordinate flipped, if writing mode is vertical-rl. |
| 21 LayoutRect boundsInFlowThread = physicalBoundingBoxInFlowThread; | 21 LayoutRect boundsInFlowThread = physicalBoundingBoxInFlowThread; |
| 22 m_flowThread.flipForWritingMode(boundsInFlowThread); | 22 m_flowThread.flipForWritingMode(boundsInFlowThread); |
| 23 | 23 |
| 24 if (m_flowThread.isHorizontalWritingMode()) { | 24 if (m_flowThread.isHorizontalWritingMode()) { |
| 25 m_logicalTopInFlowThread = boundsInFlowThread.y(); | 25 m_logicalTopInFlowThread = boundsInFlowThread.y(); |
| 26 m_logicalBottomInFlowThread = boundsInFlowThread.maxY(); | 26 m_logicalBottomInFlowThread = boundsInFlowThread.maxY(); |
| 27 } else { | 27 } else { |
| 28 m_logicalTopInFlowThread = boundsInFlowThread.x(); | 28 m_logicalTopInFlowThread = boundsInFlowThread.x(); |
| 29 m_logicalBottomInFlowThread = boundsInFlowThread.maxX(); | 29 m_logicalBottomInFlowThread = boundsInFlowThread.maxX(); |
| 30 } | 30 } |
| 31 | 31 |
| 32 // Jump to the first interesting column set. | 32 // Jump to the first interesting column set. |
| 33 m_currentColumnSet = flowThread.columnSetAtBlockOffset( | 33 m_currentColumnSet = flowThread.columnSetAtBlockOffset( |
| 34 m_logicalTopInFlowThread, LayoutBox::AssociateWithLatterPage); | 34 m_logicalTopInFlowThread, LayoutBox::AssociateWithLatterPage); |
| 35 if (!m_currentColumnSet || | 35 if (!m_currentColumnSet || |
| 36 m_currentColumnSet->logicalTopInFlowThread() >= | 36 m_currentColumnSet->logicalTopInFlowThread() >= |
| 37 m_logicalBottomInFlowThread) { | 37 m_logicalBottomInFlowThread) { |
| 38 setAtEnd(); | 38 setAtEnd(); |
| 39 return; | 39 return; |
| 40 } | 40 } |
| 41 // Then find the first interesting fragmentainer group. | 41 // Then find the first interesting fragmentainer group. |
| 42 m_currentFragmentainerGroupIndex = | 42 m_currentFragmentainerGroupIndex = |
| 43 m_currentColumnSet->fragmentainerGroupIndexAtFlowThreadOffset( | 43 m_currentColumnSet->fragmentainerGroupIndexAtFlowThreadOffset( |
| 44 m_logicalTopInFlowThread, LayoutBox::AssociateWithLatterPage); | 44 m_logicalTopInFlowThread, LayoutBox::AssociateWithLatterPage); |
| 45 | 45 |
| 46 // Now find the first and last fragmentainer we're interested in. We'll also c
lip against | 46 // Now find the first and last fragmentainer we're interested in. We'll also |
| 47 // the clip rect here. In case the clip rect doesn't intersect with any of the | 47 // clip against the clip rect here. In case the clip rect doesn't intersect |
| 48 // fragmentainers, we have to move on to the next fragmentainer group, and see
if we find | 48 // with any of the fragmentainers, we have to move on to the next |
| 49 // something there. | 49 // fragmentainer group, and see if we find something there. |
| 50 if (!setFragmentainersOfInterest()) { | 50 if (!setFragmentainersOfInterest()) { |
| 51 moveToNextFragmentainerGroup(); | 51 moveToNextFragmentainerGroup(); |
| 52 if (atEnd()) | 52 if (atEnd()) |
| 53 return; | 53 return; |
| 54 } | 54 } |
| 55 } | 55 } |
| 56 | 56 |
| 57 void FragmentainerIterator::advance() { | 57 void FragmentainerIterator::advance() { |
| 58 DCHECK(!atEnd()); | 58 DCHECK(!atEnd()); |
| 59 | 59 |
| 60 if (m_currentFragmentainerIndex < m_endFragmentainerIndex) { | 60 if (m_currentFragmentainerIndex < m_endFragmentainerIndex) { |
| 61 m_currentFragmentainerIndex++; | 61 m_currentFragmentainerIndex++; |
| 62 } else { | 62 } else { |
| 63 // That was the last fragmentainer to visit in this fragmentainer group. Adv
ance to the | 63 // That was the last fragmentainer to visit in this fragmentainer group. |
| 64 // next group. | 64 // Advance to the next group. |
| 65 moveToNextFragmentainerGroup(); | 65 moveToNextFragmentainerGroup(); |
| 66 if (atEnd()) | 66 if (atEnd()) |
| 67 return; | 67 return; |
| 68 } | 68 } |
| 69 } | 69 } |
| 70 | 70 |
| 71 LayoutSize FragmentainerIterator::paginationOffset() const { | 71 LayoutSize FragmentainerIterator::paginationOffset() const { |
| 72 DCHECK(!atEnd()); | 72 DCHECK(!atEnd()); |
| 73 const MultiColumnFragmentainerGroup& group = currentGroup(); | 73 const MultiColumnFragmentainerGroup& group = currentGroup(); |
| 74 LayoutUnit fragmentainerLogicalTopInFlowThread = | 74 LayoutUnit fragmentainerLogicalTopInFlowThread = |
| (...skipping 25 matching lines...) Expand all Loading... |
| 100 DCHECK(!atEnd()); | 100 DCHECK(!atEnd()); |
| 101 return m_currentColumnSet | 101 return m_currentColumnSet |
| 102 ->fragmentainerGroups()[m_currentFragmentainerGroupIndex]; | 102 ->fragmentainerGroups()[m_currentFragmentainerGroupIndex]; |
| 103 } | 103 } |
| 104 | 104 |
| 105 void FragmentainerIterator::moveToNextFragmentainerGroup() { | 105 void FragmentainerIterator::moveToNextFragmentainerGroup() { |
| 106 do { | 106 do { |
| 107 m_currentFragmentainerGroupIndex++; | 107 m_currentFragmentainerGroupIndex++; |
| 108 if (m_currentFragmentainerGroupIndex >= | 108 if (m_currentFragmentainerGroupIndex >= |
| 109 m_currentColumnSet->fragmentainerGroups().size()) { | 109 m_currentColumnSet->fragmentainerGroups().size()) { |
| 110 // That was the last fragmentainer group in this set. Advance to the next
set. | 110 // That was the last fragmentainer group in this set. Advance to the next. |
| 111 m_currentColumnSet = m_currentColumnSet->nextSiblingMultiColumnSet(); | 111 m_currentColumnSet = m_currentColumnSet->nextSiblingMultiColumnSet(); |
| 112 m_currentFragmentainerGroupIndex = 0; | 112 m_currentFragmentainerGroupIndex = 0; |
| 113 if (!m_currentColumnSet || | 113 if (!m_currentColumnSet || |
| 114 m_currentColumnSet->logicalTopInFlowThread() >= | 114 m_currentColumnSet->logicalTopInFlowThread() >= |
| 115 m_logicalBottomInFlowThread) { | 115 m_logicalBottomInFlowThread) { |
| 116 setAtEnd(); | 116 setAtEnd(); |
| 117 return; // No more sets or next set out of range. We're done. | 117 return; // No more sets or next set out of range. We're done. |
| 118 } | 118 } |
| 119 } | 119 } |
| 120 if (currentGroup().logicalTopInFlowThread() >= | 120 if (currentGroup().logicalTopInFlowThread() >= |
| 121 m_logicalBottomInFlowThread) { | 121 m_logicalBottomInFlowThread) { |
| 122 setAtEnd(); // This fragmentainer group doesn't intersect with the range
we're interested in. We're done. | 122 // This fragmentainer group doesn't intersect with the range we're |
| 123 // interested in. We're done. |
| 124 setAtEnd(); |
| 123 return; | 125 return; |
| 124 } | 126 } |
| 125 } while (!setFragmentainersOfInterest()); | 127 } while (!setFragmentainersOfInterest()); |
| 126 } | 128 } |
| 127 | 129 |
| 128 bool FragmentainerIterator::setFragmentainersOfInterest() { | 130 bool FragmentainerIterator::setFragmentainersOfInterest() { |
| 129 const MultiColumnFragmentainerGroup& group = currentGroup(); | 131 const MultiColumnFragmentainerGroup& group = currentGroup(); |
| 130 | 132 |
| 131 // Figure out the start and end fragmentainers for the block range we're inter
ested in. We | 133 // Figure out the start and end fragmentainers for the block range we're |
| 132 // might not have to walk the entire fragmentainer group. | 134 // interested in. We might not have to walk the entire fragmentainer group. |
| 133 group.columnIntervalForBlockRangeInFlowThread( | 135 group.columnIntervalForBlockRangeInFlowThread( |
| 134 m_logicalTopInFlowThread, m_logicalBottomInFlowThread, | 136 m_logicalTopInFlowThread, m_logicalBottomInFlowThread, |
| 135 m_currentFragmentainerIndex, m_endFragmentainerIndex); | 137 m_currentFragmentainerIndex, m_endFragmentainerIndex); |
| 136 | 138 |
| 137 if (hasClipRect()) { | 139 if (hasClipRect()) { |
| 138 // Now intersect with the fragmentainers that actually intersect with the vi
sual clip rect, to | 140 // Now intersect with the fragmentainers that actually intersect with the |
| 139 // narrow it down even further. The clip rect needs to be relative to the cu
rrent fragmentainer | 141 // visual clip rect, to narrow it down even further. The clip rect needs to |
| 140 // group. | 142 // be relative to the current fragmentainer group. |
| 141 LayoutRect clipRect = m_clipRectInMulticolContainer; | 143 LayoutRect clipRect = m_clipRectInMulticolContainer; |
| 142 LayoutSize offset = group.flowThreadTranslationAtOffset( | 144 LayoutSize offset = group.flowThreadTranslationAtOffset( |
| 143 group.logicalTopInFlowThread(), LayoutBox::AssociateWithFormerPage, | 145 group.logicalTopInFlowThread(), LayoutBox::AssociateWithFormerPage, |
| 144 CoordinateSpaceConversion::Visual); | 146 CoordinateSpaceConversion::Visual); |
| 145 clipRect.move(-offset); | 147 clipRect.move(-offset); |
| 146 unsigned firstFragmentainerInClipRect, lastFragmentainerInClipRect; | 148 unsigned firstFragmentainerInClipRect, lastFragmentainerInClipRect; |
| 147 group.columnIntervalForVisualRect(clipRect, firstFragmentainerInClipRect, | 149 group.columnIntervalForVisualRect(clipRect, firstFragmentainerInClipRect, |
| 148 lastFragmentainerInClipRect); | 150 lastFragmentainerInClipRect); |
| 149 // If the two fragmentainer intervals are disjoint, there's nothing of inter
est in this | 151 // If the two fragmentainer intervals are disjoint, there's nothing of |
| 150 // fragmentainer group. | 152 // interest in this fragmentainer group. |
| 151 if (firstFragmentainerInClipRect > m_endFragmentainerIndex || | 153 if (firstFragmentainerInClipRect > m_endFragmentainerIndex || |
| 152 lastFragmentainerInClipRect < m_currentFragmentainerIndex) | 154 lastFragmentainerInClipRect < m_currentFragmentainerIndex) |
| 153 return false; | 155 return false; |
| 154 if (m_currentFragmentainerIndex < firstFragmentainerInClipRect) | 156 if (m_currentFragmentainerIndex < firstFragmentainerInClipRect) |
| 155 m_currentFragmentainerIndex = firstFragmentainerInClipRect; | 157 m_currentFragmentainerIndex = firstFragmentainerInClipRect; |
| 156 if (m_endFragmentainerIndex > lastFragmentainerInClipRect) | 158 if (m_endFragmentainerIndex > lastFragmentainerInClipRect) |
| 157 m_endFragmentainerIndex = lastFragmentainerInClipRect; | 159 m_endFragmentainerIndex = lastFragmentainerInClipRect; |
| 158 } | 160 } |
| 159 DCHECK(m_endFragmentainerIndex >= m_currentFragmentainerIndex); | 161 DCHECK(m_endFragmentainerIndex >= m_currentFragmentainerIndex); |
| 160 return true; | 162 return true; |
| 161 } | 163 } |
| 162 | 164 |
| 163 } // namespace blink | 165 } // namespace blink |
| OLD | NEW |