Browse Source

LibGFX: Transform vertices when drawing antialiased lines

Previously we transformed each rasterized point when drawing a line.
Now we transform the lines' endpoints instead.

That means running two transforms per line instead of transforms for
each pixel. It is not clear that the overhead for the fast path is
still worth it. If we still want to optimize identity and translations,
it is probably better to do that inside AffineTransform.

In addition this will behave nicer if the transform includes scaling.
Previously this would rasterize lines before scaling. Which means
drawing too many points when scaling down, and not drawing enough
points when scaling up.
With the new approach we will automatically rasterize at pixel scale.

This is essentially the same as OpenGL, where vertices are transformed
and rasterization happens in screen space.
Florian Stellbrink 3 years ago
parent
commit
af3174c9ce

+ 7 - 20
Userland/Libraries/LibGfx/AntiAliasingPainter.cpp

@@ -16,7 +16,7 @@
 
 
 // Base algorithm from https://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm,
 // Base algorithm from https://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm,
 // because there seems to be no other known method for drawing AA'd lines (?)
 // because there seems to be no other known method for drawing AA'd lines (?)
-template<Gfx::AntiAliasingPainter::AntiAliasPolicy policy, bool apply_transform>
+template<Gfx::AntiAliasingPainter::AntiAliasPolicy policy>
 void Gfx::AntiAliasingPainter::draw_anti_aliased_line(FloatPoint const& actual_from, FloatPoint const& actual_to, Color color, float thickness, Gfx::Painter::LineStyle style, Color)
 void Gfx::AntiAliasingPainter::draw_anti_aliased_line(FloatPoint const& actual_from, FloatPoint const& actual_to, Color color, float thickness, Gfx::Painter::LineStyle style, Color)
 {
 {
     // FIXME: Implement this :P
     // FIXME: Implement this :P
@@ -25,10 +25,7 @@ void Gfx::AntiAliasingPainter::draw_anti_aliased_line(FloatPoint const& actual_f
     auto corrected_thickness = thickness > 1 ? thickness - 1 : thickness;
     auto corrected_thickness = thickness > 1 ? thickness - 1 : thickness;
     auto size = IntSize(corrected_thickness, corrected_thickness);
     auto size = IntSize(corrected_thickness, corrected_thickness);
     auto plot = [&](int x, int y, float c) {
     auto plot = [&](int x, int y, float c) {
-        Gfx::IntPoint center { x, y };
-        if constexpr (apply_transform)
-            center = m_transform.map(center);
-        m_underlying_painter.fill_rect(IntRect::centered_on(center, size), color.with_alpha(color.alpha() * c));
+        m_underlying_painter.fill_rect(IntRect::centered_on({ x, y }, size), color.with_alpha(color.alpha() * c));
     };
     };
 
 
     auto integer_part = [](float x) { return floorf(x); };
     auto integer_part = [](float x) { return floorf(x); };
@@ -115,29 +112,19 @@ void Gfx::AntiAliasingPainter::draw_anti_aliased_line(FloatPoint const& actual_f
         }
         }
     };
     };
 
 
-    draw_line(actual_from.x(), actual_from.y(), actual_to.x(), actual_to.y());
+    auto mapped_from = m_transform.map(actual_from);
+    auto mapped_to = m_transform.map(actual_to);
+    draw_line(mapped_from.x(), mapped_from.y(), mapped_to.x(), mapped_to.y());
 }
 }
 
 
 void Gfx::AntiAliasingPainter::draw_aliased_line(FloatPoint const& actual_from, FloatPoint const& actual_to, Color color, float thickness, Gfx::Painter::LineStyle style, Color alternate_color)
 void Gfx::AntiAliasingPainter::draw_aliased_line(FloatPoint const& actual_from, FloatPoint const& actual_to, Color color, float thickness, Gfx::Painter::LineStyle style, Color alternate_color)
 {
 {
-    if (m_transform.is_identity_or_translation()) {
-        m_underlying_painter.translate(m_transform.e(), m_transform.f());
-        draw_anti_aliased_line<AntiAliasPolicy::OnlyEnds, false>(actual_from, actual_to, color, thickness, style, alternate_color);
-        m_underlying_painter.translate(-m_transform.e(), -m_transform.f());
-    } else {
-        draw_anti_aliased_line<AntiAliasPolicy::OnlyEnds, true>(actual_from, actual_to, color, thickness, style, alternate_color);
-    }
+    draw_anti_aliased_line<AntiAliasPolicy::OnlyEnds>(actual_from, actual_to, color, thickness, style, alternate_color);
 }
 }
 
 
 void Gfx::AntiAliasingPainter::draw_line(FloatPoint const& actual_from, FloatPoint const& actual_to, Color color, float thickness, Gfx::Painter::LineStyle style, Color alternate_color)
 void Gfx::AntiAliasingPainter::draw_line(FloatPoint const& actual_from, FloatPoint const& actual_to, Color color, float thickness, Gfx::Painter::LineStyle style, Color alternate_color)
 {
 {
-    if (m_transform.is_identity_or_translation()) {
-        m_underlying_painter.translate(m_transform.e(), m_transform.f());
-        draw_anti_aliased_line<AntiAliasPolicy::Full, false>(actual_from, actual_to, color, thickness, style, alternate_color);
-        m_underlying_painter.translate(-m_transform.e(), -m_transform.f());
-    } else {
-        draw_anti_aliased_line<AntiAliasPolicy::Full, true>(actual_from, actual_to, color, thickness, style, alternate_color);
-    }
+    draw_anti_aliased_line<AntiAliasPolicy::Full>(actual_from, actual_to, color, thickness, style, alternate_color);
 }
 }
 
 
 void Gfx::AntiAliasingPainter::fill_path(Path& path, Color color, Painter::WindingRule rule)
 void Gfx::AntiAliasingPainter::fill_path(Path& path, Color color, Painter::WindingRule rule)

+ 1 - 1
Userland/Libraries/LibGfx/AntiAliasingPainter.h

@@ -37,7 +37,7 @@ private:
         OnlyEnds,
         OnlyEnds,
         Full,
         Full,
     };
     };
-    template<AntiAliasPolicy policy, bool apply_transform>
+    template<AntiAliasPolicy policy>
     void draw_anti_aliased_line(FloatPoint const&, FloatPoint const&, Color, float thickness, Painter::LineStyle style, Color alternate_color);
     void draw_anti_aliased_line(FloatPoint const&, FloatPoint const&, Color, float thickness, Painter::LineStyle style, Color alternate_color);
 
 
     Painter& m_underlying_painter;
     Painter& m_underlying_painter;