mirror of
https://github.com/RGBCube/serenity
synced 2025-07-28 15:17:46 +00:00
LibGfx+LibWeb: Wire up CanvasRenderingContext2D.ellipse()
Note that this is *extremely* naive, and not very good at being correct.
This commit is contained in:
parent
6c05d6d370
commit
801daf47f0
6 changed files with 104 additions and 12 deletions
|
@ -1492,7 +1492,7 @@ void Painter::for_each_line_segment_on_bezier_curve(const FloatPoint& control_po
|
|||
|
||||
static bool can_approximate_elliptical_arc(const FloatPoint& p1, const FloatPoint& p2, const FloatPoint& center, const FloatPoint radii, float x_axis_rotation, float theta_1, float theta_delta)
|
||||
{
|
||||
constexpr static float tolerance = 0.5f;
|
||||
constexpr static float tolerance = 0.3f;
|
||||
|
||||
auto half_theta_delta = theta_delta / 2.0f;
|
||||
|
||||
|
|
|
@ -30,11 +30,14 @@
|
|||
#include <AK/StringBuilder.h>
|
||||
#include <LibGfx/Painter.h>
|
||||
#include <LibGfx/Path.h>
|
||||
#include <math.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
void Path::elliptical_arc_to(const FloatPoint& next_point, const FloatPoint& radii, double x_axis_rotation, bool large_arc, bool sweep)
|
||||
void Path::elliptical_arc_to(const FloatPoint& point, const FloatPoint& radii, double x_axis_rotation, bool large_arc, bool sweep)
|
||||
{
|
||||
auto next_point = point;
|
||||
|
||||
double rx = radii.x();
|
||||
double ry = radii.y();
|
||||
|
||||
|
@ -58,6 +61,18 @@ void Path::elliptical_arc_to(const FloatPoint& next_point, const FloatPoint& rad
|
|||
if (ry < 0)
|
||||
ry *= -1.0;
|
||||
|
||||
// POSSIBLY HACK: Handle the case where both points are the same.
|
||||
auto same_endpoints = next_point == last_point;
|
||||
if (same_endpoints) {
|
||||
if (!large_arc) {
|
||||
// Nothing is going to be drawn anyway.
|
||||
return;
|
||||
}
|
||||
|
||||
// Move the endpoint by a small amount to avoid division by zero.
|
||||
next_point.move_by(0.01f, 0.01f);
|
||||
}
|
||||
|
||||
// Find (cx, cy), theta_1, theta_delta
|
||||
// Step 1: Compute (x1', y1')
|
||||
auto x_avg = (last_point.x() - next_point.x()) / 2.0f;
|
||||
|
@ -104,20 +119,18 @@ void Path::elliptical_arc_to(const FloatPoint& next_point, const FloatPoint& rad
|
|||
auto theta_delta = theta_2 - theta_1;
|
||||
|
||||
if (!sweep && theta_delta > 0.0f) {
|
||||
theta_delta -= M_TAU;
|
||||
theta_delta -= 2 * M_PI;
|
||||
} else if (sweep && theta_delta < 0) {
|
||||
theta_delta += M_TAU;
|
||||
theta_delta += 2 * M_PI;
|
||||
}
|
||||
|
||||
append_segment<EllipticalArcSegment>(
|
||||
elliptical_arc_to(
|
||||
next_point,
|
||||
FloatPoint(cx, cy),
|
||||
FloatPoint(rx, ry),
|
||||
static_cast<float>(x_axis_rotation),
|
||||
static_cast<float>(theta_1),
|
||||
static_cast<float>(theta_delta));
|
||||
|
||||
invalidate_split_lines();
|
||||
{ cx, cy },
|
||||
{ rx, ry },
|
||||
x_axis_rotation,
|
||||
theta_1,
|
||||
theta_delta);
|
||||
}
|
||||
|
||||
void Path::close()
|
||||
|
|
|
@ -160,6 +160,20 @@ public:
|
|||
elliptical_arc_to(point, { radius, radius }, 0, large_arc, sweep);
|
||||
}
|
||||
|
||||
// Note: This does not do any sanity checks!
|
||||
void elliptical_arc_to(const FloatPoint& endpoint, const FloatPoint& center, const FloatPoint& radii, double x_axis_rotation, double theta, double theta_delta)
|
||||
{
|
||||
append_segment<EllipticalArcSegment>(
|
||||
endpoint,
|
||||
center,
|
||||
radii,
|
||||
x_axis_rotation,
|
||||
theta,
|
||||
theta_delta);
|
||||
|
||||
invalidate_split_lines();
|
||||
}
|
||||
|
||||
void close();
|
||||
void close_all_subpaths();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue