OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "core/layout/FragmentainerIterator.h" |
| 6 |
| 7 #include "core/layout/LayoutMultiColumnSet.h" |
| 8 |
| 9 namespace blink { |
| 10 |
| 11 FragmentainerIterator::FragmentainerIterator(const LayoutFlowThread& flowThread,
const LayoutRect& physicalBoundingBoxInFlowThread, const LayoutRect& clipRectIn
MulticolContainer) |
| 12 : m_flowThread(flowThread) |
| 13 , m_clipRectInMulticolContainer(clipRectInMulticolContainer) |
| 14 , m_currentFragmentainerGroupIndex(0) |
| 15 { |
| 16 // Put the bounds into flow thread-local coordinates by flipping it first. T
his is how |
| 17 // rectangles typically are represented in layout, i.e. with the block direc
tion coordinate |
| 18 // flipped, if writing mode is vertical-rl. |
| 19 LayoutRect boundsInFlowThread = physicalBoundingBoxInFlowThread; |
| 20 m_flowThread.flipForWritingMode(boundsInFlowThread); |
| 21 |
| 22 if (m_flowThread.isHorizontalWritingMode()) { |
| 23 m_logicalTopInFlowThread = boundsInFlowThread.y(); |
| 24 m_logicalBottomInFlowThread = boundsInFlowThread.maxY(); |
| 25 } else { |
| 26 m_logicalTopInFlowThread = boundsInFlowThread.x(); |
| 27 m_logicalBottomInFlowThread = boundsInFlowThread.maxX(); |
| 28 } |
| 29 |
| 30 // Jump to the first interesting column set. |
| 31 m_currentColumnSet = flowThread.columnSetAtBlockOffset(m_logicalTopInFlowThr
ead); |
| 32 if (!m_currentColumnSet || m_currentColumnSet->logicalTopInFlowThread() >= m
_logicalBottomInFlowThread) { |
| 33 setAtEnd(); |
| 34 return; |
| 35 } |
| 36 // Then find the first interesting fragmentainer group. |
| 37 m_currentFragmentainerGroupIndex = m_currentColumnSet->fragmentainerGroupInd
exAtFlowThreadOffset(m_logicalTopInFlowThread); |
| 38 |
| 39 // Now find the first and last fragmentainer we're interested in. We'll also
clip against |
| 40 // the clip rect here. In case the clip rect doesn't intersect with any of t
he |
| 41 // fragmentainers, we have to move on to the next fragmentainer group, and s
ee if we find |
| 42 // something there. |
| 43 if (!setFragmentainersOfInterest()) { |
| 44 moveToNextFragmentainerGroup(); |
| 45 if (atEnd()) |
| 46 return; |
| 47 } |
| 48 |
| 49 updateOutput(); |
| 50 } |
| 51 |
| 52 void FragmentainerIterator::advance() |
| 53 { |
| 54 DCHECK(!atEnd()); |
| 55 |
| 56 if (m_currentFragmentainerIndex < m_endFragmentainerIndex) { |
| 57 m_currentFragmentainerIndex++; |
| 58 } else { |
| 59 // That was the last fragmentainer to visit in this fragmentainer group.
Advance to the |
| 60 // next group. |
| 61 moveToNextFragmentainerGroup(); |
| 62 if (atEnd()) |
| 63 return; |
| 64 } |
| 65 updateOutput(); |
| 66 } |
| 67 |
| 68 const MultiColumnFragmentainerGroup& FragmentainerIterator::currentGroup() const |
| 69 { |
| 70 DCHECK(!atEnd()); |
| 71 return m_currentColumnSet->fragmentainerGroups()[m_currentFragmentainerGroup
Index]; |
| 72 } |
| 73 |
| 74 void FragmentainerIterator::moveToNextFragmentainerGroup() |
| 75 { |
| 76 do { |
| 77 m_currentFragmentainerGroupIndex++; |
| 78 if (m_currentFragmentainerGroupIndex >= m_currentColumnSet->fragmentaine
rGroups().size()) { |
| 79 // That was the last fragmentainer group in this set. Advance to the
next set. |
| 80 m_currentColumnSet = m_currentColumnSet->nextSiblingMultiColumnSet()
; |
| 81 m_currentFragmentainerGroupIndex = 0; |
| 82 if (!m_currentColumnSet || m_currentColumnSet->logicalTopInFlowThrea
d() >= m_logicalBottomInFlowThread) { |
| 83 setAtEnd(); |
| 84 return; // No more sets or next set out of range. We're done. |
| 85 } |
| 86 } |
| 87 if (currentGroup().logicalTopInFlowThread() >= m_logicalBottomInFlowThre
ad) { |
| 88 setAtEnd(); // This fragmentainer group doesn't intersect with the r
ange we're interested in. We're done. |
| 89 return; |
| 90 } |
| 91 } while (!setFragmentainersOfInterest()); |
| 92 } |
| 93 |
| 94 bool FragmentainerIterator::setFragmentainersOfInterest() |
| 95 { |
| 96 const MultiColumnFragmentainerGroup& group = currentGroup(); |
| 97 |
| 98 // Figure out the start and end fragmentainers for the block range we're int
erested in. We |
| 99 // might not have to walk the entire fragmentainer group. |
| 100 group.columnIntervalForBlockRangeInFlowThread(m_logicalTopInFlowThread, m_lo
gicalBottomInFlowThread, m_currentFragmentainerIndex, m_endFragmentainerIndex); |
| 101 |
| 102 // Now intersect with the fragmentainers that actually intersect with the cl
ip rect, to narrow |
| 103 // it down even further. |
| 104 unsigned firstFragmentainerInClipRect, lastFragmentainerInClipRect; |
| 105 group.columnIntervalForVisualRect(m_clipRectInMulticolContainer, firstFragme
ntainerInClipRect, lastFragmentainerInClipRect); |
| 106 // If the two fragmentainer intervals are disjoint, there's nothing of inter
est in this |
| 107 // fragmentainer group. |
| 108 if (firstFragmentainerInClipRect > m_endFragmentainerIndex || lastFragmentai
nerInClipRect < m_currentFragmentainerIndex) |
| 109 return false; |
| 110 if (m_currentFragmentainerIndex < firstFragmentainerInClipRect) |
| 111 m_currentFragmentainerIndex = firstFragmentainerInClipRect; |
| 112 if (m_endFragmentainerIndex > lastFragmentainerInClipRect) |
| 113 m_endFragmentainerIndex = lastFragmentainerInClipRect; |
| 114 DCHECK(m_endFragmentainerIndex >= m_currentFragmentainerIndex); |
| 115 return true; |
| 116 } |
| 117 |
| 118 void FragmentainerIterator::updateOutput() |
| 119 { |
| 120 const MultiColumnFragmentainerGroup& group = currentGroup(); |
| 121 |
| 122 // Set the physical translation offset. |
| 123 LayoutUnit fragmentainerLogicalTopInFlowThread = group.logicalTopInFlowThrea
d() + m_currentFragmentainerIndex * group.logicalHeight(); |
| 124 m_paginationOffset = group.flowThreadTranslationAtOffset(fragmentainerLogica
lTopInFlowThread, CoordinateSpaceConversion::Visual); |
| 125 |
| 126 // Set the overflow clip rect that corresponds to the fragmentainer. |
| 127 m_clipRectInFlowThread = group.flowThreadPortionOverflowRectAt(m_currentFrag
mentainerIndex); |
| 128 |
| 129 // Flip it into a physical rectangle. |
| 130 m_flowThread.flipForWritingMode(m_clipRectInFlowThread); |
| 131 } |
| 132 |
| 133 } // namespace blink |
OLD | NEW |