Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(140)

Side by Side Diff: Source/core/layout/LayoutBlock.cpp

Issue 1158183006: Remove the old multicol implementation. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: rebase master Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/layout/LayoutBlock.h ('k') | Source/core/layout/LayoutBlockFlow.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « Source/core/layout/LayoutBlock.h ('k') | Source/core/layout/LayoutBlockFlow.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698