blob: 19b774fab3428ba504e17ed5ad61bd86b7ac3d44 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/layout/ng/ng_ink_overflow.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
namespace blink {
namespace {
PhysicalRect FromFloatRound(const FloatRect& rect) {
return {LayoutUnit::FromFloatRound(rect.X()),
LayoutUnit::FromFloatRound(rect.Y()),
LayoutUnit::FromFloatRound(rect.Width()),
LayoutUnit::FromFloatRound(rect.Height())};
}
using testing::ElementsAre;
class NGInkOverflowTest : public testing::Test, private ScopedLayoutNGForTest {
public:
NGInkOverflowTest() : ScopedLayoutNGForTest(true) {}
};
TEST_F(NGInkOverflowTest, Empty) {
NGInkOverflow overflow;
NGInkOverflow::Type type =
overflow.Set(NGInkOverflow::Type::kNotSet, {0, 0, 100, 117},
// This does not affect the visual rect even if the offset is
// outside, because the size is empty.
{-24, 50, 0, 0}, {100, 117});
EXPECT_EQ(type, NGInkOverflow::Type::kNone);
}
#define MIN_LARGE32 4
#define MIN_LARGE64 1024
#if UINTPTR_MAX == 0xFFFFFFFF
#define MIN_LARGE MIN_LARGE32
#elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu
#define MIN_LARGE MIN_LARGE64
#endif
#define MAX_SMALL (LayoutUnit(MIN_LARGE) - LayoutUnit::Epsilon())
struct RectData {
PhysicalSize size;
FloatRect rect;
FloatRect expect;
NGInkOverflow::Type type;
NGInkOverflow::Type ExpectedTypeForContents() const {
if (type == NGInkOverflow::kSelf)
return NGInkOverflow::kContents;
if (type == NGInkOverflow::kSmallSelf)
return NGInkOverflow::kSmallContents;
return type;
}
} rect_data[] = {
{{20, 10}, {0, 0, 0, 0}, {0, 0, 20, 10}, NGInkOverflow::kNone},
{{20, 10}, {0, 0, 20, 10}, {0, 0, 20, 10}, NGInkOverflow::kNone},
// 2: One of values is max small, all others are 0.
{{20, 10},
{0, 0, MAX_SMALL + 20, 10},
{0, 0, MAX_SMALL + 20, 10},
NGInkOverflow::kSmallSelf},
{{20, 10},
{0, 0, 20, MAX_SMALL + 10},
{0, 0, 20, MAX_SMALL + 10},
NGInkOverflow::kSmallSelf},
{{20, 10},
{-MAX_SMALL, 0, MAX_SMALL + 20, 10},
{-MAX_SMALL, 0, MAX_SMALL + 20, 10},
NGInkOverflow::kSmallSelf},
{{20, 10},
{0, -MAX_SMALL, 20, MAX_SMALL + 10},
{0, -MAX_SMALL, 20, MAX_SMALL + 10},
NGInkOverflow::kSmallSelf},
// 6: One of values is large, all others are 0.
{{20, 10},
{0, 0, MIN_LARGE + 20, 10},
{0, 0, MIN_LARGE + 20, 10},
NGInkOverflow::kSelf},
{{20, 10},
{0, 0, 20, MIN_LARGE + 10},
{0, 0, 20, MIN_LARGE + 10},
NGInkOverflow::kSelf},
{{20, 10},
{-MIN_LARGE, 0, MIN_LARGE + 20, 10},
{-MIN_LARGE, 0, MIN_LARGE + 20, 10},
NGInkOverflow::kSelf},
{{20, 10},
{0, -MIN_LARGE, 20, MIN_LARGE + 10},
{0, -MIN_LARGE, 20, MIN_LARGE + 10},
NGInkOverflow::kSelf},
// 10: All values are the max small values.
{{20, 10},
{-MAX_SMALL, -MAX_SMALL, MAX_SMALL * 2 + 20, MAX_SMALL * 2 + 10},
{-MAX_SMALL, -MAX_SMALL, MAX_SMALL * 2 + 20, MAX_SMALL * 2 + 10},
NGInkOverflow::kSmallSelf},
};
class RectDataTest : public NGInkOverflowTest,
public testing::WithParamInterface<RectData> {};
INSTANTIATE_TEST_SUITE_P(NGInkOverflowTest,
RectDataTest,
testing::ValuesIn(rect_data));
TEST_P(RectDataTest, Self) {
const RectData data = GetParam();
NGInkOverflow ink_overflow;
NGInkOverflow::Type type = ink_overflow.SetSelf(
NGInkOverflow::kNotSet, FromFloatRound(data.rect), data.size);
EXPECT_EQ(type, data.type);
PhysicalRect result = ink_overflow.Self(type, data.size);
EXPECT_EQ(result, FromFloatRound(data.expect));
ink_overflow.Reset(type);
}
TEST_P(RectDataTest, Contents) {
const RectData data = GetParam();
NGInkOverflow ink_overflow;
NGInkOverflow::Type type = ink_overflow.Set(
NGInkOverflow::kNotSet, {}, FromFloatRound(data.rect), data.size);
EXPECT_EQ(type, data.ExpectedTypeForContents());
PhysicalRect result = ink_overflow.SelfAndContents(type, data.size);
EXPECT_EQ(result, FromFloatRound(data.expect));
ink_overflow.Reset(type);
}
TEST_P(RectDataTest, Copy) {
const RectData data = GetParam();
NGInkOverflow original;
NGInkOverflow::Type type = original.SetSelf(
NGInkOverflow::kNotSet, FromFloatRound(data.rect), data.size);
NGInkOverflow copy(type, original);
EXPECT_EQ(copy.Self(type, data.size), original.Self(type, data.size));
original.Reset(type);
copy.Reset(type);
}
struct SelfAndContentsData {
PhysicalSize size;
PhysicalRect self;
PhysicalRect contents;
NGInkOverflow::Type type;
} self_and_contents_data[] = {
{{10, 10}, {0, 0, 10, 10}, {0, 0, 10, 10}, NGInkOverflow::kNone},
{{10, 10},
{-1, -1, 12, 12},
{0, 0, 20, 20},
NGInkOverflow::kSelfAndContents},
};
class SelfAndContentsDataTest
: public NGInkOverflowTest,
public testing::WithParamInterface<SelfAndContentsData> {};
INSTANTIATE_TEST_SUITE_P(NGInkOverflowTest,
SelfAndContentsDataTest,
testing::ValuesIn(self_and_contents_data));
TEST_P(SelfAndContentsDataTest, SelfAndContents) {
const SelfAndContentsData data = GetParam();
NGInkOverflow ink_overflow;
NGInkOverflow::Type type = ink_overflow.Set(NGInkOverflow::kNotSet, data.self,
data.contents, data.size);
EXPECT_EQ(type, data.type);
EXPECT_EQ(ink_overflow.Self(type, data.size), data.self);
EXPECT_EQ(ink_overflow.SelfAndContents(type, data.size),
UnionRect(data.self, data.contents));
ink_overflow.Reset(type);
}
} // namespace
} // namespace blink