1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 05:07:34 +00:00

LibGfx: Add Painter::draw_quadratic_bezier_curve()

Also adds a QuadraticBezierCurveTo mode to Gfx::Path
This commit is contained in:
AnotherTest 2020-05-05 05:45:17 +04:30 committed by Andreas Kling
parent 73a7a589c2
commit 9f3f98d4c0
5 changed files with 75 additions and 2 deletions

View file

@ -1049,6 +1049,47 @@ void Painter::draw_line(const Point& p1, const Point& p2, Color color, int thick
}
}
static void draw_split_quadratic_bezier_curve(Painter& painter, const Point& original_control, const Point& p1, const Point& p2, Color color, int thickness, bool dotted)
{
auto po1_midpoint = original_control + p1;
po1_midpoint /= 2;
auto po2_midpoint = original_control + p2;
po2_midpoint /= 2;
auto new_segment = po1_midpoint + po2_midpoint;
new_segment /= 2;
painter.draw_quadratic_bezier_curve(po1_midpoint, p1, new_segment, color, thickness, dotted);
painter.draw_quadratic_bezier_curve(po2_midpoint, new_segment, p2, color, thickness, dotted);
}
static bool can_approximate_bezier_curve(const Point& p1, const Point& p2, const Point& control)
{
constexpr static int tolerance = 15;
auto p1x = 3 * control.x() - 2 * p1.x() - p2.x();
auto p1y = 3 * control.y() - 2 * p1.y() - p2.y();
auto p2x = 3 * control.x() - 2 * p2.x() - p1.x();
auto p2y = 3 * control.y() - 2 * p2.y() - p1.y();
p1x = p1x * p1x;
p1y = p1y * p1y;
p2x = p2x * p2x;
p2y = p2y * p2y;
return max(p1x, p2x) + max(p1y, p2y) <= tolerance;
}
void Painter::draw_quadratic_bezier_curve(const Point& control_point, const Point& p1, const Point& p2, Color color, int thickness, bool dotted)
{
if (can_approximate_bezier_curve(p1, p2, control_point)) {
draw_line(p1, p2, color, thickness, dotted);
} else {
draw_split_quadratic_bezier_curve(*this, control_point, p1, p2, color, thickness, dotted);
}
}
void Painter::add_clip_rect(const Rect& rect)
{
state().clip_rect.intersect(rect.translated(m_clip_origin.location()));
@ -1087,6 +1128,11 @@ void Painter::stroke_path(const Path& path, Color color, int thickness)
draw_line(Point(cursor.x(), cursor.y()), Point(segment.point.x(), segment.point.y()), color, thickness);
cursor = segment.point;
break;
case Path::Segment::Type::QuadraticBezierCurveTo:
ASSERT(segment.through.has_value());
draw_quadratic_bezier_curve(Point(segment.through.value().x(), segment.through.value().y()), Point(cursor.x(), cursor.y()), Point(segment.point.x(), segment.point.y()), color, thickness);
cursor = segment.point;
break;
}
}
}