[Commits] [SCM] claws branch, gtk2, updated. 3.19.1-86-g0d61d4987

jonathan at claws-mail.org jonathan at claws-mail.org
Sun Oct 22 11:52:53 UTC 2023


The branch, gtk2 has been updated
       via  0d61d49870cf988bed2c68da52f49c1286465366 (commit)
      from  8e4a40bc0058f7513111afe0b807dbc94ca5dbda (commit)

Summary of changes:
 src/plugins/litehtml_viewer/litehtml/Makefile.am   |  11 +-
 src/plugins/litehtml_viewer/litehtml/README.md     |  15 +-
 .../litehtml_viewer/litehtml/css_properties.cpp    |   4 +-
 .../litehtml_viewer/litehtml/css_properties.h      |  15 +
 .../litehtml_viewer/litehtml/css_selector.cpp      |   5 +
 src/plugins/litehtml_viewer/litehtml/document.cpp  |  12 +-
 src/plugins/litehtml_viewer/litehtml/document.h    |   2 +-
 .../litehtml_viewer/litehtml/el_before_after.cpp   |   7 +-
 .../litehtml_viewer/litehtml/el_before_after.h     |   1 -
 src/plugins/litehtml_viewer/litehtml/el_image.cpp  |   2 +-
 src/plugins/litehtml_viewer/litehtml/el_style.h    |   2 +-
 src/plugins/litehtml_viewer/litehtml/el_table.cpp  |  17 -
 src/plugins/litehtml_viewer/litehtml/element.cpp   |  65 ++-
 src/plugins/litehtml_viewer/litehtml/element.h     |  23 +-
 .../litehtml/formatting_context.cpp                | 441 +++++++++++++++
 .../litehtml_viewer/litehtml/formatting_context.h  |  54 ++
 src/plugins/litehtml_viewer/litehtml/html_tag.cpp  | 107 ++--
 src/plugins/litehtml_viewer/litehtml/html_tag.h    |  13 +-
 src/plugins/litehtml_viewer/litehtml/line_box.cpp  |   2 +-
 src/plugins/litehtml_viewer/litehtml/master_css.h  |  25 +
 .../litehtml_viewer/litehtml/media_query.cpp       |   2 +-
 .../litehtml_viewer/litehtml/render_block.cpp      | 621 ++-------------------
 .../litehtml_viewer/litehtml/render_block.h        |  40 ++
 .../litehtml/render_block_context.cpp              |  24 +-
 .../litehtml/render_block_context.h                |  29 +
 .../litehtml_viewer/litehtml/render_flex.cpp       |   5 +-
 src/plugins/litehtml_viewer/litehtml/render_flex.h |  46 ++
 .../litehtml_viewer/litehtml/render_image.cpp      |   5 +-
 .../litehtml_viewer/litehtml/render_image.h        |  25 +
 .../litehtml_viewer/litehtml/render_inline.h       |  30 +
 .../litehtml/render_inline_context.cpp             |  71 ++-
 .../litehtml/render_inline_context.h               |  55 ++
 .../litehtml_viewer/litehtml/render_item.cpp       |  62 +-
 src/plugins/litehtml_viewer/litehtml/render_item.h | 259 +--------
 .../litehtml_viewer/litehtml/render_table.cpp      |  84 +--
 .../litehtml_viewer/litehtml/render_table.h        |  56 ++
 src/plugins/litehtml_viewer/litehtml/string_id.h   |   2 +
 src/plugins/litehtml_viewer/litehtml/style.cpp     |  17 +-
 .../litehtml_viewer/litehtml/stylesheet.cpp        |   5 +
 src/plugins/litehtml_viewer/litehtml/table.h       |  18 +-
 src/plugins/litehtml_viewer/litehtml/types.h       |  15 +-
 41 files changed, 1194 insertions(+), 1100 deletions(-)
 create mode 100644 src/plugins/litehtml_viewer/litehtml/formatting_context.cpp
 create mode 100644 src/plugins/litehtml_viewer/litehtml/formatting_context.h
 create mode 100644 src/plugins/litehtml_viewer/litehtml/render_block.h
 create mode 100644 src/plugins/litehtml_viewer/litehtml/render_block_context.h
 create mode 100644 src/plugins/litehtml_viewer/litehtml/render_flex.h
 create mode 100644 src/plugins/litehtml_viewer/litehtml/render_image.h
 create mode 100644 src/plugins/litehtml_viewer/litehtml/render_inline.h
 create mode 100644 src/plugins/litehtml_viewer/litehtml/render_inline_context.h
 create mode 100644 src/plugins/litehtml_viewer/litehtml/render_table.h


- Log -----------------------------------------------------------------
commit 0d61d49870cf988bed2c68da52f49c1286465366
Author: Jonathan Boeing <jonathan at claws-mail.org>
Date:   Sat Oct 21 02:22:33 2023 -0700

    Update LiteHTML sources
    
    Sync with upstream commit 42632777fbb047e15cb6a4f661a3304f993671ec

diff --git a/src/plugins/litehtml_viewer/litehtml/Makefile.am b/src/plugins/litehtml_viewer/litehtml/Makefile.am
index 6e103b7ba..e4b5ac94a 100644
--- a/src/plugins/litehtml_viewer/litehtml/Makefile.am
+++ b/src/plugins/litehtml_viewer/litehtml/Makefile.am
@@ -76,13 +76,14 @@ liblitehtml_la_SOURCES = \
 	el_title.h \
 	el_tr.cpp \
 	el_tr.h \
+	formatting_context.cpp \
+	formatting_context.h \
 	html.cpp \
 	html.h \
 	html_tag.cpp \
 	html_tag.h \
 	iterators.cpp \
 	iterators.h \
-	LICENSE \
 	line_box.cpp \
 	line_box.h \
 	litehtml.h \
@@ -93,16 +94,22 @@ liblitehtml_la_SOURCES = \
 	num_cvt.cpp \
 	num_cvt.h \
 	os_types.h \
-	README.md \
 	render_block_context.cpp \
+	render_block_context.h \
 	render_block.cpp \
+	render_block.h \
 	render_flex.cpp \
+	render_flex.h \
 	render_image.cpp \
+	render_image.h \
 	render_inline_context.cpp \
+	render_inline_context.h \
 	render_inline.cpp \
+	render_inline.h \
 	render_item.cpp \
 	render_item.h \
 	render_table.cpp \
+	render_table.h \
 	string_id.cpp \
 	string_id.h \
 	strtod.cpp \
