mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-30 19:02:44 +00:00 
			
		
		
		
	 f3f0b08d43
			
		
	
	
		f3f0b08d43
		
	
	
	
	
		
			
			Add LayoutPosition and LayoutRange classes. The layout tree root node now has a selection() LayoutRange. It's essentially a start and end LayoutPosition. A LayoutPosition is a LayoutNode, and an optional index into that node. The index is only relevant for text nodes, where it's the character index into the rendered text. HtmlView now updates the selection start/end of the LayoutDocument when clicking and dragging with the left mouse button. We don't paint the selection yet, and there's no way to copy what's selected. It only exists as a LayoutRange.
		
			
				
	
	
		
			50 lines
		
	
	
	
		
			1.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			50 lines
		
	
	
	
		
			1.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <LibGUI/GPainter.h>
 | |
| #include <LibHTML/Layout/LayoutDocument.h>
 | |
| #include <LibHTML/Layout/LayoutText.h>
 | |
| #include <LibHTML/Layout/LineBoxFragment.h>
 | |
| #include <LibHTML/RenderingContext.h>
 | |
| 
 | |
| void LineBoxFragment::render(RenderingContext& context)
 | |
| {
 | |
|     for (auto* ancestor = layout_node().parent(); ancestor; ancestor = ancestor->parent()) {
 | |
|         if (!ancestor->is_visible())
 | |
|             return;
 | |
|     }
 | |
| 
 | |
|     if (is<LayoutText>(layout_node())) {
 | |
|         to<LayoutText>(layout_node()).render_fragment(context, *this);
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool LineBoxFragment::is_justifiable_whitespace() const
 | |
| {
 | |
|     return text() == " ";
 | |
| }
 | |
| 
 | |
| StringView LineBoxFragment::text() const
 | |
| {
 | |
|     if (!is<LayoutText>(layout_node()))
 | |
|         return {};
 | |
|     return to<LayoutText>(layout_node()).node().data().substring_view(m_start, m_length);
 | |
| }
 | |
| 
 | |
| int LineBoxFragment::text_index_at(float x) const
 | |
| {
 | |
|     if (!layout_node().is_text())
 | |
|         return 0;
 | |
|     auto& layout_text = to<LayoutText>(layout_node());
 | |
|     auto& font = layout_text.style().font();
 | |
|     Utf8View view(text());
 | |
| 
 | |
|     float relative_x = x - m_rect.location().x();
 | |
|     float glyph_spacing = font.glyph_spacing();
 | |
| 
 | |
|     float width_so_far = 0;
 | |
|     for (auto it = view.begin(); it != view.end(); ++it) {
 | |
|         float glyph_width = font.glyph_or_emoji_width(*it);
 | |
|         if ((width_so_far + glyph_width + glyph_spacing) > relative_x)
 | |
|             return m_start + view.byte_offset_of(it);
 | |
|         width_so_far += glyph_width + glyph_spacing;
 | |
|     }
 | |
|     return m_start + m_length - 1;
 | |
| }
 |