Files
serenity/Userland/Libraries/LibWeb/Layout/LineBuilder.h
Aliaksandr Kalenik b01060c7d8 Everywhere: Limit layout text fragments to use one font for all glyphs
The ChunkIterator now limits a chunk to using only one font (before, it
was possible to have a chunk with >1 font, when `unicode-range` CSS
property is used).

This change allows us to reduce some complexity in the text shaping and
painting code and makes us compatible with the APIs in Skia and
HarfBuzz.

(cherry picked from commit 7181c3f2ea5fba73e77d98acbf9e46640b4a9015,
minorly amended to fix conflicts caused by:
* Our VectorFont not being renamed to Typeface
* Us cherry-picking https://github.com/LadybirdBrowser/ladybird/pull/502
  first
* Us still having bitmap fonts, and hence needing glyph_spacing()

Also amended for:
* AffineDisplayListPlayerCPU changes
* Removing pure virtuals for glyph_id_for_code_point and
  glyph_id_for_code_point in Font.h again since we still have BitmapFont
  which can't implement them
* Updating more Painter methods that we still had
  (Painter::draw_glyph_or_emoji(), Painter::draw_text_run())
)
2024-10-09 20:12:39 -04:00

71 lines
2.1 KiB
C++

/*
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Layout/InlineFormattingContext.h>
namespace Web::Layout {
class LineBuilder {
AK_MAKE_NONCOPYABLE(LineBuilder);
AK_MAKE_NONMOVABLE(LineBuilder);
public:
LineBuilder(InlineFormattingContext&, LayoutState&, LayoutState::UsedValues& containing_block_used_values);
~LineBuilder();
enum class ForcedBreak {
No,
Yes,
};
void break_line(ForcedBreak, Optional<CSSPixels> next_item_width = {});
void append_box(Box const&, CSSPixels leading_size, CSSPixels trailing_size, CSSPixels leading_margin, CSSPixels trailing_margin);
void append_text_chunk(TextNode const&, size_t offset_in_node, size_t length_in_node, CSSPixels leading_size, CSSPixels trailing_size, CSSPixels leading_margin, CSSPixels trailing_margin, CSSPixels content_width, CSSPixels content_height, RefPtr<Gfx::GlyphRun>);
// Returns whether a line break occurred.
bool break_if_needed(CSSPixels next_item_width)
{
if (should_break(next_item_width)) {
break_line(LineBuilder::ForcedBreak::No, next_item_width);
return true;
}
return false;
}
void update_last_line();
void remove_last_line_if_empty();
CSSPixels current_y() const { return m_current_y; }
void set_current_y(CSSPixels y) { m_current_y = y; }
void recalculate_available_space();
CSSPixels y_for_float_to_be_inserted_here(Box const&);
auto& inline_formatting_context() { return m_context; }
private:
void begin_new_line(bool increment_y, bool is_first_break_in_sequence = true);
bool should_break(CSSPixels next_item_width);
LineBox& ensure_last_line_box();
InlineFormattingContext& m_context;
LayoutState& m_layout_state;
LayoutState::UsedValues& m_containing_block_used_values;
AvailableSize m_available_width_for_current_line { AvailableSize::make_indefinite() };
CSSPixels m_current_y { 0 };
CSSPixels m_max_height_on_current_line { 0 };
CSSPixels m_text_indent { 0 };
bool m_last_line_needs_update { false };
};
}