Wire retained stroke polygon tests to poly2tri

This commit is contained in:
2026-06-13 11:45:40 +02:00
parent cf92181ae4
commit ed95b084f0
2 changed files with 136 additions and 1 deletions

View File

@@ -278,7 +278,12 @@ set_tests_properties(pp_paint_renderer_compositor_tests PROPERTIES
LABELS "renderer;paint;desktop-fast")
add_executable(pp_paint_renderer_stroke_execution_tests
paint_renderer/stroke_execution_tests.cpp)
paint_renderer/stroke_execution_tests.cpp
../libs/poly2tri/poly2tri/common/shapes.cc
../libs/poly2tri/poly2tri/sweep/advancing_front.cc
../libs/poly2tri/poly2tri/sweep/cdt.cc
../libs/poly2tri/poly2tri/sweep/sweep.cc
../libs/poly2tri/poly2tri/sweep/sweep_context.cc)
target_link_libraries(pp_paint_renderer_stroke_execution_tests PRIVATE
pp_paint_renderer
pp_test_harness)

View File

@@ -19,6 +19,8 @@
#include <utility>
#include <vector>
#include <poly2tri.h>
#include "legacy_canvas_stroke_execution_services.h"
#include "legacy_canvas_stroke_preview_services.h"
#include "test_harness.h"
@@ -34,6 +36,32 @@ using pp::panopainter::LegacyCanvasStrokeTextureInput;
using pp::panopainter::LegacyStrokePreviewCopySize;
using pp::panopainter::LegacyStrokeSampleExecutionRequest;
std::vector<vertex_t> triangulate_simple(const std::vector<vertex_t>& vertices)
{
std::vector<vertex_t> ret;
std::vector<p2t::Point> points(vertices.size());
std::vector<p2t::Point*> points_ptr(vertices.size());
for (std::size_t i = 0; i < vertices.size(); ++i)
{
points[i] = { vertices[i].pos.x, vertices[i].pos.y };
points_ptr[i] = &points[i];
}
auto cdt = std::make_unique<p2t::CDT>(points_ptr);
cdt->Triangulate();
const auto triangles = cdt->GetTriangles();
for (auto* triangle : triangles)
{
for (int i = 0; i < 3; ++i)
{
const auto index = std::distance(points.data(), triangle->GetPoint(i));
ret.push_back(vertices[static_cast<std::size_t>(index)]);
}
}
return ret;
}
namespace {
bool nearly_equal(float a, float b)
@@ -61,6 +89,16 @@ std::array<pp::paint_renderer::CanvasStrokePoint, 4> make_sample_points()
};
}
std::vector<vertex_t> make_polygon_vertices(std::initializer_list<glm::vec2> points)
{
std::vector<vertex_t> vertices;
vertices.reserve(points.size());
for (const auto& point : points) {
vertices.emplace_back(point);
}
return vertices;
}
void retained_stroke_texture_inputs_bind_and_unbind_in_declared_order(pp::tests::Harness& h)
{
const std::array<LegacyCanvasStrokeTextureBinding, 4> bindings {
@@ -281,6 +319,95 @@ void retained_stroke_sample_executor_unbinds_and_skips_draw_when_bounds_are_empt
PP_EXPECT(h, draw_calls == 0);
}
void retained_stroke_face_sample_polygon_triangulates_and_forwards_face_callbacks(pp::tests::Harness& h)
{
const auto polygon_vertices = make_polygon_vertices({
glm::vec2(10.0F, 10.0F),
glm::vec2(30.0F, 10.0F),
glm::vec2(35.0F, 20.0F),
glm::vec2(20.0F, 35.0F),
glm::vec2(5.0F, 20.0F),
});
std::vector<std::string> events;
std::vector<vertex_t> uploaded_vertices;
std::array<int, 7> copy_args {};
int upload_face_index = -1;
int draw_face_index = -1;
const auto result = pp::panopainter::execute_legacy_canvas_stroke_face_sample_polygon(
pp::panopainter::LegacyStrokeFaceSamplePolygonExecutionRequest {
.context = "test",
.target_size = glm::vec2(64.0F, 64.0F),
.polygon_vertices = polygon_vertices,
.face_index = 4,
.copy_stroke_destination = true,
.bind_destination_texture = [&](int face_index) {
events.emplace_back("bind:" + std::to_string(face_index));
},
.copy_framebuffer_to_destination_texture =
[&](int face_index, int src_x, int src_y, int dst_x, int dst_y, int width, int height) {
events.emplace_back("copy:" + std::to_string(face_index));
copy_args = { face_index, src_x, src_y, dst_x, dst_y, width, height };
},
.unbind_destination_texture = [&](int face_index) {
events.emplace_back("unbind:" + std::to_string(face_index));
},
.upload_brush_vertices = [&](int face_index, std::span<const vertex_t> vertices) {
events.emplace_back("upload:" + std::to_string(face_index) + ":" + std::to_string(vertices.size()));
upload_face_index = face_index;
uploaded_vertices.assign(vertices.begin(), vertices.end());
},
.draw_brush_shape = [&](int face_index) {
events.emplace_back("draw:" + std::to_string(face_index));
draw_face_index = face_index;
},
});
PP_EXPECT(h, result.ok);
PP_EXPECT(h, result.copy_position == glm::ivec2(4, 9));
PP_EXPECT(h, result.copy_size == glm::ivec2(32, 27));
PP_EXPECT(h, nearly_equal(result.dirty_bounds.x, 4.0F));
PP_EXPECT(h, nearly_equal(result.dirty_bounds.y, 9.0F));
PP_EXPECT(h, nearly_equal(result.dirty_bounds.z, 36.0F));
PP_EXPECT(h, nearly_equal(result.dirty_bounds.w, 36.0F));
PP_EXPECT(h, upload_face_index == 4);
PP_EXPECT(h, draw_face_index == 4);
const std::vector<std::string> expected_events {
"bind:4",
"copy:4",
"upload:4:9",
"draw:4",
"unbind:4",
};
PP_EXPECT(h, events == expected_events);
PP_EXPECT(h, copy_args[0] == 4);
PP_EXPECT(h, copy_args[1] == 4);
PP_EXPECT(h, copy_args[2] == 9);
PP_EXPECT(h, copy_args[3] == 4);
PP_EXPECT(h, copy_args[4] == 9);
PP_EXPECT(h, copy_args[5] == 32);
PP_EXPECT(h, copy_args[6] == 27);
PP_EXPECT(h, uploaded_vertices.size() == 9U);
const auto expected_triangulated_vertices = make_polygon_vertices({
glm::vec2(5.0F, 20.0F),
glm::vec2(10.0F, 10.0F),
glm::vec2(20.0F, 35.0F),
glm::vec2(20.0F, 35.0F),
glm::vec2(10.0F, 10.0F),
glm::vec2(30.0F, 10.0F),
glm::vec2(20.0F, 35.0F),
glm::vec2(30.0F, 10.0F),
glm::vec2(35.0F, 20.0F),
});
PP_EXPECT(h, uploaded_vertices.size() == expected_triangulated_vertices.size());
for (std::size_t index = 0; index < uploaded_vertices.size(); ++index) {
PP_EXPECT(h, nearly_equal(uploaded_vertices[index].pos.x, expected_triangulated_vertices[index].pos.x));
PP_EXPECT(h, nearly_equal(uploaded_vertices[index].pos.y, expected_triangulated_vertices[index].pos.y));
}
}
struct StrokeFrame {
int id = -1;
std::array<std::vector<vertex_t>, 6> shapes {};
@@ -825,6 +952,9 @@ int main()
harness.run(
"retained_stroke_sample_executor_unbinds_and_skips_draw_when_bounds_are_empty",
retained_stroke_sample_executor_unbinds_and_skips_draw_when_bounds_are_empty);
harness.run(
"retained_stroke_face_sample_polygon_triangulates_and_forwards_face_callbacks",
retained_stroke_face_sample_polygon_triangulates_and_forwards_face_callbacks);
harness.run(
"retained_stroke_frame_samples_preserve_frame_face_callback_order",
retained_stroke_frame_samples_preserve_frame_face_callback_order);