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 |