#include "Fill_Area.h" #include #include "../Axis/Abs_Axis_p.h" #include "../base/Frame_Memory.h" #include "../base/Memory.h" #include "../render/Canvas.h" namespace renderive { struct Fill_Area_Input_Data : Latest_Input_Data { std::pmr::vector points{memory_resource(Memory_Domain::Curve)}; void push(std::span values) { points.assign(values.begin(), values.end()); mark_latest_pushed(); } void push(std::pmr::vector&& values) { points = std::move(values); mark_latest_pushed(); } template void read_all(Handler handler) { if (pending) handler(points); } void clear() override { points.clear(); clear_latest(); } }; struct Fill_Area_Render_State : Render_State, Fill_Area_Prop {}; struct Fill_Area_Private : Typed_Render_Data { std::pmr::vector data_points{memory_resource(Memory_Domain::Curve)}; void prepare_data(const Render_Frame_Snapshot&, const Renderable_Frame_View& frame_view) override { Fill_Area_Input_Data* input = render_input_data(frame_view); if (!input) return; input->read_all([this](std::pmr::vector& points) { data_points.swap(points); }); frame_view.consume_input(); } void draw(Canvas& canvas, const Render_Frame_Snapshot& snapshot, const Renderable_Frame_View& frame_view) override { Fill_Area_Render_State* s = render_state(frame_view); if (!s) return; auto domain_axis = s->domain_axis.lock(); auto value_axis = s->value_axis.lock(); if (!domain_axis || !value_axis || data_points.empty()) return; Axis_Mapping_2D mapping = Axis_Render_Access::mapping(domain_axis.get(), value_axis.get(), snapshot); std::pmr::vector polygon(frame_memory_resource()); if (s->mode == Fill_Area_Mode::To_Baseline) { polygon.resize(data_points.size() + 2); polygon.front() = mapping.map(data_points.front().x, s->baseline); polygon.back() = mapping.map(data_points.back().x, s->baseline); for (int i = 0; i < data_points.size(); ++i) { const PointF& point = data_points.at(i); polygon[i + 1] = mapping.map(point); } } else { polygon.resize(data_points.size()); for (int i = 0; i < data_points.size(); ++i) { const PointF& point = data_points.at(i); polygon[i] = mapping.map(point); } } canvas.save(); canvas.set_antialias(s->antialias); canvas.set_pen(s->pen); canvas.set_brush(s->brush); canvas.draw_polygon(std::span(polygon.data(), polygon.size()), false); canvas.restore(); } }; RENDERIVE_DEFINE_RENDERABLE_BINDING(Fill_Area, Fill_Area_Private, Fill_Area_Render_State, Fill_Area_Input_Data, "FillArea") void Fill_Area::update_points(std::span points) { if (!ok()) return; Render_Input_Lease input(d()); input->push(points); } void Fill_Area::update_points(std::pmr::vector&& points) { if (!ok()) return; Render_Input_Lease input(d()); input->push(std::move(points)); } RENDERIVE_DEFINE_WEAK_STATE_PROP(Fill_Area, Fill_Area_Render_State, Abs_Axis, domain_axis) RENDERIVE_DEFINE_WEAK_STATE_PROP(Fill_Area, Fill_Area_Render_State, Abs_Axis, value_axis) RENDERIVE_DEFINE_STATE_PROP(Fill_Area, Fill_Area_Render_State, double, baseline) RENDERIVE_DEFINE_STATE_PROP(Fill_Area, Fill_Area_Render_State, Brush, brush) RENDERIVE_DEFINE_STATE_PROP(Fill_Area, Fill_Area_Render_State, Pen, pen) RENDERIVE_DEFINE_STATE_PROP(Fill_Area, Fill_Area_Render_State, bool, antialias) RENDERIVE_DEFINE_STATE_PROP(Fill_Area, Fill_Area_Render_State, Fill_Area_Mode, mode) Fill_Area::Builder::Builder(std::shared_ptr parent, std::shared_ptr domain_axis, std::shared_ptr value_axis) { ASSERT(parent, "Fill_Area build error! parent == nullptr"); ASSERT(domain_axis && value_axis, "Fill_Area build error! axis == nullptr"); ASSERT(domain_axis->attached_to_plot(), "Fill_Area build error! domain_axis->plot == nullptr"); ASSERT(domain_axis->shares_plot_with(*value_axis), "Fill_Area build error! domain_axis->plot != value_axis->plot"); ASSERT(parent->shares_plot_with(*domain_axis), "Fill_Area build error! parent->plot != axis->plot"); ASSERT(domain_axis->orientation() != value_axis->orientation(), "Fill_Area build error! axes must be orthogonal"); this->parent = parent; this->domain_axis = domain_axis; this->value_axis = value_axis; } std::shared_ptr Fill_Area::Builder::build() { auto ret = renderive::make_shared(); ret->init(parent); Fill_Area_Private* pd = ret->d(); Render_Edit_Lease edit(pd); Fill_Area_Render_State* sc = edit.operator->(); PROP_R(std::weak_ptr, domain_axis) PROP_R(std::weak_ptr, value_axis) PROP_R(double, baseline) PROP_R(Brush, brush) PROP_R(Pen, pen) PROP_R(bool, antialias) PROP_R(Fill_Area_Mode, mode) return ret; } } // namespace renderive