void box::finish(bool last_box) { if (_type == box_block) { if (!m_element) return; css_offsets offsets; if (m_element->get_element_position(&offsets) == element_position_relative) { if (!offsets.left.is_predefined()) { m_element->m_pos.x += offsets.left.calc_percent(m_box_right - m_box_left); } else if (!offsets.right.is_predefined()) { m_element->m_pos.x -= offsets.right.calc_percent(m_box_right - m_box_left); } if (!offsets.top.is_predefined()) { int h = 0; if (offsets.top.units() == css_units_percentage) { if (m_element->parent()) { m_element->parent()->get_predefined_height(h); } } m_element->m_pos.y += offsets.top.calc_percent(h); } else if (!offsets.bottom.is_predefined()) { int h = 0; if (offsets.bottom.units() == css_units_percentage) { if (m_element->parent()) { m_element->parent()->get_predefined_height(h); } } m_element->m_pos.y -= offsets.bottom.calc_percent(h); } } } else { if (is_empty() || (!is_empty() && last_box && is_break_only())) { m_height = 0; return; } for (auto i = m_items.rbegin(); i != m_items.rend(); i++) { if ((*i)->is_white_space() || (*i)->is_break()) { if (!(*i)->m_skip) { (*i)->m_skip = true; m_width -= (*i)->width(); } } else { break; } } int base_line = m_font_metrics.base_line(); int line_height = m_line_height; int add_x = 0; switch (m_text_align) { case text_align_right: if (m_width < (m_box_right - m_box_left)) { add_x = (m_box_right - m_box_left) - m_width; } break; case text_align_center: if (m_width < (m_box_right - m_box_left)) { add_x = ((m_box_right - m_box_left) - m_width) / 2; } break; default: add_x = 0; } m_height = 0; // find line box baseline and line-height for (auto &i : m_items) { if (i->get_display() == display_inline_text) { font_metrics fm; i->get_font(&fm); base_line = std::max(base_line, fm.base_line()); line_height = std::max(line_height, i->line_height()); m_height = std::max(m_height, fm.height); } i->m_pos.x += add_x; } if (m_height) { base_line += (line_height - m_height) / 2; } m_height = line_height; int y1 = 0; int y2 = m_height; for (auto &i : m_items) { if (i->get_display() == display_inline_text) { font_metrics fm; i->get_font(&fm); i->m_pos.y = m_height - base_line - fm.ascent; } else { switch (i->get_vertical_align()) { case va_super: case va_sub: case va_baseline: i->m_pos.y = m_height - base_line - i->height() + i->get_base_line() + i->content_margins_top(); break; case va_top: i->m_pos.y = y1 + i->content_margins_top(); break; case va_text_top: i->m_pos.y = m_height - base_line - m_font_metrics.ascent + i->content_margins_top(); break; case va_middle: i->m_pos.y = m_height - base_line - m_font_metrics.x_height / 2 - i->height() / 2 + i->content_margins_top(); break; case va_bottom: i->m_pos.y = y2 - i->height() + i->content_margins_top(); break; case va_text_bottom: i->m_pos.y = m_height - base_line + m_font_metrics.descent - i->height() + i->content_margins_top(); break; } y1 = std::min(y1, i->top()); y2 = std::max(y2, i->bottom()); } } css_offsets offsets; for (auto &i : m_items) { i->m_pos.y -= y1; i->m_pos.y += m_box_top; if (i->get_display() != display_inline_text) { switch (i->get_vertical_align()) { case va_top: i->m_pos.y = m_box_top + i->content_margins_top(); break; case va_bottom: i->m_pos.y = m_box_top + (y2 - y1) - i->height() + i->content_margins_top(); break; case va_baseline: //TODO: process vertical align "baseline" break; case va_middle: //TODO: process vertical align "middle" break; case va_sub: //TODO: process vertical align "sub" break; case va_super: //TODO: process vertical align "super" break; case va_text_bottom: //TODO: process vertical align "text-bottom" break; case va_text_top: //TODO: process vertical align "text-top" break; } } // update position for relative positioned elements if (i->get_element_position(&offsets) == element_position_relative) { if (!offsets.left.is_predefined()) { i->m_pos.x += offsets.left.calc_percent(m_box_right - m_box_left); } else if (!offsets.right.is_predefined()) { i->m_pos.x -= offsets.right.calc_percent(m_box_right - m_box_left); } if (!offsets.top.is_predefined()) { // TODO: m_line_height is not correct here i->m_pos.y += offsets.top.calc_percent(m_line_height); } else if (!offsets.bottom.is_predefined()) { // TODO: m_line_height is not correct here i->m_pos.y -= offsets.bottom.calc_percent(m_line_height); } } } m_height = y2 - y1; m_baseline = (base_line - y1) - (m_height - line_height); } }
void litehtml::line_box::finish(bool last_box) { if( is_empty() || (!is_empty() && last_box && is_break_only()) ) { m_height = 0; return; } for(auto i = m_items.rbegin(); i != m_items.rend(); i++) { if((*i)->is_white_space() || (*i)->is_break()) { if(!(*i)->m_skip) { (*i)->m_skip = true; m_width -= (*i)->width(); } } else { break; } } int base_line = m_font_metrics.base_line(); int line_height = m_line_height; int add_x = 0; switch(m_text_align) { case text_align_right: if(m_width < (m_box_right - m_box_left)) { add_x = (m_box_right - m_box_left) - m_width; } break; case text_align_center: if(m_width < (m_box_right - m_box_left)) { add_x = ((m_box_right - m_box_left) - m_width) / 2; } break; default: add_x = 0; } m_height = 0; // find line box baseline and line-height for(const auto& el : m_items) { if(el->get_display() == display_inline_text) { font_metrics fm; el->get_font(&fm); base_line = std::max(base_line, fm.base_line()); line_height = std::max(line_height, el->line_height()); m_height = std::max(m_height, fm.height); } el->m_pos.x += add_x; } if(m_height) { base_line += (line_height - m_height) / 2; } m_height = line_height; int y1 = 0; int y2 = m_height; for (const auto& el : m_items) { if(el->get_display() == display_inline_text) { font_metrics fm; el->get_font(&fm); el->m_pos.y = m_height - base_line - fm.ascent; } else { switch(el->get_vertical_align()) { case va_super: case va_sub: case va_baseline: el->m_pos.y = m_height - base_line - el->height() + el->get_base_line() + el->content_margins_top(); break; case va_top: el->m_pos.y = y1 + el->content_margins_top(); break; case va_text_top: el->m_pos.y = m_height - base_line - m_font_metrics.ascent + el->content_margins_top(); break; case va_middle: el->m_pos.y = m_height - base_line - m_font_metrics.x_height / 2 - el->height() / 2 + el->content_margins_top(); break; case va_bottom: el->m_pos.y = y2 - el->height() + el->content_margins_top(); break; case va_text_bottom: el->m_pos.y = m_height - base_line + m_font_metrics.descent - el->height() + el->content_margins_top(); break; } y1 = std::min(y1, el->top()); y2 = std::max(y2, el->bottom()); } } css_offsets offsets; for (const auto& el : m_items) { el->m_pos.y -= y1; el->m_pos.y += m_box_top; if(el->get_display() != display_inline_text) { switch(el->get_vertical_align()) { case va_top: el->m_pos.y = m_box_top + el->content_margins_top(); break; case va_bottom: el->m_pos.y = m_box_top + (y2 - y1) - el->height() + el->content_margins_top(); break; case va_baseline: //TODO: process vertical align "baseline" break; case va_middle: //TODO: process vertical align "middle" break; case va_sub: //TODO: process vertical align "sub" break; case va_super: //TODO: process vertical align "super" break; case va_text_bottom: //TODO: process vertical align "text-bottom" break; case va_text_top: //TODO: process vertical align "text-top" break; } } el->apply_relative_shift(m_box_right - m_box_left); } m_height = y2 - y1; m_baseline = (base_line - y1) - (m_height - line_height); }