LibWeb: Hook up canvas lineCap and plumb it to LibGfx
To rebaseline image test expecatations, I ran: out/gn/Ladybird.app/Contents/MacOS/headless-browser \ --resources $PWD/out/gn/Ladybird.app/Contents/Resources \ --dump-failed-ref-tests \ --run-tests $PWD/Tests/LibWeb \ --filter 'canvas-*' I then copied over the new baselines with D=Tests/LibWeb/Ref/reference/images cp test-dumps/canvas-implict-moves-and-lines.png \ $D/canvas-implict-moves-and-lines-ref.png (Note: No `-ref` suffix on first path, yes suffix on second path.) We currently don't track if a path is open or closed, and paint butt linecaps at the end of closed paths too. We did that with round linecaps as well, but there that wasn't visible. This makes closed paths look a bit weird now; we'll have to fix this in a follow-up. In a way, this just exposes another not-yet-implemented feature.
Before Width: | Height: | Size: 999 B After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 34 KiB |
|
@ -192,12 +192,12 @@ void AntiAliasingPainter::draw_line(FloatPoint actual_from, FloatPoint actual_to
|
|||
draw_anti_aliased_line(actual_from, actual_to, color, thickness, style, alternate_color, line_length_mode);
|
||||
}
|
||||
|
||||
void AntiAliasingPainter::stroke_path(Path const& path, Color color, float thickness)
|
||||
void AntiAliasingPainter::stroke_path(Path const& path, Color color, float thickness, Path::CapStyle cap_style)
|
||||
{
|
||||
if (thickness <= 0)
|
||||
return;
|
||||
// FIXME: Cache this? Probably at a higher level such as in LibWeb?
|
||||
fill_path(path.stroke_to_fill(thickness), color);
|
||||
fill_path(path.stroke_to_fill(thickness, cap_style), color);
|
||||
}
|
||||
|
||||
void AntiAliasingPainter::stroke_path(Path const& path, Gfx::PaintStyle const& paint_style, float thickness, float opacity, Path::CapStyle cap_style)
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
void fill_path(Path const&, Color, Painter::WindingRule rule = Painter::WindingRule::Nonzero);
|
||||
void fill_path(Path const&, PaintStyle const& paint_style, float opacity = 1.0f, Painter::WindingRule rule = Painter::WindingRule::Nonzero);
|
||||
|
||||
void stroke_path(Path const&, Color, float thickness);
|
||||
void stroke_path(Path const&, Color, float thickness, Path::CapStyle cap_style = Path::CapStyle::Round);
|
||||
void stroke_path(Path const&, PaintStyle const& paint_style, float thickness, float opacity = 1.0f, Path::CapStyle cap_style = Path::CapStyle::Round);
|
||||
|
||||
void translate(float dx, float dy) { m_transform.translate(dx, dy); }
|
||||
|
|
|
@ -31,6 +31,18 @@ public:
|
|||
return my_drawing_state().line_width;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-linecap
|
||||
void set_line_cap(Bindings::CanvasLineCap line_cap)
|
||||
{
|
||||
// On setting, the current value must be changed to the new value.
|
||||
my_drawing_state().line_cap = line_cap;
|
||||
}
|
||||
Bindings::CanvasLineCap line_cap() const
|
||||
{
|
||||
// On getting, it must return the current value.
|
||||
return my_drawing_state().line_cap;
|
||||
}
|
||||
|
||||
protected:
|
||||
CanvasPathDrawingStyles() = default;
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// https://html.spec.whatwg.org/multipage/canvas.html#canvaslinecap
|
||||
enum CanvasLineCap { "butt", "round", "square" };
|
||||
enum CanvasLineJoin { "round", "bevel", "miter" };
|
||||
// enum CanvasLineCap { "butt", "round", "square" };
|
||||
// enum CanvasLineJoin { "round", "bevel", "miter" };
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#canvaspathdrawingstyles
|
||||
interface mixin CanvasPathDrawingStyles {
|
||||
attribute unrestricted double lineWidth;
|
||||
[FIXME] attribute CanvasLineCap lineCap;
|
||||
attribute CanvasLineCap lineCap;
|
||||
[FIXME] attribute CanvasLineJoin lineJoin;
|
||||
[FIXME] attribute unrestricted double miterLimit;
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ public:
|
|||
FillOrStrokeStyle fill_style { Gfx::Color::Black };
|
||||
FillOrStrokeStyle stroke_style { Gfx::Color::Black };
|
||||
float line_width { 1 };
|
||||
Bindings::CanvasLineCap line_cap { Bindings::CanvasLineCap::Butt };
|
||||
bool image_smoothing_enabled { true };
|
||||
Bindings::ImageSmoothingQuality image_smoothing_quality { Bindings::ImageSmoothingQuality::Low };
|
||||
float global_alpha = { 1 };
|
||||
|
|
|
@ -319,10 +319,22 @@ void CanvasRenderingContext2D::stroke_internal(Gfx::Path const& path)
|
|||
{
|
||||
draw_clipped([&](auto& painter) {
|
||||
auto& drawing_state = this->drawing_state();
|
||||
Gfx::Path::CapStyle line_cap = [](Bindings::CanvasLineCap cap) {
|
||||
switch (cap) {
|
||||
case Bindings::CanvasLineCap::Butt:
|
||||
return Gfx::Path::CapStyle::Butt;
|
||||
case Bindings::CanvasLineCap::Round:
|
||||
return Gfx::Path::CapStyle::Round;
|
||||
case Bindings::CanvasLineCap::Square:
|
||||
// FIXME: Use LineCapStyle::Square once implemented.
|
||||
return Gfx::Path::CapStyle::Round;
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}(drawing_state.line_cap);
|
||||
if (auto color = drawing_state.stroke_style.as_color(); color.has_value()) {
|
||||
painter.stroke_path(path, color->with_opacity(drawing_state.global_alpha), drawing_state.line_width);
|
||||
painter.stroke_path(path, color->with_opacity(drawing_state.global_alpha), drawing_state.line_width, line_cap);
|
||||
} else {
|
||||
painter.stroke_path(path, drawing_state.stroke_style.to_gfx_paint_style(), drawing_state.line_width, drawing_state.global_alpha);
|
||||
painter.stroke_path(path, drawing_state.stroke_style.to_gfx_paint_style(), drawing_state.line_width, drawing_state.global_alpha, line_cap);
|
||||
}
|
||||
return path.bounding_box();
|
||||
});
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
|
||||
enum ImageSmoothingQuality { "low", "medium", "high" };
|
||||
|
||||
// FIXME: This should be in CanvasPathDrawingStyles.idl but then it is not exported
|
||||
enum CanvasLineCap { "butt", "round", "square" };
|
||||
enum CanvasLineJoin { "round", "bevel", "miter" };
|
||||
|
||||
// FIXME: This should be in CanvasTextDrawingStyles.idl but then it is not exported
|
||||
enum CanvasTextAlign { "start", "end", "left", "right", "center" };
|
||||
enum CanvasTextBaseline { "top", "hanging", "middle", "alphabetic", "ideographic", "bottom" };
|
||||
|
|