| 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 |