From 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Tue, 27 Jun 2017 06:07:23 +0000 Subject: webkitgtk-2.16.5 --- .../WebCore/rendering/GridTrackSizingAlgorithm.h | 241 +++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 Source/WebCore/rendering/GridTrackSizingAlgorithm.h (limited to 'Source/WebCore/rendering/GridTrackSizingAlgorithm.h') diff --git a/Source/WebCore/rendering/GridTrackSizingAlgorithm.h b/Source/WebCore/rendering/GridTrackSizingAlgorithm.h new file mode 100644 index 000000000..da66e1f9b --- /dev/null +++ b/Source/WebCore/rendering/GridTrackSizingAlgorithm.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2017 Igalia S.L. + * + * 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. ``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 + * 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. + */ +#pragma once + +#include "Grid.h" +#include "GridTrackSize.h" +#include "LayoutUnit.h" + +namespace WebCore { + +static const int infinity = -1; + +enum SizingOperation { TrackSizing, IntrinsicSizeComputation }; + +enum TrackSizeComputationPhase { + ResolveIntrinsicMinimums, + ResolveContentBasedMinimums, + ResolveMaxContentMinimums, + ResolveIntrinsicMaximums, + ResolveMaxContentMaximums, + MaximizeTracks, +}; + +class GridTrackSizingAlgorithmStrategy; + +class GridTrack { +public: + GridTrack() { } + + const LayoutUnit& baseSize() const; + void setBaseSize(LayoutUnit); + + const LayoutUnit& growthLimit() const; + void setGrowthLimit(LayoutUnit); + + bool infiniteGrowthPotential() const { return growthLimitIsInfinite() || m_infinitelyGrowable; } + const LayoutUnit& growthLimitIfNotInfinite() const; + + const LayoutUnit& plannedSize() const { return m_plannedSize; } + void setPlannedSize(LayoutUnit plannedSize) { m_plannedSize = plannedSize; } + + const LayoutUnit& tempSize() const { return m_tempSize; } + void setTempSize(const LayoutUnit&); + void growTempSize(const LayoutUnit&); + + bool infinitelyGrowable() const { return m_infinitelyGrowable; } + void setInfinitelyGrowable(bool infinitelyGrowable) { m_infinitelyGrowable = infinitelyGrowable; } + + void setGrowthLimitCap(std::optional); + std::optional growthLimitCap() const { return m_growthLimitCap; } + +private: + bool growthLimitIsInfinite() const { return m_growthLimit == infinity; } + bool isGrowthLimitBiggerThanBaseSize() const { return growthLimitIsInfinite() || m_growthLimit >= m_baseSize; } + + void ensureGrowthLimitIsBiggerThanBaseSize(); + + LayoutUnit m_baseSize { 0 }; + LayoutUnit m_growthLimit { 0 }; + LayoutUnit m_plannedSize { 0 }; + LayoutUnit m_tempSize { 0 }; + std::optional m_growthLimitCap; + bool m_infinitelyGrowable { false }; +}; + +class GridTrackSizingAlgorithm final { + friend class GridTrackSizingAlgorithmStrategy; + +public: + GridTrackSizingAlgorithm(const RenderGrid* renderGrid, Grid& grid) + : m_grid(grid) + , m_renderGrid(renderGrid) + , m_sizingState(ColumnSizingFirstIteration) + { + } + + void setup(GridTrackSizingDirection, unsigned numTracks, SizingOperation, std::optional availableSpace, std::optional freeSpace); + void run(); + void reset(); + + // Required by RenderGrid. Try to minimize the exposed surface. + const Grid& grid() const { return m_grid; } + GridTrackSize gridTrackSize(GridTrackSizingDirection, unsigned translatedIndex, SizingOperation) const; + + LayoutUnit minContentSize() const { return m_minContentSize; }; + LayoutUnit maxContentSize() const { return m_maxContentSize; }; + + Vector& tracks(GridTrackSizingDirection direction) { return direction == ForColumns ? m_columns : m_rows; } + const Vector& tracks(GridTrackSizingDirection direction) const { return direction == ForColumns ? m_columns : m_rows; } + + std::optional freeSpace(GridTrackSizingDirection direction) const { return direction == ForColumns ? m_freeSpaceColumns : m_freeSpaceRows; } + void setFreeSpace(GridTrackSizingDirection, std::optional); + +#ifndef NDEBUG + bool tracksAreWiderThanMinTrackBreadth() const; +#endif + +private: + GridTrackSize gridTrackSize(GridTrackSizingDirection direction, unsigned translatedIndex) const { return gridTrackSize(direction, translatedIndex, m_sizingOperation); } + const GridTrackSize& rawGridTrackSize(GridTrackSizingDirection, unsigned translatedIndex) const; + LayoutUnit assumedRowsSizeForOrthogonalChild(const RenderBox&) const; + LayoutUnit computeTrackBasedSize() const; + + // Helper methods for step 1. initializeTrackSizes(). + LayoutUnit initialBaseSize(const GridTrackSize&) const; + LayoutUnit initialGrowthLimit(const GridTrackSize&, LayoutUnit baseSize) const; + + // Helper methods for step 2. resolveIntrinsicTrackSizes(). + void sizeTrackToFitNonSpanningItem(const GridSpan&, RenderBox& gridItem, GridTrack&); + bool spanningItemCrossesFlexibleSizedTracks(const GridSpan&) const; + typedef struct GridItemsSpanGroupRange GridItemsSpanGroupRange; + template void increaseSizesToAccommodateSpanningItems(const GridItemsSpanGroupRange& gridItemsWithSpan); + LayoutUnit itemSizeForTrackSizeComputationPhase(TrackSizeComputationPhase, RenderBox&) const; + template void distributeSpaceToTracks(Vector& tracks, Vector* growBeyondGrowthLimitsTracks, LayoutUnit& availableLogicalSpace) const; + LayoutUnit gridAreaBreadthForChild(const RenderBox&, GridTrackSizingDirection) const; + + void computeGridContainerIntrinsicSizes(); + + // Helper methods for step 4. Strech flexible tracks. + typedef HashSet::Hash, WTF::UnsignedWithZeroKeyHashTraits> TrackIndexSet; + double computeFlexFactorUnitSize(const Vector& tracks, double flexFactorSum, LayoutUnit& leftOverSpace, const Vector& flexibleTracksIndexes, std::unique_ptr tracksToTreatAsInflexible = nullptr) const; + void computeFlexSizedTracksGrowth(double flexFraction, Vector& increments, LayoutUnit& totalGrowth) const; + double findFrUnitSize(const GridSpan& tracksSpan, LayoutUnit leftOverSpace) const; + + // Track sizing algorithm steps. Note that the "Maximize Tracks" step is done + // entirely inside the strategies, that's why we don't need an additional + // method at thise level. + void initializeTrackSizes(); + void resolveIntrinsicTrackSizes(); + void stretchFlexibleTracks(std::optional freeSpace); + + // State machine. + void advanceNextState(); + bool isValidTransition() const; + + bool m_needsSetup { true }; + std::optional m_availableSpace; + + std::optional m_freeSpaceColumns; + std::optional m_freeSpaceRows; + + // We need to keep both alive in order to properly size grids with orthogonal + // writing modes. + Vector m_columns; + Vector m_rows; + Vector m_contentSizedTracksIndex; + Vector m_flexibleSizedTracksIndex; + + GridTrackSizingDirection m_direction; + SizingOperation m_sizingOperation; + + Grid& m_grid; + + const RenderGrid* m_renderGrid; + std::unique_ptr m_strategy; + + // The track sizing algorithm is used for both layout and intrinsic size + // computation. We're normally just interested in intrinsic inline sizes + // (a.k.a widths in most of the cases) for the computeIntrinsicLogicalWidths() + // computations. That's why we don't need to keep around different values for + // rows/columns. + LayoutUnit m_minContentSize; + LayoutUnit m_maxContentSize; + + enum SizingState { + ColumnSizingFirstIteration, + RowSizingFirstIteration, + ColumnSizingSecondIteration, + RowSizingSecondIteration + }; + SizingState m_sizingState; + + // This is a RAII class used to ensure that the track sizing algorithm is + // executed as it is suppossed to be, i.e., first resolve columns and then + // rows. Only if required a second iteration is run following the same order, + // first columns and then rows. + class StateMachine { + public: + StateMachine(GridTrackSizingAlgorithm&); + ~StateMachine(); + + private: + GridTrackSizingAlgorithm& m_algorithm; + }; +}; + +class GridTrackSizingAlgorithmStrategy { +public: + LayoutUnit minContentForChild(RenderBox&) const; + LayoutUnit maxContentForChild(RenderBox&) const; + LayoutUnit minSizeForChild(RenderBox&) const; + + virtual ~GridTrackSizingAlgorithmStrategy() { } + + virtual void maximizeTracks(Vector&, std::optional& freeSpace) = 0; + virtual double findUsedFlexFraction(Vector& flexibleSizedTracksIndex, GridTrackSizingDirection, std::optional initialFreeSpace) const = 0; + virtual bool recomputeUsedFlexFractionIfNeeded(double& flexFraction, LayoutUnit& totalGrowth) const = 0; + +protected: + GridTrackSizingAlgorithmStrategy(GridTrackSizingAlgorithm& algorithm) + : m_algorithm(algorithm) { } + + virtual LayoutUnit minLogicalWidthForChild(RenderBox&, Length childMinSize, GridTrackSizingDirection) const = 0; + virtual void layoutGridItemForMinSizeComputation(RenderBox&, bool overrideSizeHasChanged) const = 0; + + LayoutUnit logicalHeightForChild(RenderBox&) const; + bool updateOverrideContainingBlockContentSizeForChild(RenderBox&, GridTrackSizingDirection) const; + + // GridTrackSizingAlgorithm accessors for subclasses. + LayoutUnit computeTrackBasedSize() const { return m_algorithm.computeTrackBasedSize(); } + GridTrackSizingDirection direction() const { return m_algorithm.m_direction; } + double findFrUnitSize(const GridSpan& tracksSpan, LayoutUnit leftOverSpace) const { return m_algorithm.findFrUnitSize(tracksSpan, leftOverSpace); } + void distributeSpaceToTracks(Vector& tracks, LayoutUnit& availableLogicalSpace) const { m_algorithm.distributeSpaceToTracks(tracks, nullptr, availableLogicalSpace); } + const RenderGrid* renderGrid() const { return m_algorithm.m_renderGrid; } + + GridTrackSizingAlgorithm& m_algorithm; +}; + +} // namespace WebCore -- cgit v1.2.1