| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2024-10-04 13:19:50 +02:00
										 |  |  |  * Copyright (c) 2018-2023, Andreas Kling <andreas@ladybird.org> | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-11 19:48:53 +01:00
										 |  |  | #include <LibWeb/DOM/Range.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-07 10:32:51 +01:00
										 |  |  | #include <LibWeb/Dump.h>
 | 
					
						
							| 
									
										
										
										
											2024-10-14 16:07:56 +02:00
										 |  |  | #include <LibWeb/Layout/TextNode.h>
 | 
					
						
							| 
									
										
										
										
											2023-02-25 11:04:29 +01:00
										 |  |  | #include <LibWeb/Layout/Viewport.h>
 | 
					
						
							| 
									
										
										
										
											2022-03-10 23:13:37 +01:00
										 |  |  | #include <LibWeb/Painting/PaintableBox.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-18 21:39:27 +02:00
										 |  |  | #include <LibWeb/Painting/StackingContext.h>
 | 
					
						
							| 
									
										
										
										
											2023-08-18 15:52:40 +02:00
										 |  |  | #include <LibWeb/Painting/ViewportPaintable.h>
 | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | namespace Web::Layout { | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  | GC_DEFINE_ALLOCATOR(Viewport); | 
					
						
							| 
									
										
										
										
											2024-04-06 10:16:04 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-26 17:42:27 +02:00
										 |  |  | Viewport::Viewport(DOM::Document& document, CSS::StyleProperties style) | 
					
						
							| 
									
										
										
										
											2021-10-06 20:02:41 +02:00
										 |  |  |     : BlockContainer(document, &document, move(style)) | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-25 11:04:29 +01:00
										 |  |  | Viewport::~Viewport() = default; | 
					
						
							| 
									
										
										
										
											2019-06-16 21:35:03 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-15 04:01:23 +13:00
										 |  |  | GC::Ptr<Painting::Paintable> Viewport::create_paintable() const | 
					
						
							| 
									
										
										
										
											2023-08-18 15:52:40 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     return Painting::ViewportPaintable::create(*this); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-28 11:07:58 +01:00
										 |  |  | void Viewport::visit_edges(Visitor& visitor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Base::visit_edges(visitor); | 
					
						
							|  |  |  |     if (!m_text_blocks.has_value()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (auto& text_block : *m_text_blocks) { | 
					
						
							|  |  |  |         for (auto& text_position : text_block.positions) | 
					
						
							|  |  |  |             visitor.visit(text_position.dom_node); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Vector<Viewport::TextBlock> const& Viewport::text_blocks() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_text_blocks.has_value()) | 
					
						
							|  |  |  |         update_text_blocks(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return *m_text_blocks; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Viewport::update_text_blocks() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     StringBuilder builder; | 
					
						
							|  |  |  |     size_t current_start_position = 0; | 
					
						
							|  |  |  |     Vector<TextPosition> text_positions; | 
					
						
							|  |  |  |     Vector<TextBlock> text_blocks; | 
					
						
							|  |  |  |     for_each_in_inclusive_subtree([&](auto const& layout_node) { | 
					
						
							| 
									
										
										
										
											2024-10-16 15:19:32 +02:00
										 |  |  |         if (layout_node.display().is_none() || !layout_node.first_paintable() || !layout_node.first_paintable()->is_visible()) | 
					
						
							| 
									
										
										
										
											2024-06-28 11:07:58 +01:00
										 |  |  |             return TraversalDecision::Continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-09 16:10:24 +09:00
										 |  |  |         if (layout_node.is_box() || layout_node.is_generated()) { | 
					
						
							| 
									
										
										
										
											2024-06-28 11:07:58 +01:00
										 |  |  |             if (!builder.is_empty()) { | 
					
						
							|  |  |  |                 text_blocks.append({ builder.to_string_without_validation(), text_positions }); | 
					
						
							|  |  |  |                 current_start_position = 0; | 
					
						
							|  |  |  |                 text_positions.clear_with_capacity(); | 
					
						
							|  |  |  |                 builder.clear(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return TraversalDecision::Continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (layout_node.is_text_node()) { | 
					
						
							|  |  |  |             auto const& text_node = verify_cast<Layout::TextNode>(layout_node); | 
					
						
							|  |  |  |             auto& dom_node = const_cast<DOM::Text&>(text_node.dom_node()); | 
					
						
							|  |  |  |             if (text_positions.is_empty()) { | 
					
						
							|  |  |  |                 text_positions.empend(dom_node); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 text_positions.empend(dom_node, current_start_position); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             auto const& current_node_text = text_node.text_for_rendering(); | 
					
						
							|  |  |  |             current_start_position += current_node_text.bytes_as_string_view().length(); | 
					
						
							|  |  |  |             builder.append(move(current_node_text)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return TraversalDecision::Continue; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!builder.is_empty()) | 
					
						
							|  |  |  |         text_blocks.append({ builder.to_string_without_validation(), text_positions }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_text_blocks = move(text_blocks); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  | } |