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 |