OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. | 2 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above | 8 * 1. Redistributions of source code must retain the above |
9 * copyright notice, this list of conditions and the following | 9 * copyright notice, this list of conditions and the following |
10 * disclaimer. | 10 * disclaimer. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 LayoutObject* curr = const_cast<LayoutObject*>(&descendant); | 45 LayoutObject* curr = const_cast<LayoutObject*>(&descendant); |
46 while (curr) { | 46 while (curr) { |
47 if (curr->isSVG() && !curr->isSVGRoot()) | 47 if (curr->isSVG() && !curr->isSVGRoot()) |
48 return nullptr; | 48 return nullptr; |
49 if (curr->isLayoutFlowThread()) | 49 if (curr->isLayoutFlowThread()) |
50 return toLayoutFlowThread(curr); | 50 return toLayoutFlowThread(curr); |
51 LayoutObject* container = curr->container(); | 51 LayoutObject* container = curr->container(); |
52 curr = curr->parent(); | 52 curr = curr->parent(); |
53 while (curr != container) { | 53 while (curr != container) { |
54 if (curr->isLayoutFlowThread()) { | 54 if (curr->isLayoutFlowThread()) { |
55 // The nearest ancestor flow thread isn't in our containing block chain.
Then we | 55 // The nearest ancestor flow thread isn't in our containing block chain. |
56 // aren't really part of any flow thread, and we should stop looking. Th
is happens | 56 // Then we aren't really part of any flow thread, and we should stop |
57 // when there are out-of-flow objects or column spanners. | 57 // looking. This happens when there are out-of-flow objects or column |
| 58 // spanners. |
58 return nullptr; | 59 return nullptr; |
59 } | 60 } |
60 curr = curr->parent(); | 61 curr = curr->parent(); |
61 } | 62 } |
62 } | 63 } |
63 return nullptr; | 64 return nullptr; |
64 } | 65 } |
65 | 66 |
66 void LayoutFlowThread::removeColumnSetFromThread( | 67 void LayoutFlowThread::removeColumnSetFromThread( |
67 LayoutMultiColumnSet* columnSet) { | 68 LayoutMultiColumnSet* columnSet) { |
68 ASSERT(columnSet); | 69 ASSERT(columnSet); |
69 m_multiColumnSetList.remove(columnSet); | 70 m_multiColumnSetList.remove(columnSet); |
70 invalidateColumnSets(); | 71 invalidateColumnSets(); |
71 // Clear the interval tree right away, instead of leaving it around with dead
objects. Not that | 72 // Clear the interval tree right away, instead of leaving it around with dead |
72 // anyone _should_ try to access the interval tree when the column sets are ma
rked as invalid, | 73 // objects. Not that anyone _should_ try to access the interval tree when the |
73 // but this is actually possible if other parts of the engine has bugs that ca
use us to not lay | 74 // column sets are marked as invalid, but this is actually possible if other |
74 // out everything that was marked for layout, so that LayoutObject::assertLaid
Out() (and a LOT | 75 // parts of the engine has bugs that cause us to not lay out everything that |
| 76 // was marked for layout, so that LayoutObject::assertLaidOut() (and a LOT |
75 // of other assertions) fails. | 77 // of other assertions) fails. |
76 m_multiColumnSetIntervalTree.clear(); | 78 m_multiColumnSetIntervalTree.clear(); |
77 } | 79 } |
78 | 80 |
79 void LayoutFlowThread::invalidateColumnSets() { | 81 void LayoutFlowThread::invalidateColumnSets() { |
80 if (m_columnSetsInvalidated) { | 82 if (m_columnSetsInvalidated) { |
81 ASSERT(selfNeedsLayout()); | 83 ASSERT(selfNeedsLayout()); |
82 return; | 84 return; |
83 } | 85 } |
84 | 86 |
85 setNeedsLayoutAndFullPaintInvalidation( | 87 setNeedsLayoutAndFullPaintInvalidation( |
86 LayoutInvalidationReason::ColumnsChanged); | 88 LayoutInvalidationReason::ColumnsChanged); |
87 | 89 |
88 m_columnSetsInvalidated = true; | 90 m_columnSetsInvalidated = true; |
89 } | 91 } |
90 | 92 |
91 void LayoutFlowThread::validateColumnSets() { | 93 void LayoutFlowThread::validateColumnSets() { |
92 m_columnSetsInvalidated = false; | 94 m_columnSetsInvalidated = false; |
93 updateLogicalWidth(); // Called to get the maximum logical width for the colu
mnSet. | 95 // Called to get the maximum logical width for the columnSet. |
| 96 updateLogicalWidth(); |
94 generateColumnSetIntervalTree(); | 97 generateColumnSetIntervalTree(); |
95 } | 98 } |
96 | 99 |
97 bool LayoutFlowThread::mapToVisualRectInAncestorSpace( | 100 bool LayoutFlowThread::mapToVisualRectInAncestorSpace( |
98 const LayoutBoxModelObject* ancestor, | 101 const LayoutBoxModelObject* ancestor, |
99 LayoutRect& rect, | 102 LayoutRect& rect, |
100 VisualRectFlags visualRectFlags) const { | 103 VisualRectFlags visualRectFlags) const { |
101 ASSERT(ancestor != | 104 // A flow thread should never be an invalidation container. |
102 this); // A flow thread should never be an invalidation container. | 105 DCHECK(ancestor != this); |
103 rect = fragmentsBoundingBox(rect); | 106 rect = fragmentsBoundingBox(rect); |
104 return LayoutBlockFlow::mapToVisualRectInAncestorSpace(ancestor, rect, | 107 return LayoutBlockFlow::mapToVisualRectInAncestorSpace(ancestor, rect, |
105 visualRectFlags); | 108 visualRectFlags); |
106 } | 109 } |
107 | 110 |
108 void LayoutFlowThread::layout() { | 111 void LayoutFlowThread::layout() { |
109 m_pageLogicalSizeChanged = m_columnSetsInvalidated && everHadLayout(); | 112 m_pageLogicalSizeChanged = m_columnSetsInvalidated && everHadLayout(); |
110 LayoutBlockFlow::layout(); | 113 LayoutBlockFlow::layout(); |
111 m_pageLogicalSizeChanged = false; | 114 m_pageLogicalSizeChanged = false; |
112 } | 115 } |
(...skipping 16 matching lines...) Expand all Loading... |
129 void LayoutFlowThread::absoluteQuadsForDescendant(const LayoutBox& descendant, | 132 void LayoutFlowThread::absoluteQuadsForDescendant(const LayoutBox& descendant, |
130 Vector<FloatQuad>& quads) { | 133 Vector<FloatQuad>& quads) { |
131 LayoutPoint offsetFromFlowThread; | 134 LayoutPoint offsetFromFlowThread; |
132 for (const LayoutObject* object = &descendant; object != this;) { | 135 for (const LayoutObject* object = &descendant; object != this;) { |
133 const LayoutObject* container = object->container(); | 136 const LayoutObject* container = object->container(); |
134 offsetFromFlowThread += object->offsetFromContainer(container); | 137 offsetFromFlowThread += object->offsetFromContainer(container); |
135 object = container; | 138 object = container; |
136 } | 139 } |
137 LayoutRect boundingRectInFlowThread(offsetFromFlowThread, | 140 LayoutRect boundingRectInFlowThread(offsetFromFlowThread, |
138 descendant.frameRect().size()); | 141 descendant.frameRect().size()); |
139 // Set up a fragments relative to the descendant, in the flow thread coordinat
e space, and | 142 // Set up a fragments relative to the descendant, in the flow thread |
140 // convert each of them, individually, to absolute coordinates. | 143 // coordinate space, and convert each of them, individually, to absolute |
| 144 // coordinates. |
141 for (FragmentainerIterator iterator(*this, boundingRectInFlowThread); | 145 for (FragmentainerIterator iterator(*this, boundingRectInFlowThread); |
142 !iterator.atEnd(); iterator.advance()) { | 146 !iterator.atEnd(); iterator.advance()) { |
143 LayoutRect fragment = boundingRectInFlowThread; | 147 LayoutRect fragment = boundingRectInFlowThread; |
144 // We use inclusiveIntersect() because intersect() would reset the coordinat
es for | 148 // We use inclusiveIntersect() because intersect() would reset the |
145 // zero-height objects. | 149 // coordinates for zero-height objects. |
146 fragment.inclusiveIntersect(iterator.fragmentainerInFlowThread()); | 150 fragment.inclusiveIntersect(iterator.fragmentainerInFlowThread()); |
147 fragment.moveBy(-offsetFromFlowThread); | 151 fragment.moveBy(-offsetFromFlowThread); |
148 quads.append(descendant.localToAbsoluteQuad(FloatRect(fragment))); | 152 quads.append(descendant.localToAbsoluteQuad(FloatRect(fragment))); |
149 } | 153 } |
150 } | 154 } |
151 | 155 |
152 bool LayoutFlowThread::nodeAtPoint(HitTestResult& result, | 156 bool LayoutFlowThread::nodeAtPoint(HitTestResult& result, |
153 const HitTestLocation& locationInContainer, | 157 const HitTestLocation& locationInContainer, |
154 const LayoutPoint& accumulatedOffset, | 158 const LayoutPoint& accumulatedOffset, |
155 HitTestAction hitTestAction) { | 159 HitTestAction hitTestAction) { |
(...skipping 18 matching lines...) Expand all Loading... |
174 LayoutMultiColumnSet* columnSet = | 178 LayoutMultiColumnSet* columnSet = |
175 columnSetAtBlockOffset(offset, pageBoundaryRule); | 179 columnSetAtBlockOffset(offset, pageBoundaryRule); |
176 if (!columnSet) | 180 if (!columnSet) |
177 return LayoutUnit(); | 181 return LayoutUnit(); |
178 | 182 |
179 return columnSet->pageRemainingLogicalHeightForOffset(offset, | 183 return columnSet->pageRemainingLogicalHeightForOffset(offset, |
180 pageBoundaryRule); | 184 pageBoundaryRule); |
181 } | 185 } |
182 | 186 |
183 void LayoutFlowThread::generateColumnSetIntervalTree() { | 187 void LayoutFlowThread::generateColumnSetIntervalTree() { |
184 // FIXME: Optimize not to clear the interval all the time. This implies manual
ly managing the tree nodes lifecycle. | 188 // FIXME: Optimize not to clear the interval all the time. This implies |
| 189 // manually managing the tree nodes lifecycle. |
185 m_multiColumnSetIntervalTree.clear(); | 190 m_multiColumnSetIntervalTree.clear(); |
186 m_multiColumnSetIntervalTree.initIfNeeded(); | 191 m_multiColumnSetIntervalTree.initIfNeeded(); |
187 for (auto columnSet : m_multiColumnSetList) | 192 for (auto columnSet : m_multiColumnSetList) |
188 m_multiColumnSetIntervalTree.add(MultiColumnSetIntervalTree::createInterval( | 193 m_multiColumnSetIntervalTree.add(MultiColumnSetIntervalTree::createInterval( |
189 columnSet->logicalTopInFlowThread(), | 194 columnSet->logicalTopInFlowThread(), |
190 columnSet->logicalBottomInFlowThread(), columnSet)); | 195 columnSet->logicalBottomInFlowThread(), columnSet)); |
191 } | 196 } |
192 | 197 |
193 LayoutUnit LayoutFlowThread::nextLogicalTopForUnbreakableContent( | 198 LayoutUnit LayoutFlowThread::nextLogicalTopForUnbreakableContent( |
194 LayoutUnit flowThreadOffset, | 199 LayoutUnit flowThreadOffset, |
(...skipping 15 matching lines...) Expand all Loading... |
210 for (auto* columnSet : m_multiColumnSetList) | 215 for (auto* columnSet : m_multiColumnSetList) |
211 result.unite(columnSet->fragmentsBoundingBox(layerBoundingBox)); | 216 result.unite(columnSet->fragmentsBoundingBox(layerBoundingBox)); |
212 | 217 |
213 return result; | 218 return result; |
214 } | 219 } |
215 | 220 |
216 void LayoutFlowThread::flowThreadToContainingCoordinateSpace( | 221 void LayoutFlowThread::flowThreadToContainingCoordinateSpace( |
217 LayoutUnit& blockPosition, | 222 LayoutUnit& blockPosition, |
218 LayoutUnit& inlinePosition) const { | 223 LayoutUnit& inlinePosition) const { |
219 LayoutPoint position(inlinePosition, blockPosition); | 224 LayoutPoint position(inlinePosition, blockPosition); |
220 // First we have to make |position| physical, because that's what offsetLeft()
expects and returns. | 225 // First we have to make |position| physical, because that's what offsetLeft() |
| 226 // expects and returns. |
221 if (!isHorizontalWritingMode()) | 227 if (!isHorizontalWritingMode()) |
222 position = position.transposedPoint(); | 228 position = position.transposedPoint(); |
223 position = flipForWritingMode(position); | 229 position = flipForWritingMode(position); |
224 | 230 |
225 position.move(columnOffset(position)); | 231 position.move(columnOffset(position)); |
226 | 232 |
227 // Make |position| logical again, and read out the values. | 233 // Make |position| logical again, and read out the values. |
228 position = flipForWritingMode(position); | 234 position = flipForWritingMode(position); |
229 if (!isHorizontalWritingMode()) | 235 if (!isHorizontalWritingMode()) |
230 position = position.transposedPoint(); | 236 position = position.transposedPoint(); |
231 blockPosition = position.y(); | 237 blockPosition = position.y(); |
232 inlinePosition = position.x(); | 238 inlinePosition = position.x(); |
233 } | 239 } |
234 | 240 |
235 void LayoutFlowThread::MultiColumnSetSearchAdapter::collectIfNeeded( | 241 void LayoutFlowThread::MultiColumnSetSearchAdapter::collectIfNeeded( |
236 const MultiColumnSetInterval& interval) { | 242 const MultiColumnSetInterval& interval) { |
237 if (m_result) | 243 if (m_result) |
238 return; | 244 return; |
239 if (interval.low() <= m_offset && interval.high() > m_offset) | 245 if (interval.low() <= m_offset && interval.high() > m_offset) |
240 m_result = interval.data(); | 246 m_result = interval.data(); |
241 } | 247 } |
242 | 248 |
243 } // namespace blink | 249 } // namespace blink |
OLD | NEW |