Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit e5fc548

Browse files
committed
[tessellator]Expose and document smoothing approximation via the C/Dart API. Minor refactor of tessellator to supply fill type to method rather than to object. (#65)
1 parent b816f8f commit e5fc548

12 files changed

+220
-78
lines changed

impeller/entity/contents/linear_gradient_contents.cc

+7-6
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,13 @@ bool LinearGradientContents::Render(const ContentContext& renderer,
4242

4343
auto vertices_builder = VertexBufferBuilder<VS::PerVertexData>();
4444
{
45-
auto result = Tessellator{entity.GetPath().GetFillType()}.Tessellate(
46-
entity.GetPath().CreatePolyline(), [&vertices_builder](Point point) {
47-
VS::PerVertexData vtx;
48-
vtx.vertices = point;
49-
vertices_builder.AppendVertex(vtx);
50-
});
45+
auto result = Tessellator{}.Tessellate(entity.GetPath().GetFillType(),
46+
entity.GetPath().CreatePolyline(),
47+
[&vertices_builder](Point point) {
48+
VS::PerVertexData vtx;
49+
vtx.vertices = point;
50+
vertices_builder.AppendVertex(vtx);
51+
});
5152
if (!result) {
5253
return false;
5354
}

impeller/entity/contents/solid_color_contents.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ VertexBuffer SolidColorContents::CreateSolidFillVertices(const Path& path,
3030

3131
VertexBufferBuilder<VS::PerVertexData> vtx_builder;
3232

33-
auto tesselation_result = Tessellator{path.GetFillType()}.Tessellate(
34-
path.CreatePolyline(), [&vtx_builder](auto point) {
33+
auto tesselation_result = Tessellator{}.Tessellate(
34+
path.GetFillType(), path.CreatePolyline(), [&vtx_builder](auto point) {
3535
VS::PerVertexData vtx;
3636
vtx.vertices = point;
3737
vtx_builder.AppendVertex(vtx);

impeller/entity/contents/text_contents.cc

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ bool TextContents::Render(const ContentContext& renderer,
7878
// atlas.
7979
{
8080
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
81-
if (!Tessellator{FillType::kPositive}.Tessellate(
81+
if (!Tessellator{}.Tessellate(
82+
FillType::kPositive,
8283
PathBuilder{}
8384
.AddRect(Rect::MakeXYWH(0.0, 0.0, 1.0, 1.0))
8485
.TakePath()

impeller/entity/contents/texture_contents.cc

+12-13
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,18 @@ bool TextureContents::Render(const ContentContext& renderer,
6161

6262
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
6363
{
64-
const auto tess_result =
65-
Tessellator{entity.GetPath().GetFillType()}.Tessellate(
66-
entity.GetPath().CreatePolyline(),
67-
[this, &vertex_builder, &coverage_rect, &texture_size](Point vtx) {
68-
VS::PerVertexData data;
69-
data.vertices = vtx;
70-
auto coverage_coords =
71-
(vtx - coverage_rect->origin) / coverage_rect->size;
72-
data.texture_coords =
73-
(source_rect_.origin + source_rect_.size * coverage_coords) /
74-
texture_size;
75-
vertex_builder.AppendVertex(data);
76-
});
64+
const auto tess_result = Tessellator{}.Tessellate(
65+
entity.GetPath().GetFillType(), entity.GetPath().CreatePolyline(),
66+
[this, &vertex_builder, &coverage_rect, &texture_size](Point vtx) {
67+
VS::PerVertexData data;
68+
data.vertices = vtx;
69+
auto coverage_coords =
70+
(vtx - coverage_rect->origin) / coverage_rect->size;
71+
data.texture_coords =
72+
(source_rect_.origin + source_rect_.size * coverage_coords) /
73+
texture_size;
74+
vertex_builder.AppendVertex(data);
75+
});
7776
if (!tess_result) {
7877
return false;
7978
}

impeller/entity/entity_unittests.cc

+31-11
Original file line numberDiff line numberDiff line change
@@ -502,10 +502,9 @@ TEST_F(EntityTest, BlendingModeOptions) {
502502
// test GUI.
503503

504504
const Entity::BlendMode b{};
505-
static_assert(
506-
b == Entity::BlendMode::kClear); // Ensure the first item in
507-
// the switch is the first
508-
// item in the enum.
505+
static_assert(b == Entity::BlendMode::kClear); // Ensure the first item in
506+
// the switch is the first
507+
// item in the enum.
509508
switch (b) {
510509
case Entity::BlendMode::kClear:
511510
blend_mode_names.push_back("Clear");
@@ -521,8 +520,7 @@ TEST_F(EntityTest, BlendingModeOptions) {
521520
blend_mode_values.push_back(Entity::BlendMode::kSourceOver);
522521
case Entity::BlendMode::kDestinationOver:
523522
blend_mode_names.push_back("DestinationOver");
524-
blend_mode_values.push_back(
525-
Entity::BlendMode::kDestinationOver);
523+
blend_mode_values.push_back(Entity::BlendMode::kDestinationOver);
526524
};
527525
}
528526

@@ -534,9 +532,8 @@ TEST_F(EntityTest, BlendingModeOptions) {
534532
ImGui::SetNextWindowPos({200, 450});
535533
}
536534

537-
auto draw_rect = [&context, &pass](
538-
Rect rect, Color color,
539-
Entity::BlendMode blend_mode) -> bool {
535+
auto draw_rect = [&context, &pass](Rect rect, Color color,
536+
Entity::BlendMode blend_mode) -> bool {
540537
using VS = SolidFillPipeline::VertexShader;
541538
VertexBufferBuilder<VS::PerVertexData> vtx_builder;
542539
{
@@ -579,8 +576,7 @@ TEST_F(EntityTest, BlendingModeOptions) {
579576
blend_mode_names.data(), blend_mode_names.size());
580577
ImGui::End();
581578

582-
Entity::BlendMode selected_mode =
583-
blend_mode_values[current_blend_index];
579+
Entity::BlendMode selected_mode = blend_mode_values[current_blend_index];
584580

585581
Point a, b, c, d;
586582
std::tie(a, b) = IMPELLER_PLAYGROUND_LINE(
@@ -601,5 +597,29 @@ TEST_F(EntityTest, BlendingModeOptions) {
601597
ASSERT_TRUE(OpenPlaygroundHere(callback));
602598
}
603599

600+
TEST_F(EntityTest, BezierCircleScaled) {
601+
Entity entity;
602+
auto path = PathBuilder{}
603+
.MoveTo({97.325, 34.818})
604+
.CubicCurveTo({98.50862885295136, 34.81812293973836},
605+
{99.46822048142015, 33.85863261475589},
606+
{99.46822048142015, 32.67499810206613})
607+
.CubicCurveTo({99.46822048142015, 31.491363589376355},
608+
{98.50862885295136, 30.53187326439389},
609+
{97.32499434685802, 30.531998226542708})
610+
.CubicCurveTo({96.14153655073771, 30.532123170035373},
611+
{95.18222070648729, 31.491540299350355},
612+
{95.18222070648729, 32.67499810206613})
613+
.CubicCurveTo({95.18222070648729, 33.85845590478189},
614+
{96.14153655073771, 34.81787303409686},
615+
{97.32499434685802, 34.81799797758954})
616+
.Close()
617+
.TakePath();
618+
entity.SetPath(path);
619+
entity.SetTransformation(Matrix::MakeScale({20.0, 20.0, 1.0}).Translate({-80, -15, 0}));
620+
entity.SetContents(SolidColorContents::Make(Color::Red()));
621+
ASSERT_TRUE(OpenPlaygroundHere(entity));
622+
}
623+
604624
} // namespace testing
605625
} // namespace impeller

impeller/geometry/path_component.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ Point CubicPathComponent::SolveDerivative(Scalar time) const {
112112

113113
/*
114114
* Paul de Casteljau's subdivision with modifications as described in
115-
* http://www.antigrain.com/research/adaptive_bezier/index.html.
115+
* http://agg.sourceforge.net/antigrain.com/research/adaptive_bezier/index.html.
116116
* Refer to the diagram on that page for a description of the points.
117117
*/
118118
static void CubicPathSmoothenRecursive(const SmoothingApproximation& approx,

impeller/geometry/path_component.h

+21
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,31 @@
1212

1313
namespace impeller {
1414

15+
/// Information about how to approximate points on a curved path segment.
16+
///
17+
/// In particular, the values in this object control how many vertices to
18+
/// generate when approximating curves, and what tolerances to use when
19+
/// calculating the sharpness of curves.
1520
struct SmoothingApproximation {
21+
/// The scaling coefficient to use when translating to screen coordinates.
22+
///
23+
/// Values approaching 0.0 will generate smoother looking curves with a
24+
/// greater number of vertices, and will be more expensive to calculate.
1625
Scalar scale;
26+
27+
/// The tolerance value in radians for calculating sharp angles.
28+
///
29+
/// Values approaching 0.0 will provide more accurate approximation of sharp
30+
/// turns. A 0.0 value means angle conditions are not considered at all.
1731
Scalar angle_tolerance;
32+
33+
/// An angle in radians at which to introduce bevel cuts.
34+
///
35+
/// Values greater than zero will restirct the sharpness of bevel cuts on
36+
/// turns.
1837
Scalar cusp_limit;
38+
39+
/// Used to more quickly detect colinear cases.
1940
Scalar distance_tolerance_square;
2041

2142
SmoothingApproximation(/* default */)

impeller/tessellator/c/tessellator.cc

+13-8
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,21 @@ void Close(PathBuilder* builder) {
3737
builder->Close();
3838
}
3939

40-
struct Vertices* Tessellate(PathBuilder* builder) {
41-
auto path = builder->CopyPath();
42-
auto polyline = path.CreatePolyline();
40+
struct Vertices* Tessellate(PathBuilder* builder,
41+
int fill_type,
42+
Scalar scale,
43+
Scalar angle_tolerance,
44+
Scalar cusp_limit) {
45+
auto path = builder->CopyPath(static_cast<FillType>(fill_type));
46+
auto smoothing = SmoothingApproximation(scale, angle_tolerance, cusp_limit);
47+
auto polyline = path.CreatePolyline(smoothing);
4348

4449
std::vector<float> points;
45-
if (!Tessellator{path.GetFillType()}.Tessellate(polyline,
46-
[&points](Point vertex) {
47-
points.push_back(vertex.x);
48-
points.push_back(vertex.y);
49-
})) {
50+
if (!Tessellator{}.Tessellate(path.GetFillType(), polyline,
51+
[&points](Point vertex) {
52+
points.push_back(vertex.x);
53+
points.push_back(vertex.y);
54+
})) {
5055
return nullptr;
5156
}
5257

impeller/tessellator/c/tessellator.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
#include "impeller/geometry/path_builder.h"
88
#include "impeller/tessellator/tessellator.h"
99

10+
#ifdef _WIN32
11+
#define IMPELLER_API __declspec(dllexport)
12+
#else
1013
#define IMPELLER_API __attribute__((visibility("default")))
14+
#endif
1115

1216
extern "C" {
1317

@@ -36,7 +40,11 @@ IMPELLER_API void CubicTo(PathBuilder* builder,
3640

3741
IMPELLER_API void Close(PathBuilder* builder);
3842

39-
IMPELLER_API struct Vertices* Tessellate(PathBuilder* builder);
43+
IMPELLER_API struct Vertices* Tessellate(PathBuilder* builder,
44+
int fill_type,
45+
Scalar scale,
46+
Scalar angle_tolerance,
47+
Scalar cusp_limit);
4048

4149
IMPELLER_API void DestroyVertices(Vertices* vertices);
4250

0 commit comments

Comments
 (0)