#include #include #include namespace { using namespace aethera; using namespace aethera::render_2d; template std::unique_ptr build_object(Args&&... args) { typename Object::Builder builder(std::forward(args)...); auto result = builder.build(); if (!result) std::terminate(); return std::move(result).value(); } bool contains_color(Image_View view) { for (int y = 0; y < view.height; ++y) { const auto* row = reinterpret_cast(view.data + static_cast(y) * view.stride); for (int x = 0; x < view.width; ++x) if (row[x] != 0) return true; } return false; } } TEST(spectrum_data, publishes_samples_and_interpolates_power) { using Frequency = Impl; using Power = Impl; using Object = Impl; auto frequency = build_object(); auto power = build_object(); auto spectrum = build_object(frequency.get(), power.get()); spectrum->update_state<&Spectrum::State::frequency_range>(Axis_Range{0.0, 100.0}); const double samples[]{-100.0, -50.0, 0.0}; spectrum->update_samples(samples); spectrum->advance(); EXPECT_EQ(spectrum->sample_count(), 3u); double value{}; EXPECT_TRUE(spectrum->power_at(25.0, value)); EXPECT_DOUBLE_EQ(value, -75.0); EXPECT_FALSE(spectrum->power_at(101.0, value)); } TEST(render_scene_2d, composites_axes_and_spectrum_into_final_frame) { using Frequency = Impl; using Power = Impl; using Spectrum_Object = Impl; using Scene_Object = Impl; initialize_runtime(2); auto frequency = build_object(); auto power = build_object(); auto spectrum = build_object(frequency.get(), power.get()); auto scene = build_object(); const Size canvas{160, 120}; frequency->update_state<&Abs_Axis::State::position>(Point_F{20.0, 100.0}); frequency->update_state<&Abs_Axis::State::canvas_size>(canvas); frequency->update_state<&Abs_Axis::State::pixel_length>(120.0); frequency->update_state<&Numeric_Axis::State::coordinate_range>(Axis_Range{0.0, 100.0}); power->update_state<&Abs_Axis::State::position>(Point_F{20.0, 100.0}); power->update_state<&Abs_Axis::State::canvas_size>(canvas); power->update_state<&Abs_Axis::State::pixel_length>(-80.0); power->update_state<&Abs_Axis::State::orientation>(Axis_Orientation::vertical); power->update_state<&Numeric_Axis::State::coordinate_range>(Axis_Range{-100.0, 0.0}); spectrum->update_state<&Spectrum::State::frequency_range>(Axis_Range{0.0, 100.0}); spectrum->update_state<&Spectrum::State::sweep_region_visible>(true); spectrum->update_state<&Spectrum::State::max_hold_visible>(true); const double samples[]{-90.0, -65.0, -20.0, -45.0, -75.0}; spectrum->update_samples(samples); scene->update_state<&Render_Scene_2D::State::viewport>(canvas); scene->update_state<&Render_Scene_2D::State::background>(Color::transparent()); scene->activate_view(); ASSERT_TRUE((scene->edit_dependency_graph([&](auto& prepare, auto& paint) { prepare.add(frequency.get()); prepare.add(power.get()); prepare.add(spectrum.get()); prepare.template add_dependency<&Numeric_Axis::State::coordinate_range>(spectrum.get(), frequency.get()); prepare.template add_dependency<&Numeric_Axis::State::coordinate_range>(spectrum.get(), power.get()); paint.add(frequency.get()); paint.add(power.get()); paint.add(spectrum.get()); }).has_value())); EXPECT_EQ(scene->render_frame(), Render_Frame_Status::rendered); EXPECT_GT(spectrum->rendered_point_count(), 0u); const Image_View frame = scene->frame_view(); ASSERT_FALSE(frame.empty()); EXPECT_TRUE(contains_color(frame)); EXPECT_EQ(scene->render_frame(), Render_Frame_Status::rendered); EXPECT_TRUE(contains_color(scene->frame_view())); EXPECT_EQ(scene->render_frame(), Render_Frame_Status::rendered); EXPECT_TRUE(contains_color(scene->frame_view())); }