LibWeb: Plumb svg stroking state to DisplayListPlayerSkia

The state is still ignored there, so no behavior change, but this
should make it fairly easy to actually implement complete stroking
support for SVGs.
This commit is contained in:
Nico Weber 2024-11-21 15:09:31 -05:00
parent fbe9395928
commit bd389d259b
7 changed files with 96 additions and 3 deletions

View file

@ -72,6 +72,19 @@ public:
void line_to(Gfx::FloatPoint const& point) { impl().line_to(point); }
void close_all_subpaths() { impl().close_all_subpaths(); }
void close() { impl().close(); }
enum class CapStyle {
Butt,
Round,
Square,
};
enum class JoinStyle {
Miter,
Round,
Bevel,
};
void elliptical_arc_to(FloatPoint point, FloatSize radii, float x_axis_rotation, bool large_arc, bool sweep) { impl().elliptical_arc_to(point, radii, x_axis_rotation, large_arc, sweep); }
void arc_to(FloatPoint point, float radius, bool large_arc, bool sweep) { impl().arc_to(point, radius, large_arc, sweep); }
void quadratic_bezier_curve_to(FloatPoint through, FloatPoint point) { impl().quadratic_bezier_curve_to(through, point); }

View file

@ -216,6 +216,11 @@ struct FillPathUsingPaintStyle {
};
struct StrokePathUsingColor {
Gfx::Path::CapStyle cap_style;
Gfx::Path::JoinStyle join_style;
float miter_limit;
Vector<float> dash_array;
float dash_offset;
Gfx::IntRect path_bounding_rect;
Gfx::Path path;
Color color;
@ -232,6 +237,11 @@ struct StrokePathUsingColor {
};
struct StrokePathUsingPaintStyle {
Gfx::Path::CapStyle cap_style;
Gfx::Path::JoinStyle join_style;
float miter_limit;
Vector<float> dash_array;
float dash_offset;
Gfx::IntRect path_bounding_rect;
Gfx::Path path;
PaintStyle paint_style;

View file

@ -817,6 +817,7 @@ void DisplayListPlayerSkia::stroke_path_using_color(StrokePathUsingColor const&
if (!command.thickness)
return;
// FIXME: Use .cap_style, .join_style, .miter_limit, .dash_array, .dash_offset.
auto& canvas = surface().canvas();
SkPaint paint;
paint.setAntiAlias(true);
@ -834,6 +835,7 @@ void DisplayListPlayerSkia::stroke_path_using_paint_style(StrokePathUsingPaintSt
if (!command.thickness)
return;
// FIXME: Use .cap_style, .join_style, .miter_limit, .dash_array, .dash_offset.
auto path = to_skia_path(command.path);
path.offset(command.aa_translation.x(), command.aa_translation.y());
auto paint = paint_style_to_skia_paint(*command.paint_style, command.bounding_rect().to_type<float>());

View file

@ -86,6 +86,11 @@ void DisplayListRecorder::stroke_path(StrokePathUsingColorParams params)
if (path_bounding_rect.is_empty())
return;
append(StrokePathUsingColor {
.cap_style = params.cap_style,
.join_style = params.join_style,
.miter_limit = params.miter_limit,
.dash_array = move(params.dash_array),
.dash_offset = params.dash_offset,
.path_bounding_rect = path_bounding_rect,
.path = move(params.path),
.color = params.color,
@ -103,6 +108,11 @@ void DisplayListRecorder::stroke_path(StrokePathUsingPaintStyleParams params)
if (path_bounding_rect.is_empty())
return;
append(StrokePathUsingPaintStyle {
.cap_style = params.cap_style,
.join_style = params.join_style,
.miter_limit = params.miter_limit,
.dash_array = move(params.dash_array),
.dash_offset = params.dash_offset,
.path_bounding_rect = path_bounding_rect,
.path = move(params.path),
.paint_style = params.paint_style,

View file

@ -61,6 +61,11 @@ public:
void fill_path(FillPathUsingPaintStyleParams params);
struct StrokePathUsingColorParams {
Gfx::Path::CapStyle cap_style;
Gfx::Path::JoinStyle join_style;
float miter_limit;
Vector<float> dash_array;
float dash_offset;
Gfx::Path path;
Gfx::Color color;
float thickness;
@ -69,6 +74,11 @@ public:
void stroke_path(StrokePathUsingColorParams params);
struct StrokePathUsingPaintStyleParams {
Gfx::Path::CapStyle cap_style;
Gfx::Path::JoinStyle join_style;
float miter_limit;
Vector<float> dash_array;
float dash_offset;
Gfx::Path path;
PaintStyle paint_style;
float thickness;

View file

@ -234,7 +234,16 @@ void MediaPaintable::paint_control_bar_speaker(PaintContext& context, HTML::HTML
path.quadratic_bezier_curve_to(device_point(16, 7.5), device_point(13, 12));
path.move_to(device_point(14, 0));
path.quadratic_bezier_curve_to(device_point(20, 7.5), device_point(14, 15));
context.display_list_recorder().stroke_path({ .path = path, .color = speaker_button_color, .thickness = 1 });
context.display_list_recorder().stroke_path({
.cap_style = Gfx::Path::CapStyle::Round,
.join_style = Gfx::Path::JoinStyle::Round,
.miter_limit = 4,
.dash_array = {},
.dash_offset = 0,
.path = path,
.color = speaker_button_color,
.thickness = 1,
});
if (media_element.muted()) {
context.display_list_recorder().draw_line(device_point(0, 0).to_type<int>(), device_point(20, 15).to_type<int>(), Color::Red, 2);

View file

@ -129,17 +129,51 @@ void SVGPathPaintable::paint(PaintContext& context, PaintPhase phase) const
});
}
auto stroke_linecap = graphics_element.stroke_linecap().value_or(CSS::StrokeLinecap::Butt);
(void)stroke_linecap; // FIXME: Use
Gfx::Path::CapStyle cap_style;
switch (graphics_element.stroke_linecap().value_or(CSS::InitialValues::stroke_linecap())) {
case CSS::StrokeLinecap::Butt:
cap_style = Gfx::Path::CapStyle::Butt;
break;
case CSS::StrokeLinecap::Round:
cap_style = Gfx::Path::CapStyle::Round;
break;
case CSS::StrokeLinecap::Square:
cap_style = Gfx::Path::CapStyle::Square;
break;
}
Gfx::Path::JoinStyle join_style;
switch (graphics_element.stroke_linejoin().value_or(CSS::InitialValues::stroke_linejoin())) {
case CSS::StrokeLinejoin::Miter:
join_style = Gfx::Path::JoinStyle::Miter;
break;
case CSS::StrokeLinejoin::Round:
join_style = Gfx::Path::JoinStyle::Round;
break;
case CSS::StrokeLinejoin::Bevel:
join_style = Gfx::Path::JoinStyle::Bevel;
break;
}
auto miter_limit = graphics_element.stroke_miterlimit().value_or(CSS::InitialValues::stroke_miterlimit()).resolved(layout_node());
auto stroke_opacity = graphics_element.stroke_opacity().value_or(1);
// Note: This is assuming .x_scale() == .y_scale() (which it does currently).
auto viewbox_scale = paint_transform.x_scale();
float stroke_thickness = graphics_element.stroke_width().value_or(1) * viewbox_scale;
auto stroke_dasharray = graphics_element.stroke_dasharray();
for (auto& value : stroke_dasharray)
value *= viewbox_scale;
float stroke_dashoffset = graphics_element.stroke_dashoffset().value_or(0) * viewbox_scale;
if (auto paint_style = graphics_element.stroke_paint_style(paint_context); paint_style.has_value()) {
context.display_list_recorder().stroke_path({
.cap_style = cap_style,
.join_style = join_style,
.miter_limit = static_cast<float>(miter_limit),
.dash_array = stroke_dasharray,
.dash_offset = stroke_dashoffset,
.path = path,
.paint_style = *paint_style,
.thickness = stroke_thickness,
@ -148,6 +182,11 @@ void SVGPathPaintable::paint(PaintContext& context, PaintPhase phase) const
});
} else if (auto stroke_color = graphics_element.stroke_color(); stroke_color.has_value()) {
context.display_list_recorder().stroke_path({
.cap_style = cap_style,
.join_style = join_style,
.miter_limit = static_cast<float>(miter_limit),
.dash_array = stroke_dasharray,
.dash_offset = stroke_dashoffset,
.path = path,
.color = stroke_color->with_opacity(stroke_opacity),
.thickness = stroke_thickness,