diff --git a/Tests/LibWeb/Ref/reference/images/border-radius-ref.png b/Tests/LibWeb/Ref/reference/images/border-radius-ref.png index c6a88ecc35..3531dfd70b 100644 Binary files a/Tests/LibWeb/Ref/reference/images/border-radius-ref.png and b/Tests/LibWeb/Ref/reference/images/border-radius-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/canvas-fillstyle-rgb.png b/Tests/LibWeb/Ref/reference/images/canvas-fillstyle-rgb.png index f67fb52fb0..543e29778c 100644 Binary files a/Tests/LibWeb/Ref/reference/images/canvas-fillstyle-rgb.png and b/Tests/LibWeb/Ref/reference/images/canvas-fillstyle-rgb.png differ diff --git a/Tests/LibWeb/Ref/reference/images/canvas-path-rect-ref.png b/Tests/LibWeb/Ref/reference/images/canvas-path-rect-ref.png index e684a704e1..efe2a7dc93 100644 Binary files a/Tests/LibWeb/Ref/reference/images/canvas-path-rect-ref.png and b/Tests/LibWeb/Ref/reference/images/canvas-path-rect-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/css-background-position-ref.png b/Tests/LibWeb/Ref/reference/images/css-background-position-ref.png index e268e454f4..b344f818e8 100644 Binary files a/Tests/LibWeb/Ref/reference/images/css-background-position-ref.png and b/Tests/LibWeb/Ref/reference/images/css-background-position-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/css-background-repeat-ref.png b/Tests/LibWeb/Ref/reference/images/css-background-repeat-ref.png index e3c2f00aca..6472b658db 100644 Binary files a/Tests/LibWeb/Ref/reference/images/css-background-repeat-ref.png and b/Tests/LibWeb/Ref/reference/images/css-background-repeat-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/css-backgrounds-ref.png b/Tests/LibWeb/Ref/reference/images/css-backgrounds-ref.png index 957321d5e7..5f40faec8e 100644 Binary files a/Tests/LibWeb/Ref/reference/images/css-backgrounds-ref.png and b/Tests/LibWeb/Ref/reference/images/css-backgrounds-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/css-gradients-ref.png b/Tests/LibWeb/Ref/reference/images/css-gradients-ref.png index 8ca07f66d2..c20e5995e4 100644 Binary files a/Tests/LibWeb/Ref/reference/images/css-gradients-ref.png and b/Tests/LibWeb/Ref/reference/images/css-gradients-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/inline-node-ref.png b/Tests/LibWeb/Ref/reference/images/inline-node-ref.png index 00d5be82bd..86457f7f68 100644 Binary files a/Tests/LibWeb/Ref/reference/images/inline-node-ref.png and b/Tests/LibWeb/Ref/reference/images/inline-node-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/input-placeholder-ref.png b/Tests/LibWeb/Ref/reference/images/input-placeholder-ref.png index 76e554854e..b1768db318 100644 Binary files a/Tests/LibWeb/Ref/reference/images/input-placeholder-ref.png and b/Tests/LibWeb/Ref/reference/images/input-placeholder-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/meter-ref.png b/Tests/LibWeb/Ref/reference/images/meter-ref.png index 6cdefe2c57..b1bcbaf912 100644 Binary files a/Tests/LibWeb/Ref/reference/images/meter-ref.png and b/Tests/LibWeb/Ref/reference/images/meter-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/object-fit-position.png b/Tests/LibWeb/Ref/reference/images/object-fit-position.png index 7e28d43164..95b59164e1 100644 Binary files a/Tests/LibWeb/Ref/reference/images/object-fit-position.png and b/Tests/LibWeb/Ref/reference/images/object-fit-position.png differ diff --git a/Tests/LibWeb/Ref/reference/images/outer-box-shadow-ref.png b/Tests/LibWeb/Ref/reference/images/outer-box-shadow-ref.png index 5f732f427d..6e477a0ac9 100644 Binary files a/Tests/LibWeb/Ref/reference/images/outer-box-shadow-ref.png and b/Tests/LibWeb/Ref/reference/images/outer-box-shadow-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/svg-gradient-spreadMethod-ref.png b/Tests/LibWeb/Ref/reference/images/svg-gradient-spreadMethod-ref.png index 845889b4fc..36a873a929 100644 Binary files a/Tests/LibWeb/Ref/reference/images/svg-gradient-spreadMethod-ref.png and b/Tests/LibWeb/Ref/reference/images/svg-gradient-spreadMethod-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/svg-radialGradient-ref.png b/Tests/LibWeb/Ref/reference/images/svg-radialGradient-ref.png index 9fe09d9264..5d221b01e1 100644 Binary files a/Tests/LibWeb/Ref/reference/images/svg-radialGradient-ref.png and b/Tests/LibWeb/Ref/reference/images/svg-radialGradient-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/svg-textPath-ref.png b/Tests/LibWeb/Ref/reference/images/svg-textPath-ref.png index 89c209776f..c35dd031c0 100644 Binary files a/Tests/LibWeb/Ref/reference/images/svg-textPath-ref.png and b/Tests/LibWeb/Ref/reference/images/svg-textPath-ref.png differ diff --git a/Tests/LibWeb/Ref/reference/images/text-shadow-ref.png b/Tests/LibWeb/Ref/reference/images/text-shadow-ref.png index 19fc3a74cd..5900ae8161 100644 Binary files a/Tests/LibWeb/Ref/reference/images/text-shadow-ref.png and b/Tests/LibWeb/Ref/reference/images/text-shadow-ref.png differ diff --git a/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp b/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp index 42d9d110bc..e878d70bb1 100644 --- a/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp +++ b/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.cpp @@ -31,10 +31,18 @@ namespace Gfx { -static Vector prepare_edges(ReadonlySpan lines, unsigned samples_per_pixel, FloatPoint origin) +static Vector prepare_edges(ReadonlySpan lines, unsigned samples_per_pixel, FloatPoint origin, + int top_clip_scanline, int bottom_clip_scanline, int& min_edge_y, int& max_edge_y) { Vector edges; edges.ensure_capacity(lines.size()); + // The first visible y value. + auto top_clip = top_clip_scanline * int(samples_per_pixel); + // The last visible y value. + auto bottom_clip = (bottom_clip_scanline + 1) * int(samples_per_pixel) - 1; + min_edge_y = bottom_clip; + max_edge_y = top_clip; + for (auto& line : lines) { auto p0 = line.a() - origin; auto p1 = line.b() - origin; @@ -54,6 +62,14 @@ static Vector prepare_edges(ReadonlySpan lines, unsigne auto min_y = static_cast(p0.y()); auto max_y = static_cast(p1.y()); + + // Clip edges that start below the bottom clip... + if (min_y > bottom_clip) + continue; + // ...and edges that end before the top clip. + if (max_y < top_clip) + continue; + float start_x = p0.x(); float end_x = p1.x(); @@ -61,6 +77,18 @@ static Vector prepare_edges(ReadonlySpan lines, unsigne auto dy = max_y - min_y; auto dxdy = dx / dy; + // Trim off the non-visible portions of the edge. + if (min_y < top_clip) { + start_x += (top_clip - min_y) * dxdy; + min_y = top_clip; + } + if (max_y > bottom_clip) { + max_y = bottom_clip; + } + + min_edge_y = min(min_y, min_edge_y); + max_edge_y = max(max_y, max_edge_y); + edges.unchecked_append(Detail::Edge { start_x, min_y, @@ -76,8 +104,8 @@ template EdgeFlagPathRasterizer::EdgeFlagPathRasterizer(IntSize size) : m_size(size.width() + 1, size.height() + 1) { + // FIXME: Clip the scanline width to the visible section (tricky). m_scanline.resize(m_size.width()); - m_edge_table.resize(m_size.height()); } template @@ -122,25 +150,24 @@ void EdgeFlagPathRasterizer::fill_internal(Painter& painter, Pa if (lines.is_empty()) return; - auto edges = prepare_edges(lines, SamplesPerPixel, origin); + int min_edge_y = 0; + int max_edge_y = 0; + auto top_clip_scanline = m_clip.top() - m_blit_origin.y(); + auto bottom_clip_scanline = m_clip.bottom() - m_blit_origin.y() - 1; + auto edges = prepare_edges(lines, SamplesPerPixel, origin, top_clip_scanline, bottom_clip_scanline, min_edge_y, max_edge_y); + if (edges.is_empty()) + return; - int min_scanline = m_size.height(); - int max_scanline = 0; + int min_scanline = min_edge_y / SamplesPerPixel; + int max_scanline = max_edge_y / SamplesPerPixel; + m_edge_table.set_scanline_range(min_scanline, max_scanline); for (auto& edge : edges) { - int start_scanline = edge.min_y / SamplesPerPixel; - int end_scanline = edge.max_y / SamplesPerPixel; - // Create a linked-list of edges starting on this scanline: + int start_scanline = edge.min_y / SamplesPerPixel; edge.next_edge = m_edge_table[start_scanline]; m_edge_table[start_scanline] = &edge; - - min_scanline = min(min_scanline, start_scanline); - max_scanline = max(max_scanline, end_scanline); } - // FIXME: We could probably clip some of the egde plotting if we know it won't be shown. - // Though care would have to be taken to ensure the active edges are correct at the first drawn scaline. - auto empty_edge_extent = [&] { return EdgeExtent { m_size.width() - 1, 0 }; }; @@ -288,14 +315,6 @@ void EdgeFlagPathRasterizer::write_pixel(Painter& painter, int template void EdgeFlagPathRasterizer::accumulate_even_odd_scanline(Painter& painter, int scanline, EdgeExtent edge_extent, auto& color_or_function) { - auto dest_y = m_blit_origin.y() + scanline; - if (!m_clip.contains_vertically(dest_y)) { - // FIXME: This memset only really needs to be done on transition from clipped to not clipped, - // or not at all if we properly clipped egde plotting. - edge_extent.memset_extent(m_scanline.data(), 0); - return; - } - SampleType sample = 0; for (int x = edge_extent.min_x; x <= edge_extent.max_x; x += 1) { sample ^= m_scanline[x]; @@ -307,14 +326,6 @@ void EdgeFlagPathRasterizer::accumulate_even_odd_scanline(Paint template void EdgeFlagPathRasterizer::accumulate_non_zero_scanline(Painter& painter, int scanline, EdgeExtent edge_extent, auto& color_or_function) { - // NOTE: Same FIXMEs apply from accumulate_even_odd_scanline() - auto dest_y = m_blit_origin.y() + scanline; - if (!m_clip.contains_vertically(dest_y)) { - edge_extent.memset_extent(m_scanline.data(), 0); - edge_extent.memset_extent(m_windings.data(), 0); - return; - } - SampleType sample = 0; WindingCounts sum_winding = {}; for (int x = edge_extent.min_x; x <= edge_extent.max_x; x += 1) { diff --git a/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.h b/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.h index 3a9a81b1ce..fe4f236749 100644 --- a/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.h +++ b/Userland/Libraries/LibGfx/EdgeFlagPathRasterizer.h @@ -163,13 +163,6 @@ private: struct EdgeExtent { int min_x; int max_x; - - template - void memset_extent(T* data, int value) - { - if (min_x <= max_x) - memset(data + min_x, value, (max_x - min_x + 1) * sizeof(T)); - } }; void fill_internal(Painter&, Path const&, auto color_or_function, Painter::WindingRule, FloatPoint offset); @@ -190,7 +183,23 @@ private: Vector m_scanline; Vector m_windings; - Vector m_edge_table; + + class EdgeTable { + public: + EdgeTable() = default; + + void set_scanline_range(int min_scanline, int max_scanline) + { + this->min_scanline = min_scanline; + edges.resize(max_scanline - min_scanline + 1); + } + + auto& operator[](int scanline) { return edges[scanline - min_scanline]; } + + private: + Vector edges; + int min_scanline { 0 }; + } m_edge_table; }; extern template class EdgeFlagPathRasterizer<8>;