Commit 57576040 authored by Jacques Newman's avatar Jacques Newman Committed by Commit Bot

[GridNG] Implementation of NGGridBlockTrackCollection

Introduces the following:
class GridBlockTrackCollection: Builds ranges given
  specified tracks, implicit tracks, and an auto repeat value.
class GridTrackList: Aids in accessing list of repeaters.
class GridTrackRepeater: Container for repeated tracks.


Bug: 1045599
Change-Id: I929e12dd5c4fcd1e98b3e0e43d6f4a26c4b1a574
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2237722
Commit-Queue: Jacques Newman <janewman@microsoft.com>
Reviewed-by: default avatarChristian Biesinger <cbiesinger@chromium.org>
Reviewed-by: default avatarKurt Catti-Schmidt <kschmi@microsoft.com>
Reviewed-by: default avatarIan Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#778570}
parent 80048905
......@@ -16,24 +16,27 @@ namespace blink {
class CORE_EXPORT NGGridTrackCollectionBase {
public:
static constexpr wtf_size_t kInvalidRangeIndex = kNotFound;
static constexpr wtf_size_t kMaxRangeIndex = kNotFound - 1;
class CORE_EXPORT RangeRepeatIterator {
public:
RangeRepeatIterator(NGGridTrackCollectionBase* collection,
RangeRepeatIterator(const NGGridTrackCollectionBase* collection,
wtf_size_t range_index);
// Moves iterator to next range, skipping over repeats in a range. Return
// true if the move was successful.
bool MoveToNextRange();
wtf_size_t RepeatCount();
wtf_size_t RepeatCount() const;
// Returns the track number for the start of the range.
wtf_size_t RangeTrackStart();
wtf_size_t RangeTrackStart() const;
// Returns the track number at the end of the range.
wtf_size_t RangeTrackEnd();
wtf_size_t RangeTrackEnd() const;
bool IsRangeCollapsed() const;
private:
bool SetRangeIndex(wtf_size_t range_index);
NGGridTrackCollectionBase* collection_;
const NGGridTrackCollectionBase* collection_;
wtf_size_t range_index_;
wtf_size_t range_count_;
......@@ -55,10 +58,150 @@ class CORE_EXPORT NGGridTrackCollectionBase {
// Returns the number of tracks in a range.
virtual wtf_size_t RangeTrackCount(wtf_size_t range_index) const = 0;
// Returns true if the range at the given index is collapsed.
virtual bool IsRangeCollapsed(wtf_size_t range_index) const = 0;
// Returns the number of track ranges in the collection.
virtual wtf_size_t RangeCount() const = 0;
};
// Stores tracks related data by compressing repeated tracks into a single node.
struct NGGridTrackRepeater {
enum class RepeatType { kCount, kAutoFill, kAutoFit };
NGGridTrackRepeater(wtf_size_t track_index,
wtf_size_t repeat_size,
wtf_size_t repeat_count,
RepeatType repeat_type);
String ToString() const;
bool operator==(const NGGridTrackRepeater& rhs) const;
// Index of the first track being repeated.
wtf_size_t track_index;
// Amount of tracks to be repeated.
wtf_size_t repeat_size;
// Amount of times the group of tracks are repeated.
wtf_size_t repeat_count;
// Type of repetition.
RepeatType repeat_type;
};
class CORE_EXPORT NGGridTrackList {
public:
NGGridTrackList();
// Returns the repeat count of the repeater at |index|, or |auto_value|
// if the repeater is auto.
wtf_size_t RepeatCount(wtf_size_t index, wtf_size_t auto_value) const;
// Returns the number of tracks in the repeater at |index|.
wtf_size_t RepeatSize(wtf_size_t index) const;
// Returns the repeat type of the repeater at |index|.
NGGridTrackRepeater::RepeatType RepeatType(wtf_size_t index) const;
// Returns the count of repeaters.
wtf_size_t RepeaterCount() const;
// Returns the total count of all the tracks in this list.
wtf_size_t TotalTrackCount() const;
// Adds a non-auto repeater.
bool AddRepeater(wtf_size_t track_index,
wtf_size_t track_count,
wtf_size_t repeat_count);
// Adds an auto repeater.
bool AddAutoRepeater(wtf_size_t track_index,
wtf_size_t track_count,
NGGridTrackRepeater::RepeatType repeat_type);
// Returns true if this list contains an auto repeater.
bool HasAutoRepeater();
// Clears all data.
void Clear();
String ToString() const;
private:
bool AddRepeater(wtf_size_t track_index,
wtf_size_t track_count,
wtf_size_t repeat_count,
NGGridTrackRepeater::RepeatType repeat_type);
// Returns the amount of tracks available before overflow.
wtf_size_t AvailableTrackCount() const;
#if DCHECK_IS_ON()
// Helper to check if |track_index| does not cause a gap or overlap with the
// tracks in this list. Ensures |track_index| is equal to 1 + the last track's
// index.
bool IsTrackContiguous(wtf_size_t track_index) const;
#endif
Vector<NGGridTrackRepeater> repeaters_;
// The index of the automatic repeater, if there is one; |kInvalidRangeIndex|
// otherwise.
wtf_size_t auto_repeater_index_;
// Total count of tracks.
wtf_size_t total_track_count_;
};
class CORE_EXPORT NGGridBlockTrackCollection
: public NGGridTrackCollectionBase {
public:
struct Range {
wtf_size_t starting_track_number;
wtf_size_t track_count;
wtf_size_t repeater_index;
wtf_size_t repeater_offset;
bool is_collapsed;
bool is_implicit_range;
};
// Sets the specified, implicit tracks, along with a given auto repeat value.
void SetSpecifiedTracks(const NGGridTrackList& specified_tracks,
wtf_size_t auto_repeat_count,
const NGGridTrackList& implicit_tracks);
// Ensures that after FinalizeRanges is called, a range will start at the
// |track_number|, and a range will end at |track_number| + |span_length|
void EnsureTrackCoverage(wtf_size_t track_number, wtf_size_t span_length);
// Build the collection of ranges based on information provided by
// SetSpecifiedTracks and EnsureTrackCoverage.
void FinalizeRanges();
// Returns the range at the given range index.
const Range& RangeAtRangeIndex(wtf_size_t range_index) const;
// Returns the range at the given track.
const Range& RangeAtTrackNumber(wtf_size_t track_number) const;
String ToString() const;
protected:
// Returns the first track number of a range.
wtf_size_t RangeTrackNumber(wtf_size_t range_index) const override;
// Returns the number of tracks in a range.
wtf_size_t RangeTrackCount(wtf_size_t range_index) const override;
// Returns true if the range at |range_index| is collapsed.
bool IsRangeCollapsed(wtf_size_t range_index) const override;
// Returns the number of track ranges in the collection.
wtf_size_t RangeCount() const override;
private:
// Returns true if this collection had implicit tracks provided.
bool HasImplicitTracks() const;
// Returns the repeat size of the implicit tracks.
wtf_size_t ImplicitRepeatSize() const;
bool track_indices_need_sort_ = false;
wtf_size_t auto_repeat_count_ = 0;
// Stores the specified and implicit tracks specified by SetSpecifiedTracks.
NGGridTrackList specified_tracks_;
NGGridTrackList implicit_tracks_;
// Starting and ending tracks mark where ranges will start and end.
// Once the ranges have been built in FinalizeRanges, these are cleared.
Vector<wtf_size_t> starting_tracks_;
Vector<wtf_size_t> ending_tracks_;
Vector<Range> ranges_;
};
} // namespace blink
WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::NGGridTrackRepeater)
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_TRACK_COLLECTION_H_
......@@ -10,7 +10,16 @@
namespace blink {
namespace {
#define EXPECT_RANGE(expected_start, expected_count, iterator) \
EXPECT_EQ(expected_count, iterator.RepeatCount()); \
EXPECT_EQ(expected_start, iterator.RangeTrackStart()); \
EXPECT_EQ(expected_start + expected_count - 1, iterator.RangeTrackEnd()); \
EXPECT_FALSE(iterator.IsRangeCollapsed());
#define EXPECT_COLLAPSED_RANGE(expected_start, expected_count, iterator) \
EXPECT_EQ(expected_start, iterator.RangeTrackStart()); \
EXPECT_EQ(expected_count, iterator.RepeatCount()); \
EXPECT_EQ(expected_start + expected_count - 1, iterator.RangeTrackEnd()); \
EXPECT_TRUE(iterator.IsRangeCollapsed());
class NGGridTrackCollectionBaseTest : public NGGridTrackCollectionBase {
public:
struct TestTrackRange {
......@@ -36,6 +45,8 @@ class NGGridTrackCollectionBaseTest : public NGGridTrackCollectionBase {
wtf_size_t RangeTrackCount(wtf_size_t range_index) const override {
return ranges_[range_index].track_count;
}
bool IsRangeCollapsed(wtf_size_t range_index) const override { return false; }
wtf_size_t RangeCount() const override { return ranges_.size(); }
private:
......@@ -82,19 +93,13 @@ TEST_F(NGGridTrackCollectionTest, TestRangeRepeatIteratorMoveNext) {
NGGridTrackCollectionBaseTest::RangeRepeatIterator iterator(&track_collection,
0u);
EXPECT_EQ(3u, iterator.RepeatCount());
EXPECT_EQ(0u, iterator.RangeTrackStart());
EXPECT_EQ(2u, iterator.RangeTrackEnd());
EXPECT_RANGE(0u, 3u, iterator);
EXPECT_TRUE(iterator.MoveToNextRange());
EXPECT_EQ(10u, iterator.RepeatCount());
EXPECT_EQ(3u, iterator.RangeTrackStart());
EXPECT_EQ(12u, iterator.RangeTrackEnd());
EXPECT_RANGE(3u, 10u, iterator);
EXPECT_TRUE(iterator.MoveToNextRange());
EXPECT_EQ(5u, iterator.RepeatCount());
EXPECT_EQ(13u, iterator.RangeTrackStart());
EXPECT_EQ(17u, iterator.RangeTrackEnd());
EXPECT_RANGE(13u, 5u, iterator);
EXPECT_FALSE(iterator.MoveToNextRange());
......@@ -110,6 +115,134 @@ TEST_F(NGGridTrackCollectionTest, TestRangeRepeatIteratorMoveNext) {
EXPECT_FALSE(empty_iterator.MoveToNextRange());
}
TEST_F(NGGridTrackCollectionTest, TestNGGridTrackList) {
NGGridTrackList track_list;
ASSERT_EQ(0u, track_list.RepeaterCount());
EXPECT_FALSE(track_list.HasAutoRepeater());
EXPECT_TRUE(track_list.AddRepeater(0, 2, 4));
ASSERT_EQ(1u, track_list.RepeaterCount());
EXPECT_EQ(8u, track_list.TotalTrackCount());
EXPECT_EQ(4u, track_list.RepeatCount(0, 77));
EXPECT_EQ(2u, track_list.RepeatSize(0));
EXPECT_FALSE(track_list.HasAutoRepeater());
EXPECT_TRUE(track_list.AddAutoRepeater(
2, 3, NGGridTrackRepeater::RepeatType::kAutoFill));
ASSERT_EQ(2u, track_list.RepeaterCount());
EXPECT_EQ(11u, track_list.TotalTrackCount());
EXPECT_EQ(77u, track_list.RepeatCount(1, 77));
EXPECT_EQ(3u, track_list.RepeatSize(1));
EXPECT_TRUE(track_list.HasAutoRepeater());
// Can't add more than one auto repeater to a list.
EXPECT_FALSE(track_list.AddAutoRepeater(
5, 3, NGGridTrackRepeater::RepeatType::kAutoFill));
EXPECT_TRUE(track_list.AddRepeater(
5, NGGridTrackCollectionBase::kMaxRangeIndex - 20, 1));
ASSERT_EQ(3u, track_list.RepeaterCount());
EXPECT_EQ(NGGridTrackCollectionBase::kMaxRangeIndex - 9,
track_list.TotalTrackCount());
EXPECT_EQ(1u, track_list.RepeatCount(2, 77));
EXPECT_EQ(NGGridTrackCollectionBase::kMaxRangeIndex - 20,
track_list.RepeatSize(2));
// Try to add a repeater that would overflow the total track count.
EXPECT_FALSE(track_list.AddRepeater(
NGGridTrackCollectionBase::kMaxRangeIndex - 15u, 3, 10));
ASSERT_EQ(3u, track_list.RepeaterCount());
// Try to add a repeater that would overflow the track size in a repeater.
EXPECT_FALSE(
track_list.AddRepeater(NGGridTrackCollectionBase::kMaxRangeIndex - 15u,
NGGridTrackCollectionBase::kMaxRangeIndex, 10));
ASSERT_EQ(3u, track_list.RepeaterCount());
}
TEST_F(NGGridTrackCollectionTest, TestNGGridBlockTrackCollection) {
NGGridTrackList specified_tracks;
ASSERT_TRUE(specified_tracks.AddRepeater(1, 2, 4));
ASSERT_TRUE(specified_tracks.AddAutoRepeater(
3, 3, NGGridTrackRepeater::RepeatType::kAutoFill));
ASSERT_EQ(2u, specified_tracks.RepeaterCount());
NGGridBlockTrackCollection block_collection;
block_collection.SetSpecifiedTracks(specified_tracks, 3, NGGridTrackList());
block_collection.FinalizeRanges();
NGGridTrackCollectionBase::RangeRepeatIterator iterator(&block_collection,
0u);
EXPECT_RANGE(1u, 8u, iterator);
EXPECT_TRUE(iterator.MoveToNextRange());
EXPECT_RANGE(9u, 9u, iterator);
EXPECT_FALSE(iterator.MoveToNextRange());
}
TEST_F(NGGridTrackCollectionTest, TestNGGridBlockTrackCollectionCollapsed) {
NGGridTrackList specified_tracks;
ASSERT_TRUE(specified_tracks.AddRepeater(1, 2, 4));
ASSERT_TRUE(specified_tracks.AddAutoRepeater(
3, 3, NGGridTrackRepeater::RepeatType::kAutoFit));
ASSERT_TRUE(specified_tracks.AddRepeater(6, 3, 7));
ASSERT_EQ(3u, specified_tracks.RepeaterCount());
NGGridBlockTrackCollection block_collection;
block_collection.SetSpecifiedTracks(specified_tracks, 3, NGGridTrackList());
block_collection.FinalizeRanges();
NGGridTrackCollectionBase::RangeRepeatIterator iterator(&block_collection,
0u);
EXPECT_RANGE(1u, 8u, iterator);
EXPECT_TRUE(iterator.MoveToNextRange());
EXPECT_COLLAPSED_RANGE(9u, 9u, iterator);
EXPECT_TRUE(iterator.MoveToNextRange());
EXPECT_RANGE(18u, 21u, iterator);
EXPECT_FALSE(iterator.MoveToNextRange());
}
TEST_F(NGGridTrackCollectionTest, TestNGGridBlockTrackCollectionImplicit) {
NGGridTrackList specified_tracks;
ASSERT_TRUE(specified_tracks.AddRepeater(1, 2, 4));
ASSERT_TRUE(specified_tracks.AddRepeater(3, 3, 3));
ASSERT_TRUE(specified_tracks.AddRepeater(6, 3, 7));
ASSERT_EQ(3u, specified_tracks.RepeaterCount());
NGGridTrackList implicit_tracks;
ASSERT_TRUE(implicit_tracks.AddRepeater(1, 8, 2));
NGGridBlockTrackCollection block_collection;
block_collection.SetSpecifiedTracks(specified_tracks, 3, implicit_tracks);
block_collection.EnsureTrackCoverage(3, 40);
block_collection.EnsureTrackCoverage(3, 40);
block_collection.FinalizeRanges();
NGGridTrackCollectionBase::RangeRepeatIterator iterator(&block_collection,
0u);
EXPECT_RANGE(1u, 2u, iterator);
EXPECT_FALSE(block_collection.RangeAtTrackNumber(1u).is_implicit_range);
EXPECT_TRUE(iterator.MoveToNextRange());
EXPECT_RANGE(3u, 6u, iterator);
EXPECT_FALSE(block_collection.RangeAtTrackNumber(4).is_implicit_range);
EXPECT_TRUE(iterator.MoveToNextRange());
EXPECT_RANGE(9u, 9u, iterator);
EXPECT_FALSE(block_collection.RangeAtTrackNumber(7).is_implicit_range);
EXPECT_TRUE(iterator.MoveToNextRange());
EXPECT_RANGE(18u, 21u, iterator);
EXPECT_FALSE(block_collection.RangeAtTrackNumber(20).is_implicit_range);
EXPECT_TRUE(iterator.MoveToNextRange());
EXPECT_TRUE(block_collection.RangeAtTrackNumber(40).is_implicit_range);
EXPECT_RANGE(39u, 4u, iterator);
EXPECT_FALSE(iterator.MoveToNextRange());
}
} // namespace
} // namespace blink
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment