/* * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include namespace Web::Layout { void InlineLevelIterator::skip_to_next() { VERIFY(m_current_node); do { m_current_node = m_current_node->next_in_pre_order(&m_container); } while (m_current_node && !m_current_node->is_inline()); } Optional InlineLevelIterator::next(float available_width) { if (!m_current_node) return {}; if (is(*m_current_node)) { auto& text_node = static_cast(*m_current_node); if (!m_text_node_context.has_value()) enter_text_node(text_node); auto chunk_opt = m_text_node_context->chunk_iterator.next(); if (!chunk_opt.has_value()) { m_text_node_context = {}; skip_to_next(); return next(available_width); } auto& chunk = chunk_opt.value(); float chunk_width = text_node.font().width(chunk.view) + text_node.font().glyph_spacing(); Item item { .type = Item::Type::Text, .node = &text_node, .offset_in_node = chunk.start, .length_in_node = chunk.length, .width = chunk_width, }; return item; } if (is(*m_current_node)) { skip_to_next(); return Item { .type = Item::Type::ForcedBreak, }; } if (!is(*m_current_node)) { skip_to_next(); return next(available_width); } if (is(*m_current_node)) { auto& replaced_box = static_cast(*m_current_node); replaced_box.prepare_for_replaced_layout(); } auto& box = verify_cast(*m_current_node); skip_to_next(); return Item { .type = Item::Type::Element, .node = &box, .offset_in_node = 0, .length_in_node = 0, .width = box.width(), }; } void InlineLevelIterator::enter_text_node(Layout::TextNode& text_node) { bool do_collapse = true; bool do_wrap_lines = true; bool do_respect_linebreaks = false; if (text_node.computed_values().white_space() == CSS::WhiteSpace::Nowrap) { do_collapse = true; do_wrap_lines = false; do_respect_linebreaks = false; } else if (text_node.computed_values().white_space() == CSS::WhiteSpace::Pre) { do_collapse = false; do_wrap_lines = false; do_respect_linebreaks = true; } else if (text_node.computed_values().white_space() == CSS::WhiteSpace::PreLine) { do_collapse = true; do_wrap_lines = true; do_respect_linebreaks = true; } else if (text_node.computed_values().white_space() == CSS::WhiteSpace::PreWrap) { do_collapse = false; do_wrap_lines = true; do_respect_linebreaks = true; } // FIXME: Pass the correct value for the last boolean! text_node.compute_text_for_rendering(do_collapse, true); m_text_node_context = TextNodeContext { .do_collapse = do_collapse, .do_wrap_lines = do_wrap_lines, .do_respect_linebreaks = do_respect_linebreaks, .chunk_iterator = TextNode::ChunkIterator { text_node.text_for_rendering(), m_layout_mode, do_wrap_lines, do_respect_linebreaks }, }; } }