1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 12:57:35 +00:00

LibWeb: Don't justify text lines that end in a forced break

These are treated the same as the last line in a block, per CSS-TEXT-3.
This commit is contained in:
Andreas Kling 2023-06-10 15:49:17 +02:00
parent 358a4fe3cb
commit 79d2c9f3e8
6 changed files with 106 additions and 12 deletions

View file

@ -18,8 +18,6 @@
namespace Web::Layout {
constexpr double text_justification_threshold = 0.1;
InlineFormattingContext::InlineFormattingContext(LayoutState& state, BlockContainer const& containing_block, BlockFormattingContext& parent)
: FormattingContext(Type::Inline, state, containing_block, &parent)
, m_containing_block_state(state.get(containing_block))
@ -191,13 +189,13 @@ void InlineFormattingContext::apply_justification_to_fragments(CSS::TextJustify
break;
}
CSSPixels excess_horizontal_space = line_box.original_available_width() - line_box.width();
// Only justify the text if the excess horizontal space is less than or
// equal to 10%, or if we are not looking at the last line box.
if (is_last_line && excess_horizontal_space / m_available_space->width.to_px().value() > text_justification_threshold)
// https://www.w3.org/TR/css-text-3/#text-align-property
// Unless otherwise specified by text-align-last, the last line before a forced break or the end of the block is start-aligned.
// FIXME: Support text-align-last.
if (is_last_line || line_box.m_has_forced_break)
return;
CSSPixels excess_horizontal_space = line_box.original_available_width() - line_box.width();
CSSPixels excess_horizontal_space_including_whitespace = excess_horizontal_space;
size_t whitespace_count = 0;
for (auto& fragment : line_box.fragments()) {
@ -249,7 +247,7 @@ void InlineFormattingContext::generate_line_boxes(LayoutMode layout_mode)
switch (item.type) {
case InlineLevelIterator::Item::Type::ForcedBreak:
line_builder.break_line();
line_builder.break_line(LineBuilder::ForcedBreak::Yes);
break;
case InlineLevelIterator::Item::Type::Element: {
auto& box = verify_cast<Layout::Box>(*item.node);

View file

@ -47,6 +47,7 @@ private:
CSSPixels m_original_available_width { 0 };
bool m_has_break { false };
bool m_has_forced_break { false };
};
}

View file

@ -25,10 +25,11 @@ LineBuilder::~LineBuilder()
update_last_line();
}
void LineBuilder::break_line(Optional<CSSPixels> next_item_width)
void LineBuilder::break_line(ForcedBreak forced_break, Optional<CSSPixels> next_item_width)
{
auto last_line_box = ensure_last_line_box();
auto& last_line_box = ensure_last_line_box();
last_line_box.m_has_break = true;
last_line_box.m_has_forced_break = forced_break == ForcedBreak::Yes;
update_last_line();
size_t break_count = 0;

View file

@ -18,7 +18,12 @@ public:
LineBuilder(InlineFormattingContext&, LayoutState&);
~LineBuilder();
void break_line(Optional<CSSPixels> next_item_width = {});
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);
@ -26,7 +31,7 @@ public:
bool break_if_needed(CSSPixels next_item_width)
{
if (should_break(next_item_width)) {
break_line(next_item_width);
break_line(LineBuilder::ForcedBreak::No, next_item_width);
return true;
}
return false;