mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 07:30:19 +00:00
LibGfx: Use the Midpoint Ellipse Algorithm
It is only used to draw non-antialiased and non-filled ellipses.
This commit is contained in:
parent
09841f56ed
commit
4219d50a21
Notes:
sideshowbarker
2024-07-17 04:05:12 +09:00
Author: https://github.com/LucasChollet Commit: https://github.com/SerenityOS/serenity/commit/4219d50a21 Pull-request: https://github.com/SerenityOS/serenity/pull/16056 Reviewed-by: https://github.com/idispatch ✅
2 changed files with 51 additions and 17 deletions
|
@ -37,17 +37,10 @@ void EllipseTool::draw_using(GUI::Painter& painter, Gfx::IntPoint const& start_p
|
|||
|
||||
switch (m_fill_mode) {
|
||||
case FillMode::Outline:
|
||||
if (m_antialias_enabled) {
|
||||
if (m_antialias_enabled)
|
||||
aa_painter.draw_ellipse(ellipse_intersecting_rect, m_editor->color_for(m_drawing_button), thickness);
|
||||
} else {
|
||||
// For some reason for non-AA draw_ellipse() the ellipse is outside of the rect (unlike all other ellipse drawing functions).
|
||||
// Scale the ellipse rect by sqrt(2) to get an ellipse arc that appears as if it was inside of the rect.
|
||||
// Ie. reduce the size by a factor of 1 - sqrt(1/2)
|
||||
auto shrink_width = ellipse_intersecting_rect.width() * (1 - AK::Sqrt1_2<float>);
|
||||
auto shrink_height = ellipse_intersecting_rect.height() * (1 - AK::Sqrt1_2<float>);
|
||||
ellipse_intersecting_rect.shrink(shrink_width, shrink_height);
|
||||
else
|
||||
painter.draw_ellipse_intersecting(ellipse_intersecting_rect, m_editor->color_for(m_drawing_button), thickness);
|
||||
}
|
||||
break;
|
||||
case FillMode::Fill:
|
||||
if (m_antialias_enabled)
|
||||
|
|
|
@ -496,17 +496,58 @@ void Painter::draw_ellipse_intersecting(IntRect const& rect, Color color, int th
|
|||
if (thickness <= 0)
|
||||
return;
|
||||
|
||||
constexpr int number_samples = 100; // FIXME: dynamically work out the number of samples based upon the rect size
|
||||
float increment = AK::Pi<float> / number_samples;
|
||||
auto const center = rect.center();
|
||||
|
||||
auto ellipse_xy = [&rect](float theta) -> IntPoint {
|
||||
float s, c;
|
||||
AK::sincos(theta, s, c);
|
||||
return IntPoint { (c * rect.width() * AK::Sqrt1_2<float>), (s * rect.height() * AK::Sqrt1_2<float>)} + 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) {
|
||||
auto const point = center + delta;
|
||||
draw_line(point, point, color, thickness);
|
||||
}
|
||||
};
|
||||
|
||||
for (auto theta = 0.f; theta < 2 * AK::Pi<float>; theta += increment) {
|
||||
draw_line(ellipse_xy(theta), ellipse_xy(theta + increment), 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue