Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 | 25 |
| 26 #include "core/layout/LayoutGrid.h" | 26 #include "core/layout/LayoutGrid.h" |
| 27 | 27 |
| 28 #include "core/layout/LayoutState.h" | 28 #include "core/layout/LayoutState.h" |
| 29 #include "core/layout/TextAutosizer.h" | 29 #include "core/layout/TextAutosizer.h" |
| 30 #include "core/paint/GridPainter.h" | 30 #include "core/paint/GridPainter.h" |
| 31 #include "core/paint/PaintLayer.h" | 31 #include "core/paint/PaintLayer.h" |
| 32 #include "core/style/ComputedStyle.h" | 32 #include "core/style/ComputedStyle.h" |
| 33 #include "core/style/GridArea.h" | 33 #include "core/style/GridArea.h" |
| 34 #include "platform/LengthFunctions.h" | 34 #include "platform/LengthFunctions.h" |
| 35 #include "platform/text/WritingMode.h" | |
| 35 #include "wtf/PtrUtil.h" | 36 #include "wtf/PtrUtil.h" |
| 36 #include <algorithm> | 37 #include <algorithm> |
| 37 #include <memory> | 38 #include <memory> |
| 38 | 39 |
| 39 namespace blink { | 40 namespace blink { |
| 40 | 41 |
| 41 static const int infinity = -1; | 42 static const int infinity = -1; |
| 42 | 43 |
| 43 class GridItemWithSpan; | 44 class GridItemWithSpan; |
| 44 | 45 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 ContentAlignmentData(){}; | 134 ContentAlignmentData(){}; |
| 134 ContentAlignmentData(LayoutUnit position, LayoutUnit distribution) | 135 ContentAlignmentData(LayoutUnit position, LayoutUnit distribution) |
| 135 : positionOffset(position), distributionOffset(distribution) {} | 136 : positionOffset(position), distributionOffset(distribution) {} |
| 136 | 137 |
| 137 bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; } | 138 bool isValid() { return positionOffset >= 0 && distributionOffset >= 0; } |
| 138 | 139 |
| 139 LayoutUnit positionOffset = LayoutUnit(-1); | 140 LayoutUnit positionOffset = LayoutUnit(-1); |
| 140 LayoutUnit distributionOffset = LayoutUnit(-1); | 141 LayoutUnit distributionOffset = LayoutUnit(-1); |
| 141 }; | 142 }; |
| 142 | 143 |
| 144 class BaselineGroup { | |
| 145 public: | |
| 146 BaselineGroup() {} | |
| 147 | |
| 148 void update(LayoutUnit ascent, LayoutUnit descent) { | |
| 149 m_maxAscent = std::max(m_maxAscent, ascent); | |
| 150 m_maxDescent = std::max(m_maxDescent, descent); | |
| 151 m_size++; | |
| 152 } | |
| 153 LayoutUnit maxAscent() const { return m_maxAscent; } | |
| 154 LayoutUnit maxDescent() const { return m_maxDescent; } | |
| 155 LayoutUnit size() const { return m_size; } | |
| 156 | |
| 157 private: | |
| 158 LayoutUnit m_maxAscent; | |
| 159 LayoutUnit m_maxDescent; | |
| 160 LayoutUnit m_size; | |
| 161 }; | |
| 162 | |
| 163 class BaselineContext { | |
| 164 public: | |
| 165 BaselineContext(const LayoutBox& child, | |
| 166 ItemPosition preference, | |
| 167 LayoutUnit ascent, | |
| 168 LayoutUnit descent) { | |
| 169 updateSharedGroup(child, preference, ascent, descent); | |
| 170 } | |
| 171 | |
| 172 const BaselineGroup& getSharedGroup(const LayoutBox& child, | |
| 173 ItemPosition preference) const { | |
| 174 if (isAscentBaseline(child.styleRef().getWritingMode(), preference)) | |
| 175 return m_ascentSharedGroup; | |
| 176 return m_descentSharedGroup; | |
| 177 } | |
| 178 | |
| 179 void updateSharedGroup(const LayoutBox& child, | |
| 180 ItemPosition preference, | |
| 181 LayoutUnit ascent, | |
| 182 LayoutUnit descent) { | |
| 183 if (isAscentBaseline(child.styleRef().getWritingMode(), preference)) | |
| 184 m_ascentSharedGroup.update(ascent, descent); | |
| 185 else | |
| 186 m_descentSharedGroup.update(ascent, descent); | |
| 187 } | |
| 188 | |
| 189 private: | |
| 190 bool isAscentBaseline(WritingMode blockDirection, | |
| 191 ItemPosition preference) const { | |
| 192 return ((blockDirection == TopToBottomWritingMode && | |
| 193 preference == ItemPositionBaseline) || | |
| 194 (blockDirection == LeftToRightWritingMode && | |
| 195 preference == ItemPositionBaseline) || | |
| 196 (blockDirection == RightToLeftWritingMode && | |
| 197 preference == ItemPositionLastBaseline)); | |
| 198 } | |
| 199 | |
| 200 BaselineGroup m_ascentSharedGroup; | |
| 201 BaselineGroup m_descentSharedGroup; | |
| 202 }; | |
| 203 | |
| 143 enum TrackSizeRestriction { | 204 enum TrackSizeRestriction { |
| 144 AllowInfinity, | 205 AllowInfinity, |
| 145 ForbidInfinity, | 206 ForbidInfinity, |
| 146 }; | 207 }; |
| 147 | 208 |
| 148 class LayoutGrid::GridIterator { | 209 class LayoutGrid::GridIterator { |
| 149 WTF_MAKE_NONCOPYABLE(GridIterator); | 210 WTF_MAKE_NONCOPYABLE(GridIterator); |
| 150 | 211 |
| 151 public: | 212 public: |
| 152 // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g | 213 // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 } | 301 } |
| 241 | 302 |
| 242 private: | 303 private: |
| 243 const GridRepresentation& m_grid; | 304 const GridRepresentation& m_grid; |
| 244 GridTrackSizingDirection m_direction; | 305 GridTrackSizingDirection m_direction; |
| 245 size_t m_rowIndex; | 306 size_t m_rowIndex; |
| 246 size_t m_columnIndex; | 307 size_t m_columnIndex; |
| 247 size_t m_childIndex; | 308 size_t m_childIndex; |
| 248 }; | 309 }; |
| 249 | 310 |
| 311 typedef HashMap<unsigned, | |
| 312 std::unique_ptr<BaselineContext>, | |
| 313 DefaultHash<unsigned>::Hash, | |
| 314 WTF::UnsignedWithZeroKeyHashTraits<unsigned>> | |
| 315 BaselineContextsMap; | |
| 316 | |
| 250 struct LayoutGrid::GridSizingData { | 317 struct LayoutGrid::GridSizingData { |
| 251 WTF_MAKE_NONCOPYABLE(GridSizingData); | 318 WTF_MAKE_NONCOPYABLE(GridSizingData); |
| 252 STACK_ALLOCATED(); | 319 STACK_ALLOCATED(); |
| 253 | 320 |
| 254 public: | 321 public: |
| 255 GridSizingData(size_t gridColumnCount, size_t gridRowCount) | 322 GridSizingData(size_t gridColumnCount, size_t gridRowCount) |
| 256 : columnTracks(gridColumnCount), rowTracks(gridRowCount) {} | 323 : columnTracks(gridColumnCount), rowTracks(gridRowCount) {} |
| 257 | 324 |
| 258 Vector<GridTrack> columnTracks; | 325 Vector<GridTrack> columnTracks; |
| 259 Vector<GridTrack> rowTracks; | 326 Vector<GridTrack> rowTracks; |
| 260 Vector<size_t> contentSizedTracksIndex; | 327 Vector<size_t> contentSizedTracksIndex; |
| 261 | 328 |
| 329 BaselineContextsMap rowAxisAlignmentContext; | |
| 330 BaselineContextsMap colAxisAlignmentContext; | |
| 331 | |
| 262 // Performance optimization: hold onto these Vectors until the end of Layout | 332 // Performance optimization: hold onto these Vectors until the end of Layout |
| 263 // to avoid repeated malloc / free. | 333 // to avoid repeated malloc / free. |
| 264 Vector<GridTrack*> filteredTracks; | 334 Vector<GridTrack*> filteredTracks; |
| 265 Vector<GridItemWithSpan> itemsSortedByIncreasingSpan; | 335 Vector<GridItemWithSpan> itemsSortedByIncreasingSpan; |
| 266 Vector<GridTrack*> growBeyondGrowthLimitsTracks; | 336 Vector<GridTrack*> growBeyondGrowthLimitsTracks; |
| 267 | 337 |
| 268 LayoutUnit& freeSpace(GridTrackSizingDirection direction) { | 338 LayoutUnit& freeSpace(GridTrackSizingDirection direction) { |
| 269 return direction == ForColumns ? freeSpaceForColumns : freeSpaceForRows; | 339 return direction == ForColumns ? freeSpaceForColumns : freeSpaceForRows; |
| 270 } | 340 } |
| 271 | 341 |
| (...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 783 track.setGrowthLimit( | 853 track.setGrowthLimit( |
| 784 computeUsedBreadthOfMaxLength(trackSize, track.baseSize(), maxSize)); | 854 computeUsedBreadthOfMaxLength(trackSize, track.baseSize(), maxSize)); |
| 785 track.setInfinitelyGrowable(false); | 855 track.setInfinitelyGrowable(false); |
| 786 | 856 |
| 787 if (trackSize.isFitContent()) { | 857 if (trackSize.isFitContent()) { |
| 788 GridLength gridLength = trackSize.fitContentTrackBreadth(); | 858 GridLength gridLength = trackSize.fitContentTrackBreadth(); |
| 789 if (!gridLength.hasPercentage() || hasDefiniteFreeSpace) | 859 if (!gridLength.hasPercentage() || hasDefiniteFreeSpace) |
| 790 track.setGrowthLimitCap(valueForLength(gridLength.length(), maxSize)); | 860 track.setGrowthLimitCap(valueForLength(gridLength.length(), maxSize)); |
| 791 } | 861 } |
| 792 | 862 |
| 793 if (trackSize.isContentSized()) | 863 if (trackSize.isContentSized()) { |
| 794 sizingData.contentSizedTracksIndex.append(i); | 864 sizingData.contentSizedTracksIndex.append(i); |
| 865 } else if (!m_gridItemArea.isEmpty()) { | |
| 866 GridIterator iterator(m_grid, direction, i); | |
| 867 while (LayoutBox* gridItem = iterator.nextGridItem()) { | |
| 868 if (isBaselineAlignment(*gridItem) && | |
| 869 (sizingData.sizingOperation != IntrinsicSizeComputation || | |
| 870 direction == ForRows)) | |
| 871 gridItem->layoutIfNeeded(); | |
| 872 updateBaselineAlignmentContextIfNeeded(*gridItem, sizingData); | |
| 873 } | |
| 874 } | |
| 795 if (trackSize.maxTrackBreadth().isFlex()) | 875 if (trackSize.maxTrackBreadth().isFlex()) |
| 796 flexibleSizedTracksIndex.append(i); | 876 flexibleSizedTracksIndex.append(i); |
| 797 } | 877 } |
| 798 | 878 |
| 799 // 2. Resolve content-based TrackSizingFunctions. | 879 // 2. Resolve content-based TrackSizingFunctions. |
| 800 if (!sizingData.contentSizedTracksIndex.isEmpty()) | 880 if (!sizingData.contentSizedTracksIndex.isEmpty()) |
| 801 resolveContentBasedTrackSizingFunctions(direction, sizingData); | 881 resolveContentBasedTrackSizingFunctions(direction, sizingData); |
| 802 | 882 |
| 803 baseSizesWithoutMaximization = growthLimitsWithoutMaximization = LayoutUnit(); | 883 baseSizesWithoutMaximization = growthLimitsWithoutMaximization = LayoutUnit(); |
| 804 | 884 |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1097 // sizes (AvailableSpaceIndefinite). | 1177 // sizes (AvailableSpaceIndefinite). |
| 1098 if ((sizingOperation == IntrinsicSizeComputation) || | 1178 if ((sizingOperation == IntrinsicSizeComputation) || |
| 1099 (direction == ForRows && !cachedHasDefiniteLogicalHeight())) { | 1179 (direction == ForRows && !cachedHasDefiniteLogicalHeight())) { |
| 1100 if (minTrackBreadth.hasPercentage()) | 1180 if (minTrackBreadth.hasPercentage()) |
| 1101 minTrackBreadth = Length(Auto); | 1181 minTrackBreadth = Length(Auto); |
| 1102 if (maxTrackBreadth.hasPercentage()) | 1182 if (maxTrackBreadth.hasPercentage()) |
| 1103 maxTrackBreadth = Length(Auto); | 1183 maxTrackBreadth = Length(Auto); |
| 1104 } | 1184 } |
| 1105 } | 1185 } |
| 1106 | 1186 |
| 1107 // Flex sizes are invalid as a min sizing function. However we still can have | 1187 // Flex sizes Laare invalid as a min sizing function. However we still can |
|
kojii
2016/11/15 04:21:15
typo?
jfernandez
2016/11/16 11:51:24
Done.
| |
| 1188 // have | |
| 1108 // a flexible |minTrackBreadth| if the track had a flex size directly (e.g. | 1189 // a flexible |minTrackBreadth| if the track had a flex size directly (e.g. |
| 1109 // "1fr"), the spec says that in this case it implies an automatic minimum. | 1190 // "1fr"), the spec says that in this case it implies an automatic minimum. |
| 1110 if (minTrackBreadth.isFlex()) | 1191 if (minTrackBreadth.isFlex()) |
| 1111 minTrackBreadth = Length(Auto); | 1192 minTrackBreadth = Length(Auto); |
| 1112 | 1193 |
| 1113 return GridTrackSize(minTrackBreadth, maxTrackBreadth); | 1194 return GridTrackSize(minTrackBreadth, maxTrackBreadth); |
| 1114 } | 1195 } |
| 1115 | 1196 |
| 1116 bool LayoutGrid::isOrthogonalChild(const LayoutBox& child) const { | 1197 bool LayoutGrid::isOrthogonalChild(const LayoutBox& child) const { |
| 1117 return child.isHorizontalWritingMode() != isHorizontalWritingMode(); | 1198 return child.isHorizontalWritingMode() != isHorizontalWritingMode(); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1129 LayoutUnit(-1)); | 1210 LayoutUnit(-1)); |
| 1130 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); | 1211 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); |
| 1131 } | 1212 } |
| 1132 | 1213 |
| 1133 // We need to clear the stretched height to properly compute logical height | 1214 // We need to clear the stretched height to properly compute logical height |
| 1134 // during layout. | 1215 // during layout. |
| 1135 if (child.needsLayout()) | 1216 if (child.needsLayout()) |
| 1136 child.clearOverrideLogicalContentHeight(); | 1217 child.clearOverrideLogicalContentHeight(); |
| 1137 | 1218 |
| 1138 child.layoutIfNeeded(); | 1219 child.layoutIfNeeded(); |
| 1139 return child.logicalHeight() + child.marginLogicalHeight(); | 1220 LayoutUnit baselineOffset = |
| 1221 updateBaselineAlignmentContextIfNeeded(child, sizingData); | |
| 1222 return baselineOffset > 0 | |
| 1223 ? baselineOffset | |
| 1224 : child.logicalHeight() + child.marginLogicalHeight(); | |
| 1140 } | 1225 } |
| 1141 | 1226 |
| 1142 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild( | 1227 GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild( |
| 1143 const LayoutBox& child, | 1228 const LayoutBox& child, |
| 1144 GridTrackSizingDirection direction) const { | 1229 GridTrackSizingDirection direction) const { |
| 1145 return !isOrthogonalChild(child) | 1230 return !isOrthogonalChild(child) |
| 1146 ? direction | 1231 ? direction |
| 1147 : (direction == ForColumns ? ForRows : ForColumns); | 1232 : (direction == ForColumns ? ForRows : ForColumns); |
| 1148 } | 1233 } |
| 1149 | 1234 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1225 | 1310 |
| 1226 // All orthogonal flow boxes were already laid out during an early layout | 1311 // All orthogonal flow boxes were already laid out during an early layout |
| 1227 // phase performed in FrameView::performLayout. | 1312 // phase performed in FrameView::performLayout. |
| 1228 // It's true that grid track sizing was not completed at that time and it may | 1313 // It's true that grid track sizing was not completed at that time and it may |
| 1229 // afffect the final height of a grid item, but since it's forbidden to | 1314 // afffect the final height of a grid item, but since it's forbidden to |
| 1230 // perform a layout during intrinsic width computation, we have to use that | 1315 // perform a layout during intrinsic width computation, we have to use that |
| 1231 // computed height for now. | 1316 // computed height for now. |
| 1232 if (direction == ForColumns && | 1317 if (direction == ForColumns && |
| 1233 sizingData.sizingOperation == IntrinsicSizeComputation) { | 1318 sizingData.sizingOperation == IntrinsicSizeComputation) { |
| 1234 DCHECK(isOrthogonalChild(child)); | 1319 DCHECK(isOrthogonalChild(child)); |
| 1235 return child.logicalHeight() + child.marginLogicalHeight(); | 1320 LayoutUnit baselineOffset = |
| 1321 updateBaselineAlignmentContextIfNeeded(child, sizingData); | |
| 1322 return baselineOffset > 0 | |
| 1323 ? baselineOffset | |
| 1324 : child.logicalHeight() + child.marginLogicalHeight(); | |
| 1236 } | 1325 } |
| 1237 | 1326 |
| 1238 if (updateOverrideContainingBlockContentSizeForChild( | 1327 if (updateOverrideContainingBlockContentSizeForChild( |
| 1239 child, childInlineDirection, sizingData)) | 1328 child, childInlineDirection, sizingData)) |
| 1240 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); | 1329 child.setNeedsLayout(LayoutInvalidationReason::GridChanged); |
| 1241 return logicalHeightForChild(child, sizingData); | 1330 return logicalHeightForChild(child, sizingData); |
| 1242 } | 1331 } |
| 1243 | 1332 |
| 1244 DISABLE_CFI_PERF | 1333 DISABLE_CFI_PERF |
| 1245 LayoutUnit LayoutGrid::maxContentForChild(LayoutBox& child, | 1334 LayoutUnit LayoutGrid::maxContentForChild(LayoutBox& child, |
| (...skipping 1493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2739 return LayoutUnit(); | 2828 return LayoutUnit(); |
| 2740 } | 2829 } |
| 2741 | 2830 |
| 2742 // FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to | 2831 // FIXME: This logic is shared by LayoutFlexibleBox, so it should be moved to |
| 2743 // LayoutBox. | 2832 // LayoutBox. |
| 2744 LayoutUnit LayoutGrid::marginLogicalHeightForChild( | 2833 LayoutUnit LayoutGrid::marginLogicalHeightForChild( |
| 2745 const LayoutBox& child) const { | 2834 const LayoutBox& child) const { |
| 2746 return isHorizontalWritingMode() ? child.marginHeight() : child.marginWidth(); | 2835 return isHorizontalWritingMode() ? child.marginHeight() : child.marginWidth(); |
| 2747 } | 2836 } |
| 2748 | 2837 |
| 2838 LayoutUnit LayoutGrid::marginLogicalWidthForChild( | |
| 2839 const LayoutBox& child) const { | |
| 2840 return isHorizontalWritingMode() ? child.marginWidth() : child.marginHeight(); | |
| 2841 } | |
| 2842 | |
| 2749 LayoutUnit LayoutGrid::computeMarginLogicalSizeForChild( | 2843 LayoutUnit LayoutGrid::computeMarginLogicalSizeForChild( |
| 2750 MarginDirection forDirection, | 2844 MarginDirection forDirection, |
| 2751 const LayoutBox& child) const { | 2845 const LayoutBox& child) const { |
| 2752 if (!child.styleRef().hasMargin()) | 2846 if (!child.styleRef().hasMargin()) |
| 2753 return LayoutUnit(); | 2847 return LayoutUnit(); |
| 2754 | 2848 |
| 2755 bool isRowAxis = forDirection == InlineDirection; | 2849 bool isRowAxis = forDirection == InlineDirection; |
| 2756 LayoutUnit marginStart; | 2850 LayoutUnit marginStart; |
| 2757 LayoutUnit marginEnd; | 2851 LayoutUnit marginEnd; |
| 2758 LayoutUnit logicalSize = | 2852 LayoutUnit logicalSize = |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2922 | 3016 |
| 2923 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, | 3017 static int synthesizedBaselineFromBorderBox(const LayoutBox& box, |
| 2924 LineDirectionMode direction) { | 3018 LineDirectionMode direction) { |
| 2925 return (direction == HorizontalLine ? box.size().height() | 3019 return (direction == HorizontalLine ? box.size().height() |
| 2926 : box.size().width()) | 3020 : box.size().width()) |
| 2927 .toInt(); | 3021 .toInt(); |
| 2928 } | 3022 } |
| 2929 | 3023 |
| 2930 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it might be | 3024 // TODO(lajava): This logic is shared by LayoutFlexibleBox, so it might be |
| 2931 // refactored somehow. | 3025 // refactored somehow. |
| 3026 bool LayoutGrid::isBaselineAlignment(const LayoutBox& child) const { | |
| 3027 bool isChildInlineFlowAlongRowAxis = !isOrthogonalChild(child); | |
| 3028 ItemPosition align = isChildInlineFlowAlongRowAxis | |
| 3029 ? alignSelfForChild(child).position() | |
| 3030 : justifySelfForChild(child).position(); | |
| 3031 bool hasAutoMargins = isChildInlineFlowAlongRowAxis | |
| 3032 ? hasAutoMarginsInColumnAxis(child) | |
| 3033 : hasAutoMarginsInRowAxis(child); | |
| 3034 return ( | |
| 3035 (align == ItemPositionBaseline || align == ItemPositionLastBaseline) && | |
| 3036 !hasAutoMargins); | |
| 3037 } | |
| 3038 | |
| 3039 LayoutUnit LayoutGrid::updateBaselineAlignmentContextIfNeeded( | |
| 3040 LayoutBox& child, | |
| 3041 GridSizingData& sizingData) const { | |
| 3042 if (!isBaselineAlignment(child)) | |
| 3043 return LayoutUnit(); | |
| 3044 | |
| 3045 bool isChildInlineFlowAlongRowAxis = !isOrthogonalChild(child); | |
| 3046 ItemPosition align = isChildInlineFlowAlongRowAxis | |
| 3047 ? alignSelfForChild(child).position() | |
| 3048 : justifySelfForChild(child).position(); | |
| 3049 const GridSpan& span = isChildInlineFlowAlongRowAxis | |
| 3050 ? cachedGridSpan(child, ForRows) | |
| 3051 : cachedGridSpan(child, ForColumns); | |
| 3052 LayoutUnit ascent = firstLineBoxBaselineForChild(child); | |
| 3053 LayoutUnit descent = descentBaselineForChild(child, ascent); | |
| 3054 BaselineContextsMap& baselineContexts = | |
| 3055 isChildInlineFlowAlongRowAxis ? sizingData.rowAxisAlignmentContext | |
| 3056 : sizingData.colAxisAlignmentContext; | |
| 3057 BaselineContext* context = nullptr; | |
| 3058 BaselineContextsMap::AddResult addResult = baselineContexts.add( | |
| 3059 span.startLine(), std::unique_ptr<BaselineContext>()); | |
| 3060 if (addResult.isNewEntry) { | |
| 3061 context = new BaselineContext(child, align, ascent, descent); | |
| 3062 addResult.storedValue->value = wrapUnique(context); | |
| 3063 } else { | |
| 3064 context = addResult.storedValue->value.get(); | |
| 3065 context->updateSharedGroup(child, align, ascent, descent); | |
| 3066 } | |
| 3067 auto group = context->getSharedGroup(child, align); | |
| 3068 return group.maxAscent() + group.maxDescent(); | |
| 3069 } | |
| 3070 | |
| 3071 LayoutUnit LayoutGrid::firstLineBoxBaselineForChild( | |
| 3072 const LayoutBox& child) const { | |
| 3073 LayoutUnit baseline(child.firstLineBoxBaseline()); | |
| 3074 // We take content-box's bottom if no valid baseline. | |
| 3075 if (baseline == -1) | |
| 3076 baseline = LayoutBlock::logicalHeightForChild(child); | |
| 3077 return baseline + marginBeforeForChild(child); | |
| 3078 } | |
| 3079 | |
| 3080 LayoutUnit LayoutGrid::descentBaselineForChild(const LayoutBox& child, | |
| 3081 LayoutUnit ascent) const { | |
| 3082 bool isChildInlineFlowAlongRowAxis = !isOrthogonalChild(child); | |
| 3083 return isChildInlineFlowAlongRowAxis | |
| 3084 ? (marginLogicalHeightForChild(child) + | |
| 3085 LayoutBlock::logicalHeightForChild(child)) - | |
| 3086 ascent | |
| 3087 : (marginLogicalWidthForChild(child) + | |
| 3088 logicalWidthForChild(child)) - | |
| 3089 ascent; | |
| 3090 } | |
| 3091 | |
| 3092 LayoutUnit LayoutGrid::columnAxisBaselineOffsetForChild( | |
| 3093 const LayoutBox& child, | |
| 3094 const GridSizingData& sizingData) const { | |
| 3095 // only parallel items participating in baseline alignment along | |
| 3096 // the grid's row axis have an offset in the column axis. | |
| 3097 if (!isInlineBaselineAlignedChild(child)) | |
| 3098 return LayoutUnit(); | |
| 3099 | |
| 3100 const GridSpan& span = cachedGridSpan(child, ForRows); | |
| 3101 const BaselineContext* context = | |
| 3102 sizingData.rowAxisAlignmentContext.get(span.startLine()); | |
| 3103 DCHECK(context); | |
| 3104 const BaselineGroup& group = | |
| 3105 context->getSharedGroup(child, alignSelfForChild(child).position()); | |
| 3106 // TODO (lajava): We could just return LayoutUnit() if there is only | |
| 3107 // 1 child in the group. | |
| 3108 return group.maxAscent() - firstLineBoxBaselineForChild(child); | |
| 3109 } | |
| 3110 | |
| 3111 LayoutUnit LayoutGrid::rowAxisBaselineOffsetForChild( | |
| 3112 const LayoutBox& child, | |
| 3113 const GridSizingData& sizingData) const { | |
| 3114 // only orthogonal items participating in baseline alignment along | |
| 3115 // the grid's column axis have an offset in the row axis. | |
| 3116 if (!isBlockBaselineAlignedChild(child)) | |
| 3117 return LayoutUnit(); | |
| 3118 | |
| 3119 const GridSpan& span = cachedGridSpan(child, ForColumns); | |
| 3120 const BaselineContext* context = | |
| 3121 sizingData.colAxisAlignmentContext.get(span.startLine()); | |
| 3122 DCHECK(context); | |
| 3123 const BaselineGroup& group = | |
| 3124 context->getSharedGroup(child, justifySelfForChild(child).position()); | |
| 3125 // TODO (lajava): We could just return LayoutUnit() if there is only | |
| 3126 // 1 child in the group. | |
| 3127 return group.maxAscent() - firstLineBoxBaselineForChild(child); | |
| 3128 } | |
| 3129 | |
| 2932 int LayoutGrid::baselinePosition(FontBaseline, | 3130 int LayoutGrid::baselinePosition(FontBaseline, |
| 2933 bool, | 3131 bool, |
| 2934 LineDirectionMode direction, | 3132 LineDirectionMode direction, |
| 2935 LinePositionMode mode) const { | 3133 LinePositionMode mode) const { |
| 2936 DCHECK_EQ(mode, PositionOnContainingLine); | 3134 DCHECK_EQ(mode, PositionOnContainingLine); |
| 2937 int baseline = firstLineBoxBaseline(); | 3135 int baseline = firstLineBoxBaseline(); |
| 2938 // We take content-box's bottom if no valid baseline. | 3136 // We take content-box's bottom if no valid baseline. |
| 2939 if (baseline == -1) | 3137 if (baseline == -1) |
| 2940 baseline = synthesizedBaselineFromContentBox(*this, direction); | 3138 baseline = synthesizedBaselineFromContentBox(*this, direction); |
| 2941 | 3139 |
| 2942 return baseline + beforeMarginInLineDirection(direction); | 3140 return baseline + beforeMarginInLineDirection(direction); |
| 2943 } | 3141 } |
| 2944 | 3142 |
| 2945 bool LayoutGrid::isInlineBaselineAlignedChild(const LayoutBox* child) const { | 3143 bool LayoutGrid::isInlineBaselineAlignedChild(const LayoutBox& child) const { |
| 2946 return alignSelfForChild(*child).position() == ItemPositionBaseline && | 3144 return !isOrthogonalChild(child) && isBaselineAlignment(child); |
| 2947 !isOrthogonalChild(*child) && !hasAutoMarginsInColumnAxis(*child); | 3145 } |
| 3146 | |
| 3147 bool LayoutGrid::isBlockBaselineAlignedChild(const LayoutBox& child) const { | |
| 3148 return isOrthogonalChild(child) && isBaselineAlignment(child); | |
| 2948 } | 3149 } |
| 2949 | 3150 |
| 2950 int LayoutGrid::firstLineBoxBaseline() const { | 3151 int LayoutGrid::firstLineBoxBaseline() const { |
| 2951 if (isWritingModeRoot() || m_grid.isEmpty()) | 3152 if (isWritingModeRoot() || m_grid.isEmpty()) |
| 2952 return -1; | 3153 return -1; |
| 2953 const LayoutBox* baselineChild = nullptr; | 3154 const LayoutBox* baselineChild = nullptr; |
| 2954 const LayoutBox* firstChild = nullptr; | 3155 const LayoutBox* firstChild = nullptr; |
| 2955 bool isBaselineAligned = false; | 3156 bool isBaselineAligned = false; |
| 2956 // Finding the first grid item in grid order. | 3157 // Finding the first grid item in grid order. |
| 2957 for (size_t column = 0; !isBaselineAligned && column < m_grid[0].size(); | 3158 for (size_t column = 0; !isBaselineAligned && column < m_grid[0].size(); |
| 2958 column++) { | 3159 column++) { |
| 2959 for (size_t index = 0; index < m_grid[0][column].size(); index++) { | 3160 for (size_t index = 0; index < m_grid[0][column].size(); index++) { |
| 2960 const LayoutBox* child = m_grid[0][column][index]; | 3161 const LayoutBox* child = m_grid[0][column][index]; |
| 2961 DCHECK(!child->isOutOfFlowPositioned()); | 3162 DCHECK(!child->isOutOfFlowPositioned()); |
| 2962 // If an item participates in baseline alignmen, we select such item. | 3163 // If an item participates in baseline alignment, we select such item. |
| 2963 if (isInlineBaselineAlignedChild(child)) { | 3164 if (isInlineBaselineAlignedChild(*child)) { |
| 2964 // TODO (lajava): self-baseline and content-baseline alignment | 3165 // TODO (lajava): self-baseline and content-baseline alignment |
| 2965 // still not implemented. | 3166 // still not implemented. |
| 2966 baselineChild = child; | 3167 baselineChild = child; |
| 2967 isBaselineAligned = true; | 3168 isBaselineAligned = true; |
| 2968 break; | 3169 break; |
| 2969 } | 3170 } |
| 2970 if (!baselineChild) { | 3171 if (!baselineChild) { |
| 2971 // Use dom order for items in the same cell. | 3172 // Use dom order for items in the same cell. |
| 2972 if (!firstChild || (m_gridItemsIndexesMap.get(child) < | 3173 if (!firstChild || (m_gridItemsIndexesMap.get(child) < |
| 2973 m_gridItemsIndexesMap.get(firstChild))) | 3174 m_gridItemsIndexesMap.get(firstChild))) |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3072 // Only used in flex layout, otherwise equivalent to 'end'. | 3273 // Only used in flex layout, otherwise equivalent to 'end'. |
| 3073 case ItemPositionFlexEnd: | 3274 case ItemPositionFlexEnd: |
| 3074 // Aligns the alignment subject to be flush with the alignment container's | 3275 // Aligns the alignment subject to be flush with the alignment container's |
| 3075 // 'end' edge (block-end) in the column axis. | 3276 // 'end' edge (block-end) in the column axis. |
| 3076 case ItemPositionEnd: | 3277 case ItemPositionEnd: |
| 3077 return GridAxisEnd; | 3278 return GridAxisEnd; |
| 3078 case ItemPositionStretch: | 3279 case ItemPositionStretch: |
| 3079 return GridAxisStart; | 3280 return GridAxisStart; |
| 3080 case ItemPositionBaseline: | 3281 case ItemPositionBaseline: |
| 3081 case ItemPositionLastBaseline: | 3282 case ItemPositionLastBaseline: |
| 3082 // FIXME: These two require implementing Baseline Alignment. For now, we | |
| 3083 // always 'start' align the child. crbug.com/234191 | |
| 3084 return GridAxisStart; | 3283 return GridAxisStart; |
| 3085 case ItemPositionAuto: | 3284 case ItemPositionAuto: |
| 3086 case ItemPositionNormal: | 3285 case ItemPositionNormal: |
| 3087 break; | 3286 break; |
| 3088 } | 3287 } |
| 3089 | 3288 |
| 3090 ASSERT_NOT_REACHED(); | 3289 ASSERT_NOT_REACHED(); |
| 3091 return GridAxisStart; | 3290 return GridAxisStart; |
| 3092 } | 3291 } |
| 3093 | 3292 |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3151 // Only used in flex layout, otherwise equivalent to 'end'. | 3350 // Only used in flex layout, otherwise equivalent to 'end'. |
| 3152 case ItemPositionFlexEnd: | 3351 case ItemPositionFlexEnd: |
| 3153 // Aligns the alignment subject to be flush with the alignment container's | 3352 // Aligns the alignment subject to be flush with the alignment container's |
| 3154 // 'end' edge (inline-end) in the row axis. | 3353 // 'end' edge (inline-end) in the row axis. |
| 3155 case ItemPositionEnd: | 3354 case ItemPositionEnd: |
| 3156 return GridAxisEnd; | 3355 return GridAxisEnd; |
| 3157 case ItemPositionStretch: | 3356 case ItemPositionStretch: |
| 3158 return GridAxisStart; | 3357 return GridAxisStart; |
| 3159 case ItemPositionBaseline: | 3358 case ItemPositionBaseline: |
| 3160 case ItemPositionLastBaseline: | 3359 case ItemPositionLastBaseline: |
| 3161 // FIXME: These two require implementing Baseline Alignment. For now, we | |
| 3162 // always 'start' align the child. crbug.com/234191 | |
| 3163 return GridAxisStart; | 3360 return GridAxisStart; |
| 3164 case ItemPositionAuto: | 3361 case ItemPositionAuto: |
| 3165 case ItemPositionNormal: | 3362 case ItemPositionNormal: |
| 3166 break; | 3363 break; |
| 3167 } | 3364 } |
| 3168 | 3365 |
| 3169 ASSERT_NOT_REACHED(); | 3366 ASSERT_NOT_REACHED(); |
| 3170 return GridAxisStart; | 3367 return GridAxisStart; |
| 3171 } | 3368 } |
| 3172 | 3369 |
| 3173 LayoutUnit LayoutGrid::columnAxisOffsetForChild( | 3370 LayoutUnit LayoutGrid::columnAxisOffsetForChild( |
| 3174 const LayoutBox& child, | 3371 const LayoutBox& child, |
| 3175 GridSizingData& sizingData) const { | 3372 GridSizingData& sizingData) const { |
| 3176 const GridSpan& rowsSpan = cachedGridSpan(child, ForRows); | 3373 const GridSpan& rowsSpan = cachedGridSpan(child, ForRows); |
| 3177 size_t childStartLine = rowsSpan.startLine(); | 3374 size_t childStartLine = rowsSpan.startLine(); |
| 3178 LayoutUnit startOfRow = m_rowPositions[childStartLine]; | 3375 LayoutUnit startOfRow = m_rowPositions[childStartLine]; |
| 3179 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); | 3376 LayoutUnit startPosition = startOfRow + marginBeforeForChild(child); |
| 3180 if (hasAutoMarginsInColumnAxis(child)) | 3377 if (hasAutoMarginsInColumnAxis(child)) |
| 3181 return startPosition; | 3378 return startPosition; |
| 3182 GridAxisPosition axisPosition = columnAxisPositionForChild(child); | 3379 GridAxisPosition axisPosition = columnAxisPositionForChild(child); |
| 3183 switch (axisPosition) { | 3380 switch (axisPosition) { |
| 3184 case GridAxisStart: | 3381 case GridAxisStart: |
| 3185 return startPosition; | 3382 return startPosition + |
| 3383 columnAxisBaselineOffsetForChild(child, sizingData); | |
| 3186 case GridAxisEnd: | 3384 case GridAxisEnd: |
| 3187 case GridAxisCenter: { | 3385 case GridAxisCenter: { |
| 3188 size_t childEndLine = rowsSpan.endLine(); | 3386 size_t childEndLine = rowsSpan.endLine(); |
| 3189 LayoutUnit endOfRow = m_rowPositions[childEndLine]; | 3387 LayoutUnit endOfRow = m_rowPositions[childEndLine]; |
| 3190 // m_rowPositions include distribution offset (because of content | 3388 // m_rowPositions include distribution offset (because of content |
| 3191 // alignment) and gutters so we need to subtract them to get the actual | 3389 // alignment) and gutters so we need to subtract them to get the actual |
| 3192 // end position for a given row (this does not have to be done for the | 3390 // end position for a given row (this does not have to be done for the |
| 3193 // last track as there are no more m_columnPositions after it). | 3391 // last track as there are no more m_columnPositions after it). |
| 3194 LayoutUnit trackGap = | 3392 LayoutUnit trackGap = |
| 3195 gridGapForDirection(ForRows, sizingData.sizingOperation); | 3393 gridGapForDirection(ForRows, sizingData.sizingOperation); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 3218 GridSizingData& sizingData) const { | 3416 GridSizingData& sizingData) const { |
| 3219 const GridSpan& columnsSpan = cachedGridSpan(child, ForColumns); | 3417 const GridSpan& columnsSpan = cachedGridSpan(child, ForColumns); |
| 3220 size_t childStartLine = columnsSpan.startLine(); | 3418 size_t childStartLine = columnsSpan.startLine(); |
| 3221 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; | 3419 LayoutUnit startOfColumn = m_columnPositions[childStartLine]; |
| 3222 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); | 3420 LayoutUnit startPosition = startOfColumn + marginStartForChild(child); |
| 3223 if (hasAutoMarginsInRowAxis(child)) | 3421 if (hasAutoMarginsInRowAxis(child)) |
| 3224 return startPosition; | 3422 return startPosition; |
| 3225 GridAxisPosition axisPosition = rowAxisPositionForChild(child); | 3423 GridAxisPosition axisPosition = rowAxisPositionForChild(child); |
| 3226 switch (axisPosition) { | 3424 switch (axisPosition) { |
| 3227 case GridAxisStart: | 3425 case GridAxisStart: |
| 3228 return startPosition; | 3426 return startPosition + rowAxisBaselineOffsetForChild(child, sizingData); |
| 3229 case GridAxisEnd: | 3427 case GridAxisEnd: |
| 3230 case GridAxisCenter: { | 3428 case GridAxisCenter: { |
| 3231 size_t childEndLine = columnsSpan.endLine(); | 3429 size_t childEndLine = columnsSpan.endLine(); |
| 3232 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; | 3430 LayoutUnit endOfColumn = m_columnPositions[childEndLine]; |
| 3233 // m_columnPositions include distribution offset (because of content | 3431 // m_columnPositions include distribution offset (because of content |
| 3234 // alignment) and gutters so we need to subtract them to get the actual | 3432 // alignment) and gutters so we need to subtract them to get the actual |
| 3235 // end position for a given column (this does not have to be done for the | 3433 // end position for a given column (this does not have to be done for the |
| 3236 // last track as there are no more m_columnPositions after it). | 3434 // last track as there are no more m_columnPositions after it). |
| 3237 LayoutUnit trackGap = | 3435 LayoutUnit trackGap = |
| 3238 gridGapForDirection(ForColumns, sizingData.sizingOperation); | 3436 gridGapForDirection(ForColumns, sizingData.sizingOperation); |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3436 if (!m_gridItemArea.isEmpty()) | 3634 if (!m_gridItemArea.isEmpty()) |
| 3437 GridPainter(*this).paintChildren(paintInfo, paintOffset); | 3635 GridPainter(*this).paintChildren(paintInfo, paintOffset); |
| 3438 } | 3636 } |
| 3439 | 3637 |
| 3440 bool LayoutGrid::cachedHasDefiniteLogicalHeight() const { | 3638 bool LayoutGrid::cachedHasDefiniteLogicalHeight() const { |
| 3441 SECURITY_DCHECK(m_hasDefiniteLogicalHeight); | 3639 SECURITY_DCHECK(m_hasDefiniteLogicalHeight); |
| 3442 return m_hasDefiniteLogicalHeight.value(); | 3640 return m_hasDefiniteLogicalHeight.value(); |
| 3443 } | 3641 } |
| 3444 | 3642 |
| 3445 } // namespace blink | 3643 } // namespace blink |
| OLD | NEW |