1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
/*
* Copyright (C) 2025 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "GridLayoutUtils.h"
namespace WebCore {
namespace Layout {
namespace GridLayoutUtils {
LayoutUnit computeGapValue(const Style::GapGutter& gap)
{
if (gap.isNormal())
return { };
// Only handle fixed length gaps for now
if (auto fixedGap = gap.tryFixed())
return Style::evaluate<LayoutUnit>(*fixedGap, 0_lu, Style::ZoomNeeded { });
ASSERT_NOT_REACHED();
return { };
}
LayoutUnit usedInlineSizeForGridItem(const PlacedGridItem& placedGridItem, LayoutUnit borderAndPadding, const TrackSizes& usedColumnSizes,
LayoutUnit columnsGap)
{
auto columnsSize = [&] {
auto columnsStartPosition = computeGridLinePosition(placedGridItem.columnStartLine(), usedColumnSizes, columnsGap);
auto columnsEndPosition = computeGridLinePosition(placedGridItem.columnEndLine(), usedColumnSizes, columnsGap);
ASSERT(columnsEndPosition >= columnsStartPosition);
return columnsEndPosition - columnsStartPosition;
};
auto& inlineAxisSizes = placedGridItem.inlineAxisSizes();
ASSERT(inlineAxisSizes.minimumSize.isFixed() && (inlineAxisSizes.maximumSize.isFixed() || inlineAxisSizes.maximumSize.isNone()));
auto& preferredSize = inlineAxisSizes.preferredSize;
if (auto fixedInlineSize = preferredSize.tryFixed())
return LayoutUnit { fixedInlineSize->resolveZoom(placedGridItem.usedZoom()) } + borderAndPadding;
if (preferredSize.isAuto()) {
// Grid item calculations for automatic sizes in a given dimensions vary by their
// self-alignment values:
auto alignmentPosition = placedGridItem.inlineAxisAlignment().position();
// normal:
// If the grid item has no preferred aspect ratio, and no natural size in the relevant
// axis (if it is a replaced element), the grid item is sized as for align-self: stretch.
//
// https://www.w3.org/TR/css-align-3/#propdef-align-self
//
// When the box’s computed width/height (as appropriate to the axis) is auto and neither of
// its margins (in the appropriate axis) are auto, sets the box’s used size to the length
// necessary to make its outer size as close to filling the alignment container as possible
// while still respecting the constraints imposed by min-height/min-width/max-height/max-width.
auto& marginStart = inlineAxisSizes.marginStart;
auto& marginEnd = inlineAxisSizes.marginEnd;
if ((alignmentPosition == ItemPosition::Normal) && !placedGridItem.hasPreferredAspectRatio() && !placedGridItem.isReplacedElement()
&& !marginStart.isAuto() && !marginEnd.isAuto()) {
auto& usedZoom = placedGridItem.usedZoom();
auto minimumSize = LayoutUnit { inlineAxisSizes.minimumSize.tryFixed()->resolveZoom(usedZoom) };
auto maximumSize = [&inlineAxisSizes, &usedZoom] {
auto& computedMaximumSize = inlineAxisSizes.maximumSize;
if (computedMaximumSize.isNone())
return LayoutUnit::max();
return LayoutUnit { computedMaximumSize.tryFixed()->resolveZoom(usedZoom) };
};
auto stretchedWidth = columnsSize() - LayoutUnit { marginStart.tryFixed()->resolveZoom(usedZoom) } - LayoutUnit { marginEnd.tryFixed()->resolveZoom(usedZoom) } - borderAndPadding;
return std::max(minimumSize, std::min(maximumSize(), stretchedWidth));
}
ASSERT_NOT_IMPLEMENTED_YET();
return { };
}
ASSERT_NOT_IMPLEMENTED_YET();
return { };
}
LayoutUnit usedBlockSizeForGridItem(const PlacedGridItem& placedGridItem)
{
auto& blockAxisSizes = placedGridItem.blockAxisSizes();
if (auto fixedBlockSize = blockAxisSizes.preferredSize.tryFixed())
return LayoutUnit { fixedBlockSize->resolveZoom(placedGridItem.usedZoom()) };
ASSERT_NOT_IMPLEMENTED_YET();
return { };
}
LayoutUnit computeGridLinePosition(size_t gridLineIndex, const TrackSizes& trackSizes, LayoutUnit gap)
{
auto trackSizesBefore = trackSizes.subspan(0, gridLineIndex);
auto sumOfTrackSizes = std::reduce(trackSizesBefore.begin(), trackSizesBefore.end());
// For grid line i, there are i-1 gaps before it (between the i tracks)
auto numberOfGaps = gridLineIndex > 0 ? gridLineIndex - 1 : 0;
return sumOfTrackSizes + (numberOfGaps * gap);
}
}
}
}
|