Forráskód Böngészése

LibWeb: Don't draw text fragments that would be clipped by the painter

This avoids a ton of work when painting large documents. Even though it
would eventually get clipped by the painter anyway, by bailing out
earlier, we avoid a lot more work (UTF-8 iteration, OpenType lookups,
etc).

It would be even nicer if we could skip entire line boxes, but we don't
have a fast way to get the bounding rect of a line box at the moment.
Andreas Kling 2 éve
szülő
commit
fe92b54137

+ 6 - 0
Userland/Libraries/LibWeb/Painting/PaintContext.cpp

@@ -5,6 +5,7 @@
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
+#include <LibGfx/Painter.h>
 #include <LibWeb/Painting/PaintContext.h>
 
 namespace Web {
@@ -140,4 +141,9 @@ CSSPixelRect PaintContext::scale_to_css_rect(DevicePixelRect rect) const
     };
 }
 
+bool PaintContext::would_be_fully_clipped_by_painter(DevicePixelRect rect) const
+{
+    return !painter().clip_rect().intersects(rect.to_type<int>().translated(painter().translation()));
+}
+
 }

+ 2 - 0
Userland/Libraries/LibWeb/Painting/PaintContext.h

@@ -35,6 +35,8 @@ public:
     void set_device_viewport_rect(DevicePixelRect const& rect) { m_device_viewport_rect = rect; }
     CSSPixelRect css_viewport_rect() const;
 
+    [[nodiscard]] bool would_be_fully_clipped_by_painter(DevicePixelRect) const;
+
     bool has_focus() const { return m_focus; }
     void set_has_focus(bool focus) { m_focus = focus; }
 

+ 5 - 2
Userland/Libraries/LibWeb/Painting/PaintableBox.cpp

@@ -598,9 +598,12 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
 
     for (auto& line_box : m_line_boxes) {
         for (auto& fragment : line_box.fragments()) {
+            auto fragment_absolute_rect = fragment.absolute_rect();
+            auto fragment_absolute_device_rect = context.enclosing_device_rect(fragment_absolute_rect);
+            if (context.would_be_fully_clipped_by_painter(fragment_absolute_device_rect))
+                continue;
             if (context.should_show_line_box_borders()) {
-                auto fragment_absolute_rect = fragment.absolute_rect();
-                context.painter().draw_rect(context.enclosing_device_rect(fragment_absolute_rect).to_type<int>(), Color::Green);
+                context.painter().draw_rect(fragment_absolute_device_rect.to_type<int>(), Color::Green);
                 context.painter().draw_line(
                     context.rounded_device_point(fragment_absolute_rect.top_left().translated(0, fragment.baseline())).to_type<int>(),
                     context.rounded_device_point(fragment_absolute_rect.top_right().translated(-1, fragment.baseline())).to_type<int>(), Color::Red);