-#include "html.h"\r
-#include "box.h"\r
-#include "html_tag.h"\r
-\r
-\r
-litehtml::box_type litehtml::block_box::get_type()\r
-{\r
- return box_block;\r
-}\r
-\r
-int litehtml::block_box::height()\r
-{\r
- return m_element->height();\r
-}\r
-\r
-int litehtml::block_box::width()\r
-{\r
- return m_element->width();\r
-}\r
-\r
-void litehtml::block_box::add_element(const element::ptr &el)\r
-{\r
- m_element = el;\r
- el->m_box = this;\r
-}\r
-\r
-void litehtml::block_box::finish(bool last_box)\r
-{\r
- if(!m_element) return;\r
- m_element->apply_relative_shift(m_box_right - m_box_left);\r
-}\r
-\r
-bool litehtml::block_box::can_hold(const element::ptr &el, white_space ws)\r
-{\r
- if(m_element || el->is_inline_box())\r
- {\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-bool litehtml::block_box::is_empty()\r
-{\r
- if(m_element)\r
- {\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-int litehtml::block_box::baseline()\r
-{\r
- if(m_element)\r
- {\r
- return m_element->get_base_line();\r
- }\r
- return 0;\r
-}\r
-\r
-void litehtml::block_box::get_elements( elements_vector& els )\r
-{\r
- els.push_back(m_element);\r
-}\r
-\r
-int litehtml::block_box::top_margin()\r
-{\r
- if(m_element && m_element->collapse_top_margin())\r
- {\r
- return m_element->m_margins.top;\r
- }\r
- return 0;\r
-}\r
-\r
-int litehtml::block_box::bottom_margin()\r
-{\r
- if(m_element && m_element->collapse_bottom_margin())\r
- {\r
- return m_element->m_margins.bottom;\r
- }\r
- return 0;\r
-}\r
-\r
-void litehtml::block_box::y_shift( int shift )\r
-{\r
- m_box_top += shift;\r
- if(m_element)\r
- {\r
- m_element->m_pos.y += shift;\r
- }\r
-}\r
-\r
-void litehtml::block_box::new_width( int left, int right, elements_vector& els )\r
-{\r
-\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////////\r
-\r
-litehtml::box_type litehtml::line_box::get_type()\r
-{\r
- return box_line;\r
-}\r
-\r
-int litehtml::line_box::height()\r
-{\r
- return m_height;\r
-}\r
-\r
-int litehtml::line_box::width()\r
-{\r
- return m_width;\r
-}\r
-\r
-void litehtml::line_box::add_element(const element::ptr &el)\r
-{\r
- el->m_skip = false;\r
- el->m_box = 0;\r
- bool add = true;\r
- if( (m_items.empty() && el->is_white_space()) || el->is_break() )\r
- {\r
- el->m_skip = true;\r
- } else if(el->is_white_space())\r
- {\r
- if (have_last_space())\r
- {\r
- add = false;\r
- el->m_skip = true;\r
- }\r
- }\r
-\r
- if(add)\r
- {\r
- el->m_box = this;\r
- m_items.push_back(el);\r
-\r
- if(!el->m_skip)\r
- {\r
- int el_shift_left = el->get_inline_shift_left();\r
- int el_shift_right = el->get_inline_shift_right();\r
-\r
- el->m_pos.x = m_box_left + m_width + el_shift_left + el->content_margins_left();\r
- el->m_pos.y = m_box_top + el->content_margins_top();\r
- m_width += el->width() + el_shift_left + el_shift_right;\r
- }\r
- }\r
-}\r
-\r
-void litehtml::line_box::finish(bool last_box)\r
-{\r
- if( is_empty() || (!is_empty() && last_box && is_break_only()) )\r
- {\r
- m_height = 0;\r
- return;\r
- }\r
-\r
- for(auto i = m_items.rbegin(); i != m_items.rend(); i++)\r
- {\r
- if((*i)->is_white_space() || (*i)->is_break())\r
- {\r
- if(!(*i)->m_skip)\r
- {\r
- (*i)->m_skip = true;\r
- m_width -= (*i)->width();\r
- }\r
- } else\r
- {\r
- break;\r
- }\r
- }\r
-\r
- int base_line = m_font_metrics.base_line();\r
- int line_height = m_line_height;\r
-\r
- int add_x = 0;\r
- switch(m_text_align)\r
- {\r
- case text_align_right:\r
- if(m_width < (m_box_right - m_box_left))\r
- {\r
- add_x = (m_box_right - m_box_left) - m_width;\r
- }\r
- break;\r
- case text_align_center:\r
- if(m_width < (m_box_right - m_box_left))\r
- {\r
- add_x = ((m_box_right - m_box_left) - m_width) / 2;\r
- }\r
- break;\r
- default:\r
- add_x = 0;\r
- }\r
-\r
- m_height = 0;\r
- // find line box baseline and line-height\r
- for(const auto& el : m_items)\r
- {\r
- if(el->get_display() == display_inline_text)\r
- {\r
- font_metrics fm;\r
- el->get_font(&fm);\r
- base_line = std::max(base_line, fm.base_line());\r
- line_height = std::max(line_height, el->line_height());\r
- m_height = std::max(m_height, fm.height);\r
- }\r
- el->m_pos.x += add_x;\r
- }\r
-\r
- if(m_height)\r
- {\r
- base_line += (line_height - m_height) / 2;\r
- }\r
-\r
- m_height = line_height;\r
-\r
- int y1 = 0;\r
- int y2 = m_height;\r
-\r
- for (const auto& el : m_items)\r
- {\r
- if(el->get_display() == display_inline_text)\r
- {\r
- font_metrics fm;\r
- el->get_font(&fm);\r
- el->m_pos.y = m_height - base_line - fm.ascent;\r
- } else\r
- {\r
- switch(el->get_vertical_align())\r
- {\r
- case va_super:\r
- case va_sub:\r
- case va_baseline:\r
- el->m_pos.y = m_height - base_line - el->height() + el->get_base_line() + el->content_margins_top();\r
- break;\r
- case va_top:\r
- el->m_pos.y = y1 + el->content_margins_top();\r
- break;\r
- case va_text_top:\r
- el->m_pos.y = m_height - base_line - m_font_metrics.ascent + el->content_margins_top();\r
- break;\r
- case va_middle:\r
- el->m_pos.y = m_height - base_line - m_font_metrics.x_height / 2 - el->height() / 2 + el->content_margins_top();\r
- break;\r
- case va_bottom:\r
- el->m_pos.y = y2 - el->height() + el->content_margins_top();\r
- break;\r
- case va_text_bottom:\r
- el->m_pos.y = m_height - base_line + m_font_metrics.descent - el->height() + el->content_margins_top();\r
- break;\r
- }\r
- y1 = std::min(y1, el->top());\r
- y2 = std::max(y2, el->bottom());\r
- }\r
- }\r
-\r
- css_offsets offsets;\r
-\r
- for (const auto& el : m_items)\r
- {\r
- el->m_pos.y -= y1;\r
- el->m_pos.y += m_box_top;\r
- if(el->get_display() != display_inline_text)\r
- {\r
- switch(el->get_vertical_align())\r
- {\r
- case va_top:\r
- el->m_pos.y = m_box_top + el->content_margins_top();\r
- break;\r
- case va_bottom:\r
- el->m_pos.y = m_box_top + (y2 - y1) - el->height() + el->content_margins_top();\r
- break;\r
- case va_baseline:\r
- //TODO: process vertical align "baseline"\r
- break;\r
- case va_middle:\r
- //TODO: process vertical align "middle"\r
- break;\r
- case va_sub:\r
- //TODO: process vertical align "sub"\r
- break;\r
- case va_super:\r
- //TODO: process vertical align "super"\r
- break;\r
- case va_text_bottom:\r
- //TODO: process vertical align "text-bottom"\r
- break;\r
- case va_text_top:\r
- //TODO: process vertical align "text-top"\r
- break;\r
- }\r
- }\r
-\r
- el->apply_relative_shift(m_box_right - m_box_left);\r
- }\r
- m_height = y2 - y1;\r
- m_baseline = (base_line - y1) - (m_height - line_height);\r
-}\r
-\r
-bool litehtml::line_box::can_hold(const element::ptr &el, white_space ws)\r
-{\r
- if(!el->is_inline_box()) return false;\r
-\r
- if(el->is_break())\r
- {\r
- return false;\r
- }\r
-\r
- if(ws == white_space_nowrap || ws == white_space_pre)\r
- {\r
- return true;\r
- }\r
-\r
- if(m_box_left + m_width + el->width() + el->get_inline_shift_left() + el->get_inline_shift_right() > m_box_right)\r
- {\r
- return false;\r
- }\r
-\r
- return true;\r
-}\r
-\r
-bool litehtml::line_box::have_last_space()\r
-{\r
- bool ret = false;\r
- for (auto i = m_items.rbegin(); i != m_items.rend() && !ret; i++)\r
- {\r
- if((*i)->is_white_space() || (*i)->is_break())\r
- {\r
- ret = true;\r
- } else\r
- {\r
- break;\r
- }\r
- }\r
- return ret;\r
-}\r
-\r
-bool litehtml::line_box::is_empty()\r
-{\r
- if(m_items.empty()) return true;\r
- for (auto i = m_items.rbegin(); i != m_items.rend(); i++)\r
- {\r
- if(!(*i)->m_skip || (*i)->is_break())\r
- {\r
- return false;\r
- }\r
- }\r
- return true;\r
-}\r
-\r
-int litehtml::line_box::baseline()\r
-{\r
- return m_baseline;\r
-}\r
-\r
-void litehtml::line_box::get_elements( elements_vector& els )\r
-{\r
- els.insert(els.begin(), m_items.begin(), m_items.end());\r
-}\r
-\r
-int litehtml::line_box::top_margin()\r
-{\r
- return 0;\r
-}\r
-\r
-int litehtml::line_box::bottom_margin()\r
-{\r
- return 0;\r
-}\r
-\r
-void litehtml::line_box::y_shift( int shift )\r
-{\r
- m_box_top += shift;\r
- for (auto& el : m_items)\r
- {\r
- el->m_pos.y += shift;\r
- }\r
-}\r
-\r
-bool litehtml::line_box::is_break_only()\r
-{\r
- if(m_items.empty()) return true;\r
-\r
- if(m_items.front()->is_break())\r
- {\r
- for (auto& el : m_items)\r
- {\r
- if(!el->m_skip)\r
- {\r
- return false;\r
- }\r
- }\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-void litehtml::line_box::new_width( int left, int right, elements_vector& els )\r
-{\r
- int add = left - m_box_left;\r
- if(add)\r
- {\r
- m_box_left = left;\r
- m_box_right = right;\r
- m_width = 0;\r
- auto remove_begin = m_items.end();\r
- for (auto i = m_items.begin() + 1; i != m_items.end(); i++)\r
- {\r
- element::ptr el = (*i);\r
-\r
- if(!el->m_skip)\r
- {\r
- if(m_box_left + m_width + el->width() + el->get_inline_shift_right() + el->get_inline_shift_left() > m_box_right)\r
- {\r
- remove_begin = i;\r
- break;\r
- } else\r
- {\r
- el->m_pos.x += add;\r
- m_width += el->width() + el->get_inline_shift_right() + el->get_inline_shift_left();\r
- }\r
- }\r
- }\r
- if(remove_begin != m_items.end())\r
- {\r
- els.insert(els.begin(), remove_begin, m_items.end());\r
- m_items.erase(remove_begin, m_items.end());\r
-\r
- for(const auto& el : els)\r
- {\r
- el->m_box = 0;\r
- }\r
- }\r
- }\r
-}\r
-\r
+#include "html.h"
+#include "box.h"
+#include "html_tag.h"
+
+
+litehtml::box_type litehtml::block_box::get_type()
+{
+ return box_block;
+}
+
+int litehtml::block_box::height()
+{
+ return m_element->height();
+}
+
+int litehtml::block_box::width()
+{
+ return m_element->width();
+}
+
+void litehtml::block_box::add_element(const element::ptr &el)
+{
+ m_element = el;
+ el->m_box = this;
+}
+
+void litehtml::block_box::finish(bool last_box)
+{
+ if(!m_element) return;
+ m_element->apply_relative_shift(m_box_right - m_box_left);
+}
+
+bool litehtml::block_box::can_hold(const element::ptr &el, white_space ws)
+{
+ if(m_element || el->is_inline_box())
+ {
+ return false;
+ }
+ return true;
+}
+
+bool litehtml::block_box::is_empty()
+{
+ if(m_element)
+ {
+ return false;
+ }
+ return true;
+}
+
+int litehtml::block_box::baseline()
+{
+ if(m_element)
+ {
+ return m_element->get_base_line();
+ }
+ return 0;
+}
+
+void litehtml::block_box::get_elements( elements_vector& els )
+{
+ els.push_back(m_element);
+}
+
+int litehtml::block_box::top_margin()
+{
+ if(m_element && m_element->collapse_top_margin())
+ {
+ return m_element->m_margins.top;
+ }
+ return 0;
+}
+
+int litehtml::block_box::bottom_margin()
+{
+ if(m_element && m_element->collapse_bottom_margin())
+ {
+ return m_element->m_margins.bottom;
+ }
+ return 0;
+}
+
+void litehtml::block_box::y_shift( int shift )
+{
+ m_box_top += shift;
+ if(m_element)
+ {
+ m_element->m_pos.y += shift;
+ }
+}
+
+void litehtml::block_box::new_width( int left, int right, elements_vector& els )
+{
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+litehtml::box_type litehtml::line_box::get_type()
+{
+ return box_line;
+}
+
+int litehtml::line_box::height()
+{
+ return m_height;
+}
+
+int litehtml::line_box::width()
+{
+ return m_width;
+}
+
+void litehtml::line_box::add_element(const element::ptr &el)
+{
+ el->m_skip = false;
+ el->m_box = 0;
+ bool add = true;
+ if( (m_items.empty() && el->is_white_space()) || el->is_break() )
+ {
+ el->m_skip = true;
+ } else if(el->is_white_space())
+ {
+ if (have_last_space())
+ {
+ add = false;
+ el->m_skip = true;
+ }
+ }
+
+ if(add)
+ {
+ el->m_box = this;
+ m_items.push_back(el);
+
+ if(!el->m_skip)
+ {
+ int el_shift_left = el->get_inline_shift_left();
+ int el_shift_right = el->get_inline_shift_right();
+
+ el->m_pos.x = m_box_left + m_width + el_shift_left + el->content_margins_left();
+ el->m_pos.y = m_box_top + el->content_margins_top();
+ m_width += el->width() + el_shift_left + el_shift_right;
+ }
+ }
+}
+
+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);
+}
+
+bool litehtml::line_box::can_hold(const element::ptr &el, white_space ws)
+{
+ if(!el->is_inline_box()) return false;
+
+ if(el->is_break())
+ {
+ return false;
+ }
+
+ if(ws == white_space_nowrap || ws == white_space_pre)
+ {
+ return true;
+ }
+
+ if(m_box_left + m_width + el->width() + el->get_inline_shift_left() + el->get_inline_shift_right() > m_box_right)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool litehtml::line_box::have_last_space()
+{
+ bool ret = false;
+ for (auto i = m_items.rbegin(); i != m_items.rend() && !ret; i++)
+ {
+ if((*i)->is_white_space() || (*i)->is_break())
+ {
+ ret = true;
+ } else
+ {
+ break;
+ }
+ }
+ return ret;
+}
+
+bool litehtml::line_box::is_empty()
+{
+ if(m_items.empty()) return true;
+ for (auto i = m_items.rbegin(); i != m_items.rend(); i++)
+ {
+ if(!(*i)->m_skip || (*i)->is_break())
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+int litehtml::line_box::baseline()
+{
+ return m_baseline;
+}
+
+void litehtml::line_box::get_elements( elements_vector& els )
+{
+ els.insert(els.begin(), m_items.begin(), m_items.end());
+}
+
+int litehtml::line_box::top_margin()
+{
+ return 0;
+}
+
+int litehtml::line_box::bottom_margin()
+{
+ return 0;
+}
+
+void litehtml::line_box::y_shift( int shift )
+{
+ m_box_top += shift;
+ for (auto& el : m_items)
+ {
+ el->m_pos.y += shift;
+ }
+}
+
+bool litehtml::line_box::is_break_only()
+{
+ if(m_items.empty()) return true;
+
+ if(m_items.front()->is_break())
+ {
+ for (auto& el : m_items)
+ {
+ if(!el->m_skip)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+void litehtml::line_box::new_width( int left, int right, elements_vector& els )
+{
+ int add = left - m_box_left;
+ if(add)
+ {
+ m_box_left = left;
+ m_box_right = right;
+ m_width = 0;
+ auto remove_begin = m_items.end();
+ for (auto i = m_items.begin() + 1; i != m_items.end(); i++)
+ {
+ element::ptr el = (*i);
+
+ if(!el->m_skip)
+ {
+ if(m_box_left + m_width + el->width() + el->get_inline_shift_right() + el->get_inline_shift_left() > m_box_right)
+ {
+ remove_begin = i;
+ break;
+ } else
+ {
+ el->m_pos.x += add;
+ m_width += el->width() + el->get_inline_shift_right() + el->get_inline_shift_left();
+ }
+ }
+ }
+ if(remove_begin != m_items.end())
+ {
+ els.insert(els.begin(), remove_begin, m_items.end());
+ m_items.erase(remove_begin, m_items.end());
+
+ for(const auto& el : els)
+ {
+ el->m_box = 0;
+ }
+ }
+ }
+}
+