From 137038b1850b76197fd2b302d978ea468a2fffac Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 9 Aug 2024 14:00:10 +0200 Subject: [PATCH] LibWeb: Port painting to use the new Skia-backed Gfx::Path SVG and and CSS border rendering now sits on top of SkPath instead of the old Gfx::DeprecatedPath. Due to an imperceptible (255, 255, 255) vs (255, 254, 255) color diff in one ref test, I changed that test to not depend on border rendering for a positive result, since that was incidental. --- .../css-namespace-tag-name-selector.txt | 8 +-- .../svg-text-with-percentage-values.txt | 16 +++--- .../Layout/expected/svg-text-with-viewbox.txt | 16 +++--- ...scrollable-contains-rotated-boxes-ref.html | 2 - .../scrollable-contains-rotated-boxes.html | 2 - Userland/Libraries/LibGfx/Path.h | 5 ++ Userland/Libraries/LibGfx/PathSkia.cpp | 40 ++++++++++++++ Userland/Libraries/LibGfx/PathSkia.h | 1 + .../Libraries/LibWeb/Layout/LayoutState.h | 5 +- .../LibWeb/Layout/SVGFormattingContext.cpp | 9 ++-- .../LibWeb/Layout/SVGFormattingContext.h | 4 +- .../LibWeb/Painting/BorderPainting.cpp | 4 +- .../LibWeb/Painting/BorderPainting.h | 2 +- .../LibWeb/Painting/CheckBoxPaintable.cpp | 4 +- Userland/Libraries/LibWeb/Painting/Command.h | 9 ++-- .../LibWeb/Painting/DisplayListPlayerSkia.cpp | 53 ++----------------- .../LibWeb/Painting/DisplayListRecorder.cpp | 8 +-- .../LibWeb/Painting/DisplayListRecorder.h | 9 ++-- .../LibWeb/Painting/MarkerPaintable.cpp | 4 +- .../LibWeb/Painting/MediaPaintable.cpp | 4 +- .../LibWeb/Painting/SVGPathPaintable.cpp | 2 +- .../LibWeb/Painting/SVGPathPaintable.h | 7 +-- .../Libraries/LibWeb/SVG/SVGCircleElement.cpp | 5 +- .../Libraries/LibWeb/SVG/SVGCircleElement.h | 2 +- .../LibWeb/SVG/SVGEllipseElement.cpp | 5 +- .../Libraries/LibWeb/SVG/SVGEllipseElement.h | 2 +- .../Libraries/LibWeb/SVG/SVGGeometryElement.h | 2 +- .../Libraries/LibWeb/SVG/SVGLineElement.cpp | 5 +- .../Libraries/LibWeb/SVG/SVGLineElement.h | 2 +- .../Libraries/LibWeb/SVG/SVGPathElement.cpp | 19 ++----- .../Libraries/LibWeb/SVG/SVGPathElement.h | 3 +- .../LibWeb/SVG/SVGPolygonElement.cpp | 5 +- .../Libraries/LibWeb/SVG/SVGPolygonElement.h | 2 +- .../LibWeb/SVG/SVGPolylineElement.cpp | 5 +- .../Libraries/LibWeb/SVG/SVGPolylineElement.h | 2 +- .../Libraries/LibWeb/SVG/SVGRectElement.cpp | 7 ++- .../Libraries/LibWeb/SVG/SVGRectElement.h | 2 +- 37 files changed, 139 insertions(+), 143 deletions(-) diff --git a/Tests/LibWeb/Layout/expected/css-namespace-tag-name-selector.txt b/Tests/LibWeb/Layout/expected/css-namespace-tag-name-selector.txt index aea1304ba4a..65e1f344ac1 100644 --- a/Tests/LibWeb/Layout/expected/css-namespace-tag-name-selector.txt +++ b/Tests/LibWeb/Layout/expected/css-namespace-tag-name-selector.txt @@ -7,8 +7,8 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline " " frag 2 from BlockContainer start: 0, length: 0, rect: [319,51 0x108] baseline: 110 SVGSVGBox at (9,9) content-size 300x150 [SVG] children: not-inline - SVGGraphicsBox at (29,25.015625) content-size 193.59375x67.578125 children: not-inline - SVGTextBox at (29,25.015625) content-size 193.59375x67.578125 children: inline + SVGGraphicsBox at (33.765625,32.4375) content-size 188.71875x60.15625 children: not-inline + SVGTextBox at (33.765625,32.4375) content-size 188.71875x60.15625 children: inline TextNode <#text> TextNode <#text> BlockContainer at (319,51) content-size 0x108 children: not-inline @@ -28,8 +28,8 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [8,8 784x201] PaintableWithLines (BlockContainer(anonymous)) [8,8 784x155] SVGSVGPaintable (SVGSVGBox) [8,8 302x152] - SVGGraphicsPaintable (SVGGraphicsBox) [29,25.015625 193.59375x67.578125] - SVGPathPaintable (SVGTextBox) [29,25.015625 193.59375x67.578125] + SVGGraphicsPaintable (SVGGraphicsBox) [33.765625,32.4375 188.71875x60.15625] + SVGPathPaintable (SVGTextBox) [33.765625,32.4375 188.71875x60.15625] TextPaintable (TextNode<#text>) PaintableWithLines (BlockContainer) [318,50 2x110] overflow: [319,51 100x100] PaintableWithLines (BlockContainer) [319,51 100x100] diff --git a/Tests/LibWeb/Layout/expected/svg-text-with-percentage-values.txt b/Tests/LibWeb/Layout/expected/svg-text-with-percentage-values.txt index 7ddf7e59a01..2de07cdfa78 100644 --- a/Tests/LibWeb/Layout/expected/svg-text-with-percentage-values.txt +++ b/Tests/LibWeb/Layout/expected/svg-text-with-percentage-values.txt @@ -5,16 +5,16 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline SVGSVGBox at (8,8) content-size 784x261.328125 [SVG] children: inline TextNode <#text> TextNode <#text> - SVGTextBox at (86.40625,65.5) content-size 48.109375x37.484375 children: inline + SVGTextBox at (89.46875,67.40625) content-size 46.46875x35.578125 children: inline TextNode <#text> TextNode <#text> - SVGTextBox at (141.28125,21.078125) content-size 148.234375x79.71875 children: inline + SVGTextBox at (146.25,35.34375) content-size 145.90625x65.453125 children: inline TextNode <#text> TextNode <#text> - SVGTextBox at (204,117.765625) content-size 34.578125x34.703125 children: inline + SVGTextBox at (206.6875,119.796875) content-size 32.84375x32.671875 children: inline TextNode <#text> TextNode <#text> - SVGTextBox at (243.1875,47.21875) content-size 519.484375x115.359375 children: inline + SVGTextBox at (249.828125,56.546875) content-size 514.125x106.03125 children: inline TextNode <#text> TextNode <#text> TextNode <#text> @@ -23,7 +23,7 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [0,0 800x600] PaintableWithLines (BlockContainer) [8,8 784x261.328125] SVGSVGPaintable (SVGSVGBox) [8,8 784x261.328125] - SVGPathPaintable (SVGTextBox.small) [86.40625,65.5 48.109375x37.484375] - SVGPathPaintable (SVGTextBox.heavy) [141.28125,21.078125 148.234375x79.71875] - SVGPathPaintable (SVGTextBox.small) [204,117.765625 34.578125x34.703125] - SVGPathPaintable (SVGTextBox.Rrrrr) [243.1875,47.21875 519.484375x115.359375] + SVGPathPaintable (SVGTextBox.small) [89.46875,67.40625 46.46875x35.578125] + SVGPathPaintable (SVGTextBox.heavy) [146.25,35.34375 145.90625x65.453125] + SVGPathPaintable (SVGTextBox.small) [206.6875,119.796875 32.84375x32.671875] + SVGPathPaintable (SVGTextBox.Rrrrr) [249.828125,56.546875 514.125x106.03125] diff --git a/Tests/LibWeb/Layout/expected/svg-text-with-viewbox.txt b/Tests/LibWeb/Layout/expected/svg-text-with-viewbox.txt index 3640b01c7d7..f899ec75adb 100644 --- a/Tests/LibWeb/Layout/expected/svg-text-with-viewbox.txt +++ b/Tests/LibWeb/Layout/expected/svg-text-with-viewbox.txt @@ -5,16 +5,16 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline SVGSVGBox at (8,8) content-size 784x261.328125 [SVG] children: inline TextNode <#text> TextNode <#text> - SVGTextBox at (73.328125,88.359375) content-size 48.109375x37.484375 children: inline + SVGTextBox at (76.40625,90.28125) content-size 46.46875x35.578125 children: inline TextNode <#text> TextNode <#text> - SVGTextBox at (138.65625,43.953125) content-size 148.234375x79.71875 children: inline + SVGTextBox at (143.640625,58.21875) content-size 145.90625x65.453125 children: inline TextNode <#text> TextNode <#text> - SVGTextBox at (187.65625,153.703125) content-size 34.578125x34.703125 children: inline + SVGTextBox at (190.359375,155.734375) content-size 32.84375x32.671875 children: inline TextNode <#text> TextNode <#text> - SVGTextBox at (220.328125,83.15625) content-size 519.484375x115.359375 children: inline + SVGTextBox at (226.96875,92.46875) content-size 514.125x106.03125 children: inline TextNode <#text> TextNode <#text> TextNode <#text> @@ -23,7 +23,7 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [0,0 800x600] PaintableWithLines (BlockContainer) [8,8 784x261.328125] SVGSVGPaintable (SVGSVGBox) [8,8 784x261.328125] - SVGPathPaintable (SVGTextBox.small) [73.328125,88.359375 48.109375x37.484375] - SVGPathPaintable (SVGTextBox.heavy) [138.65625,43.953125 148.234375x79.71875] - SVGPathPaintable (SVGTextBox.small) [187.65625,153.703125 34.578125x34.703125] - SVGPathPaintable (SVGTextBox.Rrrrr) [220.328125,83.15625 519.484375x115.359375] + SVGPathPaintable (SVGTextBox.small) [76.40625,90.28125 46.46875x35.578125] + SVGPathPaintable (SVGTextBox.heavy) [143.640625,58.21875 145.90625x65.453125] + SVGPathPaintable (SVGTextBox.small) [190.359375,155.734375 32.84375x32.671875] + SVGPathPaintable (SVGTextBox.Rrrrr) [226.96875,92.46875 514.125x106.03125] diff --git a/Tests/LibWeb/Ref/reference/scrollable-contains-rotated-boxes-ref.html b/Tests/LibWeb/Ref/reference/scrollable-contains-rotated-boxes-ref.html index 641a33c0d80..46222521943 100644 --- a/Tests/LibWeb/Ref/reference/scrollable-contains-rotated-boxes-ref.html +++ b/Tests/LibWeb/Ref/reference/scrollable-contains-rotated-boxes-ref.html @@ -12,13 +12,11 @@ height: 300px; overflow-y: scroll; background-color: #fff; - border: 10px solid blueviolet; } .rotated-box { width: 100px; height: 100px; margin: 10px; - border: 5px solid magenta; background-color: #3498db; overflow: hidden; } diff --git a/Tests/LibWeb/Ref/scrollable-contains-rotated-boxes.html b/Tests/LibWeb/Ref/scrollable-contains-rotated-boxes.html index 1be3336f657..910117ceb9e 100644 --- a/Tests/LibWeb/Ref/scrollable-contains-rotated-boxes.html +++ b/Tests/LibWeb/Ref/scrollable-contains-rotated-boxes.html @@ -12,13 +12,11 @@ height: 300px; overflow-y: scroll; background-color: #fff; - border: 10px solid blueviolet; } .rotated-box { width: 100px; height: 100px; margin: 10px; - border: 5px solid magenta; background-color: #3498db; transform: rotate(90deg); overflow: hidden; diff --git a/Userland/Libraries/LibGfx/Path.h b/Userland/Libraries/LibGfx/Path.h index 8c34c140e5a..f13ce69b87f 100644 --- a/Userland/Libraries/LibGfx/Path.h +++ b/Userland/Libraries/LibGfx/Path.h @@ -42,6 +42,7 @@ public: virtual NonnullOwnPtr clone() const = 0; virtual NonnullOwnPtr copy_transformed(Gfx::AffineTransform const&) const = 0; + virtual NonnullOwnPtr place_text_along(Utf8View text, Font const&) const = 0; }; class Path { @@ -74,6 +75,9 @@ public: void cubic_bezier_curve_to(FloatPoint c1, FloatPoint c2, FloatPoint p2) { impl().cubic_bezier_curve_to(c1, c2, p2); } void text(Utf8View text, Font const& font) { impl().text(text, font); } + void horizontal_line_to(float x) { line_to({ x, last_point().y() }); } + void vertical_line_to(float y) { line_to({ last_point().x(), y }); } + void append_path(Gfx::Path const& other) { impl().append_path(other); } void intersect(Gfx::Path const& other) { impl().intersect(other); } @@ -83,6 +87,7 @@ public: Gfx::Path clone() const { return Gfx::Path { impl().clone() }; } Gfx::Path copy_transformed(Gfx::AffineTransform const& transform) const { return Gfx::Path { impl().copy_transformed(transform) }; } + Gfx::Path place_text_along(Utf8View text, Font const& font) const { return Gfx::Path { impl().place_text_along(text, font) }; } void transform(Gfx::AffineTransform const& transform) { m_impl = impl().copy_transformed(transform); } diff --git a/Userland/Libraries/LibGfx/PathSkia.cpp b/Userland/Libraries/LibGfx/PathSkia.cpp index fd43a1c9f75..0d53aef8413 100644 --- a/Userland/Libraries/LibGfx/PathSkia.cpp +++ b/Userland/Libraries/LibGfx/PathSkia.cpp @@ -9,8 +9,11 @@ #include #include #include +#include #include #include +#include +#include #include #include @@ -129,6 +132,43 @@ void PathImplSkia::text(Utf8View string, Font const& font) { SkTextUtils::GetPath(string.as_string().characters_without_null_termination(), string.as_string().length(), SkTextEncoding::kUTF8, last_point().x(), last_point().y(), verify_cast(font).skia_font(1), m_path.ptr()); } +NonnullOwnPtr PathImplSkia::place_text_along(Utf8View text, Font const& font) const +{ + auto sk_font = verify_cast(font).skia_font(1); + size_t const text_length = text.length(); + SkScalar x = 0; + SkScalar y = 0; + SkTextBlobBuilder builder; + SkTextBlobBuilder::RunBuffer runBuffer = builder.allocRun(sk_font, text_length, x, y, nullptr); + sk_font.textToGlyphs(text.as_string().characters_without_null_termination(), text.as_string().length(), SkTextEncoding::kUTF8, runBuffer.glyphs, text_length); + SkPathMeasure pathMeasure(*m_path, false); + SkScalar accumulated_distance = 0; + auto output_path = PathImplSkia::create(); + for (size_t i = 0; i < text_length; ++i) { + SkGlyphID glyph = runBuffer.glyphs[i]; + SkPath glyphPath; + sk_font.getPath(glyph, &glyphPath); + + SkScalar advance; + sk_font.getWidths(&glyph, 1, &advance); + + SkPoint position; + SkVector tangent; + if (!pathMeasure.getPosTan(accumulated_distance, &position, &tangent)) + continue; + + SkMatrix matrix; + matrix.setTranslate(position.x(), position.y()); + matrix.preRotate(SkRadiansToDegrees(std::atan2(tangent.y(), tangent.x()))); + + glyphPath.transform(matrix); + output_path->sk_path().addPath(glyphPath); + + accumulated_distance += advance; + } + + return output_path; +} void PathImplSkia::append_path(Gfx::Path const& other) { diff --git a/Userland/Libraries/LibGfx/PathSkia.h b/Userland/Libraries/LibGfx/PathSkia.h index 1ed2db8b0d7..a8be8cb5854 100644 --- a/Userland/Libraries/LibGfx/PathSkia.h +++ b/Userland/Libraries/LibGfx/PathSkia.h @@ -38,6 +38,7 @@ public: virtual NonnullOwnPtr clone() const override; virtual NonnullOwnPtr copy_transformed(Gfx::AffineTransform const&) const override; + virtual NonnullOwnPtr place_text_along(Utf8View text, Font const&) const override; SkPath const& sk_path() const { return *m_path; } SkPath& sk_path() { return *m_path; } diff --git a/Userland/Libraries/LibWeb/Layout/LayoutState.h b/Userland/Libraries/LibWeb/Layout/LayoutState.h index 7bd10052033..fe0f0fcfb0c 100644 --- a/Userland/Libraries/LibWeb/Layout/LayoutState.h +++ b/Userland/Libraries/LibWeb/Layout/LayoutState.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -132,7 +133,7 @@ struct LayoutState { void set_table_cell_coordinates(Painting::PaintableBox::TableCellCoordinates const& table_cell_coordinates) { m_table_cell_coordinates = table_cell_coordinates; } auto const& table_cell_coordinates() const { return m_table_cell_coordinates; } - void set_computed_svg_path(Gfx::DeprecatedPath const& svg_path) { m_computed_svg_path = svg_path; } + void set_computed_svg_path(Gfx::Path const& svg_path) { m_computed_svg_path = svg_path; } auto& computed_svg_path() { return m_computed_svg_path; } void set_computed_svg_transforms(Painting::SVGGraphicsPaintable::ComputedTransforms const& computed_transforms) { m_computed_svg_transforms = computed_transforms; } @@ -163,7 +164,7 @@ struct LayoutState { Optional m_override_borders_data; Optional m_table_cell_coordinates; - Optional m_computed_svg_path; + Optional m_computed_svg_path; Optional m_computed_svg_transforms; }; diff --git a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp index 0e26f007391..99dd9fdcbae 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -301,7 +302,7 @@ void SVGFormattingContext::layout_nested_viewport(Box const& viewport) nested_context.run(static_cast(viewport), LayoutMode::Normal, *m_available_space); } -Gfx::DeprecatedPath SVGFormattingContext::compute_path_for_text(SVGTextBox const& text_box) +Gfx::Path SVGFormattingContext::compute_path_for_text(SVGTextBox const& text_box) { auto& text_element = static_cast(text_box.dom_node()); auto& font = text_box.first_available_font(); @@ -333,13 +334,13 @@ Gfx::DeprecatedPath SVGFormattingContext::compute_path_for_text(SVGTextBox const VERIFY_NOT_REACHED(); } - Gfx::DeprecatedPath path; + Gfx::Path path; path.move_to(text_offset); path.text(text_utf8, font); return path; } -Gfx::DeprecatedPath SVGFormattingContext::compute_path_for_text_path(SVGTextPathBox const& text_path_box) +Gfx::Path SVGFormattingContext::compute_path_for_text_path(SVGTextPathBox const& text_path_box) { auto& text_path_element = static_cast(text_path_box.dom_node()); auto path_or_shape = text_path_element.path_or_shape(); @@ -363,7 +364,7 @@ void SVGFormattingContext::layout_path_like_element(SVGGraphicsBox const& graphi .multiply(m_current_viewbox_transform) .multiply(graphics_box_state.computed_svg_transforms()->svg_transform()); - Gfx::DeprecatedPath path; + Gfx::Path path; if (is(graphics_box)) { auto& geometry_box = static_cast(graphics_box); path = const_cast(geometry_box).dom_node().get_path(m_viewport_size); diff --git a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h index cebc0cba453..7eea6ce41e8 100644 --- a/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/SVGFormattingContext.h @@ -32,8 +32,8 @@ private: void layout_path_like_element(SVGGraphicsBox const&); void layout_mask_or_clip(SVGBox const&); - Gfx::DeprecatedPath compute_path_for_text(SVGTextBox const&); - Gfx::DeprecatedPath compute_path_for_text_path(SVGTextPathBox const&); + [[nodiscard]] Gfx::Path compute_path_for_text(SVGTextBox const&); + [[nodiscard]] Gfx::Path compute_path_for_text_path(SVGTextPathBox const&); Gfx::AffineTransform m_parent_viewbox_transform {}; diff --git a/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp b/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp index 4816ccfef92..c28d23f8206 100644 --- a/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BorderPainting.cpp @@ -61,7 +61,7 @@ Gfx::Color border_color(BorderEdge edge, BordersDataDevicePixels const& borders_ return border_data.color; } -void paint_border(DisplayListRecorder& painter, BorderEdge edge, DevicePixelRect const& rect, Gfx::AntiAliasingPainter::CornerRadius const& radius, Gfx::AntiAliasingPainter::CornerRadius const& opposite_radius, BordersDataDevicePixels const& borders_data, Gfx::DeprecatedPath& path, bool last) +void paint_border(DisplayListRecorder& painter, BorderEdge edge, DevicePixelRect const& rect, Gfx::AntiAliasingPainter::CornerRadius const& radius, Gfx::AntiAliasingPainter::CornerRadius const& opposite_radius, BordersDataDevicePixels const& borders_data, Gfx::Path& path, bool last) { auto const& border_data = [&] { switch (edge) { @@ -553,7 +553,7 @@ void paint_all_borders(DisplayListRecorder& painter, DevicePixelRect const& bord borders.enqueue(borders.dequeue()); } - Gfx::DeprecatedPath path; + Gfx::Path path; for (BorderEdge edge : borders) { switch (edge) { case BorderEdge::Top: diff --git a/Userland/Libraries/LibWeb/Painting/BorderPainting.h b/Userland/Libraries/LibWeb/Painting/BorderPainting.h index efd54be3ed6..7f6ffda59c5 100644 --- a/Userland/Libraries/LibWeb/Painting/BorderPainting.h +++ b/Userland/Libraries/LibWeb/Painting/BorderPainting.h @@ -26,7 +26,7 @@ enum class BorderEdge { // Returns OptionalNone if there is no outline to paint. Optional borders_data_for_outline(Layout::Node const&, Color outline_color, CSS::OutlineStyle outline_style, CSSPixels outline_width); -void paint_border(DisplayListRecorder& painter, BorderEdge edge, DevicePixelRect const& rect, Gfx::AntiAliasingPainter::CornerRadius const& radius, Gfx::AntiAliasingPainter::CornerRadius const& opposite_radius, BordersDataDevicePixels const& borders_data, Gfx::DeprecatedPath& path, bool last); +void paint_border(DisplayListRecorder& painter, BorderEdge edge, DevicePixelRect const& rect, Gfx::AntiAliasingPainter::CornerRadius const& radius, Gfx::AntiAliasingPainter::CornerRadius const& opposite_radius, BordersDataDevicePixels const& borders_data, Gfx::Path&, bool last); void paint_all_borders(DisplayListRecorder& painter, DevicePixelRect const& border_rect, CornerRadii const& corner_radii, BordersDataDevicePixels const&); Gfx::Color border_color(BorderEdge edge, BordersDataDevicePixels const& borders_data); diff --git a/Userland/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp b/Userland/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp index e553103c10f..a43fd773f4c 100644 --- a/Userland/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp @@ -18,9 +18,9 @@ namespace Web::Painting { JS_DEFINE_ALLOCATOR(CheckBoxPaintable); -static Gfx::DeprecatedPath check_mark_path(Gfx::IntRect checkbox_rect) +static Gfx::Path check_mark_path(Gfx::IntRect checkbox_rect) { - Gfx::DeprecatedPath path; + Gfx::Path path; path.move_to({ 72, 14 }); path.line_to({ 37, 64 }); path.line_to({ 19, 47 }); diff --git a/Userland/Libraries/LibWeb/Painting/Command.h b/Userland/Libraries/LibWeb/Painting/Command.h index 4a00c8c4488..6d17decbc03 100644 --- a/Userland/Libraries/LibWeb/Painting/Command.h +++ b/Userland/Libraries/LibWeb/Painting/Command.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -178,7 +179,7 @@ struct FillRectWithRoundedCorners { struct FillPathUsingColor { Gfx::IntRect path_bounding_rect; - Gfx::DeprecatedPath path; + Gfx::Path path; Color color; Gfx::WindingRule winding_rule; Gfx::FloatPoint aa_translation; @@ -194,7 +195,7 @@ struct FillPathUsingColor { struct FillPathUsingPaintStyle { Gfx::IntRect path_bounding_rect; - Gfx::DeprecatedPath path; + Gfx::Path path; PaintStyle paint_style; Gfx::WindingRule winding_rule; float opacity; @@ -211,7 +212,7 @@ struct FillPathUsingPaintStyle { struct StrokePathUsingColor { Gfx::IntRect path_bounding_rect; - Gfx::DeprecatedPath path; + Gfx::Path path; Color color; float thickness; Gfx::FloatPoint aa_translation; @@ -227,7 +228,7 @@ struct StrokePathUsingColor { struct StrokePathUsingPaintStyle { Gfx::IntRect path_bounding_rect; - Gfx::DeprecatedPath path; + Gfx::Path path; PaintStyle paint_style; float thickness; float opacity = 1.0f; diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp index a0d63e04fba..0dee35765dc 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -237,57 +238,9 @@ static SkColor4f to_skia_color4f(Gfx::Color const& color) }; } -static SkPath to_skia_path(Gfx::DeprecatedPath const& path) +static SkPath to_skia_path(Gfx::Path const& path) { - Optional subpath_start_point; - Optional subpath_last_point; - SkPathBuilder path_builder; - auto close_subpath_if_needed = [&](auto last_point) { - if (subpath_start_point == last_point) - path_builder.close(); - }; - for (auto const& segment : path) { - auto point = segment.point(); - switch (segment.command()) { - case Gfx::DeprecatedPathSegment::Command::MoveTo: { - if (subpath_start_point.has_value() && subpath_last_point.has_value()) - close_subpath_if_needed(subpath_last_point.value()); - subpath_start_point = point; - path_builder.moveTo({ point.x(), point.y() }); - break; - } - case Gfx::DeprecatedPathSegment::Command::LineTo: { - if (!subpath_start_point.has_value()) - subpath_start_point = Gfx::FloatPoint { 0.0f, 0.0f }; - path_builder.lineTo({ point.x(), point.y() }); - break; - } - case Gfx::DeprecatedPathSegment::Command::QuadraticBezierCurveTo: { - if (!subpath_start_point.has_value()) - subpath_start_point = Gfx::FloatPoint { 0.0f, 0.0f }; - SkPoint pt1 = { segment.through().x(), segment.through().y() }; - SkPoint pt2 = { segment.point().x(), segment.point().y() }; - path_builder.quadTo(pt1, pt2); - break; - } - case Gfx::DeprecatedPathSegment::Command::CubicBezierCurveTo: { - if (!subpath_start_point.has_value()) - subpath_start_point = Gfx::FloatPoint { 0.0f, 0.0f }; - SkPoint pt1 = { segment.through_0().x(), segment.through_0().y() }; - SkPoint pt2 = { segment.through_1().x(), segment.through_1().y() }; - SkPoint pt3 = { segment.point().x(), segment.point().y() }; - path_builder.cubicTo(pt1, pt2, pt3); - break; - } - default: - VERIFY_NOT_REACHED(); - } - subpath_last_point = point; - } - - close_subpath_if_needed(subpath_last_point); - - return path_builder.snapshot(); + return static_cast(path.impl()).sk_path(); } static SkPathFillType to_skia_path_fill_type(Gfx::WindingRule winding_rule) diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp index 4627ab40339..91b1c715982 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.cpp @@ -62,7 +62,7 @@ void DisplayListRecorder::fill_path(FillPathUsingColorParams params) return; append(FillPathUsingColor { .path_bounding_rect = path_bounding_rect, - .path = params.path, + .path = move(params.path), .color = params.color, .winding_rule = params.winding_rule, .aa_translation = aa_translation, @@ -77,7 +77,7 @@ void DisplayListRecorder::fill_path(FillPathUsingPaintStyleParams params) return; append(FillPathUsingPaintStyle { .path_bounding_rect = path_bounding_rect, - .path = params.path, + .path = move(params.path), .paint_style = params.paint_style, .winding_rule = params.winding_rule, .opacity = params.opacity, @@ -95,7 +95,7 @@ void DisplayListRecorder::stroke_path(StrokePathUsingColorParams params) return; append(StrokePathUsingColor { .path_bounding_rect = path_bounding_rect, - .path = params.path, + .path = move(params.path), .color = params.color, .thickness = params.thickness, .aa_translation = aa_translation, @@ -112,7 +112,7 @@ void DisplayListRecorder::stroke_path(StrokePathUsingPaintStyleParams params) return; append(StrokePathUsingPaintStyle { .path_bounding_rect = path_bounding_rect, - .path = params.path, + .path = move(params.path), .paint_style = params.paint_style, .thickness = params.thickness, .opacity = params.opacity, diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h index 2c1d2e8f4fa..350da1dab84 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h +++ b/Userland/Libraries/LibWeb/Painting/DisplayListRecorder.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,7 @@ public: void fill_rect(Gfx::IntRect const& rect, Color color); struct FillPathUsingColorParams { - Gfx::DeprecatedPath path; + Gfx::Path path; Gfx::Color color; Gfx::WindingRule winding_rule = Gfx::WindingRule::EvenOdd; Optional translation = {}; @@ -51,7 +52,7 @@ public: void fill_path(FillPathUsingColorParams params); struct FillPathUsingPaintStyleParams { - Gfx::DeprecatedPath path; + Gfx::Path path; PaintStyle paint_style; Gfx::WindingRule winding_rule = Gfx::WindingRule::EvenOdd; float opacity; @@ -60,7 +61,7 @@ public: void fill_path(FillPathUsingPaintStyleParams params); struct StrokePathUsingColorParams { - Gfx::DeprecatedPath path; + Gfx::Path path; Gfx::Color color; float thickness; Optional translation = {}; @@ -68,7 +69,7 @@ public: void stroke_path(StrokePathUsingColorParams params); struct StrokePathUsingPaintStyleParams { - Gfx::DeprecatedPath path; + Gfx::Path path; PaintStyle paint_style; float thickness; float opacity; diff --git a/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp b/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp index e1bff49b1fa..739c759ee5f 100644 --- a/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp @@ -83,7 +83,7 @@ void MarkerPaintable::paint(PaintContext& context, PaintPhase phase) const // FIXME: If the image is directional, it must respond to the writing mode of the element, similar to the bidi-sensitive images feature of the Images 4 module. // Draw an equilateral triangle pointing right. - auto path = Gfx::DeprecatedPath(); + auto path = Gfx::Path(); path.move_to({ left, top }); path.line_to({ left + sin_60_deg * (right - left), (top + bottom) / 2 }); path.line_to({ left, bottom }); @@ -97,7 +97,7 @@ void MarkerPaintable::paint(PaintContext& context, PaintPhase phase) const // FIXME: If the image is directional, it must respond to the writing mode of the element, similar to the bidi-sensitive images feature of the Images 4 module. // Draw an equilateral triangle pointing down. - auto path = Gfx::DeprecatedPath(); + auto path = Gfx::Path(); path.move_to({ left, top }); path.line_to({ right, top }); path.line_to({ (left + right) / 2, top + sin_60_deg * (bottom - top) }); diff --git a/Userland/Libraries/LibWeb/Painting/MediaPaintable.cpp b/Userland/Libraries/LibWeb/Painting/MediaPaintable.cpp index cf2957f5daa..8e28eb005cb 100644 --- a/Userland/Libraries/LibWeb/Painting/MediaPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/MediaPaintable.cpp @@ -46,7 +46,7 @@ Optional MediaPaintable::mouse_position(PaintContext& context, void MediaPaintable::fill_triangle(DisplayListRecorder& painter, Gfx::IntPoint location, Array coordinates, Color color) { - Gfx::DeprecatedPath path; + Gfx::Path path; path.move_to((coordinates[0] + location).to_type()); path.line_to((coordinates[1] + location).to_type()); path.line_to((coordinates[2] + location).to_type()); @@ -217,7 +217,7 @@ void MediaPaintable::paint_control_bar_speaker(PaintContext& context, HTML::HTML auto speaker_button_is_hovered = rect_is_hovered(media_element, components.speaker_button_rect, mouse_position); auto speaker_button_color = control_button_color(speaker_button_is_hovered); - Gfx::DeprecatedPath path; + Gfx::Path path; path.move_to(device_point(0, 4)); path.line_to(device_point(5, 4)); diff --git a/Userland/Libraries/LibWeb/Painting/SVGPathPaintable.cpp b/Userland/Libraries/LibWeb/Painting/SVGPathPaintable.cpp index f90c5670582..5cfdc890b57 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGPathPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/SVGPathPaintable.cpp @@ -72,7 +72,7 @@ void SVGPathPaintable::paint(PaintContext& context, PaintPhase phase) const auto maybe_view_box = svg_node->dom_node().view_box(); auto paint_transform = computed_transforms().svg_to_device_pixels_transform(context); - Gfx::DeprecatedPath path = computed_path()->copy_transformed(paint_transform); + auto path = computed_path()->copy_transformed(paint_transform); // Fills are computed as though all subpaths are closed (https://svgwg.org/svg2-draft/painting.html#FillProperties) auto closed_path = [&] { diff --git a/Userland/Libraries/LibWeb/Painting/SVGPathPaintable.h b/Userland/Libraries/LibWeb/Painting/SVGPathPaintable.h index 65b80d04cb6..6c0530cc3a3 100644 --- a/Userland/Libraries/LibWeb/Painting/SVGPathPaintable.h +++ b/Userland/Libraries/LibWeb/Painting/SVGPathPaintable.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include @@ -24,17 +25,17 @@ public: Layout::SVGGraphicsBox const& layout_box() const; - void set_computed_path(Gfx::DeprecatedPath path) + void set_computed_path(Gfx::Path path) { m_computed_path = move(path); } - Optional const& computed_path() const { return m_computed_path; } + Optional const& computed_path() const { return m_computed_path; } protected: SVGPathPaintable(Layout::SVGGraphicsBox const&); - Optional m_computed_path = {}; + Optional m_computed_path = {}; }; } diff --git a/Userland/Libraries/LibWeb/SVG/SVGCircleElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGCircleElement.cpp index 5b3fb7ac5c4..64a6c5087e8 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGCircleElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGCircleElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -46,7 +47,7 @@ void SVGCircleElement::apply_presentational_hints(CSS::StyleProperties& style) c style.set_property(CSS::PropertyID::R, r_value.release_nonnull()); } -Gfx::DeprecatedPath SVGCircleElement::get_path(CSSPixelSize viewport_size) +Gfx::Path SVGCircleElement::get_path(CSSPixelSize viewport_size) { auto node = layout_node(); auto cx = float(node->computed_values().cx().to_px(*node, viewport_size.width())); @@ -59,7 +60,7 @@ Gfx::DeprecatedPath SVGCircleElement::get_path(CSSPixelSize viewport_size) if (r == 0) return {}; - Gfx::DeprecatedPath path; + Gfx::Path path; bool large_arc = false; bool sweep = true; diff --git a/Userland/Libraries/LibWeb/SVG/SVGCircleElement.h b/Userland/Libraries/LibWeb/SVG/SVGCircleElement.h index c17cd2fc618..d8c3e0af9b7 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGCircleElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGCircleElement.h @@ -20,7 +20,7 @@ public: virtual void apply_presentational_hints(CSS::StyleProperties&) const override; - virtual Gfx::DeprecatedPath get_path(CSSPixelSize viewport_size) override; + virtual Gfx::Path get_path(CSSPixelSize viewport_size) override; JS::NonnullGCPtr cx() const; JS::NonnullGCPtr cy() const; diff --git a/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp index 08364817bb7..20e23f92b6d 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGEllipseElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -40,13 +41,13 @@ void SVGEllipseElement::attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value) override; - virtual Gfx::DeprecatedPath get_path(CSSPixelSize viewport_size) override; + virtual Gfx::Path get_path(CSSPixelSize viewport_size) override; JS::NonnullGCPtr cx() const; JS::NonnullGCPtr cy() const; diff --git a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h index ce53c0b04b2..5d39a0840ac 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGGeometryElement.h @@ -18,7 +18,7 @@ class SVGGeometryElement : public SVGGraphicsElement { public: virtual JS::GCPtr create_layout_node(NonnullRefPtr) override; - virtual Gfx::DeprecatedPath get_path(CSSPixelSize viewport_size) = 0; + virtual Gfx::Path get_path(CSSPixelSize viewport_size) = 0; float get_total_length(); JS::NonnullGCPtr get_point_at_length(float distance); diff --git a/Userland/Libraries/LibWeb/SVG/SVGLineElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGLineElement.cpp index f9067dd3e8f..60573a3f530 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGLineElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGLineElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -40,12 +41,12 @@ void SVGLineElement::attribute_changed(FlyString const& name, Optional c } } -Gfx::DeprecatedPath SVGLineElement::get_path(CSSPixelSize viewport_size) +Gfx::Path SVGLineElement::get_path(CSSPixelSize viewport_size) { auto const viewport_width = viewport_size.width().to_float(); auto const viewport_height = viewport_size.height().to_float(); - Gfx::DeprecatedPath path; + Gfx::Path path; float const x1 = m_x1.value_or({ 0, false }).resolve_relative_to(viewport_width); float const y1 = m_y1.value_or({ 0, false }).resolve_relative_to(viewport_height); float const x2 = m_x2.value_or({ 0, false }).resolve_relative_to(viewport_width); diff --git a/Userland/Libraries/LibWeb/SVG/SVGLineElement.h b/Userland/Libraries/LibWeb/SVG/SVGLineElement.h index 2415b96226e..e8119159c53 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGLineElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGLineElement.h @@ -20,7 +20,7 @@ public: virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value) override; - virtual Gfx::DeprecatedPath get_path(CSSPixelSize viewport_size) override; + virtual Gfx::Path get_path(CSSPixelSize viewport_size) override; JS::NonnullGCPtr x1() const; JS::NonnullGCPtr y1() const; diff --git a/Userland/Libraries/LibWeb/SVG/SVGPathElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGPathElement.cpp index 15cde35a03c..62511d76385 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGPathElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGPathElement.cpp @@ -105,10 +105,9 @@ void SVGPathElement::attribute_changed(FlyString const& name, Optional c m_instructions = AttributeParser::parse_path_data(value.value_or(String {})); } -template -PathType path_from_path_instructions(ReadonlySpan instructions) +Gfx::Path path_from_path_instructions(ReadonlySpan instructions) { - PathType path; + Gfx::Path path; Optional previous_control_point; PathInstructionType last_instruction = PathInstructionType::Invalid; @@ -274,19 +273,9 @@ PathType path_from_path_instructions(ReadonlySpan instructions) return path; } -Gfx::Path path_from_path_instructions(ReadonlySpan instructions) +Gfx::Path SVGPathElement::get_path(CSSPixelSize) { - return path_from_path_instructions(instructions); -} - -Gfx::DeprecatedPath deprecated_path_from_path_instructions(ReadonlySpan instructions) -{ - return path_from_path_instructions(instructions); -} - -Gfx::DeprecatedPath SVGPathElement::get_path(CSSPixelSize) -{ - return deprecated_path_from_path_instructions(m_instructions); + return path_from_path_instructions(m_instructions); } } diff --git a/Userland/Libraries/LibWeb/SVG/SVGPathElement.h b/Userland/Libraries/LibWeb/SVG/SVGPathElement.h index b98dfd8119c..73024b8910f 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGPathElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGPathElement.h @@ -22,7 +22,7 @@ public: virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value) override; - virtual Gfx::DeprecatedPath get_path(CSSPixelSize viewport_size) override; + virtual Gfx::Path get_path(CSSPixelSize viewport_size) override; private: SVGPathElement(DOM::Document&, DOM::QualifiedName); @@ -33,6 +33,5 @@ private: }; [[nodiscard]] Gfx::Path path_from_path_instructions(ReadonlySpan); -[[nodiscard]] Gfx::DeprecatedPath deprecated_path_from_path_instructions(ReadonlySpan); } diff --git a/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.cpp index 4612cfb09fc..d2345184bcb 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGPolygonElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -33,9 +34,9 @@ void SVGPolygonElement::attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value) override; - virtual Gfx::DeprecatedPath get_path(CSSPixelSize viewport_size) override; + virtual Gfx::Path get_path(CSSPixelSize viewport_size) override; private: SVGPolygonElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.cpp index 1fd48c0af68..773248aae4c 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGPolylineElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -33,9 +34,9 @@ void SVGPolylineElement::attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value) override; - virtual Gfx::DeprecatedPath get_path(CSSPixelSize viewport_size) override; + virtual Gfx::Path get_path(CSSPixelSize viewport_size) override; private: SVGPolylineElement(DOM::Document&, DOM::QualifiedName); diff --git a/Userland/Libraries/LibWeb/SVG/SVGRectElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGRectElement.cpp index c9200aa30b8..686d0c23e04 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGRectElement.cpp +++ b/Userland/Libraries/LibWeb/SVG/SVGRectElement.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -46,14 +47,14 @@ void SVGRectElement::attribute_changed(FlyString const& name, Optional c } } -Gfx::DeprecatedPath SVGRectElement::get_path(CSSPixelSize) +Gfx::Path SVGRectElement::get_path(CSSPixelSize) { float width = m_width.value_or(0); float height = m_height.value_or(0); float x = m_x.value_or(0); float y = m_y.value_or(0); - Gfx::DeprecatedPath path; + Gfx::Path path; // If width or height is zero, rendering is disabled. if (width == 0 || height == 0) return path; @@ -106,6 +107,8 @@ Gfx::DeprecatedPath SVGRectElement::get_path(CSSPixelSize) if (rx > 0 && ry > 0) path.elliptical_arc_to({ x + rx, y }, corner_radii, x_axis_rotation, large_arc_flag, sweep_flag); + path.close(); + return path; } diff --git a/Userland/Libraries/LibWeb/SVG/SVGRectElement.h b/Userland/Libraries/LibWeb/SVG/SVGRectElement.h index 0a97725d1b6..9f67ff46b6b 100644 --- a/Userland/Libraries/LibWeb/SVG/SVGRectElement.h +++ b/Userland/Libraries/LibWeb/SVG/SVGRectElement.h @@ -20,7 +20,7 @@ public: virtual void attribute_changed(FlyString const& name, Optional const& old_value, Optional const& value) override; - virtual Gfx::DeprecatedPath get_path(CSSPixelSize viewport_size) override; + virtual Gfx::Path get_path(CSSPixelSize viewport_size) override; JS::NonnullGCPtr x() const; JS::NonnullGCPtr y() const;