mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-07 19:57:45 +03:00
LibWeb: Use Gfx::AntiAliasingPainter to draw SVG paths
This is still quite bad, but it's much more pleasing to look at when drawing random SVGs :^)
This commit is contained in:
parent
e2cd558101
commit
5a2e7d30ce
Notes:
sideshowbarker
2024-07-18 03:45:31 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/5a2e7d30ce2 Pull-request: https://github.com/SerenityOS/serenity/pull/10082
@ -16,7 +16,8 @@ static float fractional_part(float x)
|
||||
|
||||
// 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 (?)
|
||||
void Gfx::AntiAliasingPainter::draw_line(FloatPoint const& actual_from, FloatPoint const& actual_to, Color color, float thickness, Gfx::Painter::LineStyle style, Color)
|
||||
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)
|
||||
{
|
||||
// FIXME: Implement this :P
|
||||
VERIFY(style == Painter::LineStyle::Solid);
|
||||
@ -76,10 +77,18 @@ void Gfx::AntiAliasingPainter::draw_line(FloatPoint const& actual_from, FloatPoi
|
||||
auto x = first_end_point.x();
|
||||
while (x < last_end_point.x()) {
|
||||
if (is_steep) {
|
||||
draw_point({ floorf(next_intersection), x }, color_with_alpha(1 - fractional_part(next_intersection)));
|
||||
if constexpr (policy == AntiAliasPolicy::OnlyEnds) {
|
||||
draw_point({ floorf(next_intersection), x }, color);
|
||||
} else {
|
||||
draw_point({ floorf(next_intersection), x }, color_with_alpha(1 - fractional_part(next_intersection)));
|
||||
}
|
||||
draw_point({ floorf(next_intersection) + 1, x }, color_with_alpha(fractional_part(next_intersection)));
|
||||
} else {
|
||||
draw_point({ x, floorf(next_intersection) }, color_with_alpha(1 - fractional_part(next_intersection)));
|
||||
if constexpr (policy == AntiAliasPolicy::OnlyEnds) {
|
||||
draw_point({ x, floorf(next_intersection) }, color);
|
||||
} else {
|
||||
draw_point({ x, floorf(next_intersection) }, color_with_alpha(1 - fractional_part(next_intersection)));
|
||||
}
|
||||
draw_point({ x, floorf(next_intersection) + 1 }, color_with_alpha(fractional_part(next_intersection)));
|
||||
}
|
||||
next_intersection += delta_y;
|
||||
@ -87,6 +96,16 @@ void Gfx::AntiAliasingPainter::draw_line(FloatPoint const& actual_from, FloatPoi
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Detail::fill_path<Detail::FillPathMode::AllowFloatingPoints>(*this, path, color, rule);
|
||||
|
@ -18,6 +18,7 @@ public:
|
||||
}
|
||||
|
||||
void draw_line(FloatPoint const&, FloatPoint const&, Color, float thickness = 1, Painter::LineStyle style = Painter::LineStyle::Solid, Color alternate_color = Color::Transparent);
|
||||
void draw_aliased_line(FloatPoint const&, FloatPoint const&, Color, float thickness = 1, Painter::LineStyle style = Painter::LineStyle::Solid, Color alternate_color = Color::Transparent);
|
||||
void fill_path(Path&, Color, Painter::WindingRule rule = Painter::WindingRule::Nonzero);
|
||||
void stroke_path(Path const&, Color, float thickness);
|
||||
void draw_quadratic_bezier_curve(FloatPoint const& control_point, FloatPoint const&, FloatPoint const&, Color, float thickness = 1, Painter::LineStyle style = Painter::LineStyle::Solid);
|
||||
@ -27,6 +28,13 @@ public:
|
||||
void translate(FloatPoint const& delta) { m_transform.translate(delta); }
|
||||
|
||||
private:
|
||||
enum class AntiAliasPolicy {
|
||||
OnlyEnds,
|
||||
Full,
|
||||
};
|
||||
template<AntiAliasPolicy policy>
|
||||
void draw_anti_aliased_line(FloatPoint const&, FloatPoint const&, Color, float thickness, Painter::LineStyle style, Color alternate_color);
|
||||
|
||||
Painter& m_underlying_painter;
|
||||
AffineTransform m_transform;
|
||||
};
|
||||
|
@ -46,6 +46,12 @@ void fill_path(Painter& painter, Path const& path, Color color, Gfx::Painter::Wi
|
||||
{
|
||||
using GridCoordinateType = Conditional<fill_path_mode == FillPathMode::PlaceOnIntGrid, int, float>;
|
||||
using PointType = Point<GridCoordinateType>;
|
||||
auto draw_line = [&](auto... args) {
|
||||
if constexpr (requires { painter.draw_aliased_line(args...); })
|
||||
painter.draw_aliased_line(args...);
|
||||
else
|
||||
painter.draw_line(args...);
|
||||
};
|
||||
|
||||
auto const& segments = path.split_lines();
|
||||
|
||||
@ -130,7 +136,7 @@ void fill_path(Painter& painter, Path const& path, Color color, Gfx::Painter::Wi
|
||||
// inside the shape
|
||||
|
||||
dbgln_if(FILL_PATH_DEBUG, "y={}: {} at {}: {} -- {}", scanline, winding_number, i, from, to);
|
||||
painter.draw_line(from, to, color, 1);
|
||||
draw_line(from, to, color, 1);
|
||||
}
|
||||
|
||||
auto is_passing_through_maxima = scanline == previous.maximum_y
|
||||
@ -153,7 +159,7 @@ void fill_path(Painter& painter, Path const& path, Color color, Gfx::Painter::Wi
|
||||
active_list.last().x -= active_list.last().inverse_slope;
|
||||
} else {
|
||||
auto point = PointType(active_list[0].x, scanline);
|
||||
painter.draw_line(point, point, color);
|
||||
draw_line(point, point, color);
|
||||
|
||||
// update the x coord
|
||||
active_list.first().x -= active_list.first().inverse_slope;
|
||||
@ -183,7 +189,7 @@ void fill_path(Painter& painter, Path const& path, Color color, Gfx::Painter::Wi
|
||||
if constexpr (FILL_PATH_DEBUG) {
|
||||
size_t i { 0 };
|
||||
for (auto& segment : segments) {
|
||||
painter.draw_line(PointType(segment.from), PointType(segment.to), Color::from_hsv(i++ * 360.0 / segments.size(), 1.0, 1.0), 1);
|
||||
draw_line(PointType(segment.from), PointType(segment.to), Color::from_hsv(i++ * 360.0 / segments.size(), 1.0, 1.0), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibGfx/AntiAliasingPainter.h>
|
||||
#include <LibGfx/Painter.h>
|
||||
#include <LibWeb/Layout/SVGPathBox.h>
|
||||
#include <LibWeb/SVG/SVGPathElement.h>
|
||||
@ -47,10 +48,10 @@ void SVGPathBox::paint(PaintContext& context, PaintPhase phase)
|
||||
closed_path.close();
|
||||
|
||||
// Fills are computed as though all paths are closed (https://svgwg.org/svg2-draft/painting.html#FillProperties)
|
||||
auto& painter = context.painter();
|
||||
Gfx::AntiAliasingPainter painter { context.painter() };
|
||||
auto& svg_context = context.svg_context();
|
||||
|
||||
auto offset = (absolute_position() - effective_offset()).to_type<int>();
|
||||
auto offset = absolute_position() - effective_offset();
|
||||
|
||||
painter.translate(offset);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user