mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-08 04:15:23 +03:00
LibGfx: Put the Midpoint Ellipse Algorithm in its own function
This commit is contained in:
parent
9c5915b5b4
commit
d2372464a2
Notes:
sideshowbarker
2024-07-17 09:48:50 +09:00
Author: https://github.com/LucasChollet Commit: https://github.com/SerenityOS/serenity/commit/d2372464a2 Pull-request: https://github.com/SerenityOS/serenity/pull/16780
@ -472,6 +472,55 @@ void Painter::draw_circle_arc_intersecting(IntRect const& a_rect, IntPoint cente
|
||||
return draw_circle_arc_intersecting(a_rect, center, radius - 1, color, thickness - 1);
|
||||
}
|
||||
|
||||
// The callback will only be called for a quarter of the ellipse, the user is intended to deduce other points.
|
||||
// As the coordinate space is relative to the center of the rectangle, it's simply (x, y), (x, -y), (-x, y) and (-x, -y).
|
||||
static void on_each_ellipse_point(IntRect const& rect, Function<void(IntPoint)>&& callback)
|
||||
{
|
||||
// Note: This is an implementation of the Midpoint Ellipse Algorithm.
|
||||
double const a = rect.width() / 2;
|
||||
double const a_square = a * a;
|
||||
double const b = rect.height() / 2;
|
||||
double const b_square = b * b;
|
||||
|
||||
int x = 0;
|
||||
auto y = static_cast<int>(b);
|
||||
|
||||
double dx = 2 * b_square * x;
|
||||
double dy = 2 * a_square * y;
|
||||
|
||||
// For region 1:
|
||||
auto decision_parameter = b_square - a_square * b + .25 * a_square;
|
||||
|
||||
while (dx < dy) {
|
||||
callback({ x, y });
|
||||
|
||||
if (decision_parameter >= 0) {
|
||||
y--;
|
||||
dy -= 2 * a_square;
|
||||
decision_parameter -= dy;
|
||||
}
|
||||
x++;
|
||||
dx += 2 * b_square;
|
||||
decision_parameter += dx + b_square;
|
||||
}
|
||||
|
||||
// For region 2:
|
||||
decision_parameter = b_square * ((x + 0.5) * (x + 0.5)) + a_square * ((y - 1) * (y - 1)) - a_square * b_square;
|
||||
|
||||
while (y >= 0) {
|
||||
callback({ x, y });
|
||||
|
||||
if (decision_parameter <= 0) {
|
||||
x++;
|
||||
dx += 2 * b_square;
|
||||
decision_parameter += dx;
|
||||
}
|
||||
y--;
|
||||
dy -= 2 * a_square;
|
||||
decision_parameter += a_square - dy;
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::fill_ellipse(IntRect const& a_rect, Color color)
|
||||
{
|
||||
VERIFY(scale() == 1); // FIXME: Add scaling support.
|
||||
@ -498,57 +547,13 @@ void Painter::draw_ellipse_intersecting(IntRect const& rect, Color color, int th
|
||||
|
||||
auto const center = rect.center();
|
||||
|
||||
auto const draw_real_world_x4 = [this, &color, thickness, center](int x, int y) {
|
||||
IntPoint const directions[4] = { { x, y }, { x, -y }, { -x, y }, { -x, -y } };
|
||||
for (auto const& delta : directions) {
|
||||
on_each_ellipse_point(rect, [this, &color, thickness, center](IntPoint position) {
|
||||
IntPoint const directions[4] = { { position.x(), position.y() }, { position.x(), -position.y() }, { -position.x(), position.y() }, { -position.x(), -position.y() } };
|
||||
for (auto const delta : directions) {
|
||||
auto const point = center + delta;
|
||||
draw_line(point, point, color, thickness);
|
||||
}
|
||||
};
|
||||
|
||||
// Note: This is an implementation of the Midpoint Ellipse Algorithm:
|
||||
double const a = rect.width() / 2;
|
||||
double const a_square = a * a;
|
||||
double const b = rect.height() / 2;
|
||||
double const b_square = b * b;
|
||||
|
||||
int x = 0;
|
||||
auto y = static_cast<int>(b);
|
||||
|
||||
double dx = 2 * b_square * x;
|
||||
double dy = 2 * a_square * y;
|
||||
|
||||
// For region 1:
|
||||
auto decision_parameter = b_square - a_square * b + .25 * a_square;
|
||||
|
||||
while (dx < dy) {
|
||||
draw_real_world_x4(x, y);
|
||||
|
||||
if (decision_parameter >= 0) {
|
||||
y--;
|
||||
dy -= 2 * a_square;
|
||||
decision_parameter -= dy;
|
||||
}
|
||||
x++;
|
||||
dx += 2 * b_square;
|
||||
decision_parameter += dx + b_square;
|
||||
}
|
||||
|
||||
// For region 2:
|
||||
decision_parameter = b_square * ((x + 0.5) * (x + 0.5)) + a_square * ((y - 1) * (y - 1)) - a_square * b_square;
|
||||
|
||||
while (y >= 0) {
|
||||
draw_real_world_x4(x, y);
|
||||
|
||||
if (decision_parameter <= 0) {
|
||||
x++;
|
||||
dx += 2 * b_square;
|
||||
decision_parameter += dx;
|
||||
}
|
||||
y--;
|
||||
dy -= 2 * a_square;
|
||||
decision_parameter += a_square - dy;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template<typename RectType, typename Callback>
|
||||
|
Loading…
Reference in New Issue
Block a user