OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2007 David Smith (catfish.man@gmail.com) | 4 * (C) 2007 David Smith (catfish.man@gmail.com) |
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
All rights reserved. | 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
All rights reserved. |
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 using namespace HTMLNames; | 79 using namespace HTMLNames; |
80 | 80 |
81 struct SameSizeAsLayoutBlock : public LayoutBox { | 81 struct SameSizeAsLayoutBlock : public LayoutBox { |
82 LayoutObjectChildList children; | 82 LayoutObjectChildList children; |
83 LineBoxList lineBoxes; | 83 LineBoxList lineBoxes; |
84 uint32_t bitfields; | 84 uint32_t bitfields; |
85 }; | 85 }; |
86 | 86 |
87 static_assert(sizeof(LayoutBlock) == sizeof(SameSizeAsLayoutBlock), "LayoutBlock
should stay small"); | 87 static_assert(sizeof(LayoutBlock) == sizeof(SameSizeAsLayoutBlock), "LayoutBlock
should stay small"); |
88 | 88 |
89 typedef WTF::HashMap<const LayoutBox*, OwnPtr<ColumnInfo>> ColumnInfoMap; | |
90 static ColumnInfoMap* gColumnInfoMap = 0; | |
91 | |
92 static TrackedDescendantsMap* gPositionedDescendantsMap = 0; | 89 static TrackedDescendantsMap* gPositionedDescendantsMap = 0; |
93 static TrackedDescendantsMap* gPercentHeightDescendantsMap = 0; | 90 static TrackedDescendantsMap* gPercentHeightDescendantsMap = 0; |
94 | 91 |
95 static TrackedContainerMap* gPositionedContainerMap = 0; | 92 static TrackedContainerMap* gPositionedContainerMap = 0; |
96 static TrackedContainerMap* gPercentHeightContainerMap = 0; | 93 static TrackedContainerMap* gPercentHeightContainerMap = 0; |
97 | 94 |
98 typedef WTF::HashSet<LayoutBlock*> DelayedUpdateScrollInfoSet; | 95 typedef WTF::HashSet<LayoutBlock*> DelayedUpdateScrollInfoSet; |
99 static int gDelayUpdateScrollInfo = 0; | 96 static int gDelayUpdateScrollInfo = 0; |
100 static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0; | 97 static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0; |
101 | 98 |
102 static bool gColumnFlowSplitEnabled = true; | |
103 | |
104 // This class helps dispatching the 'overflow' event on layout change. overflow
can be set on LayoutBoxes, yet the existing code | 99 // This class helps dispatching the 'overflow' event on layout change. overflow
can be set on LayoutBoxes, yet the existing code |
105 // only works on LayoutBlocks. If this changes, this class should be shared with
other LayoutBoxes. | 100 // only works on LayoutBlocks. If this changes, this class should be shared with
other LayoutBoxes. |
106 class OverflowEventDispatcher { | 101 class OverflowEventDispatcher { |
107 WTF_MAKE_NONCOPYABLE(OverflowEventDispatcher); | 102 WTF_MAKE_NONCOPYABLE(OverflowEventDispatcher); |
108 public: | 103 public: |
109 OverflowEventDispatcher(const LayoutBlock* block) | 104 OverflowEventDispatcher(const LayoutBlock* block) |
110 : m_block(block) | 105 : m_block(block) |
111 , m_hadHorizontalLayoutOverflow(false) | 106 , m_hadHorizontalLayoutOverflow(false) |
112 , m_hadVerticalLayoutOverflow(false) | 107 , m_hadVerticalLayoutOverflow(false) |
113 { | 108 { |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 appendImageIfNotNull(images, blockStyle.boxReflect()->mask().image()); | 197 appendImageIfNotNull(images, blockStyle.boxReflect()->mask().image()); |
203 appendImageIfNotNull(images, blockStyle.listStyleImage()); | 198 appendImageIfNotNull(images, blockStyle.listStyleImage()); |
204 appendImageIfNotNull(images, blockStyle.borderImageSource()); | 199 appendImageIfNotNull(images, blockStyle.borderImageSource()); |
205 appendImageIfNotNull(images, blockStyle.maskBoxImageSource()); | 200 appendImageIfNotNull(images, blockStyle.maskBoxImageSource()); |
206 if (blockStyle.shapeOutside()) | 201 if (blockStyle.shapeOutside()) |
207 appendImageIfNotNull(images, blockStyle.shapeOutside()->image()); | 202 appendImageIfNotNull(images, blockStyle.shapeOutside()->image()); |
208 } | 203 } |
209 | 204 |
210 void LayoutBlock::removeFromGlobalMaps() | 205 void LayoutBlock::removeFromGlobalMaps() |
211 { | 206 { |
212 if (hasColumns()) | |
213 gColumnInfoMap->take(this); | |
214 if (gPercentHeightDescendantsMap) | 207 if (gPercentHeightDescendantsMap) |
215 removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendant
sMap, gPercentHeightContainerMap); | 208 removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendant
sMap, gPercentHeightContainerMap); |
216 if (gPositionedDescendantsMap) | 209 if (gPositionedDescendantsMap) |
217 removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMa
p, gPositionedContainerMap); | 210 removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMa
p, gPositionedContainerMap); |
218 } | 211 } |
219 | 212 |
220 LayoutBlock::~LayoutBlock() | 213 LayoutBlock::~LayoutBlock() |
221 { | 214 { |
222 removeFromGlobalMaps(); | 215 removeFromGlobalMaps(); |
223 } | 216 } |
(...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
837 | 830 |
838 ASSERT(beforeChild->parent() == this); | 831 ASSERT(beforeChild->parent() == this); |
839 if (beforeChild->parent() != this) { | 832 if (beforeChild->parent() != this) { |
840 // We should never reach here. If we do, we need to use the | 833 // We should never reach here. If we do, we need to use the |
841 // safe fallback to use the topmost beforeChild container. | 834 // safe fallback to use the topmost beforeChild container. |
842 beforeChild = beforeChildContainer; | 835 beforeChild = beforeChildContainer; |
843 } | 836 } |
844 } | 837 } |
845 } | 838 } |
846 | 839 |
847 // Check for a spanning element in columns. | |
848 if (gColumnFlowSplitEnabled && !RuntimeEnabledFeatures::regionBasedColumnsEn
abled()) { | |
849 LayoutBlockFlow* columnsBlockAncestor = columnsBlockForSpanningElement(n
ewChild); | |
850 if (columnsBlockAncestor) { | |
851 TemporaryChange<bool> columnFlowSplitEnabled(gColumnFlowSplitEnabled
, false); | |
852 // We are placing a column-span element inside a block. | |
853 LayoutBlockFlow* newBox = createAnonymousColumnSpanBlock(); | |
854 | |
855 if (columnsBlockAncestor != this && !isLayoutFlowThread()) { | |
856 // We are nested inside a multi-column element and are being spl
it by the span. We have to break up | |
857 // our block into continuations. | |
858 LayoutBoxModelObject* oldContinuation = continuation(); | |
859 | |
860 // When we split an anonymous block, there's no need to do any c
ontinuation hookup, | |
861 // since we haven't actually split a real element. | |
862 if (!isAnonymousBlock()) | |
863 setContinuation(newBox); | |
864 | |
865 splitFlow(beforeChild, newBox, newChild, oldContinuation); | |
866 return; | |
867 } | |
868 | |
869 // We have to perform a split of this block's children. This involve
s creating an anonymous block box to hold | |
870 // the column-spanning |newChild|. We take all of the children from
before |newChild| and put them into | |
871 // one anonymous columns block, and all of the children after |newCh
ild| go into another anonymous block. | |
872 makeChildrenAnonymousColumnBlocks(beforeChild, newBox, newChild); | |
873 return; | |
874 } | |
875 } | |
876 | |
877 bool madeBoxesNonInline = false; | 840 bool madeBoxesNonInline = false; |
878 | 841 |
879 // A block has to either have all of its children inline, or all of its chil
dren as blocks. | 842 // A block has to either have all of its children inline, or all of its chil
dren as blocks. |
880 // So, if our children are currently inline and a block child has to be inse
rted, we move all our | 843 // So, if our children are currently inline and a block child has to be inse
rted, we move all our |
881 // inline children into anonymous block boxes. | 844 // inline children into anonymous block boxes. |
882 if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrOutO
fFlowPositioned()) { | 845 if (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrOutO
fFlowPositioned()) { |
883 // This is a block with inline content. Wrap the inline content in anony
mous blocks. | 846 // This is a block with inline content. Wrap the inline content in anony
mous blocks. |
884 makeChildrenNonInline(beforeChild); | 847 makeChildrenNonInline(beforeChild); |
885 madeBoxesNonInline = true; | 848 madeBoxesNonInline = true; |
886 | 849 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1146 | 1109 |
1147 void LayoutBlock::removeChild(LayoutObject* oldChild) | 1110 void LayoutBlock::removeChild(LayoutObject* oldChild) |
1148 { | 1111 { |
1149 // No need to waste time in merging or removing empty anonymous blocks. | 1112 // No need to waste time in merging or removing empty anonymous blocks. |
1150 // We can just bail out if our document is getting destroyed. | 1113 // We can just bail out if our document is getting destroyed. |
1151 if (documentBeingDestroyed()) { | 1114 if (documentBeingDestroyed()) { |
1152 LayoutBox::removeChild(oldChild); | 1115 LayoutBox::removeChild(oldChild); |
1153 return; | 1116 return; |
1154 } | 1117 } |
1155 | 1118 |
1156 // This protects against column split flows when anonymous blocks are gettin
g merged. | |
1157 TemporaryChange<bool> columnFlowSplitEnabled(gColumnFlowSplitEnabled, false)
; | |
1158 | |
1159 // If this child is a block, and if our previous and next siblings are | 1119 // If this child is a block, and if our previous and next siblings are |
1160 // both anonymous blocks with inline content, then we can go ahead and | 1120 // both anonymous blocks with inline content, then we can go ahead and |
1161 // fold the inline content back together. | 1121 // fold the inline content back together. |
1162 LayoutObject* prev = oldChild->previousSibling(); | 1122 LayoutObject* prev = oldChild->previousSibling(); |
1163 LayoutObject* next = oldChild->nextSibling(); | 1123 LayoutObject* next = oldChild->nextSibling(); |
1164 bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, p
rev, next); | 1124 bool canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, p
rev, next); |
1165 if (canMergeAnonymousBlocks && prev && next) { | 1125 if (canMergeAnonymousBlocks && prev && next) { |
1166 prev->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutIn
validationReason::AnonymousBlockChange); | 1126 prev->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutIn
validationReason::AnonymousBlockChange); |
1167 LayoutBlockFlow* nextBlock = toLayoutBlockFlow(next); | 1127 LayoutBlockFlow* nextBlock = toLayoutBlockFlow(next); |
1168 LayoutBlockFlow* prevBlock = toLayoutBlockFlow(prev); | 1128 LayoutBlockFlow* prevBlock = toLayoutBlockFlow(prev); |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1425 // If we use border-box sizing, have percentage padding, and our parent has
changed width then the width available to our children has changed even | 1385 // If we use border-box sizing, have percentage padding, and our parent has
changed width then the width available to our children has changed even |
1426 // though our own width has remained the same. | 1386 // though our own width has remained the same. |
1427 widthAvailableToChildrenHasChanged |= style()->boxSizing() == BORDER_BOX &&
needsPreferredWidthsRecalculation() && view()->layoutState()->containingBlockLog
icalWidthChanged(); | 1387 widthAvailableToChildrenHasChanged |= style()->boxSizing() == BORDER_BOX &&
needsPreferredWidthsRecalculation() && view()->layoutState()->containingBlockLog
icalWidthChanged(); |
1428 | 1388 |
1429 return widthAvailableToChildrenHasChanged; | 1389 return widthAvailableToChildrenHasChanged; |
1430 } | 1390 } |
1431 | 1391 |
1432 bool LayoutBlock::updateLogicalWidthAndColumnWidth() | 1392 bool LayoutBlock::updateLogicalWidthAndColumnWidth() |
1433 { | 1393 { |
1434 LayoutUnit oldWidth = logicalWidth(); | 1394 LayoutUnit oldWidth = logicalWidth(); |
1435 LayoutUnit oldColumnWidth = desiredColumnWidth(); | |
1436 | |
1437 updateLogicalWidth(); | 1395 updateLogicalWidth(); |
1438 calcColumnWidth(); | 1396 return oldWidth != logicalWidth() || widthAvailableToChildrenHasChanged(); |
1439 | |
1440 return oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth()
|| widthAvailableToChildrenHasChanged(); | |
1441 } | 1397 } |
1442 | 1398 |
1443 void LayoutBlock::layoutBlock(bool) | 1399 void LayoutBlock::layoutBlock(bool) |
1444 { | 1400 { |
1445 ASSERT_NOT_REACHED(); | 1401 ASSERT_NOT_REACHED(); |
1446 clearNeedsLayout(); | 1402 clearNeedsLayout(); |
1447 } | 1403 } |
1448 | 1404 |
1449 void LayoutBlock::addOverflowFromChildren() | 1405 void LayoutBlock::addOverflowFromChildren() |
1450 { | 1406 { |
1451 if (!hasColumns()) { | 1407 if (childrenInline()) |
1452 if (childrenInline()) | 1408 toLayoutBlockFlow(this)->addOverflowFromInlineChildren(); |
1453 toLayoutBlockFlow(this)->addOverflowFromInlineChildren(); | 1409 else |
1454 else | 1410 addOverflowFromBlockChildren(); |
1455 addOverflowFromBlockChildren(); | |
1456 } else { | |
1457 ColumnInfo* colInfo = columnInfo(); | |
1458 if (columnCount(colInfo)) { | |
1459 LayoutRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1
); | |
1460 addLayoutOverflow(lastRect); | |
1461 addContentsVisualOverflow(lastRect); | |
1462 } | |
1463 } | |
1464 } | 1411 } |
1465 | 1412 |
1466 void LayoutBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool) | 1413 void LayoutBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool) |
1467 { | 1414 { |
1468 m_overflow.clear(); | 1415 m_overflow.clear(); |
1469 | 1416 |
1470 // Add overflow from children. | 1417 // Add overflow from children. |
1471 addOverflowFromChildren(); | 1418 addOverflowFromChildren(); |
1472 | 1419 |
1473 // Add in the overflow from positioned objects. | 1420 // Add in the overflow from positioned objects. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1521 | 1468 |
1522 IntRect inflatedRect = pixelSnappedBorderBoxRect(); | 1469 IntRect inflatedRect = pixelSnappedBorderBoxRect(); |
1523 LayoutTheme::theme().adjustPaintInvalidationRect(this, inflatedRect); | 1470 LayoutTheme::theme().adjustPaintInvalidationRect(this, inflatedRect); |
1524 addVisualOverflow(LayoutRect(inflatedRect)); | 1471 addVisualOverflow(LayoutRect(inflatedRect)); |
1525 } | 1472 } |
1526 | 1473 |
1527 bool LayoutBlock::createsNewFormattingContext() const | 1474 bool LayoutBlock::createsNewFormattingContext() const |
1528 { | 1475 { |
1529 return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() ||
hasOverflowClip() || isFlexItemIncludingDeprecated() | 1476 return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() ||
hasOverflowClip() || isFlexItemIncludingDeprecated() |
1530 || style()->specifiesColumns() || isLayoutFlowThread() || isTableCell()
|| isTableCaption() || isFieldset() || isWritingModeRoot() | 1477 || style()->specifiesColumns() || isLayoutFlowThread() || isTableCell()
|| isTableCaption() || isFieldset() || isWritingModeRoot() |
1531 || isDocumentElement() || (RuntimeEnabledFeatures::regionBasedColumnsEna
bled() ? isColumnSpanAll() : style()->columnSpan()) || isGridItem(); | 1478 || isDocumentElement() || isColumnSpanAll() || isGridItem(); |
1532 } | 1479 } |
1533 | 1480 |
1534 void LayoutBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, L
ayoutBox& child) | 1481 void LayoutBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, L
ayoutBox& child) |
1535 { | 1482 { |
1536 // FIXME: Technically percentage height objects only need a relayout if thei
r percentage isn't going to be turned into | 1483 // FIXME: Technically percentage height objects only need a relayout if thei
r percentage isn't going to be turned into |
1537 // an auto value. Add a method to determine this, so that we can avoid the r
elayout. | 1484 // an auto value. Add a method to determine this, so that we can avoid the r
elayout. |
1538 bool hasRelativeLogicalHeight = child.hasRelativeLogicalHeight() | 1485 bool hasRelativeLogicalHeight = child.hasRelativeLogicalHeight() |
1539 || (child.isAnonymous() && this->hasRelativeLogicalHeight()) | 1486 || (child.isAnonymous() && this->hasRelativeLogicalHeight()) |
1540 || child.stretchesToViewport(); | 1487 || child.stretchesToViewport(); |
1541 if (relayoutChildren || (hasRelativeLogicalHeight && !isLayoutView())) | 1488 if (relayoutChildren || (hasRelativeLogicalHeight && !isLayoutView())) |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1697 bool isHorizontal = style->isHorizontalWritingMode(); | 1644 bool isHorizontal = style->isHorizontalWritingMode(); |
1698 return style->isDisplayInlineType() ? style->hasStaticInlinePosition(isHoriz
ontal) : style->hasStaticBlockPosition(isHorizontal); | 1645 return style->isDisplayInlineType() ? style->hasStaticInlinePosition(isHoriz
ontal) : style->hasStaticBlockPosition(isHorizontal); |
1699 } | 1646 } |
1700 | 1647 |
1701 void LayoutBlock::layoutPositionedObjects(bool relayoutChildren, PositionedLayou
tBehavior info) | 1648 void LayoutBlock::layoutPositionedObjects(bool relayoutChildren, PositionedLayou
tBehavior info) |
1702 { | 1649 { |
1703 TrackedLayoutBoxListHashSet* positionedDescendants = positionedObjects(); | 1650 TrackedLayoutBoxListHashSet* positionedDescendants = positionedObjects(); |
1704 if (!positionedDescendants) | 1651 if (!positionedDescendants) |
1705 return; | 1652 return; |
1706 | 1653 |
1707 if (hasColumns()) | |
1708 view()->layoutState()->clearPaginationInformation(); // Positioned objec
ts are not part of the column flow, so they don't paginate with the columns. | |
1709 | |
1710 for (auto* positionedObject : *positionedDescendants) { | 1654 for (auto* positionedObject : *positionedDescendants) { |
1711 positionedObject->setMayNeedPaintInvalidation(); | 1655 positionedObject->setMayNeedPaintInvalidation(); |
1712 | 1656 |
1713 SubtreeLayoutScope layoutScope(*positionedObject); | 1657 SubtreeLayoutScope layoutScope(*positionedObject); |
1714 // A fixed position element with an absolute positioned ancestor has no
way of knowing if the latter has changed position. So | 1658 // A fixed position element with an absolute positioned ancestor has no
way of knowing if the latter has changed position. So |
1715 // if this is a fixed position element, mark it for layout if it has an
abspos ancestor and needs to move with that ancestor, i.e. | 1659 // if this is a fixed position element, mark it for layout if it has an
abspos ancestor and needs to move with that ancestor, i.e. |
1716 // it has static position. | 1660 // it has static position. |
1717 markFixedPositionObjectForLayoutIfNeeded(positionedObject, layoutScope); | 1661 markFixedPositionObjectForLayoutIfNeeded(positionedObject, layoutScope); |
1718 if (info == LayoutOnlyFixedPositionedObjects) { | 1662 if (info == LayoutOnlyFixedPositionedObjects) { |
1719 positionedObject->layoutIfNeeded(); | 1663 positionedObject->layoutIfNeeded(); |
(...skipping 26 matching lines...) Expand all Loading... |
1746 // to investigate why it does not trigger the correct invalidations in t
hat case. crbug.com/350756 | 1690 // to investigate why it does not trigger the correct invalidations in t
hat case. crbug.com/350756 |
1747 if (info == ForcedLayoutAfterContainingBlockMoved) | 1691 if (info == ForcedLayoutAfterContainingBlockMoved) |
1748 positionedObject->setNeedsLayout(LayoutInvalidationReason::AncestorM
oved, MarkOnlyThis); | 1692 positionedObject->setNeedsLayout(LayoutInvalidationReason::AncestorM
oved, MarkOnlyThis); |
1749 | 1693 |
1750 positionedObject->layoutIfNeeded(); | 1694 positionedObject->layoutIfNeeded(); |
1751 | 1695 |
1752 // Lay out again if our estimate was wrong. | 1696 // Lay out again if our estimate was wrong. |
1753 if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(*po
sitionedObject) != oldLogicalTop) | 1697 if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(*po
sitionedObject) != oldLogicalTop) |
1754 positionedObject->forceChildLayout(); | 1698 positionedObject->forceChildLayout(); |
1755 } | 1699 } |
1756 | |
1757 if (hasColumns()) | |
1758 view()->layoutState()->setColumnInfo(columnInfo()); // FIXME: Kind of gr
oss. We just put this back into the layout state so that pop() will work. | |
1759 } | 1700 } |
1760 | 1701 |
1761 void LayoutBlock::markPositionedObjectsForLayout() | 1702 void LayoutBlock::markPositionedObjectsForLayout() |
1762 { | 1703 { |
1763 if (TrackedLayoutBoxListHashSet* positionedDescendants = positionedObjects()
) { | 1704 if (TrackedLayoutBoxListHashSet* positionedDescendants = positionedObjects()
) { |
1764 for (auto* descendant : *positionedDescendants) | 1705 for (auto* descendant : *positionedDescendants) |
1765 descendant->setChildNeedsLayout(); | 1706 descendant->setChildNeedsLayout(); |
1766 } | 1707 } |
1767 } | 1708 } |
1768 | 1709 |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2213 else | 2154 else |
2214 checkChildren = locationInContainer.intersects(clipRect); | 2155 checkChildren = locationInContainer.intersects(clipRect); |
2215 } | 2156 } |
2216 } | 2157 } |
2217 if (checkChildren) { | 2158 if (checkChildren) { |
2218 // Hit test descendants first. | 2159 // Hit test descendants first. |
2219 LayoutSize scrolledOffset(localOffset); | 2160 LayoutSize scrolledOffset(localOffset); |
2220 if (hasOverflowClip()) | 2161 if (hasOverflowClip()) |
2221 scrolledOffset -= scrolledContentOffset(); | 2162 scrolledOffset -= scrolledContentOffset(); |
2222 | 2163 |
2223 // Hit test contents if we don't have columns. | 2164 // Hit test contents |
2224 if (!hasColumns()) { | 2165 if (hitTestContents(result, locationInContainer, toLayoutPoint(scrolledO
ffset), hitTestAction)) { |
2225 if (hitTestContents(result, locationInContainer, toLayoutPoint(scrol
ledOffset), hitTestAction)) { | |
2226 updateHitTestResult(result, flipForWritingMode(locationInContain
er.point() - localOffset)); | |
2227 return true; | |
2228 } | |
2229 if (hitTestAction == HitTestFloat && hitTestFloats(result, locationI
nContainer, toLayoutPoint(scrolledOffset))) | |
2230 return true; | |
2231 } else if (hitTestColumns(result, locationInContainer, toLayoutPoint(scr
olledOffset), hitTestAction)) { | |
2232 updateHitTestResult(result, flipForWritingMode(locationInContainer.p
oint() - localOffset)); | 2166 updateHitTestResult(result, flipForWritingMode(locationInContainer.p
oint() - localOffset)); |
2233 return true; | 2167 return true; |
2234 } | 2168 } |
| 2169 if (hitTestAction == HitTestFloat && hitTestFloats(result, locationInCon
tainer, toLayoutPoint(scrolledOffset))) |
| 2170 return true; |
2235 } | 2171 } |
2236 | 2172 |
2237 // Check if the point is outside radii. | 2173 // Check if the point is outside radii. |
2238 if (style()->hasBorderRadius()) { | 2174 if (style()->hasBorderRadius()) { |
2239 LayoutRect borderRect = borderBoxRect(); | 2175 LayoutRect borderRect = borderBoxRect(); |
2240 borderRect.moveBy(adjustedLocation); | 2176 borderRect.moveBy(adjustedLocation); |
2241 FloatRoundedRect border = style()->getRoundedBorderFor(borderRect); | 2177 FloatRoundedRect border = style()->getRoundedBorderFor(borderRect); |
2242 if (!locationInContainer.intersects(border)) | 2178 if (!locationInContainer.intersects(border)) |
2243 return false; | 2179 return false; |
2244 } | 2180 } |
2245 | 2181 |
2246 // Now hit test our background | 2182 // Now hit test our background |
2247 if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChild
BlockBackground) { | 2183 if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChild
BlockBackground) { |
2248 LayoutRect boundsRect(adjustedLocation, size()); | 2184 LayoutRect boundsRect(adjustedLocation, size()); |
2249 if (visibleToHitTestRequest(result.hitTestRequest()) && locationInContai
ner.intersects(boundsRect)) { | 2185 if (visibleToHitTestRequest(result.hitTestRequest()) && locationInContai
ner.intersects(boundsRect)) { |
2250 updateHitTestResult(result, flipForWritingMode(locationInContainer.p
oint() - localOffset)); | 2186 updateHitTestResult(result, flipForWritingMode(locationInContainer.p
oint() - localOffset)); |
2251 if (!result.addNodeToListBasedTestResult(nodeForHitTest(), locationI
nContainer, boundsRect)) | 2187 if (!result.addNodeToListBasedTestResult(nodeForHitTest(), locationI
nContainer, boundsRect)) |
2252 return true; | 2188 return true; |
2253 } | 2189 } |
2254 } | 2190 } |
2255 | 2191 |
2256 return false; | 2192 return false; |
2257 } | 2193 } |
2258 | 2194 |
2259 class ColumnRectIterator { | |
2260 WTF_MAKE_NONCOPYABLE(ColumnRectIterator); | |
2261 public: | |
2262 ColumnRectIterator(const LayoutBlock& block) | |
2263 : m_block(block) | |
2264 , m_colInfo(block.columnInfo()) | |
2265 , m_direction(m_block.style()->isFlippedBlocksWritingMode() ? 1 : -1) | |
2266 , m_isHorizontal(block.isHorizontalWritingMode()) | |
2267 , m_logicalLeft(block.logicalLeftOffsetForContent()) | |
2268 { | |
2269 int colCount = m_colInfo->columnCount(); | |
2270 m_colIndex = colCount - 1; | |
2271 m_currLogicalTopOffset = colCount * m_colInfo->columnHeight() * m_direct
ion; | |
2272 update(); | |
2273 } | |
2274 | |
2275 void advance() | |
2276 { | |
2277 ASSERT(hasMore()); | |
2278 m_colIndex--; | |
2279 update(); | |
2280 } | |
2281 | |
2282 LayoutRect columnRect() const { return m_colRect; } | |
2283 bool hasMore() const { return m_colIndex >= 0; } | |
2284 | |
2285 void adjust(LayoutSize& offset) const | |
2286 { | |
2287 LayoutUnit currLogicalLeftOffset = (m_isHorizontal ? m_colRect.x() : m_c
olRect.y()) - m_logicalLeft; | |
2288 offset += m_isHorizontal ? LayoutSize(currLogicalLeftOffset, m_currLogic
alTopOffset) : LayoutSize(m_currLogicalTopOffset, currLogicalLeftOffset); | |
2289 if (m_colInfo->progressionAxis() == ColumnInfo::BlockAxis) { | |
2290 if (m_isHorizontal) | |
2291 offset.expand(0, m_colRect.y() - m_block.borderTop() - m_block.p
addingTop()); | |
2292 else | |
2293 offset.expand(m_colRect.x() - m_block.borderLeft() - m_block.pad
dingLeft(), 0); | |
2294 } | |
2295 } | |
2296 | |
2297 private: | |
2298 void update() | |
2299 { | |
2300 if (m_colIndex < 0) | |
2301 return; | |
2302 | |
2303 m_colRect = m_block.columnRectAt(const_cast<ColumnInfo*>(m_colInfo), m_c
olIndex); | |
2304 m_block.flipForWritingMode(m_colRect); | |
2305 m_currLogicalTopOffset -= (m_isHorizontal ? m_colRect.height() : m_colRe
ct.width()) * m_direction; | |
2306 } | |
2307 | |
2308 const LayoutBlock& m_block; | |
2309 const ColumnInfo* const m_colInfo; | |
2310 const int m_direction; | |
2311 const bool m_isHorizontal; | |
2312 const LayoutUnit m_logicalLeft; | |
2313 int m_colIndex; | |
2314 LayoutUnit m_currLogicalTopOffset; | |
2315 LayoutRect m_colRect; | |
2316 }; | |
2317 | |
2318 bool LayoutBlock::hitTestColumns(HitTestResult& result, const HitTestLocation& l
ocationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestA
ction) | |
2319 { | |
2320 // We need to do multiple passes, breaking up our hit testing into strips. | |
2321 if (!hasColumns()) | |
2322 return false; | |
2323 | |
2324 for (ColumnRectIterator it(*this); it.hasMore(); it.advance()) { | |
2325 LayoutRect hitRect = LayoutRect(locationInContainer.boundingBox()); | |
2326 LayoutRect colRect = it.columnRect(); | |
2327 colRect.moveBy(accumulatedOffset); | |
2328 if (locationInContainer.intersects(colRect)) { | |
2329 // The point is inside this column. | |
2330 // Adjust accumulatedOffset to change where we hit test. | |
2331 LayoutSize offset; | |
2332 it.adjust(offset); | |
2333 LayoutPoint finalLocation = accumulatedOffset + offset; | |
2334 if (!result.isRectBasedTest() || colRect.contains(hitRect)) | |
2335 return hitTestContents(result, locationInContainer, finalLocatio
n, hitTestAction) || (hitTestAction == HitTestFloat && hitTestFloats(result, loc
ationInContainer, finalLocation)); | |
2336 | |
2337 hitTestContents(result, locationInContainer, finalLocation, hitTestA
ction); | |
2338 } | |
2339 } | |
2340 | |
2341 return false; | |
2342 } | |
2343 | |
2344 void LayoutBlock::adjustForColumnRect(LayoutSize& offset, const LayoutPoint& loc
ationInContainer) const | |
2345 { | |
2346 for (ColumnRectIterator it(*this); it.hasMore(); it.advance()) { | |
2347 LayoutRect colRect = it.columnRect(); | |
2348 if (colRect.contains(locationInContainer)) { | |
2349 it.adjust(offset); | |
2350 return; | |
2351 } | |
2352 } | |
2353 } | |
2354 | |
2355 bool LayoutBlock::hitTestContents(HitTestResult& result, const HitTestLocation&
locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTest
Action) | 2195 bool LayoutBlock::hitTestContents(HitTestResult& result, const HitTestLocation&
locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTest
Action) |
2356 { | 2196 { |
2357 if (childrenInline() && !isTable()) { | 2197 if (childrenInline() && !isTable()) { |
2358 // We have to hit-test our line boxes. | 2198 // We have to hit-test our line boxes. |
2359 if (m_lineBoxes.hitTest(this, result, locationInContainer, accumulatedOf
fset, hitTestAction)) | 2199 if (m_lineBoxes.hitTest(this, result, locationInContainer, accumulatedOf
fset, hitTestAction)) |
2360 return true; | 2200 return true; |
2361 } else { | 2201 } else { |
2362 // Hit test our children. | 2202 // Hit test our children. |
2363 HitTestAction childHitTest = hitTestAction; | 2203 HitTestAction childHitTest = hitTestAction; |
2364 if (hitTestAction == HitTestChildBlockBackgrounds) | 2204 if (hitTestAction == HitTestChildBlockBackgrounds) |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2578 return LayoutBox::positionForPoint(point); | 2418 return LayoutBox::positionForPoint(point); |
2579 } | 2419 } |
2580 | 2420 |
2581 void LayoutBlock::offsetForContents(LayoutPoint& offset) const | 2421 void LayoutBlock::offsetForContents(LayoutPoint& offset) const |
2582 { | 2422 { |
2583 offset = flipForWritingMode(offset); | 2423 offset = flipForWritingMode(offset); |
2584 | 2424 |
2585 if (hasOverflowClip()) | 2425 if (hasOverflowClip()) |
2586 offset += LayoutSize(scrolledContentOffset()); | 2426 offset += LayoutSize(scrolledContentOffset()); |
2587 | 2427 |
2588 if (hasColumns()) | |
2589 adjustPointToColumnContents(offset); | |
2590 | |
2591 offset = flipForWritingMode(offset); | 2428 offset = flipForWritingMode(offset); |
2592 } | 2429 } |
2593 | 2430 |
2594 LayoutUnit LayoutBlock::availableLogicalWidth() const | |
2595 { | |
2596 // If we have multiple columns, then the available logical width is reduced
to our column width. | |
2597 if (hasColumns()) | |
2598 return desiredColumnWidth(); | |
2599 return LayoutBox::availableLogicalWidth(); | |
2600 } | |
2601 | |
2602 int LayoutBlock::columnGap() const | 2431 int LayoutBlock::columnGap() const |
2603 { | 2432 { |
2604 if (style()->hasNormalColumnGap()) | 2433 if (style()->hasNormalColumnGap()) |
2605 return style()->fontDescription().computedPixelSize(); // "1em" is recom
mended as the normal gap setting. Matches <p> margins. | 2434 return style()->fontDescription().computedPixelSize(); // "1em" is recom
mended as the normal gap setting. Matches <p> margins. |
2606 return static_cast<int>(style()->columnGap()); | 2435 return static_cast<int>(style()->columnGap()); |
2607 } | 2436 } |
2608 | 2437 |
2609 void LayoutBlock::calcColumnWidth() | |
2610 { | |
2611 if (RuntimeEnabledFeatures::regionBasedColumnsEnabled()) | |
2612 return; | |
2613 | |
2614 // Calculate our column width and column count. | |
2615 // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibli
ng4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744 | |
2616 unsigned desiredColumnCount = 1; | |
2617 LayoutUnit desiredColumnWidth = contentLogicalWidth(); | |
2618 | |
2619 // For now, we don't support multi-column layouts when printing, since we ha
ve to do a lot of work for proper pagination. | |
2620 if (document().paginated() || !style()->specifiesColumns()) { | |
2621 setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth); | |
2622 return; | |
2623 } | |
2624 | |
2625 LayoutUnit availWidth = desiredColumnWidth; | |
2626 LayoutUnit colGap = columnGap(); | |
2627 LayoutUnit colWidth = std::max<LayoutUnit>(1, LayoutUnit(style()->columnWidt
h())); | |
2628 int colCount = std::max<int>(1, style()->columnCount()); | |
2629 | |
2630 if (style()->hasAutoColumnWidth() && !style()->hasAutoColumnCount()) { | |
2631 desiredColumnCount = colCount; | |
2632 desiredColumnWidth = std::max<LayoutUnit>(0, (availWidth - ((desiredColu
mnCount - 1) * colGap)) / desiredColumnCount); | |
2633 } else if (!style()->hasAutoColumnWidth() && style()->hasAutoColumnCount())
{ | |
2634 desiredColumnCount = std::max<LayoutUnit>(1, (availWidth + colGap) / (co
lWidth + colGap)); | |
2635 desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colG
ap; | |
2636 } else { | |
2637 desiredColumnCount = std::max<LayoutUnit>(std::min<LayoutUnit>(colCount,
(availWidth + colGap) / (colWidth + colGap)), 1); | |
2638 desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colG
ap; | |
2639 } | |
2640 setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth); | |
2641 } | |
2642 | |
2643 bool LayoutBlock::requiresColumns(int desiredColumnCount) const | |
2644 { | |
2645 // Paged overflow is treated as multicol here, unless this element was the o
ne that got its | |
2646 // overflow propagated to the viewport. | |
2647 bool isPaginated = style()->isOverflowPaged() && node() != document().viewpo
rtDefiningElement(); | |
2648 | |
2649 return firstChild() | |
2650 && (desiredColumnCount != 1 || !style()->hasAutoColumnWidth() || isPagin
ated) | |
2651 && !firstChild()->isAnonymousColumnsBlock() | |
2652 && !firstChild()->isAnonymousColumnSpanBlock() && !isFlexibleBoxIncludin
gDeprecated(); | |
2653 } | |
2654 | |
2655 void LayoutBlock::setDesiredColumnCountAndWidth(int count, LayoutUnit width) | |
2656 { | |
2657 bool destroyColumns = !requiresColumns(count); | |
2658 if (destroyColumns) { | |
2659 if (hasColumns()) { | |
2660 gColumnInfoMap->take(this); | |
2661 setHasColumns(false); | |
2662 } | |
2663 } else { | |
2664 ColumnInfo* info; | |
2665 if (hasColumns()) { | |
2666 info = gColumnInfoMap->get(this); | |
2667 } else { | |
2668 if (!gColumnInfoMap) | |
2669 gColumnInfoMap = new ColumnInfoMap; | |
2670 info = new ColumnInfo; | |
2671 gColumnInfoMap->add(this, adoptPtr(info)); | |
2672 setHasColumns(true); | |
2673 } | |
2674 info->setDesiredColumnWidth(width); | |
2675 if (style()->isOverflowPaged()) { | |
2676 info->setDesiredColumnCount(1); | |
2677 info->setProgressionAxis(style()->hasInlinePaginationAxis() ? Column
Info::InlineAxis : ColumnInfo::BlockAxis); | |
2678 } else { | |
2679 info->setDesiredColumnCount(count); | |
2680 info->setProgressionAxis(ColumnInfo::InlineAxis); | |
2681 } | |
2682 } | |
2683 } | |
2684 | |
2685 LayoutUnit LayoutBlock::desiredColumnWidth() const | |
2686 { | |
2687 if (!hasColumns()) | |
2688 return contentLogicalWidth(); | |
2689 return gColumnInfoMap->get(this)->desiredColumnWidth(); | |
2690 } | |
2691 | |
2692 ColumnInfo* LayoutBlock::columnInfo() const | |
2693 { | |
2694 if (!hasColumns()) | |
2695 return 0; | |
2696 return gColumnInfoMap->get(this); | |
2697 } | |
2698 | |
2699 unsigned LayoutBlock::columnCount(ColumnInfo* colInfo) const | |
2700 { | |
2701 ASSERT(hasColumns()); | |
2702 ASSERT(gColumnInfoMap->get(this) == colInfo); | |
2703 return colInfo->columnCount(); | |
2704 } | |
2705 | |
2706 LayoutRect LayoutBlock::columnRectAt(ColumnInfo* colInfo, unsigned index) const | |
2707 { | |
2708 ASSERT(hasColumns() && gColumnInfoMap->get(this) == colInfo); | |
2709 | |
2710 // Compute the appropriate rect based off our information. | |
2711 LayoutUnit colLogicalWidth = colInfo->desiredColumnWidth(); | |
2712 LayoutUnit colLogicalHeight = colInfo->columnHeight(); | |
2713 LayoutUnit colLogicalTop = borderBefore() + paddingBefore(); | |
2714 LayoutUnit colLogicalLeft = logicalLeftOffsetForContent(); | |
2715 LayoutUnit colGap = columnGap(); | |
2716 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { | |
2717 if (style()->isLeftToRightDirection()) | |
2718 colLogicalLeft += index * (colLogicalWidth + colGap); | |
2719 else | |
2720 colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index *
(colLogicalWidth + colGap); | |
2721 } else { | |
2722 colLogicalTop += index * (colLogicalHeight + colGap); | |
2723 } | |
2724 | |
2725 if (isHorizontalWritingMode()) | |
2726 return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLog
icalHeight); | |
2727 return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogica
lWidth); | |
2728 } | |
2729 | |
2730 void LayoutBlock::adjustPointToColumnContents(LayoutPoint& point) const | |
2731 { | |
2732 // Just bail if we have no columns. | |
2733 if (!hasColumns()) | |
2734 return; | |
2735 | |
2736 ColumnInfo* colInfo = columnInfo(); | |
2737 if (!columnCount(colInfo)) | |
2738 return; | |
2739 | |
2740 // Determine which columns we intersect. | |
2741 LayoutUnit colGap = columnGap(); | |
2742 LayoutUnit halfColGap = colGap / 2; | |
2743 LayoutPoint columnPoint(columnRectAt(colInfo, 0).location()); | |
2744 LayoutUnit logicalOffset = 0; | |
2745 for (unsigned i = 0; i < colInfo->columnCount(); i++) { | |
2746 // Add in half the column gap to the left and right of the rect. | |
2747 LayoutRect colRect = columnRectAt(colInfo, i); | |
2748 flipForWritingMode(colRect); | |
2749 if (isHorizontalWritingMode() == (colInfo->progressionAxis() == ColumnIn
fo::InlineAxis)) { | |
2750 LayoutRect gapAndColumnRect(colRect.x() - halfColGap, colRect.y(), c
olRect.width() + colGap, colRect.height()); | |
2751 if (point.x() >= gapAndColumnRect.x() && point.x() < gapAndColumnRec
t.maxX()) { | |
2752 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { | |
2753 // FIXME: The clamping that follows is not completely right
for right-to-left | |
2754 // content. | |
2755 if (point.y() < gapAndColumnRect.y()) { | |
2756 // Clamp everything above the column to its top left. | |
2757 point = gapAndColumnRect.location(); | |
2758 } else if (point.y() >= gapAndColumnRect.maxY()) { | |
2759 // Clamp everything below the column to the next column'
s top left. If there is | |
2760 // no next column, this still maps to just after this co
lumn. | |
2761 point = gapAndColumnRect.location(); | |
2762 point.move(0, gapAndColumnRect.height()); | |
2763 } | |
2764 } else { | |
2765 if (point.x() < colRect.x()) | |
2766 point.setX(colRect.x()); | |
2767 else if (point.x() >= colRect.maxX()) | |
2768 point.setX(colRect.maxX() - 1); | |
2769 } | |
2770 | |
2771 // We're inside the column. Translate the x and y into our colu
mn coordinate space. | |
2772 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) | |
2773 point.move(columnPoint.x() - colRect.x(), (!style()->isFlipp
edBlocksWritingMode() ? logicalOffset : -logicalOffset)); | |
2774 else | |
2775 point.move((!style()->isFlippedBlocksWritingMode() ? logical
Offset : -logicalOffset) - colRect.x() + borderLeft() + paddingLeft(), 0); | |
2776 return; | |
2777 } | |
2778 | |
2779 // Move to the next position. | |
2780 logicalOffset += colInfo->progressionAxis() == ColumnInfo::InlineAxi
s ? colRect.height() : colRect.width(); | |
2781 } else { | |
2782 LayoutRect gapAndColumnRect(colRect.x(), colRect.y() - halfColGap, c
olRect.width(), colRect.height() + colGap); | |
2783 if (point.y() >= gapAndColumnRect.y() && point.y() < gapAndColumnRec
t.maxY()) { | |
2784 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { | |
2785 // FIXME: The clamping that follows is not completely right
for right-to-left | |
2786 // content. | |
2787 if (point.x() < gapAndColumnRect.x()) { | |
2788 // Clamp everything above the column to its top left. | |
2789 point = gapAndColumnRect.location(); | |
2790 } else if (point.x() >= gapAndColumnRect.maxX()) { | |
2791 // Clamp everything below the column to the next column'
s top left. If there is | |
2792 // no next column, this still maps to just after this co
lumn. | |
2793 point = gapAndColumnRect.location(); | |
2794 point.move(gapAndColumnRect.width(), 0); | |
2795 } | |
2796 } else { | |
2797 if (point.y() < colRect.y()) | |
2798 point.setY(colRect.y()); | |
2799 else if (point.y() >= colRect.maxY()) | |
2800 point.setY(colRect.maxY() - 1); | |
2801 } | |
2802 | |
2803 // We're inside the column. Translate the x and y into our colu
mn coordinate space. | |
2804 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) | |
2805 point.move((!style()->isFlippedBlocksWritingMode() ? logical
Offset : -logicalOffset), columnPoint.y() - colRect.y()); | |
2806 else | |
2807 point.move(0, (!style()->isFlippedBlocksWritingMode() ? logi
calOffset : -logicalOffset) - colRect.y() + borderTop() + paddingTop()); | |
2808 return; | |
2809 } | |
2810 | |
2811 // Move to the next position. | |
2812 logicalOffset += colInfo->progressionAxis() == ColumnInfo::InlineAxi
s ? colRect.width() : colRect.height(); | |
2813 } | |
2814 } | |
2815 } | |
2816 | |
2817 void LayoutBlock::adjustRectForColumns(LayoutRect& r) const | |
2818 { | |
2819 // Just bail if we have no columns. | |
2820 if (!hasColumns()) | |
2821 return; | |
2822 | |
2823 ColumnInfo* colInfo = columnInfo(); | |
2824 | |
2825 // Determine which columns we intersect. | |
2826 unsigned colCount = columnCount(colInfo); | |
2827 if (!colCount) | |
2828 return; | |
2829 | |
2830 // Begin with a result rect that is empty. | |
2831 LayoutRect result; | |
2832 | |
2833 bool isHorizontal = isHorizontalWritingMode(); | |
2834 LayoutUnit beforeBorderPadding = borderBefore() + paddingBefore(); | |
2835 LayoutUnit colHeight = colInfo->columnHeight(); | |
2836 if (!colHeight) | |
2837 return; | |
2838 | |
2839 LayoutUnit startOffset = std::max(isHorizontal ? r.y() : r.x(), beforeBorder
Padding); | |
2840 LayoutUnit endOffset = std::max(std::min<LayoutUnit>(isHorizontal ? r.maxY()
: r.maxX(), beforeBorderPadding + colCount * colHeight), beforeBorderPadding); | |
2841 | |
2842 // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibli
ng4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744 | |
2843 unsigned startColumn = (startOffset - beforeBorderPadding) / colHeight; | |
2844 unsigned endColumn = (endOffset - beforeBorderPadding) / colHeight; | |
2845 | |
2846 if (startColumn == endColumn) { | |
2847 // The rect is fully contained within one column. Adjust for our offsets | |
2848 // and issue paint invalidations only that portion. | |
2849 LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent(); | |
2850 LayoutRect colRect = columnRectAt(colInfo, startColumn); | |
2851 LayoutRect paintInvalidationRect = r; | |
2852 | |
2853 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) { | |
2854 if (isHorizontal) | |
2855 paintInvalidationRect.move(colRect.x() - logicalLeftOffset, - st
atic_cast<int>(startColumn) * colHeight); | |
2856 else | |
2857 paintInvalidationRect.move(- static_cast<int>(startColumn) * col
Height, colRect.y() - logicalLeftOffset); | |
2858 } else { | |
2859 if (isHorizontal) | |
2860 paintInvalidationRect.move(0, colRect.y() - startColumn * colHei
ght - beforeBorderPadding); | |
2861 else | |
2862 paintInvalidationRect.move(colRect.x() - startColumn * colHeight
- beforeBorderPadding, 0); | |
2863 } | |
2864 paintInvalidationRect.intersect(colRect); | |
2865 result.unite(paintInvalidationRect); | |
2866 } else { | |
2867 // We span multiple columns. We can just unite the start and end column
to get the final | |
2868 // paint invalidation rect. | |
2869 result.unite(columnRectAt(colInfo, startColumn)); | |
2870 result.unite(columnRectAt(colInfo, endColumn)); | |
2871 } | |
2872 | |
2873 r = result; | |
2874 } | |
2875 | |
2876 LayoutPoint LayoutBlock::flipForWritingModeIncludingColumns(const LayoutPoint& p
oint) const | |
2877 { | |
2878 ASSERT(hasColumns()); | |
2879 if (!hasColumns() || !style()->isFlippedBlocksWritingMode()) | |
2880 return point; | |
2881 ColumnInfo* colInfo = columnInfo(); | |
2882 LayoutUnit columnLogicalHeight = colInfo->columnHeight(); | |
2883 LayoutUnit expandedLogicalHeight = borderBefore() + paddingBefore() + column
Count(colInfo) * columnLogicalHeight + borderAfter() + paddingAfter() + scrollba
rLogicalHeight(); | |
2884 if (isHorizontalWritingMode()) | |
2885 return LayoutPoint(point.x(), expandedLogicalHeight - point.y()); | |
2886 return LayoutPoint(expandedLogicalHeight - point.x(), point.y()); | |
2887 } | |
2888 | |
2889 void LayoutBlock::adjustStartEdgeForWritingModeIncludingColumns(LayoutRect& rect
) const | |
2890 { | |
2891 ASSERT(hasColumns()); | |
2892 if (!hasColumns() || !style()->isFlippedBlocksWritingMode()) | |
2893 return; | |
2894 | |
2895 ColumnInfo* colInfo = columnInfo(); | |
2896 LayoutUnit columnLogicalHeight = colInfo->columnHeight(); | |
2897 LayoutUnit expandedLogicalHeight = borderBefore() + paddingBefore() + column
Count(colInfo) * columnLogicalHeight + borderAfter() + paddingAfter() + scrollba
rLogicalHeight(); | |
2898 | |
2899 if (isHorizontalWritingMode()) | |
2900 rect.setY(expandedLogicalHeight - rect.maxY()); | |
2901 else | |
2902 rect.setX(expandedLogicalHeight - rect.maxX()); | |
2903 } | |
2904 | |
2905 LayoutSize LayoutBlock::columnOffset(const LayoutPoint& point) const | |
2906 { | |
2907 if (!hasColumns()) | |
2908 return LayoutSize(); | |
2909 | |
2910 ColumnInfo* colInfo = columnInfo(); | |
2911 | |
2912 LayoutUnit logicalLeft = logicalLeftOffsetForContent(); | |
2913 unsigned colCount = columnCount(colInfo); | |
2914 LayoutUnit colLogicalWidth = colInfo->desiredColumnWidth(); | |
2915 LayoutUnit colLogicalHeight = colInfo->columnHeight(); | |
2916 | |
2917 for (unsigned i = 0; i < colCount; ++i) { | |
2918 // Compute the edges for a given column in the block progression directi
on. | |
2919 LayoutRect sliceRect = LayoutRect(logicalLeft, borderBefore() + paddingB
efore() + i * colLogicalHeight, colLogicalWidth, colLogicalHeight); | |
2920 if (!isHorizontalWritingMode()) | |
2921 sliceRect = sliceRect.transposedRect(); | |
2922 | |
2923 LayoutUnit logicalOffset = i * colLogicalHeight; | |
2924 | |
2925 // Now we're in the same coordinate space as the point. See if it is in
side the rectangle. | |
2926 if (isHorizontalWritingMode()) { | |
2927 if (point.y() >= sliceRect.y() && point.y() < sliceRect.maxY()) { | |
2928 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) | |
2929 return LayoutSize(columnRectAt(colInfo, i).x() - logicalLeft
, -logicalOffset); | |
2930 return LayoutSize(0, columnRectAt(colInfo, i).y() - logicalOffse
t - borderBefore() - paddingBefore()); | |
2931 } | |
2932 } else { | |
2933 if (point.x() >= sliceRect.x() && point.x() < sliceRect.maxX()) { | |
2934 if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) | |
2935 return LayoutSize(-logicalOffset, columnRectAt(colInfo, i).y
() - logicalLeft); | |
2936 return LayoutSize(columnRectAt(colInfo, i).x() - logicalOffset -
borderBefore() - paddingBefore(), 0); | |
2937 } | |
2938 } | |
2939 } | |
2940 | |
2941 return LayoutSize(); | |
2942 } | |
2943 | |
2944 void LayoutBlock::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, Lay
outUnit& maxLogicalWidth) const | 2438 void LayoutBlock::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, Lay
outUnit& maxLogicalWidth) const |
2945 { | 2439 { |
2946 if (childrenInline()) { | 2440 if (childrenInline()) { |
2947 // FIXME: Remove this const_cast. | 2441 // FIXME: Remove this const_cast. |
2948 toLayoutBlockFlow(const_cast<LayoutBlock*>(this))->computeInlinePreferre
dLogicalWidths(minLogicalWidth, maxLogicalWidth); | 2442 toLayoutBlockFlow(const_cast<LayoutBlock*>(this))->computeInlinePreferre
dLogicalWidths(minLogicalWidth, maxLogicalWidth); |
2949 } else { | 2443 } else { |
2950 computeBlockPreferredLogicalWidths(minLogicalWidth, maxLogicalWidth); | 2444 computeBlockPreferredLogicalWidths(minLogicalWidth, maxLogicalWidth); |
2951 } | 2445 } |
2952 | 2446 |
2953 maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth); | 2447 maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth); |
2954 | 2448 |
2955 // The flow thread based multicol implementation will do this adjustment on
the flow thread, and | |
2956 // not here on the multicol container, so that spanners won't incorrectly be
treated as column | |
2957 // content (and have spanners' preferred widths multiplied by the number of
columns, etc.). | |
2958 if (style()->specifiesColumns() && !RuntimeEnabledFeatures::regionBasedColum
nsEnabled()) | |
2959 adjustIntrinsicLogicalWidthsForColumns(minLogicalWidth, maxLogicalWidth)
; | |
2960 | |
2961 if (isTableCell()) { | 2449 if (isTableCell()) { |
2962 Length tableCellWidth = toLayoutTableCell(this)->styleOrColLogicalWidth(
); | 2450 Length tableCellWidth = toLayoutTableCell(this)->styleOrColLogicalWidth(
); |
2963 if (tableCellWidth.isFixed() && tableCellWidth.value() > 0) | 2451 if (tableCellWidth.isFixed() && tableCellWidth.value() > 0) |
2964 maxLogicalWidth = std::max(minLogicalWidth, adjustContentBoxLogicalW
idthForBoxSizing(tableCellWidth.value())); | 2452 maxLogicalWidth = std::max(minLogicalWidth, adjustContentBoxLogicalW
idthForBoxSizing(tableCellWidth.value())); |
2965 } | 2453 } |
2966 | 2454 |
2967 int scrollbarWidth = intrinsicScrollbarLogicalWidth(); | 2455 int scrollbarWidth = intrinsicScrollbarLogicalWidth(); |
2968 maxLogicalWidth += scrollbarWidth; | 2456 maxLogicalWidth += scrollbarWidth; |
2969 minLogicalWidth += scrollbarWidth; | 2457 minLogicalWidth += scrollbarWidth; |
2970 } | 2458 } |
(...skipping 30 matching lines...) Expand all Loading... |
3001 m_maxPreferredLogicalWidth = m_maxPreferredLogicalWidth.ceil(); | 2489 m_maxPreferredLogicalWidth = m_maxPreferredLogicalWidth.ceil(); |
3002 } | 2490 } |
3003 | 2491 |
3004 LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth(); | 2492 LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth(); |
3005 m_minPreferredLogicalWidth += borderAndPadding; | 2493 m_minPreferredLogicalWidth += borderAndPadding; |
3006 m_maxPreferredLogicalWidth += borderAndPadding; | 2494 m_maxPreferredLogicalWidth += borderAndPadding; |
3007 | 2495 |
3008 clearPreferredLogicalWidthsDirty(); | 2496 clearPreferredLogicalWidthsDirty(); |
3009 } | 2497 } |
3010 | 2498 |
3011 void LayoutBlock::adjustIntrinsicLogicalWidthsForColumns(LayoutUnit& minLogicalW
idth, LayoutUnit& maxLogicalWidth) const | |
3012 { | |
3013 ASSERT(!RuntimeEnabledFeatures::regionBasedColumnsEnabled()); | |
3014 if (!style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth()) { | |
3015 // The min/max intrinsic widths calculated really tell how much space el
ements need when | |
3016 // laid out inside the columns. In order to eventually end up with the d
esired column width, | |
3017 // we need to convert them to values pertaining to the multicol containe
r. | |
3018 int columnCount = style()->hasAutoColumnCount() ? 1 : style()->columnCou
nt(); | |
3019 LayoutUnit columnWidth; | |
3020 LayoutUnit gapExtra = (columnCount - 1) * columnGap(); | |
3021 if (style()->hasAutoColumnWidth()) { | |
3022 minLogicalWidth = minLogicalWidth * columnCount + gapExtra; | |
3023 } else { | |
3024 columnWidth = style()->columnWidth(); | |
3025 minLogicalWidth = std::min(minLogicalWidth, columnWidth); | |
3026 } | |
3027 // FIXME: If column-count is auto here, we should resolve it to calculat
e the maximum | |
3028 // intrinsic width, instead of pretending that it's 1. The only way to d
o that is by | |
3029 // performing a layout pass, but this is not an appropriate time or plac
e for layout. The | |
3030 // good news is that if height is unconstrained and there are no explici
t breaks, the | |
3031 // resolved column-count really should be 1. | |
3032 maxLogicalWidth = std::max(maxLogicalWidth, columnWidth) * columnCount +
gapExtra; | |
3033 } | |
3034 } | |
3035 | |
3036 void LayoutBlock::computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth
, LayoutUnit& maxLogicalWidth) const | 2499 void LayoutBlock::computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth
, LayoutUnit& maxLogicalWidth) const |
3037 { | 2500 { |
3038 const ComputedStyle& styleToUse = styleRef(); | 2501 const ComputedStyle& styleToUse = styleRef(); |
3039 bool nowrap = styleToUse.whiteSpace() == NOWRAP; | 2502 bool nowrap = styleToUse.whiteSpace() == NOWRAP; |
3040 | 2503 |
3041 LayoutObject* child = firstChild(); | 2504 LayoutObject* child = firstChild(); |
3042 LayoutBlock* containingBlock = this->containingBlock(); | 2505 LayoutBlock* containingBlock = this->containingBlock(); |
3043 LayoutUnit floatLeftWidth = 0, floatRightWidth = 0; | 2506 LayoutUnit floatLeftWidth = 0, floatRightWidth = 0; |
3044 while (child) { | 2507 while (child) { |
3045 // Positioned children don't affect the min/max width. Spanners only aff
ect the min/max | 2508 // Positioned children don't affect the min/max width. Spanners only aff
ect the min/max |
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3644 void LayoutBlock::setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage) | 3107 void LayoutBlock::setPageBreak(LayoutUnit offset, LayoutUnit spaceShortage) |
3645 { | 3108 { |
3646 if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) | 3109 if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) |
3647 flowThread->setPageBreak(offsetFromLogicalTopOfFirstPage() + offset, spa
ceShortage); | 3110 flowThread->setPageBreak(offsetFromLogicalTopOfFirstPage() + offset, spa
ceShortage); |
3648 } | 3111 } |
3649 | 3112 |
3650 void LayoutBlock::updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeigh
t) | 3113 void LayoutBlock::updateMinimumPageHeight(LayoutUnit offset, LayoutUnit minHeigh
t) |
3651 { | 3114 { |
3652 if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) | 3115 if (LayoutFlowThread* flowThread = flowThreadContainingBlock()) |
3653 flowThread->updateMinimumPageHeight(offsetFromLogicalTopOfFirstPage() +
offset, minHeight); | 3116 flowThread->updateMinimumPageHeight(offsetFromLogicalTopOfFirstPage() +
offset, minHeight); |
3654 else if (ColumnInfo* colInfo = view()->layoutState()->columnInfo()) | |
3655 colInfo->updateMinimumColumnHeight(minHeight); | |
3656 } | 3117 } |
3657 | 3118 |
3658 LayoutUnit LayoutBlock::collapsedMarginBeforeForChild(const LayoutBox& child) co
nst | 3119 LayoutUnit LayoutBlock::collapsedMarginBeforeForChild(const LayoutBox& child) co
nst |
3659 { | 3120 { |
3660 // If the child has the same directionality as we do, then we can just retur
n its | 3121 // If the child has the same directionality as we do, then we can just retur
n its |
3661 // collapsed margin. | 3122 // collapsed margin. |
3662 if (!child.isWritingModeRoot()) | 3123 if (!child.isWritingModeRoot()) |
3663 return child.collapsedMarginBefore(); | 3124 return child.collapsedMarginBefore(); |
3664 | 3125 |
3665 // The child has a different directionality. If the child is parallel, then
it's just | 3126 // The child has a different directionality. If the child is parallel, then
it's just |
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3921 void LayoutBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m
arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Layout
Object* obj) const | 3382 void LayoutBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* m
arkedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const Layout
Object* obj) const |
3922 { | 3383 { |
3923 showLayoutObject(); | 3384 showLayoutObject(); |
3924 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot
Box()) | 3385 for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRoot
Box()) |
3925 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa
bel2, obj, 1); | 3386 root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLa
bel2, obj, 1); |
3926 } | 3387 } |
3927 | 3388 |
3928 #endif | 3389 #endif |
3929 | 3390 |
3930 } // namespace blink | 3391 } // namespace blink |
OLD | NEW |