diff --git a/src/plugins/litehtml_viewer/litehtml/README.md b/src/plugins/litehtml_viewer/litehtml/README.md
index 293f591bc..ab897f517 100644
--- a/src/plugins/litehtml_viewer/litehtml/README.md
+++ b/src/plugins/litehtml_viewer/litehtml/README.md
@@ -1,5 +1,3 @@
-[![Travis Build Status](https://travis-ci.org/litehtml/litehtml.svg?branch=master)](https://travis-ci.org/litehtml/litehtml)
-
 # What is litehtml?
 
 **litehtml** is the lightweight HTML rendering engine with CSS2/CSS3 support. Note that **litehtml** itself does not draw any text, pictures or other graphics and that **litehtml** does not depend on any image/draw/font library. You are free to use any library to draw images, fonts and any other graphics. **litehtml** just parses HTML/CSS and places the HTML elements into the correct positions (renders HTML). To draw the HTML elements you have to implement the simple callback interface [document_container](https://github.com/litehtml/litehtml/wiki/document_container). This interface is really simple, check it out! The [document_container](https://github.com/litehtml/litehtml/wiki/document_container) implementation is required to render HTML correctly.
@@ -14,7 +12,7 @@
 
 ## Compatibility
 
-**litehtml** is compatible with any platform suported by C++ and STL. For Windows MS Visual Studio 2013 is recommended. **litehtml** supports both UTF-8 and Unicode strings on Windows and UTF-8 strings on Linux and Haiku.
+**litehtml** is compatible with any platform supported by C++ and STL. For Windows MS Visual Studio 2013 is recommended. **litehtml** supports only UTF-8 strings.
 
 ## Support for HTML and CSS standards
 
@@ -34,12 +32,7 @@ The litebrowser source codes are available on GitHub:
 **litehtml** is distributed under [New BSD License](https://opensource.org/licenses/BSD-3-Clause).
 The **gumbo-parser** is disributed under [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0)
 
-## Support litehtml project
-
-If you like the work **litehtml** is doing please consider a small donation:
-
-[ ![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif) ](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UHBQG6EAFCRBA) [ ![Patreon](https://img.shields.io/badge/patreon-Become%20a%20Patron!-red.png?style=for-the-badge&logo=patreon) ](https://www.patreon.com/tordex)
-
-Bitcoin: **1CS1174GVSLbP33TBp8RFwqPS6KmQK6kLY**
+## Links
 
-![BitCoin](https://www.tordex.com/assets/images/litehtml-bitcoin.png)
+  * [source code](https://github.com/litehtml/litehtml)
+  * [website](http://www.litehtml.com/)
diff --git a/src/plugins/litehtml_viewer/litehtml/css_properties.cpp b/src/plugins/litehtml_viewer/litehtml/css_properties.cpp
index 1efccb609..2696ae28f 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_properties.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/css_properties.cpp
@@ -1,5 +1,6 @@
 #include "html.h"
 #include "css_properties.h"
+#include <cmath>
 
 #define offset(member) ((uint_ptr)&this->member - (uint_ptr)this)
 
@@ -20,6 +21,7 @@ void litehtml::css_properties::compute(const element* el, const document::ptr& d
 	m_vertical_align = (vertical_align)	  el->get_enum_property( _vertical_align_,	false,	va_baseline,			 offset(m_vertical_align));
 	m_text_transform = (text_transform)	  el->get_enum_property( _text_transform_,	true,	text_transform_none,	 offset(m_text_transform));
 	m_white_space	 = (white_space)	  el->get_enum_property( _white_space_,		true,	white_space_normal,		 offset(m_white_space));
+	m_caption_side	 = (caption_side)	  el->get_enum_property( _caption_side_,	true,	caption_side_top,		 offset(m_caption_side));
 
 	// https://www.w3.org/TR/CSS22/visuren.html#dis-pos-flo
 	if (m_display == display_none)
@@ -221,7 +223,7 @@ void litehtml::css_properties::compute(const element* el, const document::ptr& d
 		m_line_height = m_font_metrics.height;
 	} else if(m_css_line_height.units() == css_units_none)
 	{
-		m_line_height = (int) (m_css_line_height.val() * font_size);
+		m_line_height = (int) std::nearbyint(m_css_line_height.val() * font_size);
 	} else
 	{
 		m_line_height = doc->to_pixels(m_css_line_height, font_size, font_size);
diff --git a/src/plugins/litehtml_viewer/litehtml/css_properties.h b/src/plugins/litehtml_viewer/litehtml/css_properties.h
index 0eed09d9a..739e35fc2 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_properties.h
+++ b/src/plugins/litehtml_viewer/litehtml/css_properties.h
@@ -70,6 +70,8 @@ namespace litehtml
 		flex_align_self			m_flex_align_self;
 		flex_align_content		m_flex_align_content;
 
+		caption_side			m_caption_side;
+
 	private:
 		void compute_font(const element* el, const std::shared_ptr<document>& doc);
 		void compute_background(const element* el, const std::shared_ptr<document>& doc);
@@ -238,6 +240,9 @@ namespace litehtml
 		const css_length& get_border_spacing_y() const;
 		void set_border_spacing_y(const css_length& mBorderSpacingY);
 
+		caption_side get_caption_side() const;
+		void set_caption_side(caption_side side);
+
 		float get_flex_grow() const;
 		float get_flex_shrink() const;
 		const css_length& get_flex_basis() const;
@@ -638,6 +643,16 @@ namespace litehtml
 	{
 		return m_flex_align_content;
 	}
+
+	inline caption_side css_properties::get_caption_side() const
+	{
+		return m_caption_side;
+	}
+	inline void css_properties::set_caption_side(caption_side side)
+	{
+		m_caption_side = side;
+	}
+
 }
 
 #endif //LITEHTML_CSS_PROPERTIES_H
diff --git a/src/plugins/litehtml_viewer/litehtml/css_selector.cpp b/src/plugins/litehtml_viewer/litehtml/css_selector.cpp
index 6ace9bb07..5843cb1a6 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_selector.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/css_selector.cpp
@@ -183,6 +183,11 @@ void litehtml::css_element_selector::parse( const string& txt )
 						string::size_type pos2 = txt.find_first_of('\"', pos + 1);
 						attribute.val = txt.substr(pos + 1, pos2 == string::npos ? pos2 : (pos2 - pos - 1));
 						pos = pos2 == string::npos ? pos2 : (pos2 + 1);
+					} else if(txt[pos] == '\'')
+					{
+						string::size_type pos2 = txt.find_first_of('\'', pos + 1);
+						attribute.val = txt.substr(pos + 1, pos2 == string::npos ? pos2 : (pos2 - pos - 1));
+						pos = pos2 == string::npos ? pos2 : (pos2 + 1);
 					} else if(txt[pos] == ']')
 					{
 						pos ++;
diff --git a/src/plugins/litehtml_viewer/litehtml/document.cpp b/src/plugins/litehtml_viewer/litehtml/document.cpp
index 8623bff41..ec336613d 100644
--- a/src/plugins/litehtml_viewer/litehtml/document.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/document.cpp
@@ -27,6 +27,8 @@
 #include "gumbo.h"
 #include "utf8_strings.h"
 #include "render_item.h"
+#include "render_table.h"
+#include "render_block.h"
 
 litehtml::document::document(document_container* objContainer)
 {
@@ -54,7 +56,7 @@ litehtml::document::ptr litehtml::document::createFromString( const char* str, d
 	document::ptr doc = std::make_shared<document>(objPainter);
 
 	// Create litehtml::elements.
-	elements_vector root_elements;
+	elements_list root_elements;
 	doc->create_node(output->root, root_elements, true);
 	if (!root_elements.empty())
 	{
@@ -304,7 +306,7 @@ int litehtml::document::render( int max_width, render_type rt )
 			m_root_render->render_positioned(rt);
 		} else
 		{
-			ret = m_root_render->render(0, 0, cb_context);
+			ret = m_root_render->render(0, 0, cb_context, nullptr);
 			if(m_root_render->fetch_positioned())
 			{
 				m_fixed_boxes.clear();
@@ -718,7 +720,7 @@ void litehtml::document::add_media_list( const media_query_list::ptr& list )
 	}
 }
 
-void litehtml::document::create_node(void* gnode, elements_vector& elements, bool parseTextNode)
+void litehtml::document::create_node(void* gnode, elements_list& elements, bool parseTextNode)
 {
 	auto* node = (GumboNode*)gnode;
 	switch (node->type)
@@ -756,7 +758,7 @@ void litehtml::document::create_node(void* gnode, elements_vector& elements, boo
 			}
 			if (ret)
 			{
-				elements_vector child;
+				elements_list child;
 				for (unsigned int i = 0; i < node->v.element.children.length; i++)
 				{
 					child.clear();
@@ -1018,7 +1020,7 @@ void litehtml::document::append_children_from_string(element& parent, const char
 	GumboOutput* output = gumbo_parse(str);
 
 	// Create litehtml::elements.
-	elements_vector child_elements;
+	elements_list child_elements;
 	create_node(output->root, child_elements, true);
 
 	// Destroy GumboOutput
diff --git a/src/plugins/litehtml_viewer/litehtml/document.h b/src/plugins/litehtml_viewer/litehtml/document.h
index 11322f899..b4b268ba8 100644
--- a/src/plugins/litehtml_viewer/litehtml/document.h
+++ b/src/plugins/litehtml_viewer/litehtml/document.h
@@ -111,7 +111,7 @@ namespace litehtml
 	private:
 		uint_ptr	add_font(const char* name, int size, const char* weight, const char* style, const char* decoration, font_metrics* fm);
 
-		void create_node(void* gnode, elements_vector& elements, bool parseTextNode);
+		void create_node(void* gnode, elements_list& elements, bool parseTextNode);
 		bool update_media_lists(const media_features& features);
 		void fix_tables_layout();
 		void fix_table_children(const std::shared_ptr<render_item>& el_ptr, style_display disp, const char* disp_str);
diff --git a/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp b/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp
index 4455642e8..8c24eec98 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp
@@ -109,7 +109,7 @@ void litehtml::el_before_after_base::add_text( const string& txt )
 					word.clear();
 				}
 				word += chr;
-				element::ptr el = std::make_shared<el_text>(word.c_str(), get_document());
+				element::ptr el = std::make_shared<el_space>(word.c_str(), get_document());
 				appendChild(el);
 				word.clear();
 			} else
@@ -197,8 +197,3 @@ litehtml::string litehtml::el_before_after_base::convert_escape( const char* txt
     u_str[1] = 0;
 	return litehtml::string(litehtml_from_wchar(u_str));
 }
-
-void litehtml::el_before_after_base::apply_stylesheet( const litehtml::css& stylesheet )
-{
-
-}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_before_after.h b/src/plugins/litehtml_viewer/litehtml/el_before_after.h
index ac966f395..eed5f3dad 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_before_after.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_before_after.h
@@ -11,7 +11,6 @@ namespace litehtml
 		el_before_after_base(const std::shared_ptr<document>& doc, bool before);
 
 		void add_style(const style& style) override;
-		void apply_stylesheet(const litehtml::css& stylesheet) override;
 	private:
 		void	add_text(const string& txt);
 		void	add_function(const string& fnc, const string& params);
diff --git a/src/plugins/litehtml_viewer/litehtml/el_image.cpp b/src/plugins/litehtml_viewer/litehtml/el_image.cpp
index 34b8a7aef..9cf8146b4 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_image.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_image.cpp
@@ -1,6 +1,6 @@
 #include "html.h"
 #include "el_image.h"
-#include "render_item.h"
+#include "render_image.h"
 
 litehtml::el_image::el_image(const document::ptr& doc) : html_tag(doc)
 {
diff --git a/src/plugins/litehtml_viewer/litehtml/el_style.h b/src/plugins/litehtml_viewer/litehtml/el_style.h
index b6258932d..62f154625 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_style.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_style.h
@@ -7,7 +7,7 @@ namespace litehtml
 {
 	class el_style : public element
 	{
-		elements_vector		m_children;
+		elements_list		m_children;
 	public:
 		explicit el_style(const std::shared_ptr<document>& doc);
 
diff --git a/src/plugins/litehtml_viewer/litehtml/el_table.cpp b/src/plugins/litehtml_viewer/litehtml/el_table.cpp
index d0c711c4d..0bb864843 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_table.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_table.cpp
@@ -30,23 +30,6 @@ void litehtml::el_table::parse_attributes()
 		m_style.add_property(_width_, str);
 	}
 
-	str = get_attr("align");
-	if(str)
-	{
-		int align = value_index(str, "left;center;right");
-		switch(align)
-		{
-		case 1:
-			m_style.add_property(_margin_left_, "auto");
-			m_style.add_property(_margin_right_, "auto");
-			break;
-		case 2:
-			m_style.add_property(_margin_left_, "auto");
-			m_style.add_property(_margin_right_, "0");
-			break;
-		}
-	}
-
 	str = get_attr("cellspacing");
 	if(str)
 	{
diff --git a/src/plugins/litehtml_viewer/litehtml/element.cpp b/src/plugins/litehtml_viewer/litehtml/element.cpp
index 2438b1325..1d0a509b1 100644
--- a/src/plugins/litehtml_viewer/litehtml/element.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/element.cpp
@@ -2,6 +2,9 @@
 #include "element.h"
 #include "document.h"
 #include "render_item.h"
+#include "render_flex.h"
+#include "render_inline.h"
+#include "render_table.h"
 #include "el_before_after.h"
 
 namespace litehtml
@@ -44,7 +47,7 @@ position element::get_placement() const
 	return pos;
 }
 
-bool element::is_inline_box() const
+bool element::is_inline() const
 {
 	if(	css().get_display() == display_inline ||
 		   css().get_display() == display_inline_table ||
@@ -57,6 +60,17 @@ bool element::is_inline_box() const
 	return false;
 }
 
+bool element::is_inline_box() const
+{
+	if(	css().get_display() == display_inline_table ||
+		   css().get_display() == display_inline_block ||
+		   css().get_display() == display_inline_flex)
+	{
+		return true;
+	}
+	return false;
+}
+
 bool element::is_ancestor(const ptr &el) const
 {
 	element::ptr el_parent = parent();
@@ -244,30 +258,41 @@ bool element::find_styles_changes( position::vector& redraw_boxes)
 
 element::ptr element::_add_before_after(int type, const style& style)
 {
-	if(style.get_property(_content_).m_type != prop_type_invalid)
+	element::ptr el;
+	if(type == 0)
 	{
-		element::ptr el;
-		if(type == 0)
-		{
-			el = std::make_shared<el_before>(get_document());
-			m_children.insert(m_children.begin(), el);
-		} else
-		{
-			el = std::make_shared<el_after>(get_document());
-			m_children.insert(m_children.end(), el);
-		}
-		el->parent(shared_from_this());
-		return el;
+		el = std::make_shared<el_before>(get_document());
+		m_children.insert(m_children.begin(), el);
+	} else
+	{
+		el = std::make_shared<el_after>(get_document());
+		m_children.insert(m_children.end(), el);
 	}
-	return nullptr;
+	el->parent(shared_from_this());
+	return el;
 }
 
+bool element::is_block_formatting_context() const
+{
+	if(	m_css.get_display() == display_inline_block ||
+		   m_css.get_display() == display_table_cell ||
+		   m_css.get_display() == display_table_caption ||
+		   is_root() ||
+		   m_css.get_float() != float_none ||
+		   m_css.get_position() == element_position_absolute ||
+		   m_css.get_position() == element_position_fixed ||
+		   m_css.get_overflow() > overflow_visible)
+	{
+		return true;
+	}
+	return false;
+}
 
 const background* element::get_background(bool own_only)						LITEHTML_RETURN_FUNC(nullptr)
 void element::add_style( const style& style)	        						LITEHTML_EMPTY_FUNC
-void element::select_all(const css_selector& selector, elements_vector& res)	LITEHTML_EMPTY_FUNC
-elements_vector element::select_all(const css_selector& selector)				LITEHTML_RETURN_FUNC(elements_vector())
-elements_vector element::select_all(const string& selector)						LITEHTML_RETURN_FUNC(elements_vector())
+void element::select_all(const css_selector& selector, elements_list& res)	LITEHTML_EMPTY_FUNC
+elements_list element::select_all(const css_selector& selector)				LITEHTML_RETURN_FUNC(elements_list())
+elements_list element::select_all(const string& selector)						LITEHTML_RETURN_FUNC(elements_list())
 element::ptr element::select_one( const css_selector& selector )				LITEHTML_RETURN_FUNC(nullptr)
 element::ptr element::select_one( const string& selector )						LITEHTML_RETURN_FUNC(nullptr)
 element::ptr element::find_adjacent_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo /*= true*/, bool* is_pseudo /*= 0*/) LITEHTML_RETURN_FUNC(nullptr)
@@ -275,10 +300,6 @@ element::ptr element::find_sibling(const element::ptr& el, const css_selector& s
 bool element::is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const		LITEHTML_RETURN_FUNC(false)
 bool element::is_nth_child(const element::ptr&, int num, int off, bool of_type) const		LITEHTML_RETURN_FUNC(false)
 bool element::is_only_child(const element::ptr& el, bool of_type)	 const	LITEHTML_RETURN_FUNC(false)
-element::ptr element::get_child( int idx ) const					LITEHTML_RETURN_FUNC(nullptr)
-size_t element::get_children_count() const							LITEHTML_RETURN_FUNC(0)
-void element::update_floats(int dy, const ptr &parent)				LITEHTML_EMPTY_FUNC
-bool element::is_floats_holder() const								LITEHTML_RETURN_FUNC(false)
 void element::get_content_size( size& sz, int max_width )			LITEHTML_EMPTY_FUNC
 bool element::appendChild(const ptr &el)							LITEHTML_RETURN_FUNC(false)
 bool element::removeChild(const ptr &el)							LITEHTML_RETURN_FUNC(false)
diff --git a/src/plugins/litehtml_viewer/litehtml/element.h b/src/plugins/litehtml_viewer/litehtml/element.h
index 2fa160c2c..e330b5c01 100644
--- a/src/plugins/litehtml_viewer/litehtml/element.h
+++ b/src/plugins/litehtml_viewer/litehtml/element.h
@@ -28,12 +28,12 @@ namespace litehtml
 	protected:
 		std::weak_ptr<element>					m_parent;
 		std::weak_ptr<document>					m_doc;
-		elements_vector							m_children;
+		elements_list							m_children;
 		css_properties							m_css;
 		std::list<std::weak_ptr<render_item>>	m_renders;
 		used_selector::vector					m_used_styles;
 
-		virtual void select_all(const css_selector& selector, elements_vector& res);
+		virtual void select_all(const css_selector& selector, elements_list& res);
 		element::ptr _add_before_after(int type, const style& style);
 	public:
 		explicit element(const std::shared_ptr<document>& doc);
@@ -43,13 +43,14 @@ namespace litehtml
 		css_properties&				css_w();
 
 		bool						in_normal_flow()			const;
-		bool						is_inline_box()				const;
+		bool						is_inline()					const;	// returns true if element is inline
+		bool						is_inline_box()				const;	// returns true if element is inline box (inline-table, inline-box, inline-flex)
 		bool						is_block_box()				const;
 		position					get_placement()				const;
 		bool						is_positioned()				const;
 		bool						is_float()					const;
+		bool						is_block_formatting_context() const;
 
-		bool						have_parent() const;
 		bool						is_root() const;
 		element::ptr				parent() const;
 		void						parent(const element::ptr& par);
@@ -57,9 +58,10 @@ namespace litehtml
 		bool						is_table_skip() const;
 
 		std::shared_ptr<document>	get_document() const;
+		const std::list<std::shared_ptr<element>>& children() const;
 
-		virtual elements_vector		select_all(const string& selector);
-		virtual elements_vector		select_all(const css_selector& selector);
+		virtual elements_list		select_all(const string& selector);
+		virtual elements_list		select_all(const css_selector& selector);
 
 		virtual element::ptr		select_one(const string& selector);
 		virtual element::ptr		select_one(const css_selector& selector);
@@ -73,8 +75,6 @@ namespace litehtml
 		virtual const char*			get_tagName() const;
 		virtual void				set_tagName(const char* tag);
 		virtual void				set_data(const char* data);
-		virtual size_t				get_children_count() const;
-		virtual element::ptr		get_child(int idx) const;
 
 		virtual void				set_attr(const char* name, const char* val);
 		virtual const char*			get_attr(const char* name, const char* def = nullptr) const;
@@ -119,8 +119,6 @@ namespace litehtml
 		virtual element::ptr		find_adjacent_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr);
 		virtual element::ptr		find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr);
 		virtual void				get_content_size(size& sz, int max_width);
-		virtual bool				is_floats_holder() const;
-		virtual void				update_floats(int dy, const ptr &parent);
 		virtual bool				is_nth_child(const element::ptr& el, int num, int off, bool of_type) const;
 		virtual bool				is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const;
 		virtual bool				is_only_child(const element::ptr& el, bool of_type) const;
@@ -211,6 +209,11 @@ namespace litehtml
 		}
 		return false;
 	}
+
+	inline const std::list<std::shared_ptr<element>>& element::children() const
+	{
+		return m_children;
+	}
 }
 
 #endif  // LH_ELEMENT_H
diff --git a/src/plugins/litehtml_viewer/litehtml/formatting_context.cpp b/src/plugins/litehtml_viewer/litehtml/formatting_context.cpp
new file mode 100644
index 000000000..4e41c7b5f
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/formatting_context.cpp
@@ -0,0 +1,441 @@
+#include "html.h"
+#include "render_item.h"
+#include "formatting_context.h"
+
+void litehtml::formatting_context::add_float(const std::shared_ptr<render_item> &el, int min_width, int context)
+{
+	floated_box fb;
+	fb.pos.x		= el->left() + m_current_left;
+	fb.pos.y		= el->top() + m_current_top;
+	fb.pos.width	= el->width();
+	fb.pos.height	= el->height();
+	fb.float_side	= el->src_el()->css().get_float();
+	fb.clear_floats	= el->src_el()->css().get_clear();
+	fb.el			= el;
+	fb.context		= context;
+	fb.min_width	= min_width;
+
+	if(fb.float_side == float_left)
+	{
+		if(m_floats_left.empty())
+		{
+			m_floats_left.push_back(fb);
+		} else
+		{
+			bool inserted = false;
+			for(auto i = m_floats_left.begin(); i != m_floats_left.end(); i++)
+			{
+				if(fb.pos.right() > i->pos.right())
+				{
+					m_floats_left.insert(i, std::move(fb));
+					inserted = true;
+					break;
+				}
+			}
+			if(!inserted)
+			{
+				m_floats_left.push_back(std::move(fb));
+			}
+		}
+		m_cache_line_left.invalidate();
+	} else if(fb.float_side == float_right)
+	{
+		if(m_floats_right.empty())
+		{
+			m_floats_right.push_back(std::move(fb));
+		} else
+		{
+			bool inserted = false;
+			for(auto i = m_floats_right.begin(); i != m_floats_right.end(); i++)
+			{
+				if(fb.pos.left() < i->pos.left())
+				{
+					m_floats_right.insert(i, std::move(fb));
+					inserted = true;
+					break;
+				}
+			}
+			if(!inserted)
+			{
+				m_floats_right.push_back(fb);
+			}
+		}
+		m_cache_line_right.invalidate();
+	}
+}
+
+int litehtml::formatting_context::get_floats_height(element_float el_float) const
+{
+	int h = 0;
+
+	for(const auto& fb : m_floats_left)
+	{
+		bool process = false;
+		switch(el_float)
+		{
+			case float_none:
+				process = true;
+				break;
+			case float_left:
+				if (fb.clear_floats == clear_left || fb.clear_floats == clear_both)
+				{
+					process = true;
+				}
+				break;
+			case float_right:
+				if (fb.clear_floats == clear_right || fb.clear_floats == clear_both)
+				{
+					process = true;
+				}
+				break;
+		}
+		if(process)
+		{
+			if(el_float == float_none)
+			{
+				h = std::max(h, fb.pos.bottom());
+			} else
+			{
+				h = std::max(h, fb.pos.top());
+			}
+		}
+	}
+
+
+	for(const auto& fb : m_floats_right)
+	{
+		int process = false;
+		switch(el_float)
+		{
+			case float_none:
+				process = true;
+				break;
+			case float_left:
+				if (fb.clear_floats == clear_left || fb.clear_floats == clear_both)
+				{
+					process = true;
+				}
+				break;
+			case float_right:
+				if (fb.clear_floats == clear_right || fb.clear_floats == clear_both)
+				{
+					process = true;
+				}
+				break;
+		}
+		if(process)
+		{
+			if(el_float == float_none)
+			{
+				h = std::max(h, fb.pos.bottom());
+			} else
+			{
+				h = std::max(h, fb.pos.top());
+			}
+		}
+	}
+
+	return h - m_current_top;
+}
+
+int litehtml::formatting_context::get_left_floats_height() const
+{
+	int h = 0;
+	if(!m_floats_left.empty())
+	{
+		for (const auto& fb : m_floats_left)
+		{
+			h = std::max(h, fb.pos.bottom());
+		}
+	}
+	return h - m_current_top;
+}
+
+int litehtml::formatting_context::get_right_floats_height() const
+{
+	int h = 0;
+	if(!m_floats_right.empty())
+	{
+		for(const auto& fb : m_floats_right)
+		{
+			h = std::max(h, fb.pos.bottom());
+		}
+	}
+	return h - m_current_top;
+}
+
+int litehtml::formatting_context::get_line_left(int y )
+{
+	y += m_current_top;
+
+	if(m_cache_line_left.is_valid && m_cache_line_left.hash == y)
+	{
+		if(m_cache_line_left.val - m_current_left < 0)
+		{
+			return 0;
+		}
+		return m_cache_line_left.val - m_current_left;
+	}
+
+	int w = 0;
+	for(const auto& fb : m_floats_left)
+	{
+		if (y >= fb.pos.top() && y < fb.pos.bottom())
+		{
+			w = std::max(w, fb.pos.right());
+			if (w < fb.pos.right())
+			{
+				break;
+			}
+		}
+	}
+	m_cache_line_left.set_value(y, w);
+	w -= m_current_left;
+	if(w < 0) return 0;
+	return w;
+}
+
+int litehtml::formatting_context::get_line_right(int y, int def_right )
+{
+	y += m_current_top;
+	def_right += m_current_left;
+	if(m_cache_line_right.is_valid && m_cache_line_right.hash == y)
+	{
+		if(m_cache_line_right.is_default)
+		{
+			return def_right - m_current_left;
+		} else
+		{
+			int w = std::min(m_cache_line_right.val, def_right) - m_current_left;
+			if(w < 0) return 0;
+			return w;
+		}
+	}
+
+	int w = def_right;
+	m_cache_line_right.is_default = true;
+	for(const auto& fb : m_floats_right)
+	{
+		if(y >= fb.pos.top() && y < fb.pos.bottom())
+		{
+			w = std::min(w, fb.pos.left());
+			m_cache_line_right.is_default = false;
+			if(w > fb.pos.left())
+			{
+				break;
+			}
+		}
+	}
+	m_cache_line_right.set_value(y, w);
+	w -= m_current_left;
+	if(w < 0) return 0;
+	return w;
+}
+
+
+void litehtml::formatting_context::clear_floats(int context)
+{
+	auto iter = m_floats_left.begin();
+	while(iter != m_floats_left.end())
+	{
+		if(iter->context >= context)
+		{
+			iter = m_floats_left.erase(iter);
+			m_cache_line_left.invalidate();
+		} else
+		{
+			iter++;
+		}
+	}
+
+	iter = m_floats_right.begin();
+	while(iter != m_floats_right.end())
+	{
+		if(iter->context >= context)
+		{
+			iter = m_floats_right.erase(iter);
+			m_cache_line_right.invalidate();
+		} else
+		{
+			iter++;
+		}
+	}
+}
+
+int litehtml::formatting_context::get_cleared_top(const std::shared_ptr<render_item> &el, int line_top) const
+{
+	switch(el->src_el()->css().get_clear())
+	{
+		case clear_left:
+			{
+				int fh = get_left_floats_height();
+				if(fh && fh > line_top)
+				{
+					line_top = fh;
+				}
+			}
+			break;
+		case clear_right:
+			{
+				int fh = get_right_floats_height();
+				if(fh && fh > line_top)
+				{
+					line_top = fh;
+				}
+			}
+			break;
+		case clear_both:
+			{
+				int fh = get_floats_height(float_none);
+				if(fh && fh > line_top)
+				{
+					line_top = fh;
+				}
+			}
+			break;
+		default:
+			if(el->src_el()->css().get_float() != float_none)
+			{
+				int fh = get_floats_height(el->src_el()->css().get_float());
+				if(fh && fh > line_top)
+				{
+					line_top = fh;
+				}
+			}
+			break;
+	}
+	return line_top;
+}
+
+int litehtml::formatting_context::find_next_line_top(int top, int width, int def_right )
+{
+	top += m_current_top;
+	def_right += m_current_left;
+
+	int new_top = top;
+	int_vector points;
+
+	for(const auto& fb : m_floats_left)
+	{
+		if(fb.pos.top() >= top)
+		{
+			if(find(points.begin(), points.end(), fb.pos.top()) == points.end())
+			{
+				points.push_back(fb.pos.top());
+			}
+		}
+		if (fb.pos.bottom() >= top)
+		{
+			if (find(points.begin(), points.end(), fb.pos.bottom()) == points.end())
+			{
+				points.push_back(fb.pos.bottom());
+			}
+		}
+	}
+
+	for (const auto& fb : m_floats_right)
+	{
+		if (fb.pos.top() >= top)
+		{
+			if (find(points.begin(), points.end(), fb.pos.top()) == points.end())
+			{
+				points.push_back(fb.pos.top());
+			}
+		}
+		if (fb.pos.bottom() >= top)
+		{
+			if (find(points.begin(), points.end(), fb.pos.bottom()) == points.end())
+			{
+				points.push_back(fb.pos.bottom());
+			}
+		}
+	}
+
+	if(!points.empty())
+	{
+		sort(points.begin(), points.end(), std::less<int>( ));
+		new_top = points.back();
+
+		for(auto pt : points)
+		{
+			int pos_left	= 0;
+			int pos_right	= def_right;
+			get_line_left_right(pt - m_current_top, def_right - m_current_left, pos_left, pos_right);
+
+			if(pos_right - pos_left >= width)
+			{
+				new_top = pt;
+				break;
+			}
+		}
+	}
+	return new_top - m_current_top;
+}
+
+void litehtml::formatting_context::update_floats(int dy, const std::shared_ptr<render_item> &parent)
+{
+	bool reset_cache = false;
+	for(auto fb = m_floats_left.rbegin(); fb != m_floats_left.rend(); fb++)
+	{
+		if(fb->el->src_el()->is_ancestor(parent->src_el()))
+		{
+			reset_cache	= true;
+			fb->pos.y	+= dy;
+		}
+	}
+	if(reset_cache)
+	{
+		m_cache_line_left.invalidate();
+	}
+	reset_cache = false;
+	for(auto fb = m_floats_right.rbegin(); fb != m_floats_right.rend(); fb++)
+	{
+		if(fb->el->src_el()->is_ancestor(parent->src_el()))
+		{
+			reset_cache	= true;
+			fb->pos.y	+= dy;
+		}
+	}
+	if(reset_cache)
+	{
+		m_cache_line_right.invalidate();
+	}
+}
+
+void litehtml::formatting_context::apply_relative_shift(const containing_block_context &containing_block_size)
+{
+	for (const auto& fb : m_floats_left)
+	{
+		fb.el->apply_relative_shift(containing_block_size);
+	}
+}
+
+int litehtml::formatting_context::find_min_left(int y, int context_idx)
+{
+	y += m_current_top;
+	int min_left = m_current_left;
+	for(const auto& fb : m_floats_left)
+	{
+		if (y >= fb.pos.top() && y < fb.pos.bottom() && fb.context == context_idx)
+		{
+			min_left += fb.min_width;
+		}
+	}
+	if(min_left < m_current_left) return 0;
+	return min_left - m_current_left;
+}
+
+int litehtml::formatting_context::find_min_right(int y, int right, int context_idx)
+{
+	y += m_current_top;
+	int min_right = right + m_current_left;
+	for(const auto& fb : m_floats_right)
+	{
+		if (y >= fb.pos.top() && y < fb.pos.bottom() && fb.context == context_idx)
+		{
+			min_right -= fb.min_width;
+		}
+	}
+	if(min_right < m_current_left) return 0;
+	return min_right - m_current_left;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/formatting_context.h b/src/plugins/litehtml_viewer/litehtml/formatting_context.h
new file mode 100644
index 000000000..eee481dc4
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/formatting_context.h
@@ -0,0 +1,54 @@
+#ifndef LITEHTML_FLOATS_HOLDER_H
+#define LITEHTML_FLOATS_HOLDER_H
+
+#include <list>
+#include "types.h"
+
+namespace litehtml
+{
+	class formatting_context
+	{
+	private:
+		std::list<floated_box> m_floats_left;
+		std::list<floated_box> m_floats_right;
+		int_int_cache m_cache_line_left;
+		int_int_cache m_cache_line_right;
+		int m_current_top;
+		int m_current_left;
+
+	public:
+		formatting_context() : m_current_top(0), m_current_left(0)	{}
+
+		void push_position(int x, int y)
+		{
+			m_current_left += x;
+			m_current_top += y;
+		}
+		void pop_position(int x, int y)
+		{
+			m_current_left -= x;
+			m_current_top -= y;
+		}
+
+		void add_float(const std::shared_ptr<render_item> &el, int min_width, int context);
+		void clear_floats(int context);
+		int find_next_line_top( int top, int width, int def_right );
+		int get_floats_height(element_float el_float = float_none) const;
+		int get_left_floats_height() const;
+		int get_right_floats_height() const;
+		int get_line_left( int y );
+		void get_line_left_right( int y, int def_right, int& ln_left, int& ln_right )
+		{
+			ln_left		= get_line_left(y);
+			ln_right	= get_line_right(y, def_right);
+		}
+		int get_line_right( int y, int def_right );
+		int get_cleared_top(const std::shared_ptr<render_item> &el, int line_top) const;
+		void update_floats(int dy, const std::shared_ptr<render_item> &parent);
+		void apply_relative_shift(const containing_block_context &containing_block_size);
+		int find_min_left(int y, int context_idx);
+		int find_min_right(int y, int right, int context_idx);
+	};
+}
+
+#endif //LITEHTML_FLOATS_HOLDER_H
diff --git a/src/plugins/litehtml_viewer/litehtml/html_tag.cpp b/src/plugins/litehtml_viewer/litehtml/html_tag.cpp
index d1e7302e4..0b978f56a 100644
--- a/src/plugins/litehtml_viewer/litehtml/html_tag.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/html_tag.cpp
@@ -121,7 +121,7 @@ const char* litehtml::html_tag::get_attr( const char* name, const char* def ) co
 	return def;
 }
 
-litehtml::elements_vector litehtml::html_tag::select_all( const string& selector )
+litehtml::elements_list litehtml::html_tag::select_all(const string& selector )
 {
 	css_selector sel;
 	sel.parse(selector);
@@ -129,14 +129,14 @@ litehtml::elements_vector litehtml::html_tag::select_all( const string& selector
 	return select_all(sel);
 }
 
-litehtml::elements_vector litehtml::html_tag::select_all( const css_selector& selector )
+litehtml::elements_list litehtml::html_tag::select_all(const css_selector& selector )
 {
-	litehtml::elements_vector res;
+	litehtml::elements_list res;
 	select_all(selector, res);
 	return res;
 }
 
-void litehtml::html_tag::select_all(const css_selector& selector, elements_vector& res)
+void litehtml::html_tag::select_all(const css_selector& selector, elements_list& res)
 {
 	if(select(selector))
 	{
@@ -178,6 +178,11 @@ litehtml::element::ptr litehtml::html_tag::select_one( const css_selector& selec
 
 void litehtml::html_tag::apply_stylesheet( const litehtml::css& stylesheet )
 {
+	if(is_root())
+	{
+		int i = 0;
+		i++;
+	}
 	for(const auto& sel : stylesheet.selectors())
 	{
 		// optimization
@@ -203,45 +208,59 @@ void litehtml::html_tag::apply_stylesheet( const litehtml::css& stylesheet )
 
 			if(sel->is_media_valid())
 			{
-				if(apply & select_match_pseudo_class)
-				{
-					if(select(*sel, true))
+				auto apply_before_after = [&]()
 					{
+						const auto& content_property = sel->m_style->get_property(_content_);
+						bool content_none = content_property.m_type == prop_type_string && content_property.m_string == "none";
+						bool create = !content_none && (sel->m_right.m_attrs.size() > 1 || sel->m_right.m_tag != star_id);
+
+						element::ptr el;
 						if(apply & select_match_with_after)
 						{
-							element::ptr el = get_element_after(*sel->m_style, true);
-							if(el)
+							el = get_element_after(*sel->m_style, create);
+						} else if(apply & select_match_with_before)
+						{
+							el = get_element_before(*sel->m_style, create);
+						} else
+						{
+							return;
+						}
+						if(el)
+						{
+							if(!content_none)
 							{
 								el->add_style(*sel->m_style);
+							} else
+							{
+								el->parent()->removeChild(el);
 							}
-						} else if(apply & select_match_with_before)
+						} else
 						{
-							element::ptr el = get_element_before(*sel->m_style, true);
-							if(el)
+							if(!content_none)
 							{
-								el->add_style(*sel->m_style);
+								add_style(*sel->m_style);
 							}
 						}
-						else
+						us->m_used = true;
+					};
+
+
+				if(apply & select_match_pseudo_class)
+				{
+					if(select(*sel, true))
+					{
+						if((apply & (select_match_with_after | select_match_with_before)))
+						{
+							apply_before_after();
+						} else
 						{
 							add_style(*sel->m_style);
 							us->m_used = true;
 						}
 					}
-				} else if(apply & select_match_with_after)
+				} else if((apply & (select_match_with_after | select_match_with_before)))
 				{
-					element::ptr el = get_element_after(*sel->m_style, true);
-					if(el)
-					{
-						el->add_style(*sel->m_style);
-					}
-				} else if(apply & select_match_with_before)
-				{
-					element::ptr el = get_element_before(*sel->m_style, true);
-					if(el)
-					{
-						el->add_style(*sel->m_style);
-					}
+					apply_before_after();
 				} else
 				{
 					add_style(*sel->m_style);
@@ -537,9 +556,17 @@ int litehtml::html_tag::select(const css_element_selector& selector, bool apply_
 		case select_pseudo_element:
 			if(attr.name == _after_)
 			{
+				if(selector.m_attrs.size() == 1 && selector.m_tag == star_id && m_tag != __tag_after_)
+				{
+					return select_no_match;
+				}
 				res |= select_match_with_after;
 			} else if(attr.name == _before_)
 			{
+				if(selector.m_attrs.size() == 1 && selector.m_tag == star_id && m_tag != __tag_before_)
+				{
+					return select_no_match;
+				}
 				res |= select_match_with_before;
 			} else
 			{
@@ -1063,32 +1090,6 @@ bool litehtml::html_tag::is_replaced() const
 	return false;
 }
 
-bool litehtml::html_tag::is_floats_holder() const
-{
-	if(	m_css.get_display() == display_inline_block || 
-		m_css.get_display() == display_table_cell ||
-		is_root() ||
-		m_css.get_float() != float_none ||
-		m_css.get_position() == element_position_absolute ||
-		m_css.get_position() == element_position_fixed ||
-		m_css.get_overflow() > overflow_visible)
-	{
-		return true;
-	}
-	return false;
-}
-
-size_t litehtml::html_tag::get_children_count() const
-{
-	return m_children.size();
-}
-
-litehtml::element::ptr litehtml::html_tag::get_child( int idx ) const
-{
-	return m_children[idx];
-}
-
-
 void litehtml::html_tag::init_background_paint(position pos, std::vector<background_paint>& bg_paint, const background* bg, const std::shared_ptr<render_item>& ri)
 {
 	bg_paint = { background_paint() };
diff --git a/src/plugins/litehtml_viewer/litehtml/html_tag.h b/src/plugins/litehtml_viewer/litehtml/html_tag.h
index 71b9cb345..9148031b2 100644
--- a/src/plugins/litehtml_viewer/litehtml/html_tag.h
+++ b/src/plugins/litehtml_viewer/litehtml/html_tag.h
@@ -31,7 +31,7 @@ namespace litehtml
 		string_map				m_attrs;
 		std::vector<string_id>	m_pseudo_classes;
 
-		void			select_all(const css_selector& selector, elements_vector& res) override;
+		void			select_all(const css_selector& selector, elements_list& res) override;
 
 	public:
 		explicit html_tag(const std::shared_ptr<document>& doc);
@@ -46,8 +46,6 @@ namespace litehtml
 		const char*			get_tagName() const override;
 		void				set_tagName(const char* tag) override;
 		void				set_data(const char* data) override;
-		size_t				get_children_count() const override;
-		element::ptr		get_child(int idx) const override;
 
 		void				set_attr(const char* name, const char* val) override;
 		const char*			get_attr(const char* name, const char* def = nullptr) const override;
@@ -84,7 +82,7 @@ namespace litehtml
 		size_vector			get_size_vector_property  (string_id name, bool inherited, const size_vector&   default_value, uint_ptr css_properties_member_offset) const override;
 		string				get_custom_property(string_id name, const string& default_value) const override;
 
-		elements_vector&	children();
+		elements_list&	children();
 
 		int					select(const string& selector) override;
 		int					select(const css_selector& selector, bool apply_pseudo = true) override;
@@ -92,8 +90,8 @@ namespace litehtml
 		int					select_pseudoclass(const css_attribute_selector& sel);
 		int					select_attribute(const css_attribute_selector& sel);
 
-		elements_vector		select_all(const string& selector) override;
-		elements_vector		select_all(const css_selector& selector) override;
+		elements_list		select_all(const string& selector) override;
+		elements_list		select_all(const css_selector& selector) override;
 
 		element::ptr		select_one(const string& selector) override;
 		element::ptr		select_one(const css_selector& selector) override;
@@ -105,7 +103,6 @@ namespace litehtml
 		void				parse_attributes() override;
 
 		void				get_content_size(size& sz, int max_width) override;
-		bool				is_floats_holder() const override;
 		void				add_style(const style& style) override;
 
 		bool				is_nth_child(const element::ptr& el, int num, int off, bool of_type) const override;
@@ -128,7 +125,7 @@ namespace litehtml
 	/*                        Inline Functions                              */
 	/************************************************************************/
 
-	inline elements_vector& litehtml::html_tag::children()
+	inline elements_list& litehtml::html_tag::children()
 	{
 		return m_children;
 	}
diff --git a/src/plugins/litehtml_viewer/litehtml/line_box.cpp b/src/plugins/litehtml_viewer/litehtml/line_box.cpp
index 269dd4672..1ca9c85d7 100644
--- a/src/plugins/litehtml_viewer/litehtml/line_box.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/line_box.cpp
@@ -551,7 +551,7 @@ std::shared_ptr<litehtml::render_item> litehtml::line_box::get_last_text_part()
 
 bool litehtml::line_box::can_hold(const std::unique_ptr<line_box_item>& item, white_space ws) const
 {
-    if(!item->get_el()->src_el()->is_inline_box()) return false;
+    if(!item->get_el()->src_el()->is_inline()) return false;
 
 	if(item->get_type() == line_box_item::type_text_part)
 	{
diff --git a/src/plugins/litehtml_viewer/litehtml/master_css.h b/src/plugins/litehtml_viewer/litehtml/master_css.h
index b5c7f3f03..0e7b0ca4e 100644
--- a/src/plugins/litehtml_viewer/litehtml/master_css.h
+++ b/src/plugins/litehtml_viewer/litehtml/master_css.h
@@ -224,6 +224,19 @@ table[border|=0] td, table[border|=0] th {
     border-style:none;
 }
 
+table[align=left] {
+   float: left;
+}
+
+table[align=right] {
+   float: right;
+}
+
+table[align=center] {
+   margin-left: auto;
+   margin-right: auto;
+}
+
 caption {
 	display: table-caption;
 }
@@ -347,5 +360,17 @@ sup {
 	font-size: smaller;
 }
 
+figure {
+	display: block;
+	margin-top: 1em;
+	margin-bottom: 1em;
+	margin-left: 40px;
+	margin-right: 40px;
+}
+
+figcaption {
+	display: block;
+}
+
 )##"; }
 #endif  // LH_MASTER_CSS_H
diff --git a/src/plugins/litehtml_viewer/litehtml/media_query.cpp b/src/plugins/litehtml_viewer/litehtml/media_query.cpp
index 763620367..7cddb15a2 100644
--- a/src/plugins/litehtml_viewer/litehtml/media_query.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/media_query.cpp
@@ -31,7 +31,7 @@ litehtml::media_query::ptr litehtml::media_query::create_from_string(const strin
 		} else if(token.at(0) == '(')
 		{
 			token.erase(0, 1);
-			if(token.at(token.length() - 1) == ')')
+			if(!token.empty() && token.at(token.length() - 1) == ')')
 			{
 				token.erase(token.length() - 1, 1);
 			}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_block.cpp b/src/plugins/litehtml_viewer/litehtml/render_block.cpp
index 8e1d107b4..d653f3114 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_block.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_block.cpp
@@ -1,557 +1,55 @@
 #include "html.h"
-#include "render_item.h"
+#include "render_block.h"
+#include "render_inline_context.h"
+#include "render_block_context.h"
 #include "document.h"
 
-int litehtml::render_item_block::place_float(const std::shared_ptr<render_item> &el, int top, const containing_block_context &self_size)
+int litehtml::render_item_block::place_float(const std::shared_ptr<render_item> &el, int top, const containing_block_context &self_size, formatting_context* fmt_ctx)
 {
-    int line_top	= get_cleared_top(el, top);
+    int line_top	= fmt_ctx->get_cleared_top(el, top);
     int line_left	= 0;
     int line_right	= self_size.render_width;
-    get_line_left_right(line_top, self_size.render_width, line_left, line_right);
+	fmt_ctx->get_line_left_right(line_top, self_size.render_width, line_left, line_right);
 
     int ret_width = 0;
 
+	int min_rendered_width = el->render(line_left, line_top, self_size.new_width(line_right), fmt_ctx);
+	if(min_rendered_width < el->width() && el->src_el()->css().get_width().is_predefined())
+	{
+		el->render(line_left, line_top, self_size.new_width(min_rendered_width), fmt_ctx);
+	}
+
     if (el->src_el()->css().get_float() == float_left)
     {
-        el->render(line_left, line_top, self_size.new_width(line_right));
         if(el->right() > line_right)
         {
-            int new_top = find_next_line_top(el->top(), el->width(), self_size.render_width);
-            el->pos().x = get_line_left(new_top) + el->content_offset_left();
-            el->pos().y = new_top + el->content_offset_top();
+			line_top = fmt_ctx->find_next_line_top(el->top(), el->width(), self_size.render_width);
+            el->pos().x = fmt_ctx->get_line_left(line_top) + el->content_offset_left();
+            el->pos().y = line_top + el->content_offset_top();
         }
-        add_float(el, 0, 0, self_size.context_idx);
-		fix_line_width(float_left, self_size);
-		ret_width = el->right();
+		fmt_ctx->add_float(el, min_rendered_width, self_size.context_idx);
+		fix_line_width(float_left, self_size, fmt_ctx);
+
+		ret_width = fmt_ctx->find_min_left(line_top, self_size.context_idx);
     } else if (el->src_el()->css().get_float() == float_right)
     {
-        el->render(0, line_top, self_size.new_width(line_right));
-
         if(line_left + el->width() > line_right)
         {
-            int new_top = find_next_line_top(el->top(), el->width(), self_size.render_width);
-            el->pos().x = get_line_right(new_top, self_size.render_width) - el->width() + el->content_offset_left();
+            int new_top = fmt_ctx->find_next_line_top(el->top(), el->width(), self_size.render_width);
+            el->pos().x = fmt_ctx->get_line_right(new_top, self_size.render_width) - el->width() + el->content_offset_left();
             el->pos().y = new_top + el->content_offset_top();
         } else
         {
             el->pos().x = line_right - el->width() + el->content_offset_left();
         }
-        add_float(el, 0, 0, self_size.context_idx);
-		fix_line_width(float_right, self_size);
-		line_left	= 0;
-		line_right	= self_size.render_width;
-		get_line_left_right(line_top, self_size.render_width, line_left, line_right);
-
-		ret_width = ret_width + (self_size.render_width - line_right);
+		fmt_ctx->add_float(el, min_rendered_width, self_size.context_idx);
+		fix_line_width(float_right, self_size, fmt_ctx);
+		line_right = fmt_ctx->find_min_right(line_top, self_size.render_width, self_size.context_idx);
+		ret_width = self_size.render_width - line_right;
     }
     return ret_width;
 }
 
-int litehtml::render_item_block::get_floats_height(element_float el_float) const
-{
-    if(src_el()->is_floats_holder())
-    {
-        int h = 0;
-
-        for(const auto& fb : m_floats_left)
-        {
-            bool process = false;
-            switch(el_float)
-            {
-                case float_none:
-                    process = true;
-                    break;
-                case float_left:
-                    if (fb.clear_floats == clear_left || fb.clear_floats == clear_both)
-                    {
-                        process = true;
-                    }
-                    break;
-                case float_right:
-                    if (fb.clear_floats == clear_right || fb.clear_floats == clear_both)
-                    {
-                        process = true;
-                    }
-                    break;
-            }
-            if(process)
-            {
-                if(el_float == float_none)
-                {
-                    h = std::max(h, fb.pos.bottom());
-                } else
-                {
-                    h = std::max(h, fb.pos.top());
-                }
-            }
-        }
-
-
-        for(const auto& fb : m_floats_right)
-        {
-            int process = false;
-            switch(el_float)
-            {
-                case float_none:
-                    process = true;
-                    break;
-                case float_left:
-                    if (fb.clear_floats == clear_left || fb.clear_floats == clear_both)
-                    {
-                        process = true;
-                    }
-                    break;
-                case float_right:
-                    if (fb.clear_floats == clear_right || fb.clear_floats == clear_both)
-                    {
-                        process = true;
-                    }
-                    break;
-            }
-            if(process)
-            {
-                if(el_float == float_none)
-                {
-                    h = std::max(h, fb.pos.bottom());
-                } else
-                {
-                    h = std::max(h, fb.pos.top());
-                }
-            }
-        }
-
-        return h;
-    }
-    auto el_parent = parent();
-    if (el_parent)
-    {
-        int h = el_parent->get_floats_height(el_float);
-        return h - m_pos.y;
-    }
-    return 0;
-}
-
-int litehtml::render_item_block::get_left_floats_height() const
-{
-    if(src_el()->is_floats_holder())
-    {
-        int h = 0;
-        if(!m_floats_left.empty())
-        {
-            for (const auto& fb : m_floats_left)
-            {
-                h = std::max(h, fb.pos.bottom());
-            }
-        }
-        return h;
-    }
-    auto el_parent = parent();
-    if (el_parent)
-    {
-        int h = el_parent->get_left_floats_height();
-        return h - m_pos.y;
-    }
-    return 0;
-}
-
-int litehtml::render_item_block::get_right_floats_height() const
-{
-    if(src_el()->is_floats_holder())
-    {
-        int h = 0;
-        if(!m_floats_right.empty())
-        {
-            for(const auto& fb : m_floats_right)
-            {
-                h = std::max(h, fb.pos.bottom());
-            }
-        }
-        return h;
-    }
-    auto el_parent = parent();
-    if (el_parent)
-    {
-        int h = el_parent->get_right_floats_height();
-        return h - m_pos.y;
-    }
-    return 0;
-}
-
-int litehtml::render_item_block::get_line_left( int y )
-{
-    if(src_el()->is_floats_holder())
-    {
-        if(m_cache_line_left.is_valid && m_cache_line_left.hash == y)
-        {
-            return m_cache_line_left.val;
-        }
-
-        int w = 0;
-        for(const auto& fb : m_floats_left)
-        {
-            if (y >= fb.pos.top() && y < fb.pos.bottom())
-            {
-                w = std::max(w, fb.pos.right());
-                if (w < fb.pos.right())
-                {
-                    break;
-                }
-            }
-        }
-        m_cache_line_left.set_value(y, w);
-        return w;
-    }
-    auto el_parent = parent();
-    if (el_parent)
-    {
-        int w = el_parent->get_line_left(y + m_pos.y);
-        if (w < 0)
-        {
-            w = 0;
-        }
-        return w - (w ? m_pos.x : 0);
-    }
-    return 0;
-}
-
-int litehtml::render_item_block::get_line_right( int y, int def_right )
-{
-    if(src_el()->is_floats_holder())
-    {
-        if(m_cache_line_right.is_valid && m_cache_line_right.hash == y)
-        {
-            if(m_cache_line_right.is_default)
-            {
-                return def_right;
-            } else
-            {
-                return std::min(m_cache_line_right.val, def_right);
-            }
-        }
-
-        int w = def_right;
-        m_cache_line_right.is_default = true;
-        for(const auto& fb : m_floats_right)
-        {
-            if(y >= fb.pos.top() && y < fb.pos.bottom())
-            {
-                w = std::min(w, fb.pos.left());
-                m_cache_line_right.is_default = false;
-                if(w > fb.pos.left())
-                {
-                    break;
-                }
-            }
-        }
-        m_cache_line_right.set_value(y, w);
-        return w;
-    }
-    auto el_parent = parent();
-    if (el_parent)
-    {
-        int w = el_parent->get_line_right(y + m_pos.y, def_right + m_pos.x);
-        return w - m_pos.x;
-    }
-    return 0;
-}
-
-
-void litehtml::render_item_block::get_line_left_right( int y, int def_right, int& ln_left, int& ln_right )
-{
-    if(src_el()->is_floats_holder())
-    {
-        ln_left		= get_line_left(y);
-        ln_right	= get_line_right(y, def_right);
-    } else
-    {
-        auto el_parent = parent();
-        if (el_parent)
-        {
-            el_parent->get_line_left_right(y + m_pos.y, def_right + m_pos.x, ln_left, ln_right);
-        }
-        ln_right -= m_pos.x;
-
-        if(ln_left < 0)
-        {
-            ln_left = 0;
-        } else if (ln_left > 0)
-        {
-            ln_left -= m_pos.x;
-            if (ln_left < 0)
-            {
-                ln_left = 0;
-            }
-        }
-    }
-}
-
-void litehtml::render_item_block::clear_floats(int context)
-{
-	if(src_el()->is_floats_holder())
-	{
-		auto iter = m_floats_left.begin();
-		while(iter != m_floats_left.end())
-		{
-			if(iter->context >= context)
-			{
-				iter = m_floats_left.erase(iter);
-				m_cache_line_left.invalidate();
-			} else
-			{
-				iter++;
-			}
-		}
-
-		iter = m_floats_right.begin();
-		while(iter != m_floats_right.end())
-		{
-			if(iter->context >= context)
-			{
-				iter = m_floats_right.erase(iter);
-				m_cache_line_right.invalidate();
-			} else
-			{
-				iter++;
-			}
-		}
-	} else
-	{
-		auto el_parent = parent();
-		if (el_parent)
-		{
-			el_parent->clear_floats(context);
-		}
-	}
-}
-
-void litehtml::render_item_block::add_float(const std::shared_ptr<render_item> &el, int x, int y, int context)
-{
-    if(src_el()->is_floats_holder())
-    {
-        floated_box fb;
-        fb.pos.x		= el->left() + x;
-        fb.pos.y		= el->top() + y;
-        fb.pos.width	= el->width();
-        fb.pos.height	= el->height();
-        fb.float_side	= el->src_el()->css().get_float();
-        fb.clear_floats	= el->src_el()->css().get_clear();
-        fb.el			= el;
-		fb.context		= context;
-
-        if(fb.float_side == float_left)
-        {
-            if(m_floats_left.empty())
-            {
-                m_floats_left.push_back(fb);
-            } else
-            {
-                bool inserted = false;
-                for(auto i = m_floats_left.begin(); i != m_floats_left.end(); i++)
-                {
-                    if(fb.pos.right() > i->pos.right())
-                    {
-                        m_floats_left.insert(i, std::move(fb));
-                        inserted = true;
-                        break;
-                    }
-                }
-                if(!inserted)
-                {
-                    m_floats_left.push_back(std::move(fb));
-                }
-            }
-            m_cache_line_left.invalidate();
-        } else if(fb.float_side == float_right)
-        {
-            if(m_floats_right.empty())
-            {
-                m_floats_right.push_back(std::move(fb));
-            } else
-            {
-                bool inserted = false;
-                for(auto i = m_floats_right.begin(); i != m_floats_right.end(); i++)
-                {
-                    if(fb.pos.left() < i->pos.left())
-                    {
-                        m_floats_right.insert(i, std::move(fb));
-                        inserted = true;
-                        break;
-                    }
-                }
-                if(!inserted)
-                {
-                    m_floats_right.push_back(fb);
-                }
-            }
-            m_cache_line_right.invalidate();
-        }
-    } else
-    {
-        auto el_parent = parent();
-        if (el_parent)
-        {
-            el_parent->add_float(el, x + m_pos.x, y + m_pos.y, context);
-        }
-    }
-}
-
-int litehtml::render_item_block::get_cleared_top(const std::shared_ptr<render_item> &el, int line_top) const
-{
-    switch(el->src_el()->css().get_clear())
-    {
-        case clear_left:
-        {
-            int fh = get_left_floats_height();
-            if(fh && fh > line_top)
-            {
-                line_top = fh;
-            }
-        }
-            break;
-        case clear_right:
-        {
-            int fh = get_right_floats_height();
-            if(fh && fh > line_top)
-            {
-                line_top = fh;
-            }
-        }
-            break;
-        case clear_both:
-        {
-            int fh = get_floats_height(float_none);
-            if(fh && fh > line_top)
-            {
-                line_top = fh;
-            }
-        }
-            break;
-        default:
-            if(el->src_el()->css().get_float() != float_none)
-            {
-                int fh = get_floats_height(el->src_el()->css().get_float());
-                if(fh && fh > line_top)
-                {
-                    line_top = fh;
-                }
-            }
-            break;
-    }
-    return line_top;
-}
-
-int litehtml::render_item_block::find_next_line_top( int top, int width, int def_right )
-{
-    if(src_el()->is_floats_holder())
-    {
-        int new_top = top;
-        int_vector points;
-
-        for(const auto& fb : m_floats_left)
-        {
-            if(fb.pos.top() >= top)
-            {
-                if(find(points.begin(), points.end(), fb.pos.top()) == points.end())
-                {
-                    points.push_back(fb.pos.top());
-                }
-            }
-            if (fb.pos.bottom() >= top)
-            {
-                if (find(points.begin(), points.end(), fb.pos.bottom()) == points.end())
-                {
-                    points.push_back(fb.pos.bottom());
-                }
-            }
-        }
-
-        for (const auto& fb : m_floats_right)
-        {
-            if (fb.pos.top() >= top)
-            {
-                if (find(points.begin(), points.end(), fb.pos.top()) == points.end())
-                {
-                    points.push_back(fb.pos.top());
-                }
-            }
-            if (fb.pos.bottom() >= top)
-            {
-                if (find(points.begin(), points.end(), fb.pos.bottom()) == points.end())
-                {
-                    points.push_back(fb.pos.bottom());
-                }
-            }
-        }
-
-        if(!points.empty())
-        {
-            sort(points.begin(), points.end(), std::less<int>( ));
-            new_top = points.back();
-
-            for(auto pt : points)
-            {
-                int pos_left	= 0;
-                int pos_right	= def_right;
-                get_line_left_right(pt, def_right, pos_left, pos_right);
-
-                if(pos_right - pos_left >= width)
-                {
-                    new_top = pt;
-                    break;
-                }
-            }
-        }
-        return new_top;
-    }
-    auto el_parent = parent();
-    if (el_parent)
-    {
-        int new_top = el_parent->find_next_line_top(top + m_pos.y, width, def_right + m_pos.x);
-        return new_top - m_pos.y;
-    }
-    return 0;
-}
-
-void litehtml::render_item_block::update_floats(int dy, const std::shared_ptr<render_item> &_parent)
-{
-    if(src_el()->is_floats_holder())
-    {
-        bool reset_cache = false;
-        for(auto fb = m_floats_left.rbegin(); fb != m_floats_left.rend(); fb++)
-        {
-            if(fb->el->src_el()->is_ancestor(_parent->src_el()))
-            {
-                reset_cache	= true;
-                fb->pos.y	+= dy;
-            }
-        }
-        if(reset_cache)
-        {
-            m_cache_line_left.invalidate();
-        }
-        reset_cache = false;
-        for(auto fb = m_floats_right.rbegin(); fb != m_floats_right.rend(); fb++)
-        {
-            if(fb->el->src_el()->is_ancestor(_parent->src_el()))
-            {
-                reset_cache	= true;
-                fb->pos.y	+= dy;
-            }
-        }
-        if(reset_cache)
-        {
-            m_cache_line_right.invalidate();
-        }
-    } else
-    {
-        auto el_parent = parent();
-        if (el_parent)
-        {
-            el_parent->update_floats(dy, _parent);
-        }
-    }
-}
-
 std::shared_ptr<litehtml::render_item> litehtml::render_item_block::init()
 {
     {
@@ -571,9 +69,8 @@ std::shared_ptr<litehtml::render_item> litehtml::render_item_block::init()
         if (auto p = src_el()->parent())
         {
             int val = atoi(p->get_attr("start", "1"));
-            for (int i = 0; i < (int)p->get_children_count(); i++)
+			for(const auto &child : p->children())
             {
-                auto child = p->get_child(i);
                 if (child == src_el())
                 {
                     src_el()->set_attr("list_index", std::to_string(val).c_str());
@@ -618,7 +115,7 @@ std::shared_ptr<litehtml::render_item> litehtml::render_item_block::init()
 			if (el->src_el()->is_block_box())
 			{
 				has_block_level = true;
-			} else if (el->src_el()->is_inline_box())
+			} else if (el->src_el()->is_inline())
 			{
 				has_inlines = true;
 			}
@@ -637,7 +134,7 @@ std::shared_ptr<litehtml::render_item> litehtml::render_item_block::init()
         bool not_ws_added = false;
         for (const auto& el : m_children)
         {
-            if(el->src_el()->is_inline_box())
+            if(el->src_el()->is_inline())
             {
                 inlines.push_back(el);
                 if(!el->src_el()->is_white_space())
@@ -698,28 +195,14 @@ std::shared_ptr<litehtml::render_item> litehtml::render_item_block::init()
     return ret;
 }
 
-int litehtml::render_item_block::render(int x, int y, const containing_block_context &containing_block_size, bool second_pass)
+int litehtml::render_item_block::_render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass)
 {
-    int ret_width = 0;
-    calc_outlines(containing_block_size.width);
-
-    m_pos.clear();
-    m_pos.move_to(x, y);
-
-    m_pos.x += content_offset_left();
-    m_pos.y += content_offset_top();
-
-    m_floats_left.clear();
-    m_floats_right.clear();
-    m_cache_line_left.invalidate();
-    m_cache_line_right.invalidate();
-
 	containing_block_context self_size = calculate_containing_block_context(containing_block_size);
 
     //*****************************************
     // Render content
     //*****************************************
-    ret_width = _render_content(x, y, second_pass, ret_width, self_size);
+	int ret_width = _render_content(x, y, second_pass, self_size, fmt_ctx);
     //*****************************************
 
 	bool requires_rerender = false;		// when true, the second pass for content rendering is required
@@ -733,22 +216,7 @@ int litehtml::render_item_block::render(int x, int y, const containing_block_con
 		m_pos.width = self_size.render_width;
 	} else
 	{
-		if(src_el()->is_inline_box() ||
-			src_el()->css().get_float() != float_none ||
-			src_el()->css().get_display() == display_table_cell ||
-			src_el()->css().get_display() == display_table_caption ||
-			src_el()->css().get_position() > element_position_relative)
-		{
-			m_pos.width = ret_width;
-			if(ret_width < self_size.render_width && !second_pass)
-			{
-				// We have to render content again with new max_width
-				requires_rerender = true;
-			}
-		} else
-		{
-			m_pos.width = self_size.render_width;
-		}
+		m_pos.width = self_size.render_width;
 	}
 
 	// Fix width with min-width attribute
@@ -774,32 +242,32 @@ int litehtml::render_item_block::render(int x, int y, const containing_block_con
 	// re-render content with new width if required
 	if (requires_rerender && !second_pass && !is_root())
 	{
-		if(src_el()->is_floats_holder())
+		if(src_el()->is_block_formatting_context())
 		{
-			m_floats_left.clear();
-			m_floats_right.clear();
+			fmt_ctx->clear_floats(-1);
 		} else
 		{
-			clear_floats(self_size.context_idx);
+			fmt_ctx->clear_floats(self_size.context_idx);
 		}
-		m_cache_line_left.invalidate();
-		m_cache_line_right.invalidate();
 
-		_render_content(x, y, true, ret_width, self_size.new_width(m_pos.width));
+		_render_content(x, y, true, self_size.new_width(m_pos.width), fmt_ctx);
 	}
 
 	// Set block height
 	if (self_size.height.type != containing_block_context::cbc_value_type_auto)
 	{
-		m_pos.height = self_size.height;
+		if(self_size.height > 0)
+		{
+			m_pos.height = self_size.height;
+		}
 		if(src_el()->css().get_box_sizing() == box_sizing_border_box)
 		{
 			m_pos.height -= box_sizing_height();
 		}
-	} else if (src_el()->is_floats_holder())
+	} else if (src_el()->is_block_formatting_context())
     {
 		// add the floats' height to the block height
-        int floats_height = get_floats_height();
+        int floats_height = fmt_ctx->get_floats_height();
         if (floats_height > m_pos.height)
         {
             m_pos.height = floats_height;
@@ -845,12 +313,5 @@ int litehtml::render_item_block::render(int x, int y, const containing_block_con
 
     }
 
-    if (src_el()->is_floats_holder() && !second_pass)
-    {
-        for (const auto& fb : m_floats_left)
-        {
-            fb.el->apply_relative_shift(containing_block_size);
-        }
-    }
     return ret_width + content_offset_width();
 }
diff --git a/src/plugins/litehtml_viewer/litehtml/render_block.h b/src/plugins/litehtml_viewer/litehtml/render_block.h
new file mode 100644
index 000000000..eb058c618
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_block.h
@@ -0,0 +1,40 @@
+#ifndef LITEHTML_RENDER_BLOCK_H
+#define LITEHTML_RENDER_BLOCK_H
+
+#include "render_item.h"
+
+namespace litehtml
+{
+	class render_item_block : public render_item
+	{
+	protected:
+		/**
+		 * Render block content.
+		 *
+		 * @param x - horizontal position of the content
+		 * @param y - vertical position of the content
+		 * @param second_pass - true is this is the second pass.
+		 * @param ret_width - input minimal width.
+		 * @param self_size - defines calculated size of block
+		 * @return return value is the minimal width of the content in block. Must be greater or equal to ret_width parameter
+		 */
+		virtual int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) {return 0;}
+		int _render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) override;
+		int place_float(const std::shared_ptr<render_item> &el, int top, const containing_block_context &self_size, formatting_context* fmt_ctx);
+		virtual void fix_line_width(element_float flt,
+									const containing_block_context &containing_block_size, formatting_context* fmt_ctx)
+		{}
+
+	public:
+		explicit render_item_block(std::shared_ptr<element>  src_el) : render_item(std::move(src_el))
+		{}
+
+		std::shared_ptr<render_item> clone() override
+		{
+			return std::make_shared<render_item_block>(src_el());
+		}
+		std::shared_ptr<render_item> init() override;
+	};
+}
+
+#endif //LITEHTML_RENDER_BLOCK_H
diff --git a/src/plugins/litehtml_viewer/litehtml/render_block_context.cpp b/src/plugins/litehtml_viewer/litehtml/render_block_context.cpp
index b0aa444d7..7591378c2 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_block_context.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_block_context.cpp
@@ -1,12 +1,12 @@
 #include "html.h"
-#include "render_item.h"
+#include "render_block_context.h"
 #include "document.h"
 
-int litehtml::render_item_block_context::_render_content(int x, int y, bool second_pass, int ret_width,
-														 const containing_block_context &self_size)
+int litehtml::render_item_block_context::_render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx)
 {
     element_position el_position;
 
+	int ret_width = 0;
     int child_top = 0;
     int last_margin = 0;
 	std::shared_ptr<render_item> last_margin_el;
@@ -22,7 +22,7 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco
 
         if(el->src_el()->css().get_float() != float_none)
         {
-            int rw = place_float(el, child_top, self_size);
+            int rw = place_float(el, child_top, self_size, fmt_ctx);
             if (rw > ret_width)
             {
                 ret_width = rw;
@@ -31,10 +31,14 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco
         {
             if(el->src_el()->css().get_position() == element_position_absolute || el->src_el()->css().get_position() == element_position_fixed)
             {
-                el->render(0, child_top, self_size);
+				int min_rendered_width = el->render(0, child_top, self_size, fmt_ctx);
+				if(min_rendered_width < el->width() && el->src_el()->css().get_width().is_predefined())
+				{
+					el->render(0, child_top, self_size.new_width(min_rendered_width), fmt_ctx);
+				}
             } else
             {
-                child_top = get_cleared_top(el, child_top);
+                child_top = fmt_ctx->get_cleared_top(el, child_top);
                 int child_x  = 0;
                 int child_width = self_size.render_width;
 
@@ -59,11 +63,11 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco
                     }
                 }
 
-                if(el->src_el()->is_replaced() || el->src_el()->is_floats_holder() || el->src_el()->css().get_display() == display_table)
+                if(el->src_el()->is_replaced() || el->src_el()->is_block_formatting_context() || el->src_el()->css().get_display() == display_table)
                 {
                     int ln_left = 0;
                     int ln_right = child_width;
-                    get_line_left_right(child_top, child_width, ln_left, ln_right);
+                    fmt_ctx->get_line_left_right(child_top, child_width, ln_left, ln_right);
                     child_x = ln_left;
                     child_width = ln_right - ln_left;
 
@@ -72,11 +76,11 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco
                     el->pos().height = el->src_el()->css().get_height().calc_percent(el_parent ? el_parent->pos().height : 0);
                 }
 
-                int rw = el->render(child_x, child_top, self_size.new_width(child_width));
+                int rw = el->render(child_x, child_top, self_size.new_width(child_width), fmt_ctx);
 				// Render table with "width: auto" into returned width
 				if(el->src_el()->css().get_display() == display_table && rw < child_width && el->src_el()->css().get_width().is_predefined())
 				{
-					el->render(child_x, child_top, self_size.new_width(rw));
+					el->render(child_x, child_top, self_size.new_width(rw), fmt_ctx);
 				}
 				int auto_margin = el->calc_auto_margins(child_width);
 				if(auto_margin)
diff --git a/src/plugins/litehtml_viewer/litehtml/render_block_context.h b/src/plugins/litehtml_viewer/litehtml/render_block_context.h
new file mode 100644
index 000000000..3b5192261
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_block_context.h
@@ -0,0 +1,29 @@
+#ifndef LITEHTML_RENDER_BLOCK_CONTEXT_H
+#define LITEHTML_RENDER_BLOCK_CONTEXT_H
+
+#include "render_block.h"
+
+namespace litehtml
+{
+	/**
+	 * In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a
+	 * containing block.
+	 * https://www.w3.org/TR/CSS22/visuren.html#block-formatting
+	 */
+	class render_item_block_context : public render_item_block
+	{
+	protected:
+		int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) override;
+
+	public:
+		explicit render_item_block_context(std::shared_ptr<element>  src_el) : render_item_block(std::move(src_el))
+		{}
+
+		std::shared_ptr<render_item> clone() override
+		{
+			return std::make_shared<render_item_block_context>(src_el());
+		}
+	};
+}
+
+#endif //LITEHTML_RENDER_BLOCK_CONTEXT_H
diff --git a/src/plugins/litehtml_viewer/litehtml/render_flex.cpp b/src/plugins/litehtml_viewer/litehtml/render_flex.cpp
index c9cf8e538..2cab59e04 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_flex.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_flex.cpp
@@ -1,9 +1,8 @@
 #include "html.h"
-#include "render_item.h"
 #include "types.h"
+#include "render_flex.h"
 
-int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass, int ret_width,
-												const containing_block_context &self_size)
+int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx)
 {
     return 0;
 }
diff --git a/src/plugins/litehtml_viewer/litehtml/render_flex.h b/src/plugins/litehtml_viewer/litehtml/render_flex.h
new file mode 100644
index 000000000..5d31bc9bf
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_flex.h
@@ -0,0 +1,46 @@
+#ifndef LITEHTML_RENDER_FLEX_H
+#define LITEHTML_RENDER_FLEX_H
+
+#include "render_block.h"
+
+namespace litehtml
+{
+	class render_item_flex : public render_item_block
+	{
+		struct flex_item
+		{
+			std::shared_ptr<render_item> el;
+			int base_size;
+			int main_size;
+			int min_width;
+			int max_width;
+			int line;
+
+			explicit flex_item(std::shared_ptr<render_item>  _el) :
+					el(std::move(_el)),
+					min_width(0),
+					max_width(0),
+					line(0),
+					base_size(0),
+					main_size(0)
+			{}
+		};
+	protected:
+		std::list<std::unique_ptr<flex_item>>   m_flex_items;
+
+		int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) override;
+
+	public:
+		explicit render_item_flex(std::shared_ptr<element>  src_el) : render_item_block(std::move(src_el))
+		{}
+
+		std::shared_ptr<render_item> clone() override
+		{
+			return std::make_shared<render_item_flex>(src_el());
+		}
+		void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override;
+		std::shared_ptr<render_item> init() override;
+	};
+}
+
+#endif //LITEHTML_RENDER_FLEX_H
diff --git a/src/plugins/litehtml_viewer/litehtml/render_image.cpp b/src/plugins/litehtml_viewer/litehtml/render_image.cpp
index 38f576bc1..63e622d7b 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_image.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_image.cpp
@@ -1,9 +1,8 @@
 #include "html.h"
-#include "render_item.h"
+#include "render_image.h"
 #include "document.h"
 
-int
-litehtml::render_item_image::render(int x, int y, const containing_block_context &containing_block_size, bool second_pass)
+int litehtml::render_item_image::_render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass)
 {
     int parent_width = containing_block_size.width;
 
diff --git a/src/plugins/litehtml_viewer/litehtml/render_image.h b/src/plugins/litehtml_viewer/litehtml/render_image.h
new file mode 100644
index 000000000..e85f487ca
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_image.h
@@ -0,0 +1,25 @@
+#ifndef LITEHTML_RENDER_IMAGE_H
+#define LITEHTML_RENDER_IMAGE_H
+
+#include "render_item.h"
+
+namespace litehtml
+{
+	class render_item_image : public render_item
+	{
+	protected:
+		int calc_max_height(int image_height, int containing_block_height);
+		int _render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) override;
+
+	public:
+		explicit render_item_image(std::shared_ptr<element>  src_el) : render_item(std::move(src_el))
+		{}
+
+		std::shared_ptr<render_item> clone() override
+		{
+			return std::make_shared<render_item_image>(src_el());
+		}
+	};
+}
+
+#endif //LITEHTML_RENDER_IMAGE_H
diff --git a/src/plugins/litehtml_viewer/litehtml/render_inline.h b/src/plugins/litehtml_viewer/litehtml/render_inline.h
new file mode 100644
index 000000000..476011563
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_inline.h
@@ -0,0 +1,30 @@
+#ifndef LITEHTML_RENDER_INLINE_H
+#define LITEHTML_RENDER_INLINE_H
+
+#include "render_item.h"
+
+namespace litehtml
+{
+	class render_item_inline : public render_item
+	{
+	protected:
+		position::vector m_boxes;
+
+	public:
+		explicit render_item_inline(std::shared_ptr<element>  src_el) : render_item(std::move(src_el))
+		{}
+
+		void get_inline_boxes( position::vector& boxes ) const override { boxes = m_boxes; }
+		void set_inline_boxes( position::vector& boxes ) override { m_boxes = boxes; }
+		void add_inline_box( const position& box ) override { m_boxes.emplace_back(box); };
+		void clear_inline_boxes() override { m_boxes.clear(); }
+		int get_base_line() override { return src_el()->css().get_font_metrics().base_line(); }
+
+		std::shared_ptr<render_item> clone() override
+		{
+			return std::make_shared<render_item_inline>(src_el());
+		}
+	};
+}
+
+#endif //LITEHTML_RENDER_INLINE_H
diff --git a/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp b/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp
index b348a8cf7..2d8f2e173 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp
@@ -1,10 +1,9 @@
 #include "html.h"
-#include "render_item.h"
+#include "render_inline_context.h"
 #include "document.h"
 #include "iterators.h"
 
-int litehtml::render_item_inline_context::_render_content(int x, int y, bool second_pass, int ret_width,
-														  const containing_block_context &self_size)
+int litehtml::render_item_inline_context::_render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx)
 {
     m_line_boxes.clear();
 	m_max_line_width = 0;
@@ -50,20 +49,20 @@ int litehtml::render_item_inline_context::_render_content(int x, int y, bool sec
 							}
 						}
 						// place element into rendering flow
-						place_inline(std::unique_ptr<line_box_item>(new line_box_item(el)), self_size);
+						place_inline(std::unique_ptr<line_box_item>(new line_box_item(el)), self_size, fmt_ctx);
 					}
 					break;
 
 				case iterator_item_type_start_parent:
 					{
 						el->clear_inline_boxes();
-						place_inline(std::unique_ptr<lbi_start>(new lbi_start(el)), self_size);
+						place_inline(std::unique_ptr<lbi_start>(new lbi_start(el)), self_size, fmt_ctx);
 					}
 					break;
 
 				case iterator_item_type_end_parent:
 				{
-					place_inline(std::unique_ptr<lbi_end>(new lbi_end(el)), self_size);
+					place_inline(std::unique_ptr<lbi_end>(new lbi_end(el)), self_size, fmt_ctx);
 				}
 					break;
 			}
@@ -79,7 +78,7 @@ int litehtml::render_item_inline_context::_render_content(int x, int y, bool sec
             m_margins.top = std::max(m_line_boxes.front()->top_margin(), m_margins.top);
             if (m_margins.top != old_top)
             {
-                update_floats(m_margins.top - old_top, shared_from_this());
+                fmt_ctx->update_floats(m_margins.top - old_top, shared_from_this());
             }
         }
         if (collapse_bottom_margin())
@@ -93,13 +92,13 @@ int litehtml::render_item_inline_context::_render_content(int x, int y, bool sec
         }
     }
 
-    return std::max(ret_width, m_max_line_width);
+    return m_max_line_width;
 }
 
 void litehtml::render_item_inline_context::fix_line_width(element_float flt,
-														  const containing_block_context &self_size)
+														  const containing_block_context &self_size,
+														  formatting_context* fmt_ctx)
 {
-    int ret_width = 0;
     if(!m_line_boxes.empty())
     {
 		auto el_front = m_line_boxes.back()->get_first_text_part();
@@ -128,7 +127,7 @@ void litehtml::render_item_inline_context::fix_line_width(element_float flt,
 
             for(auto& item : items)
             {
-                place_inline(std::move(item), self_size);
+                place_inline(std::move(item), self_size, fmt_ctx);
             }
         } else
         {
@@ -137,7 +136,7 @@ void litehtml::render_item_inline_context::fix_line_width(element_float flt,
 
             int line_left	= 0;
             int line_right	= self_size.render_width;
-            get_line_left_right(line_top, self_size.render_width, line_left, line_right);
+            fmt_ctx->get_line_left_right(line_top, self_size.render_width, line_left, line_right);
 
             if(m_line_boxes.size() == 1)
             {
@@ -157,7 +156,7 @@ void litehtml::render_item_inline_context::fix_line_width(element_float flt,
             auto items = m_line_boxes.back()->new_width(line_left, line_right);
             for(auto& item : items)
             {
-                place_inline(std::move(item), self_size);
+                place_inline(std::move(item), self_size, fmt_ctx);
             }
         }
     }
@@ -183,7 +182,7 @@ std::list<std::unique_ptr<litehtml::line_box_item> > litehtml::render_item_inlin
     return ret;
 }
 
-int litehtml::render_item_inline_context::new_box(const std::unique_ptr<line_box_item>& el, line_context& line_ctx, const containing_block_context &self_size)
+int litehtml::render_item_inline_context::new_box(const std::unique_ptr<line_box_item>& el, line_context& line_ctx, const containing_block_context &self_size, formatting_context* fmt_ctx)
 {
 	auto items = finish_last_box(false, self_size);
 	int line_top = 0;
@@ -191,22 +190,22 @@ int litehtml::render_item_inline_context::new_box(const std::unique_ptr<line_box
 	{
 		line_top = m_line_boxes.back()->bottom();
 	}
-    line_ctx.top = get_cleared_top(el->get_el(), line_top);
+    line_ctx.top = fmt_ctx->get_cleared_top(el->get_el(), line_top);
 
     line_ctx.left = 0;
     line_ctx.right = self_size.render_width;
     line_ctx.fix_top();
-    get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right);
+	fmt_ctx->get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right);
 
-    if(el->get_el()->src_el()->is_inline_box() || el->get_el()->src_el()->is_floats_holder())
+    if(el->get_el()->src_el()->is_inline() || el->get_el()->src_el()->is_block_formatting_context())
     {
         if (el->get_el()->width() > line_ctx.right - line_ctx.left)
         {
-            line_ctx.top = find_next_line_top(line_ctx.top, el->get_el()->width(), self_size.render_width);
+            line_ctx.top = fmt_ctx->find_next_line_top(line_ctx.top, el->get_el()->width(), self_size.render_width);
             line_ctx.left = 0;
             line_ctx.right = self_size.render_width;
             line_ctx.fix_top();
-            get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right);
+			fmt_ctx->get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right);
         }
     }
 
@@ -241,7 +240,7 @@ int litehtml::render_item_inline_context::new_box(const std::unique_ptr<line_box
     return line_ctx.top;
 }
 
-void litehtml::render_item_inline_context::place_inline(std::unique_ptr<line_box_item> item, const containing_block_context &self_size)
+void litehtml::render_item_inline_context::place_inline(std::unique_ptr<line_box_item> item, const containing_block_context &self_size, formatting_context* fmt_ctx)
 {
     if(item->get_el()->src_el()->css().get_display() == display_none) return;
 
@@ -252,7 +251,7 @@ void litehtml::render_item_inline_context::place_inline(std::unique_ptr<line_box
         {
             line_top = m_line_boxes.back()->top();
         }
-        int ret = place_float(item->get_el(), line_top, self_size);
+        int ret = place_float(item->get_el(), line_top, self_size, fmt_ctx);
 		if(ret > m_max_line_width)
 		{
 			m_max_line_width = ret;
@@ -269,24 +268,24 @@ void litehtml::render_item_inline_context::place_inline(std::unique_ptr<line_box
     line_ctx.left = 0;
     line_ctx.right = self_size.render_width;
     line_ctx.fix_top();
-    get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right);
+	fmt_ctx->get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right);
 
 	if(item->get_type() == line_box_item::type_text_part)
 	{
-		switch (item->get_el()->src_el()->css().get_display())
+		if(item->get_el()->src_el()->is_inline_box())
 		{
-			case display_inline_block:
-			case display_inline_table:
-				item->set_rendered_min_width(item->get_el()->render(line_ctx.left, line_ctx.top, self_size.new_width(line_ctx.right)));
-				break;
-			case display_inline_text:
+			int min_rendered_width = item->get_el()->render(line_ctx.left, line_ctx.top, self_size.new_width(line_ctx.right), fmt_ctx);
+			if(min_rendered_width < item->get_el()->width() && item->get_el()->src_el()->css().get_width().is_predefined())
 			{
-				litehtml::size sz;
-				item->get_el()->src_el()->get_content_size(sz, line_ctx.right);
-				item->get_el()->pos() = sz;
-				item->set_rendered_min_width(sz.width);
+				item->get_el()->render(line_ctx.left, line_ctx.top, self_size.new_width(min_rendered_width), fmt_ctx);
 			}
-				break;
+			item->set_rendered_min_width(min_rendered_width);
+		} else if(item->get_el()->src_el()->css().get_display() == display_inline_text)
+		{
+			litehtml::size sz;
+			item->get_el()->src_el()->get_content_size(sz, line_ctx.right);
+			item->get_el()->pos() = sz;
+			item->set_rendered_min_width(sz.width);
 		}
 	}
 
@@ -300,7 +299,7 @@ void litehtml::render_item_inline_context::place_inline(std::unique_ptr<line_box
     }
     if(add_box)
     {
-        new_box(item, line_ctx, self_size);
+        new_box(item, line_ctx, self_size, fmt_ctx);
     } else if(!m_line_boxes.empty())
     {
         line_ctx.top = m_line_boxes.back()->top();
@@ -311,10 +310,10 @@ void litehtml::render_item_inline_context::place_inline(std::unique_ptr<line_box
         line_ctx.left = 0;
         line_ctx.right = self_size.render_width;
         line_ctx.fix_top();
-        get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right);
+		fmt_ctx->get_line_left_right(line_ctx.top, self_size.render_width, line_ctx.left, line_ctx.right);
     }
 
-    if(!item->get_el()->src_el()->is_inline_box())
+    if(!item->get_el()->src_el()->is_inline())
     {
         if(m_line_boxes.size() == 1)
         {
diff --git a/src/plugins/litehtml_viewer/litehtml/render_inline_context.h b/src/plugins/litehtml_viewer/litehtml/render_inline_context.h
new file mode 100644
index 000000000..894cfe989
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_inline_context.h
@@ -0,0 +1,55 @@
+#ifndef LITEHTML_RENDER_INLINE_CONTEXT_H
+#define LITEHTML_RENDER_INLINE_CONTEXT_H
+
+#include "render_block.h"
+
+namespace litehtml
+{
+	/**
+	 * An inline formatting context is established by a block container box that contains no block-level boxes.
+	 * https://www.w3.org/TR/CSS22/visuren.html#inline-formatting
+	 */
+	class render_item_inline_context : public render_item_block
+	{
+		/**
+		 *	Structure contains elements with display: inline
+		 *	members:
+		 *	- element: 		render_item with display: inline
+		 *	- boxes: 		rectangles represented inline element content. There are can be many boxes if content
+		 *			 is split into some lines
+		 *	- start_box:	the start position of currently calculated box
+		 */
+		struct inlines_item
+		{
+			std::shared_ptr<render_item> element;
+			position::vector boxes;
+			position	start_box;
+
+			explicit inlines_item(const std::shared_ptr<render_item>& el) : element(el) {}
+		};
+	protected:
+		std::vector<std::unique_ptr<litehtml::line_box> > m_line_boxes;
+		int m_max_line_width;
+
+		int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) override;
+		void fix_line_width(element_float flt,
+							const containing_block_context &self_size, formatting_context* fmt_ctx) override;
+
+		std::list<std::unique_ptr<line_box_item> > finish_last_box(bool end_of_render, const containing_block_context &self_size);
+		void place_inline(std::unique_ptr<line_box_item> item, const containing_block_context &self_size, formatting_context* fmt_ctx);
+		int new_box(const std::unique_ptr<line_box_item>& el, line_context& line_ctx, const containing_block_context &self_size, formatting_context* fmt_ctx);
+		void apply_vertical_align() override;
+	public:
+		explicit render_item_inline_context(std::shared_ptr<element>  src_el) : render_item_block(std::move(src_el)), m_max_line_width(0)
+		{}
+
+		std::shared_ptr<render_item> clone() override
+		{
+			return std::make_shared<render_item_inline_context>(src_el());
+		}
+
+		int get_base_line() override;
+	};
+}
+
+#endif //LITEHTML_RENDER_INLINE_CONTEXT_H
diff --git a/src/plugins/litehtml_viewer/litehtml/render_item.cpp b/src/plugins/litehtml_viewer/litehtml/render_item.cpp
index 2fc8e99c7..4eb25757d 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_item.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_item.cpp
@@ -27,6 +27,36 @@ litehtml::render_item::render_item(std::shared_ptr<element>  _src_el) :
     m_borders.bottom	= doc->to_pixels(src_el()->css().get_borders().bottom.width, fnt_size);
 }
 
+int litehtml::render_item::render(int x, int y, const containing_block_context& containing_block_size, formatting_context* fmt_ctx, bool second_pass)
+{
+	int ret;
+
+	calc_outlines(containing_block_size.width);
+
+	m_pos.clear();
+	m_pos.move_to(x, y);
+
+	int content_left = content_offset_left();
+	int content_top = content_offset_top();
+
+	m_pos.x += content_left;
+	m_pos.y += content_top;
+
+
+	if(src_el()->is_block_formatting_context() || ! fmt_ctx)
+	{
+		formatting_context fmt;
+		fmt.push_position(content_left, content_top);
+		ret = _render(x, y, containing_block_size, &fmt, second_pass);
+		fmt.apply_relative_shift(containing_block_size);
+	} else
+	{
+		fmt_ctx->push_position(x + content_left, y + content_top);
+		ret = _render(x, y, containing_block_size, fmt_ctx, second_pass);
+		fmt_ctx->pop_position(x + content_left, y + content_top);
+	}
+	return ret;
+}
 
 void litehtml::render_item::calc_outlines( int parent_width )
 {
@@ -119,10 +149,10 @@ bool litehtml::render_item::get_predefined_height(int& p_height, int containing_
     if(h.units() == css_units_percentage)
     {
 		p_height = h.calc_percent(containing_block_height);
-		return containing_block_height != 0;
+		return containing_block_height > 0;
     }
     p_height = src_el()->get_document()->to_pixels(h, src_el()->css().get_font_size());
-    return true;
+    return p_height > 0;
 }
 
 int litehtml::render_item::calc_width(int defVal, int containing_block_width) const
@@ -438,7 +468,7 @@ void litehtml::render_item::render_positioned(render_type rt)
             if(need_render)
             {
                 position pos = el->m_pos;
-				el->render(el->left(), el->top(), containing_block_size.new_width(el->width()), true);
+				el->render(el->left(), el->top(), containing_block_size.new_width(el->width()), nullptr, true);
                 el->m_pos = pos;
             }
 
@@ -632,7 +662,7 @@ void litehtml::render_item::draw_children(uint_ptr hdc, int x, int y, const posi
                     }
                     break;
                 case draw_block:
-                    if (!el->src_el()->is_inline_box() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned())
+                    if (!el->src_el()->is_inline() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned())
                     {
                         el->src_el()->draw(hdc, pos.x, pos.y, clip, el);
                     }
@@ -646,7 +676,7 @@ void litehtml::render_item::draw_children(uint_ptr hdc, int x, int y, const posi
                     }
                     break;
                 case draw_inlines:
-                    if (el->src_el()->is_inline_box() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned())
+                    if (el->src_el()->is_inline() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned())
                     {
                         el->src_el()->draw(hdc, pos.x, pos.y, clip, el);
                         if (el->src_el()->css().get_display() == display_inline_block)
@@ -734,7 +764,7 @@ std::shared_ptr<litehtml::element>  litehtml::render_item::get_child_by_point(in
                     }
                     break;
                 case draw_block:
-                    if(!el->src_el()->is_inline_box() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned())
+                    if(!el->src_el()->is_inline() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned())
                     {
                         if(el->is_point_inside(el_pos.x, el_pos.y))
                         {
@@ -755,7 +785,7 @@ std::shared_ptr<litehtml::element>  litehtml::render_item::get_child_by_point(in
                     }
                     break;
                 case draw_inlines:
-                    if(el->src_el()->is_inline_box() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned())
+                    if(el->src_el()->is_inline() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned())
                     {
                         if(el->src_el()->css().get_display() == display_inline_block ||
                                 el->src_el()->css().get_display() == display_inline_table ||
@@ -1056,21 +1086,3 @@ litehtml::containing_block_context litehtml::render_item::calculate_containing_b
 	}
 	return ret;
 }
-
-void litehtml::render_item_table_row::get_inline_boxes( position::vector& boxes ) const
-{
-	position pos;
-	for(auto& el : m_children)
-	{
-		if(el->src_el()->css().get_display() == display_table_cell)
-		{
-			pos.x		= el->left() + el->margin_left();
-			pos.y		= el->top() - m_padding.top - m_borders.top;
-
-			pos.width	= el->right() - pos.x - el->margin_right() - el->margin_left();
-			pos.height	= el->height() + m_padding.top + m_padding.bottom + m_borders.top + m_borders.bottom;
-
-			boxes.push_back(pos);
-		}
-	}
-}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_item.h b/src/plugins/litehtml_viewer/litehtml/render_item.h
index f3575778f..9d4561e5a 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_item.h
+++ b/src/plugins/litehtml_viewer/litehtml/render_item.h
@@ -8,6 +8,7 @@
 #include "types.h"
 #include "line_box.h"
 #include "table.h"
+#include "formatting_context.h"
 
 namespace litehtml
 {
@@ -28,6 +29,10 @@ namespace litehtml
 
 		containing_block_context calculate_containing_block_context(const containing_block_context& cb_context);
 		void calc_cb_length(const css_length& len, int percent_base, containing_block_context::typed_int& out_value) const;
+		virtual int _render(int x, int y, const containing_block_context& containing_block_size, formatting_context* fmt_ctx, bool second_pass = false)
+		{
+			return 0;
+		}
 
     public:
         explicit render_item(std::shared_ptr<element>  src_el);
@@ -268,11 +273,6 @@ namespace litehtml
             ri->parent(shared_from_this());
         }
 
-        virtual int render(int x, int y, const containing_block_context& containing_block_size, bool second_pass = false)
-		{
-			return 0;
-		}
-
 		bool is_root() const
 		{
 			return m_parent.expired();
@@ -303,6 +303,7 @@ namespace litehtml
             return !(m_skip || src_el()->css().get_display() == display_none || src_el()->css().get_visibility() != visibility_visible);
         }
 
+		int render(int x, int y, const containing_block_context& containing_block_size, formatting_context* fmt_ctx, bool second_pass = false);
         int calc_width(int defVal, int containing_block_width) const;
         bool get_predefined_height(int& p_height, int containing_block_height) const;
         void apply_relative_shift(const containing_block_context &containing_block_size);
@@ -345,255 +346,7 @@ namespace litehtml
          * @return
          */
         void get_rendering_boxes( position::vector& redraw_boxes);
-
-		virtual void get_line_left_right( int y, int def_right, int& ln_left, int& ln_right ) {}
-		virtual int get_line_left( int y )	{ return 0; }
-		virtual int get_line_right( int y, int def_right ) { return 0; }
-		virtual int get_left_floats_height() const	{ return 0; }
-		virtual int get_right_floats_height() const	{ return 0; }
-		virtual int get_floats_height(element_float el_float = float_none) const { return 0; }
-		virtual int find_next_line_top( int top, int width, int def_right ) { return 0; }
-		virtual void add_float(const std::shared_ptr<render_item> &el, int x, int y, int context) {}
-		virtual void clear_floats(int context) {}
-		virtual void update_floats(int dy, const std::shared_ptr<render_item> &_parent) {}
 	};
-
-    class render_item_block : public render_item
-    {
-    protected:
-		std::list<floated_box> m_floats_left;
-		std::list<floated_box> m_floats_right;
-        int_int_cache m_cache_line_left;
-        int_int_cache m_cache_line_right;
-
-		/**
-		 * Render block content.
-		 *
-		 * @param x - horizontal position of the content
-		 * @param y - vertical position of the content
-		 * @param second_pass - true is this is the second pass.
-		 * @param ret_width - input minimal width.
-		 * @param self_size - defines calculated size of block
-		 * @return return value is the minimal width of the content in block. Must be greater or equal to ret_width parameter
-		 */
-        virtual int _render_content(int x, int y, bool second_pass, int ret_width, const containing_block_context &self_size) {return ret_width;}
-		int render(int x, int y, const containing_block_context &containing_block_size, bool second_pass) override;
-
-        int place_float(const std::shared_ptr<render_item> &el, int top, const containing_block_context &self_size);
-        int get_floats_height(element_float el_float = float_none) const override;
-        int get_left_floats_height() const override;
-        int get_right_floats_height() const override;
-        int get_line_left( int y ) override;
-        int get_line_right( int y, int def_right ) override;
-        void get_line_left_right( int y, int def_right, int& ln_left, int& ln_right ) override;
-        void add_float(const std::shared_ptr<render_item> &el, int x, int y, int context) override;
-		void clear_floats(int context) override;
-		int get_cleared_top(const std::shared_ptr<render_item> &el, int line_top) const;
-        int find_next_line_top( int top, int width, int def_right ) override;
-        virtual void fix_line_width(element_float flt,
-									const containing_block_context &containing_block_size)
-		{}
-        void update_floats(int dy, const std::shared_ptr<render_item> &_parent) override;
-    public:
-        explicit render_item_block(std::shared_ptr<element>  src_el) : render_item(std::move(src_el))
-        {}
-
-        std::shared_ptr<render_item> clone() override
-        {
-            return std::make_shared<render_item_block>(src_el());
-        }
-        std::shared_ptr<render_item> init() override;
-    };
-
-    /**
-     * In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a
-     * containing block.
-     * https://www.w3.org/TR/CSS22/visuren.html#block-formatting
-     */
-    class render_item_block_context : public render_item_block
-    {
-    protected:
-        int _render_content(int x, int y, bool second_pass, int ret_width,
-							const containing_block_context &self_size) override;
-
-    public:
-        explicit render_item_block_context(std::shared_ptr<element>  src_el) : render_item_block(std::move(src_el))
-        {}
-
-        std::shared_ptr<render_item> clone() override
-        {
-            return std::make_shared<render_item_block_context>(src_el());
-        }
-    };
-
-    /**
-     * An inline formatting context is established by a block container box that contains no block-level boxes.
-     * https://www.w3.org/TR/CSS22/visuren.html#inline-formatting
-     */
-    class render_item_inline_context : public render_item_block
-    {
-		/**
-		 *	Structure contains elements with display: inline
-		 *	members:
-		 *	- element: 		render_item with display: inline
-		 *	- boxes: 		rectangles represented inline element content. There are can be many boxes if content
-		 *			 is split into some lines
-		 *	- start_box:	the start position of currently calculated box
-		 */
-		struct inlines_item
-		{
-			std::shared_ptr<render_item> element;
-			position::vector boxes;
-			position	start_box;
-
-			explicit inlines_item(const std::shared_ptr<render_item>& el) : element(el) {}
-		};
-    protected:
-        std::vector<std::unique_ptr<litehtml::line_box> > m_line_boxes;
-		int m_max_line_width;
-
-        int _render_content(int x, int y, bool second_pass, int ret_width,
-							const containing_block_context &self_size) override;
-        void fix_line_width(element_float flt,
-							const containing_block_context &self_size) override;
-
-        std::list<std::unique_ptr<line_box_item> > finish_last_box(bool end_of_render, const containing_block_context &self_size);
-        void place_inline(std::unique_ptr<line_box_item> item, const containing_block_context &self_size);
-        int new_box(const std::unique_ptr<line_box_item>& el, line_context& line_ctx, const containing_block_context &self_size);
-        void apply_vertical_align() override;
-    public:
-        explicit render_item_inline_context(std::shared_ptr<element>  src_el) : render_item_block(std::move(src_el)), m_max_line_width(0)
-        {}
-
-        std::shared_ptr<render_item> clone() override
-        {
-            return std::make_shared<render_item_inline_context>(src_el());
-        }
-
-        int get_base_line() override;
-    };
-
-    class render_item_table : public render_item
-    {
-    protected:
-        // data for table rendering
-        std::unique_ptr<table_grid>	m_grid;
-        int						    m_border_spacing_x;
-        int						    m_border_spacing_y;
-
-    public:
-        explicit render_item_table(std::shared_ptr<element>  src_el);
-
-        std::shared_ptr<render_item> clone() override
-        {
-            return std::make_shared<render_item_table>(src_el());
-        }
-		int render(int x, int y, const containing_block_context &containing_block_size, bool second_pass) override;
-        void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override;
-        int get_draw_vertical_offset() override;
-        std::shared_ptr<render_item> init() override;
-    };
-
-	class render_item_table_part : public render_item
-	{
-	public:
-		explicit render_item_table_part(std::shared_ptr<element>  src_el) : render_item(std::move(src_el))
-		{}
-
-		std::shared_ptr<render_item> clone() override
-		{
-			return std::make_shared<render_item_table_part>(src_el());
-		}
-	};
-
-	class render_item_table_row : public render_item
-	{
-	public:
-		explicit render_item_table_row(std::shared_ptr<element>  src_el) : render_item(std::move(src_el))
-		{}
-
-		std::shared_ptr<render_item> clone() override
-		{
-			return std::make_shared<render_item_table_row>(src_el());
-		}
-		void get_inline_boxes( position::vector& boxes ) const override;
-	};
-
-	class render_item_inline : public render_item
-    {
-    protected:
-		position::vector m_boxes;
-
-    public:
-        explicit render_item_inline(std::shared_ptr<element>  src_el) : render_item(std::move(src_el))
-        {}
-
-		void get_inline_boxes( position::vector& boxes ) const override { boxes = m_boxes; }
-		void set_inline_boxes( position::vector& boxes ) override { m_boxes = boxes; }
-		void add_inline_box( const position& box ) override { m_boxes.emplace_back(box); };
-		void clear_inline_boxes() override { m_boxes.clear(); }
-		int get_base_line() override { return src_el()->css().get_font_metrics().base_line(); }
-
-		std::shared_ptr<render_item> clone() override
-        {
-            return std::make_shared<render_item_inline>(src_el());
-        }
-    };
-
-    class render_item_image : public render_item
-    {
-    protected:
-        int calc_max_height(int image_height, int containing_block_height);
-
-    public:
-        explicit render_item_image(std::shared_ptr<element>  src_el) : render_item(std::move(src_el))
-        {}
-
-		int render(int x, int y, const containing_block_context &containing_block_size, bool second_pass) override;
-        std::shared_ptr<render_item> clone() override
-        {
-            return std::make_shared<render_item_image>(src_el());
-        }
-    };
-
-    class render_item_flex : public render_item_block
-    {
-        struct flex_item
-        {
-            std::shared_ptr<render_item> el;
-            int base_size;
-            int main_size;
-            int min_width;
-            int max_width;
-            int line;
-
-            explicit flex_item(std::shared_ptr<render_item>  _el) :
-                el(std::move(_el)),
-                min_width(0),
-                max_width(0),
-                line(0),
-                base_size(0),
-                main_size(0)
-            {}
-        };
-    protected:
-        std::list<std::unique_ptr<flex_item>>   m_flex_items;
-
-        int _render_content(int x, int y, bool second_pass, int ret_width,
-							const containing_block_context &self_size) override;
-
-    public:
-        explicit render_item_flex(std::shared_ptr<element>  src_el) : render_item_block(std::move(src_el))
-        {}
-
-        std::shared_ptr<render_item> clone() override
-        {
-            return std::make_shared<render_item_flex>(src_el());
-        }
-        void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override;
-        std::shared_ptr<render_item> init() override;
-    };
-
 }
 
 #endif //LH_RENDER_ITEM_H
diff --git a/src/plugins/litehtml_viewer/litehtml/render_table.cpp b/src/plugins/litehtml_viewer/litehtml/render_table.cpp
index 2ec048a98..1a3859641 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_table.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_table.cpp
@@ -1,5 +1,5 @@
 #include "html.h"
-#include "render_item.h"
+#include "render_table.h"
 #include "document.h"
 #include "iterators.h"
 
@@ -11,30 +11,12 @@ litehtml::render_item_table::render_item_table(std::shared_ptr<element> _src_el)
 {
 }
 
-int litehtml::render_item_table::render(int x, int y, const containing_block_context &containing_block_size, bool second_pass)
+int litehtml::render_item_table::_render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass)
 {
     if (!m_grid) return 0;
 
-    calc_outlines(containing_block_size.width);
-
-    m_pos.clear();
-    m_pos.move_to(x, y);
-
-    m_pos.x += content_offset_left();
-    m_pos.y += content_offset_top();
-
 	containing_block_context self_size = calculate_containing_block_context(containing_block_size);
 
-/*	if(cb_size.width_type == containing_block_context::cbc_value_type_auto)
-	{
-		max_width -= content_offset_left() + content_offset_right();
-	} else
-	{
-		max_width -= m_padding.width() + m_borders.width();
-	}
-	if(max_width < 0) max_width = 0;
-	max_width = std::min(max_width, cb_size.width);
-*/
     // Calculate table spacing
     int table_width_spacing = 0;
     if (src_el()->css().get_border_collapse() == border_collapse_separate)
@@ -71,7 +53,7 @@ int litehtml::render_item_table::render(int x, int y, const containing_block_con
             table_cell* cell = m_grid->cell(0, row);
             if (cell && cell->el)
             {
-                cell->min_width = cell->max_width = cell->el->render(0, 0, self_size.new_width(self_size.render_width - table_width_spacing));
+                cell->min_width = cell->max_width = cell->el->render(0, 0, self_size.new_width(self_size.render_width - table_width_spacing), fmt_ctx);
                 cell->el->pos().width = cell->min_width - cell->el->content_offset_left() -
 						cell->el->content_offset_right();
             }
@@ -89,7 +71,7 @@ int litehtml::render_item_table::render(int x, int y, const containing_block_con
                     if (!m_grid->column(col).css_width.is_predefined() && m_grid->column(col).css_width.units() != css_units_percentage)
                     {
                         int css_w = m_grid->column(col).css_width.calc_percent(self_size.width);
-                        int el_w = cell->el->render(0, 0, self_size.new_width(css_w));
+                        int el_w = cell->el->render(0, 0, self_size.new_width(css_w),fmt_ctx);
                         cell->min_width = cell->max_width = std::max(css_w, el_w);
                         cell->el->pos().width = cell->min_width - cell->el->content_offset_left() -
 								cell->el->content_offset_right();
@@ -97,9 +79,9 @@ int litehtml::render_item_table::render(int x, int y, const containing_block_con
                     else
                     {
                         // calculate minimum content width
-                        cell->min_width = cell->el->render(0, 0, self_size.new_width(cell->el->content_offset_width()));
+                        cell->min_width = cell->el->render(0, 0, self_size.new_width(cell->el->content_offset_width()), fmt_ctx);
                         // calculate maximum content width
-                        cell->max_width = cell->el->render(0, 0, self_size.new_width(self_size.render_width - table_width_spacing));
+                        cell->max_width = cell->el->render(0, 0, self_size.new_width(self_size.render_width - table_width_spacing), fmt_ctx);
                     }
                 }
             }
@@ -201,7 +183,7 @@ int litehtml::render_item_table::render(int x, int y, const containing_block_con
                 //if (cell->el->pos().width != cell_width - cell->el->content_offset_left() -
 				//									 cell->el->content_offset_right())
                 {
-                    cell->el->render(m_grid->column(col).left, 0, self_size.new_width(cell_width), true);
+                    cell->el->render(m_grid->column(col).left, 0, self_size.new_width(cell_width), fmt_ctx, true);
                     cell->el->pos().width = cell_width - cell->el->content_offset_left() -
 							cell->el->content_offset_right();
                 }
@@ -339,40 +321,54 @@ int litehtml::render_item_table::render(int x, int y, const containing_block_con
 
     // Render table captions
     // Table border doesn't round the caption, so we have to start caption in the border position
-    int captions_height = -border_top();
+    int top_captions = -border_top();
 
     for (auto& caption : m_grid->captions())
     {
-        caption->render(-border_left(), captions_height, self_size.new_width(table_width + border_left() + border_right()));
-        captions_height += caption->height();
+		if(caption->css().get_caption_side() == caption_side_top)
+		{
+			caption->render(-border_left(), top_captions, self_size.new_width(table_width + border_left() + border_right()), fmt_ctx);
+			top_captions += caption->height();
+		}
     }
 
-    if (captions_height)
+    if (top_captions)
     {
         // Add border height to get the top of cells
-        captions_height += border_top();
+        top_captions += border_top();
 
         // Save caption height for draw_background
-        m_grid->captions_height(captions_height);
+		m_grid->top_captions_height(top_captions);
 
         // Move table cells to the bottom side
         for (int row = 0; row < m_grid->rows_count(); row++)
         {
-            m_grid->row(row).el_row->pos().y += captions_height;
+            m_grid->row(row).el_row->pos().y += top_captions;
             for (int col = 0; col < m_grid->cols_count(); col++)
             {
                 table_cell* cell = m_grid->cell(col, row);
                 if (cell->el)
                 {
-                    cell->el->pos().y += captions_height;
+                    cell->el->pos().y += top_captions;
                 }
             }
         }
     }
 
+	int bottom_captions = 0;
+
+	for (auto& caption : m_grid->captions())
+	{
+		if(caption->css().get_caption_side() == caption_side_bottom)
+		{
+			caption->render(-border_left(), table_height + top_captions + bottom_captions, self_size.new_width(table_width + border_left() + border_right()), fmt_ctx);
+			bottom_captions += caption->height();
+		}
+	}
+
 	m_pos.move_to(x + content_offset_left(), y + content_offset_top());
 	m_pos.width = table_width;
-	m_pos.height = table_height + captions_height;
+	m_pos.height = table_height + top_captions + bottom_captions;
 
 	if(self_size.width.type != containing_block_context::cbc_value_type_absolute)
 	{
@@ -476,7 +472,25 @@ int litehtml::render_item_table::get_draw_vertical_offset()
 {
     if(m_grid)
     {
-        return m_grid->captions_height();
+        return m_grid->top_captions_height();
     }
     return 0;
 }
+
+void litehtml::render_item_table_row::get_inline_boxes( position::vector& boxes ) const
+{
+	position pos;
+	for(auto& el : m_children)
+	{
+		if(el->src_el()->css().get_display() == display_table_cell)
+		{
+			pos.x		= el->left() + el->margin_left();
+			pos.y		= el->top() - m_padding.top - m_borders.top;
+
+			pos.width	= el->right() - pos.x - el->margin_right() - el->margin_left();
+			pos.height	= el->height() + m_padding.top + m_padding.bottom + m_borders.top + m_borders.bottom;
+
+			boxes.push_back(pos);
+		}
+	}
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_table.h b/src/plugins/litehtml_viewer/litehtml/render_table.h
new file mode 100644
index 000000000..57fe435df
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_table.h
@@ -0,0 +1,56 @@
+#ifndef LITEHTML_RENDER_TABLE_H
+#define LITEHTML_RENDER_TABLE_H
+
+#include "render_item.h"
+
+namespace litehtml
+{
+	class render_item_table : public render_item
+	{
+	protected:
+		// data for table rendering
+		std::unique_ptr<table_grid>	m_grid;
+		int						    m_border_spacing_x;
+		int						    m_border_spacing_y;
+
+		int _render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) override;
+
+	public:
+		explicit render_item_table(std::shared_ptr<element>  src_el);
+
+		std::shared_ptr<render_item> clone() override
+		{
+			return std::make_shared<render_item_table>(src_el());
+		}
+		void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override;
+		int get_draw_vertical_offset() override;
+		std::shared_ptr<render_item> init() override;
+	};
+
+	class render_item_table_part : public render_item
+	{
+	public:
+		explicit render_item_table_part(std::shared_ptr<element>  src_el) : render_item(std::move(src_el))
+		{}
+
+		std::shared_ptr<render_item> clone() override
+		{
+			return std::make_shared<render_item_table_part>(src_el());
+		}
+	};
+
+	class render_item_table_row : public render_item
+	{
+	public:
+		explicit render_item_table_row(std::shared_ptr<element>  src_el) : render_item(std::move(src_el))
+		{}
+
+		std::shared_ptr<render_item> clone() override
+		{
+			return std::make_shared<render_item_table_row>(src_el());
+		}
+		void get_inline_boxes( position::vector& boxes ) const override;
+	};
+}
+
+#endif //LITEHTML_RENDER_TABLE_H
diff --git a/src/plugins/litehtml_viewer/litehtml/string_id.h b/src/plugins/litehtml_viewer/litehtml/string_id.h
index 340ac7fbc..60d30f5e4 100644
--- a/src/plugins/litehtml_viewer/litehtml/string_id.h
+++ b/src/plugins/litehtml_viewer/litehtml/string_id.h
@@ -287,6 +287,8 @@ STRING_ID(
 	_flex_grow_,
 	_flex_shrink_,
 	_flex_basis_,
+
+	_caption_side_,
 );
 #undef STRING_ID
 extern const string_id empty_id; // _id("")
diff --git a/src/plugins/litehtml_viewer/litehtml/style.cpp b/src/plugins/litehtml_viewer/litehtml/style.cpp
index ca6b18f06..5642d36c4 100644
--- a/src/plugins/litehtml_viewer/litehtml/style.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/style.cpp
@@ -44,6 +44,8 @@ std::map<string_id, string> style::m_valid_values =
 	{ _align_items_, flex_align_items_strings },
 	{ _align_content_, flex_align_content_strings },
 	{ _align_self_, flex_align_self_strings },
+
+	{ _caption_side_, caption_side_strings },
 };
 
 void style::parse(const string& txt, const string& baseurl, document_container* container)
@@ -130,6 +132,8 @@ void style::add_property(string_id name, const string& val, const string& baseur
 	case _align_content_:
 	case _align_self_:
 
+	case _caption_side_:
+
 		idx = value_index(val, m_valid_values[name]);
 		if (idx >= 0)
 		{
@@ -238,7 +242,7 @@ void style::add_property(string_id name, const string& val, const string& baseur
 				add_parsed_property(_border_top_width_,		width);
 				add_parsed_property(_border_bottom_width_,	width);
 			}
-			else
+			else if (web_color::is_color(token, container))
 			{
 				web_color _color = web_color::from_string(token, container);
 				property_value color(_color, important);
@@ -271,7 +275,7 @@ void style::add_property(string_id name, const string& val, const string& baseur
 				property_value width(parse_border_width(token), important);
 				add_parsed_property(_id(_s(name) + "-width"), width);
 			}
-			else
+			else if (web_color::is_color(token, container))
 			{
 				web_color color = web_color::from_string(token, container);
 				add_parsed_property(_id(_s(name) + "-color"), property_value(color, important));
@@ -334,11 +338,12 @@ void style::add_property(string_id name, const string& val, const string& baseur
 	case _border_bottom_color_:
 	case _border_left_color_:
 	case _border_right_color_:
-	{
-		web_color color = web_color::from_string(val, container);
-		add_parsed_property(name, property_value(color, important));
+		if (web_color::is_color(val, container))
+		{
+			web_color color = web_color::from_string(val, container);
+			add_parsed_property(name, property_value(color, important));
+		}
 		break;
-	}
 
 	// Parse border radius shorthand properties 
 	case _border_bottom_left_radius_:
diff --git a/src/plugins/litehtml_viewer/litehtml/stylesheet.cpp b/src/plugins/litehtml_viewer/litehtml/stylesheet.cpp
index 12bfd721d..8c4b78431 100644
--- a/src/plugins/litehtml_viewer/litehtml/stylesheet.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/stylesheet.cpp
@@ -13,6 +13,11 @@ void litehtml::css::parse_stylesheet(const char* str, const char* baseurl, const
 	while(c_start != string::npos)
 	{
 		string::size_type c_end = text.find("*/", c_start + 2);
+		if(c_end == string::npos)
+		{
+			text.erase(c_start);
+			break;
+		}
 		text.erase(c_start, c_end - c_start + 2);
 		c_start = text.find("/*");
 	}
diff --git a/src/plugins/litehtml_viewer/litehtml/table.h b/src/plugins/litehtml_viewer/litehtml/table.h
index edd5f055e..d738b63eb 100644
--- a/src/plugins/litehtml_viewer/litehtml/table.h
+++ b/src/plugins/litehtml_viewer/litehtml/table.h
@@ -204,14 +204,16 @@ namespace litehtml
 		table_column::vector	m_columns;
 		table_row::vector		m_rows;
 		std::vector<std::shared_ptr<render_item>> m_captions;
-		int						m_captions_height;
+		int						m_top_captions_height;
+		int						m_bottom_captions_height;
 	public:
 
-		table_grid()
+		table_grid() :
+			m_rows_count(0),
+			m_cols_count(0),
+			m_top_captions_height(0),
+			m_bottom_captions_height(0)
 		{
-			m_rows_count	= 0;
-			m_cols_count	= 0;
-			m_captions_height = 0;
 		}
 
 		void			clear();
@@ -227,8 +229,10 @@ namespace litehtml
 		int				rows_count() const	{ return m_rows_count;	}
 		int				cols_count() const	{ return m_cols_count; }
 
-		void			captions_height(int height) { m_captions_height = height; }
-		int				captions_height() const { return m_captions_height; }
+		void			top_captions_height(int height) { m_top_captions_height = height; }
+		int				top_captions_height() const { return m_top_captions_height; }
+		void			bottom_captions_height(int height) { m_bottom_captions_height = height; }
+		int				bottom_captions_height() const { return m_bottom_captions_height; }
 
 		void			distribute_max_width(int width, int start, int end);
 		void			distribute_min_width(int width, int start, int end);
diff --git a/src/plugins/litehtml_viewer/litehtml/types.h b/src/plugins/litehtml_viewer/litehtml/types.h
index 7946a3f08..b1feeeea6 100644
--- a/src/plugins/litehtml_viewer/litehtml/types.h
+++ b/src/plugins/litehtml_viewer/litehtml/types.h
@@ -5,6 +5,7 @@
 #include <memory>
 #include <map>
 #include <vector>
+#include <list>
 
 namespace litehtml
 {
@@ -12,7 +13,7 @@ namespace litehtml
 	class element;
 
 	typedef std::map<string, string>					string_map;
-	typedef std::vector< std::shared_ptr<element> >		elements_vector;
+	typedef std::list< std::shared_ptr<element> >		elements_list;
 	typedef std::vector<int>							int_vector;
 	typedef std::vector<string>							string_vector;
 
@@ -598,6 +599,7 @@ namespace litehtml
 		element_clear	                clear_floats;
 		std::shared_ptr<render_item>	el;
 		int								context;
+		int 							min_width;
 
 		floated_box() = default;
 		floated_box(const floated_box& val)
@@ -607,6 +609,7 @@ namespace litehtml
 			clear_floats = val.clear_floats;
 			el = val.el;
 			context = val.context;
+			min_width = val.min_width;
 		}
 		floated_box& operator=(const floated_box& val)
 		{
@@ -615,6 +618,7 @@ namespace litehtml
 			clear_floats = val.clear_floats;
 			el = val.el;
 			context = val.context;
+			min_width = val.min_width;
 			return *this;
 		}
 		floated_box(floated_box&& val)
@@ -624,6 +628,7 @@ namespace litehtml
 			clear_floats = val.clear_floats;
 			el = std::move(val.el);
 			context = val.context;
+			min_width = val.min_width;
 		}
 		void operator=(floated_box&& val)
 		{
@@ -632,6 +637,7 @@ namespace litehtml
 			clear_floats = val.clear_floats;
 			el = std::move(val.el);
 			context = val.context;
+			min_width = val.min_width;
 		}
 	};
 
@@ -899,6 +905,13 @@ namespace litehtml
 		flex_basis_max_content,
 	};
 
+#define caption_side_strings		"top;bottom"
+
+	enum caption_side
+	{
+		caption_side_top,
+		caption_side_bottom
+	};
 }
 
 #endif  // LH_TYPES_H

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list