Exemplo n.º 1
0
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);
    }
}
Exemplo n.º 2
0
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);
}