blob: a84735f35b21d2dc5ce641e88db96896963ec2cd [file] [log] [blame]
// Copyright 2013 The Flutter 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 "fml/logging.h"
#include "gtest/gtest.h"
#include "flutter/impeller/geometry/geometry_asserts.h"
#include "flutter/impeller/tessellator/circle_tessellator.h"
namespace impeller {
namespace testing {
TEST(CircleTessellator, DivisionVertexCounts) {
auto tessellator = std::make_shared<Tessellator>();
auto test = [&tessellator](const Matrix& transform, Scalar radius) {
CircleTessellator circle_tessellator(tessellator, transform, radius);
size_t quadrant_divisions = circle_tessellator.GetQuadrantDivisionCount();
EXPECT_EQ(circle_tessellator.GetCircleVertexCount(),
(quadrant_divisions + 1) * 4)
<< "transform = " << transform << ", radius = " << radius;
// Confirm the approximation error is within the currently accepted
// |kCircleTolerance| value advertised by |CircleTessellator|.
// (With an additional 1% tolerance for floating point rounding.)
double angle = kPiOver2 / quadrant_divisions;
Point first = {radius, 0};
Point next = {static_cast<Scalar>(cos(angle) * radius),
static_cast<Scalar>(sin(angle) * radius)};
Point midpoint = (first + next) * 0.5;
EXPECT_GE(midpoint.GetLength(),
radius - CircleTessellator::kCircleTolerance * 1.01)
<< ", transform = " << transform << ", radius = " << radius
<< ", divisions = " << quadrant_divisions;
};
test({}, 0.0);
test({}, 0.9);
test({}, 1.0);
test({}, 1.9);
test(Matrix::MakeScale(Vector2(2.0, 2.0)), 0.95);
test({}, 2.0);
test(Matrix::MakeScale(Vector2(2.0, 2.0)), 1.0);
test({}, 11.9);
test({}, 12.0);
test({}, 35.9);
for (int i = 36; i < 10000; i += 4) {
test({}, i);
}
}
TEST(CircleTessellator, CircleTessellationVertices) {
auto tessellator = std::make_shared<Tessellator>();
auto test = [&tessellator](Scalar pixel_radius, Point center, Scalar radius) {
CircleTessellator circle_tessellator(tessellator, {}, pixel_radius);
auto vertex_count = circle_tessellator.GetCircleVertexCount();
auto vertices = std::vector<Point>();
circle_tessellator.GenerateCircleTriangleStrip(
[&vertices](const Point& p) { //
vertices.push_back(p);
},
center, radius);
ASSERT_EQ(vertices.size(), vertex_count);
ASSERT_EQ(vertex_count % 4, 0u);
auto quadrant_count = vertex_count / 4;
for (size_t i = 0; i < quadrant_count; i++) {
double angle = kPiOver2 * i / (quadrant_count - 1);
double rsin = sin(angle) * radius;
double rcos = cos(angle) * radius;
EXPECT_POINT_NEAR(vertices[i * 2],
Point(center.x - rcos, center.y + rsin))
<< "vertex " << i << ", angle = " << angle * 180.0 / kPi << std::endl;
EXPECT_POINT_NEAR(vertices[i * 2 + 1],
Point(center.x - rcos, center.y - rsin))
<< "vertex " << i << ", angle = " << angle * 180.0 / kPi << std::endl;
EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 1],
Point(center.x + rcos, center.y - rsin))
<< "vertex " << i << ", angle = " << angle * 180.0 / kPi << std::endl;
EXPECT_POINT_NEAR(vertices[vertex_count - i * 2 - 2],
Point(center.x + rcos, center.y + rsin))
<< "vertex " << i << ", angle = " << angle * 180.0 / kPi << std::endl;
}
};
test(2.0, {}, 2.0);
test(2.0, {10, 10}, 2.0);
test(1000.0, {}, 2.0);
test(2.0, {}, 1000.0);
}
} // namespace testing
} // namespace impeller