[Commits] [SCM] claws branch, gtk2, updated. 3.19.1-78-g90a8ad19e
jonathan at claws-mail.org
jonathan at claws-mail.org
Sun Oct 22 11:52:31 UTC 2023
The branch, gtk2 has been updated
via 90a8ad19e0f5535d6255f3e2b120a0faaca4fb9e (commit)
from 63f2bb0cac13b6477a03982f9a23bf7e5e20104f (commit)
Summary of changes:
src/plugins/litehtml_viewer/litehtml/Makefile.am | 143 +-
src/plugins/litehtml_viewer/litehtml/attributes.h | 35 -
.../litehtml_viewer/litehtml/background.cpp | 79 -
src/plugins/litehtml_viewer/litehtml/background.h | 51 +-
src/plugins/litehtml_viewer/litehtml/borders.h | 28 +-
src/plugins/litehtml_viewer/litehtml/box.cpp | 434 --
src/plugins/litehtml_viewer/litehtml/box.h | 120 -
src/plugins/litehtml_viewer/litehtml/codepoint.cpp | 82 +
src/plugins/litehtml_viewer/litehtml/codepoint.h | 51 +
src/plugins/litehtml_viewer/litehtml/context.cpp | 12 -
src/plugins/litehtml_viewer/litehtml/context.h | 20 -
.../litehtml_viewer/litehtml/css_borders.cpp | 7 +
.../litehtml_viewer/litehtml/css_length.cpp | 47 +-
src/plugins/litehtml_viewer/litehtml/css_length.h | 42 +-
src/plugins/litehtml_viewer/litehtml/css_margins.h | 13 +-
src/plugins/litehtml_viewer/litehtml/css_offsets.h | 13 +-
.../litehtml_viewer/litehtml/css_position.h | 29 +-
.../litehtml_viewer/litehtml/css_properties.cpp | 456 ++
.../litehtml_viewer/litehtml/css_properties.h | 643 +++
.../litehtml_viewer/litehtml/css_selector.cpp | 261 +-
.../litehtml_viewer/litehtml/css_selector.h | 56 +-
src/plugins/litehtml_viewer/litehtml/document.cpp | 586 +--
src/plugins/litehtml_viewer/litehtml/document.h | 95 +-
.../litehtml/document_container.cpp | 44 +
.../litehtml_viewer/litehtml/document_container.h | 71 +
src/plugins/litehtml_viewer/litehtml/el_anchor.cpp | 11 +-
src/plugins/litehtml_viewer/litehtml/el_anchor.h | 7 +-
src/plugins/litehtml_viewer/litehtml/el_base.cpp | 9 +-
src/plugins/litehtml_viewer/litehtml/el_base.h | 5 +-
.../litehtml_viewer/litehtml/el_before_after.cpp | 146 +-
.../litehtml_viewer/litehtml/el_before_after.h | 17 +-
src/plugins/litehtml_viewer/litehtml/el_body.cpp | 5 -
src/plugins/litehtml_viewer/litehtml/el_body.h | 5 +-
src/plugins/litehtml_viewer/litehtml/el_break.cpp | 5 -
src/plugins/litehtml_viewer/litehtml/el_break.h | 7 +-
src/plugins/litehtml_viewer/litehtml/el_cdata.cpp | 13 +-
src/plugins/litehtml_viewer/litehtml/el_cdata.h | 9 +-
.../litehtml_viewer/litehtml/el_comment.cpp | 12 +-
src/plugins/litehtml_viewer/litehtml/el_comment.h | 15 +-
src/plugins/litehtml_viewer/litehtml/el_div.cpp | 11 +-
src/plugins/litehtml_viewer/litehtml/el_div.h | 5 +-
src/plugins/litehtml_viewer/litehtml/el_font.cpp | 33 +-
src/plugins/litehtml_viewer/litehtml/el_font.h | 5 +-
src/plugins/litehtml_viewer/litehtml/el_image.cpp | 233 +-
src/plugins/litehtml_viewer/litehtml/el_image.h | 23 +-
src/plugins/litehtml_viewer/litehtml/el_li.cpp | 38 -
src/plugins/litehtml_viewer/litehtml/el_li.h | 21 -
src/plugins/litehtml_viewer/litehtml/el_link.cpp | 19 +-
src/plugins/litehtml_viewer/litehtml/el_link.h | 5 +-
src/plugins/litehtml_viewer/litehtml/el_para.cpp | 11 +-
src/plugins/litehtml_viewer/litehtml/el_para.h | 5 +-
src/plugins/litehtml_viewer/litehtml/el_script.cpp | 16 +-
src/plugins/litehtml_viewer/litehtml/el_script.h | 12 +-
src/plugins/litehtml_viewer/litehtml/el_space.cpp | 23 +-
src/plugins/litehtml_viewer/litehtml/el_space.h | 9 +-
src/plugins/litehtml_viewer/litehtml/el_style.cpp | 20 +-
src/plugins/litehtml_viewer/litehtml/el_style.h | 10 +-
src/plugins/litehtml_viewer/litehtml/el_table.cpp | 80 +-
src/plugins/litehtml_viewer/litehtml/el_table.h | 8 +-
src/plugins/litehtml_viewer/litehtml/el_td.cpp | 32 +-
src/plugins/litehtml_viewer/litehtml/el_td.h | 5 +-
src/plugins/litehtml_viewer/litehtml/el_text.cpp | 166 +-
src/plugins/litehtml_viewer/litehtml/el_text.h | 27 +-
src/plugins/litehtml_viewer/litehtml/el_title.cpp | 10 +-
src/plugins/litehtml_viewer/litehtml/el_title.h | 5 +-
src/plugins/litehtml_viewer/litehtml/el_tr.cpp | 37 +-
src/plugins/litehtml_viewer/litehtml/el_tr.h | 6 +-
src/plugins/litehtml_viewer/litehtml/element.cpp | 552 +--
src/plugins/litehtml_viewer/litehtml/element.h | 398 +-
src/plugins/litehtml_viewer/litehtml/html.cpp | 198 +-
src/plugins/litehtml_viewer/litehtml/html.h | 95 +-
src/plugins/litehtml_viewer/litehtml/html_tag.cpp | 4948 ++++----------------
src/plugins/litehtml_viewer/litehtml/html_tag.h | 302 +-
src/plugins/litehtml_viewer/litehtml/iterators.cpp | 111 +-
src/plugins/litehtml_viewer/litehtml/iterators.h | 88 +-
src/plugins/litehtml_viewer/litehtml/line_box.cpp | 698 +++
src/plugins/litehtml_viewer/litehtml/line_box.h | 170 +
src/plugins/litehtml_viewer/litehtml/litehtml.h | 1 +
src/plugins/litehtml_viewer/litehtml/master_css.h | 351 ++
.../litehtml_viewer/litehtml/media_query.cpp | 61 +-
src/plugins/litehtml_viewer/litehtml/media_query.h | 4 +-
src/plugins/litehtml_viewer/litehtml/num_cvt.cpp | 63 +-
src/plugins/litehtml_viewer/litehtml/num_cvt.h | 11 +-
src/plugins/litehtml_viewer/litehtml/os_types.h | 86 +-
.../litehtml_viewer/litehtml/render_block.cpp | 856 ++++
.../litehtml/render_block_context.cpp | 125 +
.../litehtml_viewer/litehtml/render_flex.cpp | 91 +
.../litehtml_viewer/litehtml/render_image.cpp | 148 +
.../litehtml_viewer/litehtml/render_inline.cpp | 3 +
.../litehtml/render_inline_context.cpp | 403 ++
.../litehtml_viewer/litehtml/render_item.cpp | 1076 +++++
src/plugins/litehtml_viewer/litehtml/render_item.h | 599 +++
.../litehtml_viewer/litehtml/render_table.cpp | 482 ++
src/plugins/litehtml_viewer/litehtml/string_id.cpp | 54 +
src/plugins/litehtml_viewer/litehtml/string_id.h | 300 ++
src/plugins/litehtml_viewer/litehtml/strtod.cpp | 275 ++
src/plugins/litehtml_viewer/litehtml/style.cpp | 1433 ++++--
src/plugins/litehtml_viewer/litehtml/style.h | 215 +-
.../litehtml_viewer/litehtml/stylesheet.cpp | 123 +-
src/plugins/litehtml_viewer/litehtml/stylesheet.h | 23 +-
src/plugins/litehtml_viewer/litehtml/table.cpp | 97 +-
src/plugins/litehtml_viewer/litehtml/table.h | 65 +-
.../litehtml_viewer/litehtml/tstring_view.cpp | 46 +
.../litehtml_viewer/litehtml/tstring_view.h | 136 +
src/plugins/litehtml_viewer/litehtml/types.h | 363 +-
src/plugins/litehtml_viewer/litehtml/url.cpp | 163 +
src/plugins/litehtml_viewer/litehtml/url.h | 139 +
src/plugins/litehtml_viewer/litehtml/url_path.cpp | 86 +
src/plugins/litehtml_viewer/litehtml/url_path.h | 51 +
.../litehtml_viewer/litehtml/utf8_strings.cpp | 2 +
.../litehtml_viewer/litehtml/utf8_strings.h | 12 +-
src/plugins/litehtml_viewer/litehtml/web_color.cpp | 382 +-
src/plugins/litehtml_viewer/litehtml/web_color.h | 50 +-
113 files changed, 12329 insertions(+), 8165 deletions(-)
delete mode 100644 src/plugins/litehtml_viewer/litehtml/attributes.h
delete mode 100644 src/plugins/litehtml_viewer/litehtml/background.cpp
delete mode 100644 src/plugins/litehtml_viewer/litehtml/box.cpp
delete mode 100644 src/plugins/litehtml_viewer/litehtml/box.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/codepoint.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/codepoint.h
delete mode 100644 src/plugins/litehtml_viewer/litehtml/context.cpp
delete mode 100644 src/plugins/litehtml_viewer/litehtml/context.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/css_borders.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/css_properties.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/css_properties.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/document_container.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/document_container.h
delete mode 100644 src/plugins/litehtml_viewer/litehtml/el_li.cpp
delete mode 100644 src/plugins/litehtml_viewer/litehtml/el_li.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/line_box.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/line_box.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/master_css.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/render_block.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/render_block_context.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/render_flex.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/render_image.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/render_inline.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/render_item.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/render_item.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/render_table.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/string_id.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/string_id.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/strtod.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/tstring_view.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/tstring_view.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/url.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/url.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/url_path.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/url_path.h
- Log -----------------------------------------------------------------
commit 90a8ad19e0f5535d6255f3e2b120a0faaca4fb9e
Author: Jonathan Boeing <jonathan at claws-mail.org>
Date: Mon Oct 9 00:28:03 2023 -0700
Sync with litehtml v0.7
diff --git a/src/plugins/litehtml_viewer/litehtml/Makefile.am b/src/plugins/litehtml_viewer/litehtml/Makefile.am
index 7a539fecd..6e103b7ba 100644
--- a/src/plugins/litehtml_viewer/litehtml/Makefile.am
+++ b/src/plugins/litehtml_viewer/litehtml/Makefile.am
@@ -16,50 +16,113 @@ endif
liblitehtml_la_CXXFLAGS = -std=c++11
liblitehtml_la_SOURCES = \
- attributes.h \
- background.cpp background.h \
+ background.h \
borders.h \
- box.cpp box.h \
- context.cpp context.h \
- css_length.cpp css_length.h \
- css_margins.h css_offsets.h css_position.h \
- css_selector.cpp css_selector.h \
- document.cpp document.h \
- el_anchor.cpp el_anchor.h \
- el_base.cpp el_base.h \
- el_before_after.cpp el_before_after.h \
- el_body.cpp el_body.h \
- el_break.cpp el_break.h \
- el_cdata.cpp el_cdata.h \
- el_comment.cpp el_comment.h \
- el_div.cpp el_div.h \
- element.cpp element.h \
- el_font.cpp el_font.h \
- el_image.cpp el_image.h \
- el_li.cpp el_li.h \
- el_link.cpp el_link.h \
- el_para.cpp el_para.h \
- el_script.cpp el_script.h \
- el_space.cpp el_space.h \
- el_style.cpp el_style.h \
- el_table.cpp el_table.h \
- el_td.cpp el_td.h \
- el_text.cpp el_text.h \
- el_title.cpp el_title.h \
- el_tr.cpp el_tr.h \
- html.cpp html.h \
- html_tag.cpp html_tag.h \
- iterators.cpp iterators.h \
+ codepoint.cpp \
+ codepoint.h \
+ css_borders.cpp \
+ css_length.cpp \
+ css_length.h \
+ css_margins.h \
+ css_offsets.h \
+ css_position.h \
+ css_properties.cpp \
+ css_properties.h \
+ css_selector.cpp \
+ css_selector.h \
+ document_container.cpp \
+ document_container.h \
+ document.cpp \
+ document.h \
+ el_anchor.cpp \
+ el_anchor.h \
+ el_base.cpp \
+ el_base.h \
+ el_before_after.cpp \
+ el_before_after.h \
+ el_body.cpp \
+ el_body.h \
+ el_break.cpp \
+ el_break.h \
+ el_cdata.cpp \
+ el_cdata.h \
+ el_comment.cpp \
+ el_comment.h \
+ el_div.cpp \
+ el_div.h \
+ element.cpp \
+ element.h \
+ el_font.cpp \
+ el_font.h \
+ el_image.cpp \
+ el_image.h \
+ el_link.cpp \
+ el_link.h \
+ el_para.cpp \
+ el_para.h \
+ el_script.cpp \
+ el_script.h \
+ el_space.cpp \
+ el_space.h \
+ el_style.cpp \
+ el_style.h \
+ el_table.cpp \
+ el_table.h \
+ el_td.cpp \
+ el_td.h \
+ el_text.cpp \
+ el_text.h \
+ el_title.cpp \
+ el_title.h \
+ el_tr.cpp \
+ el_tr.h \
+ html.cpp \
+ html.h \
+ html_tag.cpp \
+ html_tag.h \
+ iterators.cpp \
+ iterators.h \
+ LICENSE \
+ line_box.cpp \
+ line_box.h \
litehtml.h \
- media_query.cpp media_query.h \
- num_cvt.cpp num_cvt.h \
+ Makefile.am \
+ master_css.h \
+ media_query.cpp \
+ media_query.h \
+ num_cvt.cpp \
+ num_cvt.h \
os_types.h \
- style.cpp style.h \
- stylesheet.cpp stylesheet.h \
- table.cpp table.h \
+ README.md \
+ render_block_context.cpp \
+ render_block.cpp \
+ render_flex.cpp \
+ render_image.cpp \
+ render_inline_context.cpp \
+ render_inline.cpp \
+ render_item.cpp \
+ render_item.h \
+ render_table.cpp \
+ string_id.cpp \
+ string_id.h \
+ strtod.cpp \
+ style.cpp \
+ style.h \
+ stylesheet.cpp \
+ stylesheet.h \
+ table.cpp \
+ table.h \
+ tstring_view.cpp \
+ tstring_view.h \
types.h \
- utf8_strings.cpp utf8_strings.h \
- web_color.cpp web_color.h
+ url.cpp \
+ url.h \
+ url_path.cpp \
+ url_path.h \
+ utf8_strings.cpp \
+ utf8_strings.h \
+ web_color.cpp \
+ web_color.h
liblitehtml_la_LDFLAGS = \
-avoid-version -module \
diff --git a/src/plugins/litehtml_viewer/litehtml/attributes.h b/src/plugins/litehtml_viewer/litehtml/attributes.h
deleted file mode 100644
index 98487f02e..000000000
--- a/src/plugins/litehtml_viewer/litehtml/attributes.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef LH_ATTRIBUTES_H
-#define LH_ATTRIBUTES_H
-
-namespace litehtml
-{
- struct attr_color
- {
- unsigned char rgbBlue;
- unsigned char rgbGreen;
- unsigned char rgbRed;
- unsigned char rgbAlpha;
- attr_color()
- {
- rgbAlpha = 255;
- rgbBlue = 0;
- rgbGreen = 0;
- rgbRed = 0;
- }
- };
-
- struct attr_border
- {
- style_border border;
- int width;
- attr_color color;
-
- attr_border()
- {
- border = borderNone;
- width = 0;
- }
- };
-}
-
-#endif // LH_ATTRIBUTES_H
diff --git a/src/plugins/litehtml_viewer/litehtml/background.cpp b/src/plugins/litehtml_viewer/litehtml/background.cpp
deleted file mode 100644
index 1c65e3042..000000000
--- a/src/plugins/litehtml_viewer/litehtml/background.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-#include "html.h"
-#include "background.h"
-
-litehtml::background::background(void)
-{
- m_attachment = background_attachment_scroll;
- m_repeat = background_repeat_repeat;
- m_clip = background_box_border;
- m_origin = background_box_padding;
- m_color.alpha = 0;
- m_color.red = 0;
- m_color.green = 0;
- m_color.blue = 0;
-}
-
-litehtml::background::background( const background& val )
-{
- m_image = val.m_image;
- m_baseurl = val.m_baseurl;
- m_color = val.m_color;
- m_attachment = val.m_attachment;
- m_position = val.m_position;
- m_repeat = val.m_repeat;
- m_clip = val.m_clip;
- m_origin = val.m_origin;
-}
-
-litehtml::background::~background(void)
-{
-}
-
-litehtml::background& litehtml::background::operator=( const background& val )
-{
- m_image = val.m_image;
- m_baseurl = val.m_baseurl;
- m_color = val.m_color;
- m_attachment = val.m_attachment;
- m_position = val.m_position;
- m_repeat = val.m_repeat;
- m_clip = val.m_clip;
- m_origin = val.m_origin;
- return *this;
-}
-
-
-litehtml::background_paint::background_paint() : color(0, 0, 0, 0)
-{
- position_x = 0;
- position_y = 0;
- attachment = background_attachment_scroll;
- repeat = background_repeat_repeat;
- is_root = false;
-}
-
-litehtml::background_paint::background_paint( const background_paint& val )
-{
- image = val.image;
- baseurl = val.baseurl;
- attachment = val.attachment;
- repeat = val.repeat;
- color = val.color;
- clip_box = val.clip_box;
- origin_box = val.origin_box;
- border_box = val.border_box;
- border_radius = val.border_radius;
- image_size = val.image_size;
- position_x = val.position_x;
- position_y = val.position_y;
- is_root = val.is_root;
-}
-
-void litehtml::background_paint::operator=( const background& val )
-{
- attachment = val.m_attachment;
- baseurl = val.m_baseurl;
- image = val.m_image;
- repeat = val.m_repeat;
- color = val.m_color;
-}
diff --git a/src/plugins/litehtml_viewer/litehtml/background.h b/src/plugins/litehtml_viewer/litehtml/background.h
index ce0b69a63..c56443d54 100644
--- a/src/plugins/litehtml_viewer/litehtml/background.h
+++ b/src/plugins/litehtml_viewer/litehtml/background.h
@@ -2,7 +2,6 @@
#define LH_BACKGROUND_H
#include "types.h"
-#include "attributes.h"
#include "css_length.h"
#include "css_position.h"
#include "web_color.h"
@@ -13,29 +12,34 @@ namespace litehtml
class background
{
public:
- tstring m_image;
- tstring m_baseurl;
+ string_vector m_image;
+ string m_baseurl;
web_color m_color;
- background_attachment m_attachment;
- css_position m_position;
- background_repeat m_repeat;
- background_box m_clip;
- background_box m_origin;
- css_border_radius m_radius;
+ int_vector m_attachment;
+ length_vector m_position_x;
+ length_vector m_position_y;
+ size_vector m_size;
+ int_vector m_repeat;
+ int_vector m_clip;
+ int_vector m_origin;
- public:
- background(void);
- background(const background& val);
- ~background(void);
-
- background& operator=(const background& val);
+ bool is_empty() const
+ {
+ if(m_color.alpha != 0) return false;
+ if(m_image.empty()) return true;
+ for(const auto& img : m_image)
+ {
+ if(!img.empty()) return false;
+ }
+ return true;
+ }
};
class background_paint
{
public:
- tstring image;
- tstring baseurl;
+ string image;
+ string baseurl;
background_attachment attachment;
background_repeat repeat;
web_color color;
@@ -47,10 +51,17 @@ namespace litehtml
int position_x;
int position_y;
bool is_root;
+
public:
- background_paint();
- background_paint(const background_paint& val);
- void operator=(const background& val);
+ background_paint()
+ {
+ attachment = background_attachment_scroll;
+ repeat = background_repeat_repeat;
+ color = web_color::transparent;
+ position_x = 0;
+ position_y = 0;
+ is_root = false;
+ }
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/borders.h b/src/plugins/litehtml_viewer/litehtml/borders.h
index 9956a2a35..e690db6d3 100644
--- a/src/plugins/litehtml_viewer/litehtml/borders.h
+++ b/src/plugins/litehtml_viewer/litehtml/borders.h
@@ -3,6 +3,7 @@
#include "css_length.h"
#include "types.h"
+#include "web_color.h"
namespace litehtml
{
@@ -31,6 +32,8 @@ namespace litehtml
color = val.color;
return *this;
}
+
+ string to_string() const;
};
struct border
@@ -199,7 +202,7 @@ namespace litehtml
bottom_right_y = val.bottom_right_y;
return *this;
}
- border_radiuses calc_percents(int width, int height)
+ border_radiuses calc_percents(int width, int height) const
{
border_radiuses ret;
ret.bottom_left_x = bottom_left_x.calc_percent(width);
@@ -222,9 +225,11 @@ namespace litehtml
css_border bottom;
css_border_radius radius;
- css_borders()
- {
+ css_borders() = default;
+ bool is_visible() const
+ {
+ return left.width.val() != 0 || right.width.val() != 0 || top.width.val() != 0 || bottom.width.val() != 0;
}
css_borders(const css_borders& val)
@@ -245,6 +250,13 @@ namespace litehtml
radius = val.radius;
return *this;
}
+ string to_string() const
+ {
+ return "left: " + left.to_string() +
+ ", top: " + top.to_string() +
+ ", right: " + top.to_string() +
+ ", bottom: " + bottom.to_string();
+ }
};
struct borders
@@ -255,10 +267,7 @@ namespace litehtml
border bottom;
border_radiuses radius;
- borders()
- {
-
- }
+ borders() = default;
borders(const borders& val)
{
@@ -277,6 +286,11 @@ namespace litehtml
bottom = val.bottom;
}
+ bool is_visible() const
+ {
+ return left.width != 0 || right.width != 0 || top.width != 0 || bottom.width != 0;
+ }
+
borders& operator=(const borders& val)
{
left = val.left;
diff --git a/src/plugins/litehtml_viewer/litehtml/box.cpp b/src/plugins/litehtml_viewer/litehtml/box.cpp
deleted file mode 100644
index 4ad23c529..000000000
--- a/src/plugins/litehtml_viewer/litehtml/box.cpp
+++ /dev/null
@@ -1,434 +0,0 @@
-#include "html.h"
-#include "box.h"
-#include "html_tag.h"
-
-
-litehtml::box_type litehtml::block_box::get_type()
-{
- return box_block;
-}
-
-int litehtml::block_box::height()
-{
- return m_element->height();
-}
-
-int litehtml::block_box::width()
-{
- return m_element->width();
-}
-
-void litehtml::block_box::add_element(const element::ptr &el)
-{
- m_element = el;
- el->m_box = this;
-}
-
-void litehtml::block_box::finish(bool last_box)
-{
- if(!m_element) return;
- m_element->apply_relative_shift(m_box_right - m_box_left);
-}
-
-bool litehtml::block_box::can_hold(const element::ptr &el, white_space ws)
-{
- if(m_element || el->is_inline_box())
- {
- return false;
- }
- return true;
-}
-
-bool litehtml::block_box::is_empty()
-{
- if(m_element)
- {
- return false;
- }
- return true;
-}
-
-int litehtml::block_box::baseline()
-{
- if(m_element)
- {
- return m_element->get_base_line();
- }
- return 0;
-}
-
-void litehtml::block_box::get_elements( elements_vector& els )
-{
- els.push_back(m_element);
-}
-
-int litehtml::block_box::top_margin()
-{
- if(m_element && m_element->collapse_top_margin())
- {
- return m_element->m_margins.top;
- }
- return 0;
-}
-
-int litehtml::block_box::bottom_margin()
-{
- if(m_element && m_element->collapse_bottom_margin())
- {
- return m_element->m_margins.bottom;
- }
- return 0;
-}
-
-void litehtml::block_box::y_shift( int shift )
-{
- m_box_top += shift;
- if(m_element)
- {
- m_element->m_pos.y += shift;
- }
-}
-
-void litehtml::block_box::new_width( int left, int right, elements_vector& els )
-{
-
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-litehtml::box_type litehtml::line_box::get_type()
-{
- return box_line;
-}
-
-int litehtml::line_box::height()
-{
- return m_height;
-}
-
-int litehtml::line_box::width()
-{
- return m_width;
-}
-
-void litehtml::line_box::add_element(const element::ptr &el)
-{
- el->m_skip = false;
- el->m_box = 0;
- bool add = true;
- if( (m_items.empty() && el->is_white_space()) || el->is_break() )
- {
- el->m_skip = true;
- } else if(el->is_white_space())
- {
- if (have_last_space())
- {
- add = false;
- el->m_skip = true;
- }
- }
-
- if(add)
- {
- el->m_box = this;
- m_items.push_back(el);
-
- if(!el->m_skip)
- {
- int el_shift_left = el->get_inline_shift_left();
- int el_shift_right = el->get_inline_shift_right();
-
- el->m_pos.x = m_box_left + m_width + el_shift_left + el->content_margins_left();
- el->m_pos.y = m_box_top + el->content_margins_top();
- m_width += el->width() + el_shift_left + el_shift_right;
- }
- }
-}
-
-void litehtml::line_box::finish(bool last_box)
-{
- if( is_empty() || (!is_empty() && last_box && is_break_only()) )
- {
- m_height = 0;
- return;
- }
-
- for(auto i = m_items.rbegin(); i != m_items.rend(); i++)
- {
- if((*i)->is_white_space() || (*i)->is_break())
- {
- if(!(*i)->m_skip)
- {
- (*i)->m_skip = true;
- m_width -= (*i)->width();
- }
- } else
- {
- break;
- }
- }
-
- int base_line = m_font_metrics.base_line();
- int line_height = m_line_height;
-
- int add_x = 0;
- switch(m_text_align)
- {
- case text_align_right:
- if(m_width < (m_box_right - m_box_left))
- {
- add_x = (m_box_right - m_box_left) - m_width;
- }
- break;
- case text_align_center:
- if(m_width < (m_box_right - m_box_left))
- {
- add_x = ((m_box_right - m_box_left) - m_width) / 2;
- }
- break;
- default:
- add_x = 0;
- }
-
- m_height = 0;
- // find line box baseline and line-height
- for(const auto& el : m_items)
- {
- if(el->get_display() == display_inline_text)
- {
- font_metrics fm;
- el->get_font(&fm);
- base_line = std::max(base_line, fm.base_line());
- line_height = std::max(line_height, el->line_height());
- m_height = std::max(m_height, fm.height);
- }
- el->m_pos.x += add_x;
- }
-
- if(m_height)
- {
- base_line += (line_height - m_height) / 2;
- }
-
- m_height = line_height;
-
- int y1 = 0;
- int y2 = m_height;
-
- for (const auto& el : m_items)
- {
- if(el->get_display() == display_inline_text)
- {
- font_metrics fm;
- el->get_font(&fm);
- el->m_pos.y = m_height - base_line - fm.ascent;
- } else
- {
- switch(el->get_vertical_align())
- {
- case va_super:
- case va_sub:
- case va_baseline:
- el->m_pos.y = m_height - base_line - el->height() + el->get_base_line() + el->content_margins_top();
- break;
- case va_top:
- el->m_pos.y = y1 + el->content_margins_top();
- break;
- case va_text_top:
- el->m_pos.y = m_height - base_line - m_font_metrics.ascent + el->content_margins_top();
- break;
- case va_middle:
- el->m_pos.y = m_height - base_line - m_font_metrics.x_height / 2 - el->height() / 2 + el->content_margins_top();
- break;
- case va_bottom:
- el->m_pos.y = y2 - el->height() + el->content_margins_top();
- break;
- case va_text_bottom:
- el->m_pos.y = m_height - base_line + m_font_metrics.descent - el->height() + el->content_margins_top();
- break;
- }
- y1 = std::min(y1, el->top());
- y2 = std::max(y2, el->bottom());
- }
- }
-
- css_offsets offsets;
-
- for (const auto& el : m_items)
- {
- el->m_pos.y -= y1;
- el->m_pos.y += m_box_top;
- if(el->get_display() != display_inline_text)
- {
- switch(el->get_vertical_align())
- {
- case va_top:
- el->m_pos.y = m_box_top + el->content_margins_top();
- break;
- case va_bottom:
- el->m_pos.y = m_box_top + (y2 - y1) - el->height() + el->content_margins_top();
- break;
- case va_baseline:
- //TODO: process vertical align "baseline"
- break;
- case va_middle:
- //TODO: process vertical align "middle"
- break;
- case va_sub:
- //TODO: process vertical align "sub"
- break;
- case va_super:
- //TODO: process vertical align "super"
- break;
- case va_text_bottom:
- //TODO: process vertical align "text-bottom"
- break;
- case va_text_top:
- //TODO: process vertical align "text-top"
- break;
- }
- }
-
- el->apply_relative_shift(m_box_right - m_box_left);
- }
- m_height = y2 - y1;
- m_baseline = (base_line - y1) - (m_height - line_height);
-}
-
-bool litehtml::line_box::can_hold(const element::ptr &el, white_space ws)
-{
- if(!el->is_inline_box()) return false;
-
- if(el->is_break())
- {
- return false;
- }
-
- if(ws == white_space_nowrap || ws == white_space_pre)
- {
- return true;
- }
-
- if(m_box_left + m_width + el->width() + el->get_inline_shift_left() + el->get_inline_shift_right() > m_box_right)
- {
- return false;
- }
-
- return true;
-}
-
-bool litehtml::line_box::have_last_space()
-{
- bool ret = false;
- for (auto i = m_items.rbegin(); i != m_items.rend() && !ret; i++)
- {
- if((*i)->is_white_space() || (*i)->is_break())
- {
- ret = true;
- } else
- {
- break;
- }
- }
- return ret;
-}
-
-bool litehtml::line_box::is_empty()
-{
- if(m_items.empty()) return true;
- for (auto i = m_items.rbegin(); i != m_items.rend(); i++)
- {
- if(!(*i)->m_skip || (*i)->is_break())
- {
- return false;
- }
- }
- return true;
-}
-
-int litehtml::line_box::baseline()
-{
- return m_baseline;
-}
-
-void litehtml::line_box::get_elements( elements_vector& els )
-{
- els.insert(els.begin(), m_items.begin(), m_items.end());
-}
-
-int litehtml::line_box::top_margin()
-{
- return 0;
-}
-
-int litehtml::line_box::bottom_margin()
-{
- return 0;
-}
-
-void litehtml::line_box::y_shift( int shift )
-{
- m_box_top += shift;
- for (auto& el : m_items)
- {
- el->m_pos.y += shift;
- }
-}
-
-bool litehtml::line_box::is_break_only()
-{
- if(m_items.empty()) return true;
-
- if(m_items.front()->is_break())
- {
- for (auto& el : m_items)
- {
- if(!el->m_skip)
- {
- return false;
- }
- }
- return true;
- }
- return false;
-}
-
-void litehtml::line_box::new_width( int left, int right, elements_vector& els )
-{
- int add = left - m_box_left;
- if(add)
- {
- m_box_left = left;
- m_box_right = right;
- m_width = 0;
- auto remove_begin = m_items.end();
- for (auto i = m_items.begin() + 1; i != m_items.end(); i++)
- {
- element::ptr el = (*i);
-
- if(!el->m_skip)
- {
- if(m_box_left + m_width + el->width() + el->get_inline_shift_right() + el->get_inline_shift_left() > m_box_right)
- {
- remove_begin = i;
- break;
- } else
- {
- el->m_pos.x += add;
- m_width += el->width() + el->get_inline_shift_right() + el->get_inline_shift_left();
- }
- }
- }
- if(remove_begin != m_items.end())
- {
- els.insert(els.begin(), remove_begin, m_items.end());
- m_items.erase(remove_begin, m_items.end());
-
- for(const auto& el : els)
- {
- el->m_box = 0;
- }
- }
- }
-}
-
diff --git a/src/plugins/litehtml_viewer/litehtml/box.h b/src/plugins/litehtml_viewer/litehtml/box.h
deleted file mode 100644
index eeeea51c8..000000000
--- a/src/plugins/litehtml_viewer/litehtml/box.h
+++ /dev/null
@@ -1,120 +0,0 @@
-#ifndef LH_BOX_H
-#define LH_BOX_H
-
-namespace litehtml
-{
- class html_tag;
-
- enum box_type
- {
- box_block,
- box_line
- };
-
- class box
- {
- public:
- typedef std::unique_ptr<litehtml::box> ptr;
- typedef std::vector< box::ptr > vector;
- protected:
- int m_box_top;
- int m_box_left;
- int m_box_right;
- public:
- box(int top, int left, int right)
- {
- m_box_top = top;
- m_box_left = left;
- m_box_right = right;
- }
- virtual ~box() {}
-
- int bottom() { return m_box_top + height(); }
- int top() { return m_box_top; }
- int right() { return m_box_left + width(); }
- int left() { return m_box_left; }
-
- virtual litehtml::box_type get_type() = 0;
- virtual int height() = 0;
- virtual int width() = 0;
- virtual void add_element(const element::ptr &el) = 0;
- virtual bool can_hold(const element::ptr &el, white_space ws) = 0;
- virtual void finish(bool last_box = false) = 0;
- virtual bool is_empty() = 0;
- virtual int baseline() = 0;
- virtual void get_elements(elements_vector& els) = 0;
- virtual int top_margin() = 0;
- virtual int bottom_margin() = 0;
- virtual void y_shift(int shift) = 0;
- virtual void new_width(int left, int right, elements_vector& els) = 0;
- };
-
- //////////////////////////////////////////////////////////////////////////
-
- class block_box : public box
- {
- element::ptr m_element;
- public:
- block_box(int top, int left, int right) : box(top, left, right)
- {
- m_element = 0;
- }
-
- virtual litehtml::box_type get_type();
- virtual int height();
- virtual int width();
- virtual void add_element(const element::ptr &el);
- virtual bool can_hold(const element::ptr &el, white_space ws);
- virtual void finish(bool last_box = false);
- virtual bool is_empty();
- virtual int baseline();
- virtual void get_elements(elements_vector& els);
- virtual int top_margin();
- virtual int bottom_margin();
- virtual void y_shift(int shift);
- virtual void new_width(int left, int right, elements_vector& els);
- };
-
- //////////////////////////////////////////////////////////////////////////
-
- class line_box : public box
- {
- elements_vector m_items;
- int m_height;
- int m_width;
- int m_line_height;
- font_metrics m_font_metrics;
- int m_baseline;
- text_align m_text_align;
- public:
- line_box(int top, int left, int right, int line_height, font_metrics& fm, text_align align) : box(top, left, right)
- {
- m_height = 0;
- m_width = 0;
- m_font_metrics = fm;
- m_line_height = line_height;
- m_baseline = 0;
- m_text_align = align;
- }
-
- virtual litehtml::box_type get_type();
- virtual int height();
- virtual int width();
- virtual void add_element(const element::ptr &el);
- virtual bool can_hold(const element::ptr &el, white_space ws);
- virtual void finish(bool last_box = false);
- virtual bool is_empty();
- virtual int baseline();
- virtual void get_elements(elements_vector& els);
- virtual int top_margin();
- virtual int bottom_margin();
- virtual void y_shift(int shift);
- virtual void new_width(int left, int right, elements_vector& els);
-
- private:
- bool have_last_space();
- bool is_break_only();
- };
-}
-
-#endif // LH_BOX_H
diff --git a/src/plugins/litehtml_viewer/litehtml/codepoint.cpp b/src/plugins/litehtml_viewer/litehtml/codepoint.cpp
new file mode 100644
index 000000000..a89057022
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/codepoint.cpp
@@ -0,0 +1,82 @@
+// Copyright (C) 2020-2021 Primate Labs Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the names of the copyright holders nor the names of their
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "codepoint.h"
+
+#include <iostream>
+
+namespace {
+
+bool lookup(const uint32_t* table, char c)
+{
+ return table[c >> 5] & (1 << (c & 0x1f));
+}
+
+} // namespace
+
+namespace litehtml {
+
+bool is_ascii_codepoint(char c)
+{
+ return (c < 128);
+}
+
+// https://datatracker.ietf.org/doc/html/rfc3986#section-2.2
+bool is_url_reserved_codepoint(char c)
+{
+ static const uint32_t reserved_lookup[] = {
+ 0x00000000,
+ 0xac009fda,
+ 0x28000001,
+ 0x00000000
+ };
+
+ if (!is_ascii_codepoint(c)) {
+ return false;
+ }
+ return lookup(reserved_lookup, c);
+}
+
+// https://datatracker.ietf.org/doc/html/rfc3986#section-3.1
+bool is_url_scheme_codepoint(char c)
+{
+ static const uint32_t scheme_lookup[] = {
+ 0x00000000,
+ 0x03ff6800,
+ 0x07fffffe,
+ 0x07fffffe,
+ };
+
+ if (!is_ascii_codepoint(c)) {
+ return false;
+ }
+ return lookup(scheme_lookup, c);
+}
+
+} // namespace litehtml
diff --git a/src/plugins/litehtml_viewer/litehtml/codepoint.h b/src/plugins/litehtml_viewer/litehtml/codepoint.h
new file mode 100644
index 000000000..52dd49555
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/codepoint.h
@@ -0,0 +1,51 @@
+// Copyright (C) 2020-2021 Primate Labs Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the names of the copyright holders nor the names of their
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef LITEHTML_CODEPOINT_H__
+#define LITEHTML_CODEPOINT_H__
+
+#include <string>
+
+#include "os_types.h"
+
+namespace litehtml {
+
+bool is_ascii_codepoint(char c);
+
+// Returns true if the codepoint is a reserved codepoint for URLs.
+// https://datatracker.ietf.org/doc/html/rfc3986#section-2.2
+bool is_url_reserved_codepoint(char c);
+
+// Returns true if the codepoint is a scheme codepoint for URLs.
+// https://datatracker.ietf.org/doc/html/rfc3986#section-3.1
+bool is_url_scheme_codepoint(char c);
+
+} // namespace litehtml
+
+#endif // LITEHTML_CODEPOINT_H__
diff --git a/src/plugins/litehtml_viewer/litehtml/context.cpp b/src/plugins/litehtml_viewer/litehtml/context.cpp
deleted file mode 100644
index 4cea5d3d8..000000000
--- a/src/plugins/litehtml_viewer/litehtml/context.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "html.h"
-#include "context.h"
-#include "stylesheet.h"
-
-
-void litehtml::context::load_master_stylesheet( const tchar_t* str )
-{
- media_query_list::ptr media;
-
- m_master_css.parse_stylesheet(str, 0, std::shared_ptr<litehtml::document>(), media_query_list::ptr());
- m_master_css.sort_selectors();
-}
diff --git a/src/plugins/litehtml_viewer/litehtml/context.h b/src/plugins/litehtml_viewer/litehtml/context.h
deleted file mode 100644
index b6450f8f5..000000000
--- a/src/plugins/litehtml_viewer/litehtml/context.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef LH_CONTEXT_H
-#define LH_CONTEXT_H
-
-#include "stylesheet.h"
-
-namespace litehtml
-{
- class context
- {
- litehtml::css m_master_css;
- public:
- void load_master_stylesheet(const tchar_t* str);
- litehtml::css& master_css()
- {
- return m_master_css;
- }
- };
-}
-
-#endif // LH_CONTEXT_H
diff --git a/src/plugins/litehtml_viewer/litehtml/css_borders.cpp b/src/plugins/litehtml_viewer/litehtml/css_borders.cpp
new file mode 100644
index 000000000..478e9df5b
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/css_borders.cpp
@@ -0,0 +1,7 @@
+#include "html.h"
+#include "borders.h"
+
+litehtml::string litehtml::css_border::to_string() const
+{
+ return width.to_string() + "/" + index_value(style, border_style_strings) + "/" + color.to_string();
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/css_length.cpp b/src/plugins/litehtml_viewer/litehtml/css_length.cpp
index 472cd546b..d1c69d261 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_length.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/css_length.cpp
@@ -1,17 +1,17 @@
#include "html.h"
#include "css_length.h"
-void litehtml::css_length::fromString( const tstring& str, const tstring& predefs, int defValue )
+void litehtml::css_length::fromString( const string& str, const string& predefs, int defValue )
{
// TODO: Make support for calc
- if(str.substr(0, 4) == _t("calc"))
+ if(str.substr(0, 4) == "calc")
{
m_is_predefined = true;
- m_predef = 0;
+ m_predef = defValue;
return;
}
- int predef = value_index(str.c_str(), predefs.c_str(), -1);
+ int predef = value_index(str, predefs, -1);
if(predef >= 0)
{
m_is_predefined = true;
@@ -20,16 +20,16 @@ void litehtml::css_length::fromString( const tstring& str, const tstring& predef
{
m_is_predefined = false;
- tstring num;
- tstring un;
+ string num;
+ string un;
bool is_unit = false;
- for(tstring::const_iterator chr = str.begin(); chr != str.end(); chr++)
+ for(char chr : str)
{
if(!is_unit)
{
- if(t_isdigit(*chr) || *chr == _t('.') || *chr == _t('+') || *chr == _t('-'))
+ if(t_isdigit(chr) || chr == '.' || chr == '+' || chr == '-')
{
- num += *chr;
+ num += chr;
} else
{
is_unit = true;
@@ -37,13 +37,13 @@ void litehtml::css_length::fromString( const tstring& str, const tstring& predef
}
if(is_unit)
{
- un += *chr;
+ un += chr;
}
}
if(!num.empty())
{
- m_value = (float) t_strtod(num.c_str(), 0);
- m_units = (css_units) value_index(un.c_str(), css_units_strings, css_units_none);
+ m_value = t_strtof(num);
+ m_units = (css_units) value_index(un, css_units_strings, css_units_none);
} else
{
// not a number so it is predefined
@@ -52,3 +52,26 @@ void litehtml::css_length::fromString( const tstring& str, const tstring& predef
}
}
}
+
+litehtml::css_length litehtml::css_length::from_string(const string& str, const string& predefs, int defValue)
+{
+ css_length len;
+ len.fromString(str, predefs, defValue);
+ return len;
+}
+
+litehtml::string litehtml::css_length::to_string() const
+{
+ if(m_is_predefined)
+ {
+ return "def(" + std::to_string(m_predef) + ")";
+ }
+ return std::to_string(m_value) + "{" + index_value(m_units, css_units_strings) + "}";
+}
+
+litehtml::css_length litehtml::css_length::predef_value(int val)
+{
+ css_length len;
+ len.predef(val);
+ return len;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/css_length.h b/src/plugins/litehtml_viewer/litehtml/css_length.h
index 13a3d77b7..ae787105a 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_length.h
+++ b/src/plugins/litehtml_viewer/litehtml/css_length.h
@@ -16,20 +16,24 @@ namespace litehtml
bool m_is_predefined;
public:
css_length();
- css_length(const css_length& val);
-
- css_length& operator=(const css_length& val);
+ css_length(float val, css_units units = css_units_px);
css_length& operator=(float val);
+
bool is_predefined() const;
void predef(int val);
int predef() const;
+ static css_length predef_value(int val = 0);
void set_value(float val, css_units units);
float val() const;
css_units units() const;
int calc_percent(int width) const;
- void fromString(const tstring& str, const tstring& predefs = _t(""), int defValue = 0);
+ void fromString(const string& str, const string& predefs = "", int defValue = 0);
+ static css_length from_string(const string& str, const string& predefs = "", int defValue = 0);
+ string to_string() const;
};
+ using length_vector = std::vector<css_length>;
+
// css_length inlines
inline css_length::css_length()
@@ -40,31 +44,11 @@ namespace litehtml
m_is_predefined = false;
}
- inline css_length::css_length(const css_length& val)
+ inline css_length::css_length(float val, css_units units)
{
- if(val.is_predefined())
- {
- m_predef = val.m_predef;
- } else
- {
- m_value = val.m_value;
- }
- m_units = val.m_units;
- m_is_predefined = val.m_is_predefined;
- }
-
- inline css_length& css_length::operator=(const css_length& val)
- {
- if(val.is_predefined())
- {
- m_predef = val.m_predef;
- } else
- {
- m_value = val.m_value;
- }
- m_units = val.m_units;
- m_is_predefined = val.m_is_predefined;
- return *this;
+ m_value = val;
+ m_units = units;
+ m_is_predefined = false;
}
inline css_length& css_length::operator=(float val)
@@ -95,7 +79,7 @@ namespace litehtml
return 0;
}
- inline void css_length::set_value(float val, css_units units)
+ inline void css_length::set_value(float val, css_units units)
{
m_value = val;
m_is_predefined = false;
diff --git a/src/plugins/litehtml_viewer/litehtml/css_margins.h b/src/plugins/litehtml_viewer/litehtml/css_margins.h
index 5c99a8b26..17dc7698d 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_margins.h
+++ b/src/plugins/litehtml_viewer/litehtml/css_margins.h
@@ -12,10 +12,7 @@ namespace litehtml
css_length top;
css_length bottom;
- css_margins()
- {
-
- }
+ css_margins() = default;
css_margins(const css_margins& val)
{
@@ -33,6 +30,14 @@ namespace litehtml
bottom = val.bottom;
return *this;
}
+
+ string to_string() const
+ {
+ return "left: " + left.to_string() +
+ ", right: " + right.to_string() +
+ ", top: " + top.to_string() +
+ ", bottom: " + bottom.to_string();
+ }
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/css_offsets.h b/src/plugins/litehtml_viewer/litehtml/css_offsets.h
index 18d7f2652..5ab175ce2 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_offsets.h
+++ b/src/plugins/litehtml_viewer/litehtml/css_offsets.h
@@ -12,10 +12,7 @@ namespace litehtml
css_length right;
css_length bottom;
- css_offsets()
- {
-
- }
+ css_offsets() = default;
css_offsets(const css_offsets& val)
{
@@ -33,6 +30,14 @@ namespace litehtml
bottom = val.bottom;
return *this;
}
+
+ string to_string() const
+ {
+ return "left: " + left.to_string() +
+ ", top: " + top.to_string() +
+ ", right: " + right.to_string() +
+ ", bottom: " + bottom.to_string();
+ }
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/css_position.h b/src/plugins/litehtml_viewer/litehtml/css_position.h
index 308a14fee..978a81ab5 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_position.h
+++ b/src/plugins/litehtml_viewer/litehtml/css_position.h
@@ -11,29 +11,18 @@ namespace litehtml
css_length y;
css_length width;
css_length height;
+ };
- css_position()
- {
-
- }
-
- css_position(const css_position& val)
- {
- x = val.x;
- y = val.y;
- width = val.width;
- height = val.height;
- }
+ struct css_size
+ {
+ css_length width;
+ css_length height;
- css_position& operator=(const css_position& val)
- {
- x = val.x;
- y = val.y;
- width = val.width;
- height = val.height;
- return *this;
- }
+ css_size() = default;
+ css_size(css_length width, css_length height) : width(width), height(height) {}
};
+
+ using size_vector = std::vector<css_size>;
}
#endif // LH_CSS_POSITION_H
diff --git a/src/plugins/litehtml_viewer/litehtml/css_properties.cpp b/src/plugins/litehtml_viewer/litehtml/css_properties.cpp
new file mode 100644
index 000000000..1efccb609
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/css_properties.cpp
@@ -0,0 +1,456 @@
+#include "html.h"
+#include "css_properties.h"
+
+#define offset(member) ((uint_ptr)&this->member - (uint_ptr)this)
+
+void litehtml::css_properties::compute(const element* el, const document::ptr& doc)
+{
+ compute_font(el, doc);
+ int font_size = get_font_size();
+ m_color = el->get_color_property(_color_, true, web_color::black, offset(m_color));
+
+ m_el_position = (element_position) el->get_enum_property( _position_, false, element_position_static, offset(m_el_position));
+ m_display = (style_display) el->get_enum_property( _display_, false, display_inline, offset(m_display));
+ m_visibility = (visibility) el->get_enum_property( _visibility_, true, visibility_visible, offset(m_visibility));
+ m_float = (element_float) el->get_enum_property( _float_, false, float_none, offset(m_float));
+ m_clear = (element_clear) el->get_enum_property( _clear_, false, clear_none, offset(m_clear));
+ m_box_sizing = (box_sizing) el->get_enum_property( _box_sizing_, false, box_sizing_content_box, offset(m_box_sizing));
+ m_overflow = (overflow) el->get_enum_property( _overflow_, false, overflow_visible, offset(m_overflow));
+ m_text_align = (text_align) el->get_enum_property( _text_align_, true, text_align_left, offset(m_text_align));
+ 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));
+
+ // https://www.w3.org/TR/CSS22/visuren.html#dis-pos-flo
+ if (m_display == display_none)
+ {
+ // 1. If 'display' has the value 'none', then 'position' and 'float' do not apply. In this case, the element
+ // generates no box.
+ m_float = float_none;
+ } else
+ {
+ // 2. Otherwise, if 'position' has the value 'absolute' or 'fixed', the box is absolutely positioned,
+ // the computed value of 'float' is 'none', and display is set according to the table below.
+ // The position of the box will be determined by the 'top', 'right', 'bottom' and 'left' properties
+ // and the box's containing block.
+ if (m_el_position == element_position_absolute || m_el_position == element_position_fixed)
+ {
+ m_float = float_none;
+
+ if (m_display == display_inline_table)
+ {
+ m_display = display_table;
+ } else if (m_display == display_inline ||
+ m_display == display_table_row_group ||
+ m_display == display_table_column ||
+ m_display == display_table_column_group ||
+ m_display == display_table_header_group ||
+ m_display == display_table_footer_group ||
+ m_display == display_table_row ||
+ m_display == display_table_cell ||
+ m_display == display_table_caption ||
+ m_display == display_inline_block)
+ {
+ m_display = display_block;
+ }
+ } else if (m_float != float_none)
+ {
+ // 3. Otherwise, if 'float' has a value other than 'none', the box is floated and 'display' is set
+ // according to the table below.
+ if (m_display == display_inline_table)
+ {
+ m_display = display_table;
+ } else if (m_display == display_inline ||
+ m_display == display_table_row_group ||
+ m_display == display_table_column ||
+ m_display == display_table_column_group ||
+ m_display == display_table_header_group ||
+ m_display == display_table_footer_group ||
+ m_display == display_table_row ||
+ m_display == display_table_cell ||
+ m_display == display_table_caption ||
+ m_display == display_inline_block)
+ {
+ m_display = display_block;
+ }
+ } else if(el->is_root())
+ {
+ // 4. Otherwise, if the element is the root element, 'display' is set according to the table below,
+ // except that it is undefined in CSS 2.2 whether a specified value of 'list-item' becomes a
+ // computed value of 'block' or 'list-item'.
+ if (m_display == display_inline_table)
+ {
+ m_display = display_table;
+ } else if (m_display == display_inline ||
+ m_display == display_table_row_group ||
+ m_display == display_table_column ||
+ m_display == display_table_column_group ||
+ m_display == display_table_header_group ||
+ m_display == display_table_footer_group ||
+ m_display == display_table_row ||
+ m_display == display_table_cell ||
+ m_display == display_table_caption ||
+ m_display == display_inline_block ||
+ m_display == display_list_item)
+ {
+ m_display = display_block;
+ }
+ }
+ }
+ // 5. Otherwise, the remaining 'display' property values apply as specified.
+
+ const css_length _auto = css_length::predef_value(0);
+ const css_length none = _auto, normal = _auto;
+
+ m_css_width = el->get_length_property(_width_, false, _auto, offset(m_css_width));
+ m_css_height = el->get_length_property(_height_, false, _auto, offset(m_css_height));
+
+ m_css_min_width = el->get_length_property(_min_width_, false, _auto, offset(m_css_min_width));
+ m_css_min_height = el->get_length_property(_min_height_, false, _auto, offset(m_css_min_height));
+
+ m_css_max_width = el->get_length_property(_max_width_, false, none, offset(m_css_max_width));
+ m_css_max_height = el->get_length_property(_max_height_, false, none, offset(m_css_max_height));
+
+ doc->cvt_units(m_css_width, font_size);
+ doc->cvt_units(m_css_height, font_size);
+
+ doc->cvt_units(m_css_min_width, font_size);
+ doc->cvt_units(m_css_min_height, font_size);
+
+ doc->cvt_units(m_css_max_width, font_size);
+ doc->cvt_units(m_css_max_height, font_size);
+
+ m_css_margins.left = el->get_length_property(_margin_left_, false, 0, offset(m_css_margins.left));
+ m_css_margins.right = el->get_length_property(_margin_right_, false, 0, offset(m_css_margins.right));
+ m_css_margins.top = el->get_length_property(_margin_top_, false, 0, offset(m_css_margins.top));
+ m_css_margins.bottom = el->get_length_property(_margin_bottom_, false, 0, offset(m_css_margins.bottom));
+
+ doc->cvt_units(m_css_margins.left, font_size);
+ doc->cvt_units(m_css_margins.right, font_size);
+ doc->cvt_units(m_css_margins.top, font_size);
+ doc->cvt_units(m_css_margins.bottom, font_size);
+
+ m_css_padding.left = el->get_length_property(_padding_left_, false, 0, offset(m_css_padding.left));
+ m_css_padding.right = el->get_length_property(_padding_right_, false, 0, offset(m_css_padding.right));
+ m_css_padding.top = el->get_length_property(_padding_top_, false, 0, offset(m_css_padding.top));
+ m_css_padding.bottom = el->get_length_property(_padding_bottom_, false, 0, offset(m_css_padding.bottom));
+
+ doc->cvt_units(m_css_padding.left, font_size);
+ doc->cvt_units(m_css_padding.right, font_size);
+ doc->cvt_units(m_css_padding.top, font_size);
+ doc->cvt_units(m_css_padding.bottom, font_size);
+
+ m_css_borders.left.color = el->get_color_property(_border_left_color_, false, m_color, offset(m_css_borders.left.color));
+ m_css_borders.right.color = el->get_color_property(_border_right_color_, false, m_color, offset(m_css_borders.right.color));
+ m_css_borders.top.color = el->get_color_property(_border_top_color_, false, m_color, offset(m_css_borders.top.color));
+ m_css_borders.bottom.color = el->get_color_property(_border_bottom_color_, false, m_color, offset(m_css_borders.bottom.color));
+
+ m_css_borders.left.style = (border_style) el->get_enum_property(_border_left_style_, false, border_style_none, offset(m_css_borders.left.style));
+ m_css_borders.right.style = (border_style) el->get_enum_property(_border_right_style_, false, border_style_none, offset(m_css_borders.right.style));
+ m_css_borders.top.style = (border_style) el->get_enum_property(_border_top_style_, false, border_style_none, offset(m_css_borders.top.style));
+ m_css_borders.bottom.style = (border_style) el->get_enum_property(_border_bottom_style_, false, border_style_none, offset(m_css_borders.bottom.style));
+
+ m_css_borders.left.width = el->get_length_property(_border_left_width_, false, border_width_medium_value, offset(m_css_borders.left.width));
+ m_css_borders.right.width = el->get_length_property(_border_right_width_, false, border_width_medium_value, offset(m_css_borders.right.width));
+ m_css_borders.top.width = el->get_length_property(_border_top_width_, false, border_width_medium_value, offset(m_css_borders.top.width));
+ m_css_borders.bottom.width = el->get_length_property(_border_bottom_width_, false, border_width_medium_value, offset(m_css_borders.bottom.width));
+
+ if (m_css_borders.left.style == border_style_none || m_css_borders.left.style == border_style_hidden)
+ m_css_borders.left.width = 0;
+ if (m_css_borders.right.style == border_style_none || m_css_borders.right.style == border_style_hidden)
+ m_css_borders.right.width = 0;
+ if (m_css_borders.top.style == border_style_none || m_css_borders.top.style == border_style_hidden)
+ m_css_borders.top.width = 0;
+ if (m_css_borders.bottom.style == border_style_none || m_css_borders.bottom.style == border_style_hidden)
+ m_css_borders.bottom.width = 0;
+
+ doc->cvt_units(m_css_borders.left.width, font_size);
+ doc->cvt_units(m_css_borders.right.width, font_size);
+ doc->cvt_units(m_css_borders.top.width, font_size);
+ doc->cvt_units(m_css_borders.bottom.width, font_size);
+
+ m_css_borders.radius.top_left_x = el->get_length_property(_border_top_left_radius_x_, false, 0, offset(m_css_borders.radius.top_left_x));
+ m_css_borders.radius.top_left_y = el->get_length_property(_border_top_left_radius_y_, false, 0, offset(m_css_borders.radius.top_left_y));
+
+ m_css_borders.radius.top_right_x = el->get_length_property(_border_top_right_radius_x_, false, 0, offset(m_css_borders.radius.top_right_x));
+ m_css_borders.radius.top_right_y = el->get_length_property(_border_top_right_radius_y_, false, 0, offset(m_css_borders.radius.top_right_y));
+
+ m_css_borders.radius.bottom_left_x = el->get_length_property(_border_bottom_left_radius_x_, false, 0, offset(m_css_borders.radius.bottom_left_x));
+ m_css_borders.radius.bottom_left_y = el->get_length_property(_border_bottom_left_radius_y_, false, 0, offset(m_css_borders.radius.bottom_left_y));
+
+ m_css_borders.radius.bottom_right_x = el->get_length_property(_border_bottom_right_radius_x_, false, 0, offset(m_css_borders.radius.bottom_right_x));
+ m_css_borders.radius.bottom_right_y = el->get_length_property(_border_bottom_right_radius_y_, false, 0, offset(m_css_borders.radius.bottom_right_y));
+
+ doc->cvt_units( m_css_borders.radius.top_left_x, font_size);
+ doc->cvt_units( m_css_borders.radius.top_left_y, font_size);
+ doc->cvt_units( m_css_borders.radius.top_right_x, font_size);
+ doc->cvt_units( m_css_borders.radius.top_right_y, font_size);
+ doc->cvt_units( m_css_borders.radius.bottom_left_x, font_size);
+ doc->cvt_units( m_css_borders.radius.bottom_left_y, font_size);
+ doc->cvt_units( m_css_borders.radius.bottom_right_x, font_size);
+ doc->cvt_units( m_css_borders.radius.bottom_right_y, font_size);
+
+ m_border_collapse = (border_collapse) el->get_enum_property(_border_collapse_, true, border_collapse_separate, offset(m_border_collapse));
+
+ m_css_border_spacing_x = el->get_length_property(__litehtml_border_spacing_x_, true, 0, offset(m_css_border_spacing_x));
+ m_css_border_spacing_y = el->get_length_property(__litehtml_border_spacing_y_, true, 0, offset(m_css_border_spacing_y));
+
+ doc->cvt_units(m_css_border_spacing_x, font_size);
+ doc->cvt_units(m_css_border_spacing_y, font_size);
+
+ m_css_offsets.left = el->get_length_property(_left_, false, _auto, offset(m_css_offsets.left));
+ m_css_offsets.right = el->get_length_property(_right_, false, _auto, offset(m_css_offsets.right));
+ m_css_offsets.top = el->get_length_property(_top_, false, _auto, offset(m_css_offsets.top));
+ m_css_offsets.bottom = el->get_length_property(_bottom_,false, _auto, offset(m_css_offsets.bottom));
+
+ doc->cvt_units(m_css_offsets.left, font_size);
+ doc->cvt_units(m_css_offsets.right, font_size);
+ doc->cvt_units(m_css_offsets.top, font_size);
+ doc->cvt_units(m_css_offsets.bottom, font_size);
+
+ m_z_index = el->get_length_property(_z_index_, false, _auto, offset(m_z_index));
+ m_content = el->get_string_property(_content_, false, "", offset(m_content));
+ m_cursor = el->get_string_property(_cursor_, true, "auto", offset(m_cursor));
+
+ m_css_text_indent = el->get_length_property(_text_indent_, true, 0, offset(m_css_text_indent));
+ doc->cvt_units(m_css_text_indent, font_size);
+
+ m_css_line_height = el->get_length_property(_line_height_, true, normal, offset(m_css_line_height));
+ if(m_css_line_height.is_predefined())
+ {
+ 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);
+ } else
+ {
+ m_line_height = doc->to_pixels(m_css_line_height, font_size, font_size);
+ m_css_line_height = (float) m_line_height;
+ }
+
+ m_list_style_type = (list_style_type) el->get_enum_property(_list_style_type_, true, list_style_type_disc, offset(m_list_style_type));
+ m_list_style_position = (list_style_position) el->get_enum_property(_list_style_position_, true, list_style_position_outside, offset(m_list_style_position));
+
+ m_list_style_image = el->get_string_property(_list_style_image_, true, "", offset(m_list_style_image));
+ if (!m_list_style_image.empty())
+ {
+ m_list_style_image_baseurl = el->get_string_property(_list_style_image_baseurl_, true, "", offset(m_list_style_image_baseurl));
+ doc->container()->load_image(m_list_style_image.c_str(), m_list_style_image_baseurl.c_str(), true);
+ }
+
+ compute_background(el, doc);
+ compute_flex(el, doc);
+}
+
+static const int font_size_table[8][7] =
+{
+ { 9, 9, 9, 9, 11, 14, 18},
+ { 9, 9, 9, 10, 12, 15, 20},
+ { 9, 9, 9, 11, 13, 17, 22},
+ { 9, 9, 10, 12, 14, 18, 24},
+ { 9, 9, 10, 13, 16, 20, 26},
+ { 9, 9, 11, 14, 17, 21, 28},
+ { 9, 10, 12, 15, 17, 23, 30},
+ { 9, 10, 13, 16, 18, 24, 32}
+};
+
+void litehtml::css_properties::compute_font(const element* el, const document::ptr& doc)
+{
+ // initialize font size
+ css_length sz = el->get_length_property(_font_size_, true, css_length::predef_value(font_size_medium), offset(m_font_size));
+
+ int parent_sz = 0;
+ int doc_font_size = doc->container()->get_default_font_size();
+ element::ptr el_parent = el->parent();
+ if (el_parent)
+ {
+ parent_sz = el_parent->css().get_font_size();
+ } else
+ {
+ parent_sz = doc_font_size;
+ }
+
+ int font_size = parent_sz;
+
+ if(sz.is_predefined())
+ {
+ int idx_in_table = doc_font_size - 9;
+ if(idx_in_table >= 0 && idx_in_table <= 7)
+ {
+ if(sz.predef() >= font_size_xx_small && sz.predef() <= font_size_xx_large)
+ {
+ font_size = font_size_table[idx_in_table][sz.predef()];
+ } else if(sz.predef() == font_size_smaller)
+ {
+ font_size = (int) (parent_sz / 1.2);
+ } else if(sz.predef() == font_size_larger)
+ {
+ font_size = (int) (parent_sz * 1.2);
+ } else
+ {
+ font_size = parent_sz;
+ }
+ } else
+ {
+ switch(sz.predef())
+ {
+ case font_size_xx_small:
+ font_size = doc_font_size * 3 / 5;
+ break;
+ case font_size_x_small:
+ font_size = doc_font_size * 3 / 4;
+ break;
+ case font_size_small:
+ font_size = doc_font_size * 8 / 9;
+ break;
+ case font_size_large:
+ font_size = doc_font_size * 6 / 5;
+ break;
+ case font_size_x_large:
+ font_size = doc_font_size * 3 / 2;
+ break;
+ case font_size_xx_large:
+ font_size = doc_font_size * 2;
+ break;
+ case font_size_smaller:
+ font_size = (int) (parent_sz / 1.2);
+ break;
+ case font_size_larger:
+ font_size = (int) (parent_sz * 1.2);
+ break;
+ default:
+ font_size = parent_sz;
+ break;
+ }
+ }
+ } else
+ {
+ if(sz.units() == css_units_percentage)
+ {
+ font_size = sz.calc_percent(parent_sz);
+ } else
+ {
+ font_size = doc->to_pixels(sz, parent_sz);
+ }
+ }
+
+ m_font_size = (float)font_size;
+
+ // initialize font
+ m_font_family = el->get_string_property(_font_family_, true, doc->container()->get_default_font_name(), offset(m_font_family));
+ m_font_weight = (font_weight) el->get_enum_property( _font_weight_, true, font_weight_normal, offset(m_font_weight));
+ m_font_style = (font_style) el->get_enum_property( _font_style_, true, font_style_normal, offset(m_font_style));
+ m_text_decoration = el->get_string_property(_text_decoration_, true, "none", offset(m_text_decoration));
+
+ m_font = doc->get_font(
+ m_font_family.c_str(),
+ font_size,
+ index_value(m_font_weight, font_weight_strings).c_str(),
+ index_value(m_font_style, font_style_strings).c_str(),
+ m_text_decoration.c_str(),
+ &m_font_metrics);
+}
+
+void litehtml::css_properties::compute_background(const element* el, const document::ptr& doc)
+{
+ int font_size = get_font_size();
+
+ m_bg.m_color = el->get_color_property(_background_color_, false, web_color::transparent, offset(m_bg.m_color));
+
+ const css_size auto_auto(css_length::predef_value(background_size_auto), css_length::predef_value(background_size_auto));
+ m_bg.m_position_x = el->get_length_vector_property(_background_position_x_, false, { css_length(0, css_units_percentage) }, offset(m_bg.m_position_x));
+ m_bg.m_position_y = el->get_length_vector_property(_background_position_y_, false, { css_length(0, css_units_percentage) }, offset(m_bg.m_position_y));
+ m_bg.m_size = el->get_size_vector_property (_background_size_, false, { auto_auto }, offset(m_bg.m_size));
+
+ for (auto& x : m_bg.m_position_x) doc->cvt_units(x, font_size);
+ for (auto& y : m_bg.m_position_y) doc->cvt_units(y, font_size);
+ for (auto& size : m_bg.m_size)
+ {
+ doc->cvt_units(size.width, font_size);
+ doc->cvt_units(size.height, font_size);
+ }
+
+ m_bg.m_attachment = el->get_int_vector_property(_background_attachment_, false, { background_attachment_scroll }, offset(m_bg.m_attachment));
+ m_bg.m_repeat = el->get_int_vector_property(_background_repeat_, false, { background_repeat_repeat }, offset(m_bg.m_repeat));
+ m_bg.m_clip = el->get_int_vector_property(_background_clip_, false, { background_box_border }, offset(m_bg.m_clip));
+ m_bg.m_origin = el->get_int_vector_property(_background_origin_, false, { background_box_padding }, offset(m_bg.m_origin));
+
+ m_bg.m_image = el->get_string_vector_property(_background_image_, false, {""}, offset(m_bg.m_image));
+ m_bg.m_baseurl = el->get_string_property(_background_image_baseurl_, false, "", offset(m_bg.m_baseurl));
+
+ for (const auto& image : m_bg.m_image)
+ {
+ if (!image.empty())
+ {
+ doc->container()->load_image(image.c_str(), m_bg.m_baseurl.c_str(), true);
+ }
+ }
+}
+
+void litehtml::css_properties::compute_flex(const element* el, const document::ptr& doc)
+{
+ if (m_display == display_flex)
+ {
+ m_flex_direction = (flex_direction) el->get_enum_property(_flex_direction_, false, flex_direction_row, offset(m_flex_direction));
+ m_flex_wrap = (flex_wrap) el->get_enum_property(_flex_wrap_, false, flex_wrap_nowrap, offset(m_flex_wrap));
+
+ m_flex_justify_content = (flex_justify_content) el->get_enum_property(_justify_content_, false, flex_justify_content_flex_start, offset(m_flex_justify_content));
+ m_flex_align_items = (flex_align_items) el->get_enum_property(_align_items_, false, flex_align_items_stretch, offset(m_flex_align_items));
+ m_flex_align_content = (flex_align_content) el->get_enum_property(_align_content_, false, flex_align_content_stretch, offset(m_flex_align_content));
+ }
+ auto parent = el->parent();
+ if (parent && parent->css().m_display == display_flex)
+ {
+ m_flex_grow = el->get_number_property(_flex_grow_, false, 0, offset(m_flex_grow));
+ m_flex_shrink = el->get_number_property(_flex_shrink_, false, 1, offset(m_flex_shrink));
+ m_flex_align_self = (flex_align_self) el->get_enum_property(_align_self_, false, flex_align_self_auto, offset(m_flex_align_self));
+ m_flex_basis = el->get_length_property(_flex_shrink_, false, css_length::predef_value(flex_basis_auto), offset(m_flex_basis));
+ doc->cvt_units(m_flex_basis, get_font_size());
+ if(m_display == display_inline || m_display == display_inline_block)
+ {
+ m_display = display_block;
+ } else if(m_display == display_inline_table)
+ {
+ m_display = display_table;
+ } else if(m_display == display_inline_flex)
+ {
+ m_display = display_flex;
+ }
+ }
+}
+
+std::vector<std::tuple<litehtml::string, litehtml::string>> litehtml::css_properties::dump_get_attrs()
+{
+ std::vector<std::tuple<string, string>> ret;
+
+ ret.emplace_back(std::make_tuple("display", index_value(m_display, style_display_strings)));
+ ret.emplace_back(std::make_tuple("el_position", index_value(m_el_position, element_position_strings)));
+ ret.emplace_back(std::make_tuple("text_align", index_value(m_text_align, text_align_strings)));
+ ret.emplace_back(std::make_tuple("font_size", m_font_size.to_string()));
+ ret.emplace_back(std::make_tuple("overflow", index_value(m_overflow, overflow_strings)));
+ ret.emplace_back(std::make_tuple("white_space", index_value(m_white_space, white_space_strings)));
+ ret.emplace_back(std::make_tuple("visibility", index_value(m_visibility, visibility_strings)));
+ ret.emplace_back(std::make_tuple("box_sizing", index_value(m_box_sizing, box_sizing_strings)));
+ ret.emplace_back(std::make_tuple("z_index", m_z_index.to_string()));
+ ret.emplace_back(std::make_tuple("vertical_align", index_value(m_vertical_align, vertical_align_strings)));
+ ret.emplace_back(std::make_tuple("float", index_value(m_float, element_float_strings)));
+ ret.emplace_back(std::make_tuple("clear", index_value(m_clear, element_clear_strings)));
+ ret.emplace_back(std::make_tuple("margins", m_css_margins.to_string()));
+ ret.emplace_back(std::make_tuple("padding", m_css_padding.to_string()));
+ ret.emplace_back(std::make_tuple("borders", m_css_borders.to_string()));
+ ret.emplace_back(std::make_tuple("width", m_css_width.to_string()));
+ ret.emplace_back(std::make_tuple("height", m_css_height.to_string()));
+ ret.emplace_back(std::make_tuple("min_width", m_css_min_width.to_string()));
+ ret.emplace_back(std::make_tuple("min_height", m_css_min_width.to_string()));
+ ret.emplace_back(std::make_tuple("max_width", m_css_max_width.to_string()));
+ ret.emplace_back(std::make_tuple("max_height", m_css_max_width.to_string()));
+ ret.emplace_back(std::make_tuple("offsets", m_css_offsets.to_string()));
+ ret.emplace_back(std::make_tuple("text_indent", m_css_text_indent.to_string()));
+ ret.emplace_back(std::make_tuple("line_height", std::to_string(m_line_height)));
+ ret.emplace_back(std::make_tuple("list_style_type", index_value(m_list_style_type, list_style_type_strings)));
+ ret.emplace_back(std::make_tuple("list_style_position", index_value(m_list_style_position, list_style_position_strings)));
+ ret.emplace_back(std::make_tuple("border_spacing_x", m_css_border_spacing_x.to_string()));
+ ret.emplace_back(std::make_tuple("border_spacing_y", m_css_border_spacing_y.to_string()));
+
+ return ret;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/css_properties.h b/src/plugins/litehtml_viewer/litehtml/css_properties.h
new file mode 100644
index 000000000..0eed09d9a
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/css_properties.h
@@ -0,0 +1,643 @@
+#ifndef LITEHTML_CSS_PROPERTIES_H
+#define LITEHTML_CSS_PROPERTIES_H
+
+#include "os_types.h"
+#include "types.h"
+#include "css_margins.h"
+#include "borders.h"
+#include "css_offsets.h"
+#include "background.h"
+
+namespace litehtml
+{
+ class element;
+ class document;
+
+ class css_properties
+ {
+ private:
+ element_position m_el_position;
+ text_align m_text_align;
+ overflow m_overflow;
+ white_space m_white_space;
+ style_display m_display;
+ visibility m_visibility;
+ box_sizing m_box_sizing;
+ css_length m_z_index;
+ vertical_align m_vertical_align;
+ element_float m_float;
+ element_clear m_clear;
+ css_margins m_css_margins;
+ css_margins m_css_padding;
+ css_borders m_css_borders;
+ css_length m_css_width;
+ css_length m_css_height;
+ css_length m_css_min_width;
+ css_length m_css_min_height;
+ css_length m_css_max_width;
+ css_length m_css_max_height;
+ css_offsets m_css_offsets;
+ css_length m_css_text_indent;
+ css_length m_css_line_height;
+ int m_line_height;
+ list_style_type m_list_style_type;
+ list_style_position m_list_style_position;
+ string m_list_style_image;
+ string m_list_style_image_baseurl;
+ background m_bg;
+ uint_ptr m_font;
+ css_length m_font_size;
+ string m_font_family;
+ font_weight m_font_weight;
+ font_style m_font_style;
+ string m_text_decoration;
+ font_metrics m_font_metrics;
+ text_transform m_text_transform;
+ web_color m_color;
+ string m_cursor;
+ string m_content;
+ border_collapse m_border_collapse;
+ css_length m_css_border_spacing_x;
+ css_length m_css_border_spacing_y;
+
+ float m_flex_grow;
+ float m_flex_shrink;
+ css_length m_flex_basis;
+ flex_direction m_flex_direction;
+ flex_wrap m_flex_wrap;
+ flex_justify_content m_flex_justify_content;
+ flex_align_items m_flex_align_items;
+ flex_align_self m_flex_align_self;
+ flex_align_content m_flex_align_content;
+
+ 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);
+ void compute_flex(const element* el, const std::shared_ptr<document>& doc);
+
+ public:
+ css_properties() :
+ m_el_position(element_position_static),
+ m_text_align(text_align_left),
+ m_overflow(overflow_visible),
+ m_white_space(white_space_normal),
+ m_display(display_inline),
+ m_visibility(visibility_visible),
+ m_box_sizing(box_sizing_content_box),
+ m_z_index(0),
+ m_vertical_align(va_baseline),
+ m_float(float_none),
+ m_clear(clear_none),
+ m_css_margins(),
+ m_css_padding(),
+ m_css_borders(),
+ m_css_width(),
+ m_css_height(),
+ m_css_min_width(),
+ m_css_min_height(),
+ m_css_max_width(),
+ m_css_max_height(),
+ m_css_offsets(),
+ m_css_text_indent(),
+ m_css_line_height(0),
+ m_line_height(0),
+ m_list_style_type(list_style_type_none),
+ m_list_style_position(list_style_position_outside),
+ m_bg(),
+ m_font_size(0),
+ m_font(0),
+ m_font_metrics(),
+ m_text_transform(text_transform_none),
+ m_border_collapse(border_collapse_separate),
+ m_css_border_spacing_x(),
+ m_css_border_spacing_y(),
+ m_flex_grow(0),
+ m_flex_shrink(1),
+ m_flex_direction(flex_direction_row),
+ m_flex_wrap(flex_wrap_nowrap),
+ m_flex_justify_content(flex_justify_content_flex_start),
+ m_flex_align_items(flex_align_items_stretch),
+ m_flex_align_self(flex_align_self_auto),
+ m_flex_align_content(flex_align_content_stretch)
+ {}
+
+ void compute(const element* el, const std::shared_ptr<document>& doc);
+ std::vector<std::tuple<string, string>> dump_get_attrs();
+
+ element_position get_position() const;
+ void set_position(element_position mElPosition);
+
+ text_align get_text_align() const;
+ void set_text_align(text_align mTextAlign);
+
+ overflow get_overflow() const;
+ void set_overflow(overflow mOverflow);
+
+ white_space get_white_space() const;
+ void set_white_space(white_space mWhiteSpace);
+
+ style_display get_display() const;
+ void set_display(style_display mDisplay);
+
+ visibility get_visibility() const;
+ void set_visibility(visibility mVisibility);
+
+ box_sizing get_box_sizing() const;
+ void set_box_sizing(box_sizing mBoxSizing);
+
+ int get_z_index() const;
+ void set_z_index(int mZIndex);
+
+ vertical_align get_vertical_align() const;
+ void set_vertical_align(vertical_align mVerticalAlign);
+
+ element_float get_float() const;
+ void set_float(element_float mFloat);
+
+ element_clear get_clear() const;
+ void set_clear(element_clear mClear);
+
+ const css_margins &get_margins() const;
+ void set_margins(const css_margins &mCssMargins);
+
+ const css_margins &get_padding() const;
+ void set_padding(const css_margins &mCssPadding);
+
+ const css_borders &get_borders() const;
+ void set_borders(const css_borders &mCssBorders);
+
+ const css_length &get_width() const;
+ void set_width(const css_length &mCssWidth);
+
+ const css_length &get_height() const;
+ void set_height(const css_length &mCssHeight);
+
+ const css_length &get_min_width() const;
+ void set_min_width(const css_length &mCssMinWidth);
+
+ const css_length &get_min_height() const;
+ void set_min_height(const css_length &mCssMinHeight);
+
+ const css_length &get_max_width() const;
+ void set_max_width(const css_length &mCssMaxWidth);
+
+ const css_length &get_max_height() const;
+ void set_max_height(const css_length &mCssMaxHeight);
+
+ const css_offsets &get_offsets() const;
+ void set_offsets(const css_offsets &mCssOffsets);
+
+ const css_length &get_text_indent() const;
+ void set_text_indent(const css_length &mCssTextIndent);
+
+ int get_line_height() const;
+ void set_line_height(int mLineHeight);
+
+ list_style_type get_list_style_type() const;
+ void set_list_style_type(list_style_type mListStyleType);
+
+ list_style_position get_list_style_position() const;
+ void set_list_style_position(list_style_position mListStylePosition);
+
+ string get_list_style_image() const;
+ void set_list_style_image(const string& url);
+
+ string get_list_style_image_baseurl() const;
+ void set_list_style_image_baseurl(const string& url);
+
+ const background &get_bg() const;
+ void set_bg(const background &mBg);
+
+ int get_font_size() const;
+ void set_font_size(int mFontSize);
+
+ uint_ptr get_font() const;
+ void set_font(uint_ptr mFont);
+
+ const font_metrics& get_font_metrics() const;
+ void set_font_metrics(const font_metrics& mFontMetrics);
+
+ text_transform get_text_transform() const;
+ void set_text_transform(text_transform mTextTransform);
+
+ web_color get_color() const;
+ void set_color(web_color color);
+
+ string get_cursor() const;
+ void set_cursor(const string& cursor);
+
+ string get_content() const;
+ void set_content(const string& content);
+
+ border_collapse get_border_collapse() const;
+ void set_border_collapse(border_collapse mBorderCollapse);
+
+ const css_length& get_border_spacing_x() const ;
+ void set_border_spacing_x(const css_length& mBorderSpacingX);
+
+ const css_length& get_border_spacing_y() const;
+ void set_border_spacing_y(const css_length& mBorderSpacingY);
+
+ float get_flex_grow() const;
+ float get_flex_shrink() const;
+ const css_length& get_flex_basis() const;
+ flex_direction get_flex_direction() const;
+ flex_wrap get_flex_wrap() const;
+ flex_justify_content get_flex_justify_content() const;
+ flex_align_items get_flex_align_items() const;
+ flex_align_self get_flex_align_self() const;
+ flex_align_content get_flex_align_content() const;
+ };
+
+ inline element_position css_properties::get_position() const
+ {
+ return m_el_position;
+ }
+
+ inline void css_properties::set_position(element_position mElPosition)
+ {
+ m_el_position = mElPosition;
+ }
+
+ inline text_align css_properties::get_text_align() const
+ {
+ return m_text_align;
+ }
+
+ inline void css_properties::set_text_align(text_align mTextAlign)
+ {
+ m_text_align = mTextAlign;
+ }
+
+ inline overflow css_properties::get_overflow() const
+ {
+ return m_overflow;
+ }
+
+ inline void css_properties::set_overflow(overflow mOverflow)
+ {
+ m_overflow = mOverflow;
+ }
+
+ inline white_space css_properties::get_white_space() const
+ {
+ return m_white_space;
+ }
+
+ inline void css_properties::set_white_space(white_space mWhiteSpace)
+ {
+ m_white_space = mWhiteSpace;
+ }
+
+ inline style_display css_properties::get_display() const
+ {
+ return m_display;
+ }
+
+ inline void css_properties::set_display(style_display mDisplay)
+ {
+ m_display = mDisplay;
+ }
+
+ inline visibility css_properties::get_visibility() const
+ {
+ return m_visibility;
+ }
+
+ inline void css_properties::set_visibility(visibility mVisibility)
+ {
+ m_visibility = mVisibility;
+ }
+
+ inline box_sizing css_properties::get_box_sizing() const
+ {
+ return m_box_sizing;
+ }
+
+ inline void css_properties::set_box_sizing(box_sizing mBoxSizing)
+ {
+ m_box_sizing = mBoxSizing;
+ }
+
+ inline int css_properties::get_z_index() const
+ {
+ return (int)m_z_index.val();
+ }
+
+ inline void css_properties::set_z_index(int mZIndex)
+ {
+ m_z_index.set_value((float)mZIndex, css_units_none);
+ }
+
+ inline vertical_align css_properties::get_vertical_align() const
+ {
+ return m_vertical_align;
+ }
+
+ inline void css_properties::set_vertical_align(vertical_align mVerticalAlign)
+ {
+ m_vertical_align = mVerticalAlign;
+ }
+
+ inline element_float css_properties::get_float() const
+ {
+ return m_float;
+ }
+
+ inline void css_properties::set_float(element_float mFloat)
+ {
+ m_float = mFloat;
+ }
+
+ inline element_clear css_properties::get_clear() const
+ {
+ return m_clear;
+ }
+
+ inline void css_properties::set_clear(element_clear mClear)
+ {
+ m_clear = mClear;
+ }
+
+ inline const css_margins &css_properties::get_margins() const
+ {
+ return m_css_margins;
+ }
+
+ inline void css_properties::set_margins(const css_margins &mCssMargins)
+ {
+ m_css_margins = mCssMargins;
+ }
+
+ inline const css_margins &css_properties::get_padding() const
+ {
+ return m_css_padding;
+ }
+
+ inline void css_properties::set_padding(const css_margins &mCssPadding)
+ {
+ m_css_padding = mCssPadding;
+ }
+
+ inline const css_borders &css_properties::get_borders() const
+ {
+ return m_css_borders;
+ }
+
+ inline void css_properties::set_borders(const css_borders &mCssBorders)
+ {
+ m_css_borders = mCssBorders;
+ }
+
+ inline const css_length &css_properties::get_width() const
+ {
+ return m_css_width;
+ }
+
+ inline void css_properties::set_width(const css_length &mCssWidth)
+ {
+ m_css_width = mCssWidth;
+ }
+
+ inline const css_length &css_properties::get_height() const
+ {
+ return m_css_height;
+ }
+
+ inline void css_properties::set_height(const css_length &mCssHeight)
+ {
+ m_css_height = mCssHeight;
+ }
+
+ inline const css_length &css_properties::get_min_width() const
+ {
+ return m_css_min_width;
+ }
+
+ inline void css_properties::set_min_width(const css_length &mCssMinWidth)
+ {
+ m_css_min_width = mCssMinWidth;
+ }
+
+ inline const css_length &css_properties::get_min_height() const
+ {
+ return m_css_min_height;
+ }
+
+ inline void css_properties::set_min_height(const css_length &mCssMinHeight)
+ {
+ m_css_min_height = mCssMinHeight;
+ }
+
+ inline const css_length &css_properties::get_max_width() const
+ {
+ return m_css_max_width;
+ }
+
+ inline void css_properties::set_max_width(const css_length &mCssMaxWidth)
+ {
+ m_css_max_width = mCssMaxWidth;
+ }
+
+ inline const css_length &css_properties::get_max_height() const
+ {
+ return m_css_max_height;
+ }
+
+ inline void css_properties::set_max_height(const css_length &mCssMaxHeight)
+ {
+ m_css_max_height = mCssMaxHeight;
+ }
+
+ inline const css_offsets &css_properties::get_offsets() const
+ {
+ return m_css_offsets;
+ }
+
+ inline void css_properties::set_offsets(const css_offsets &mCssOffsets)
+ {
+ m_css_offsets = mCssOffsets;
+ }
+
+ inline const css_length &css_properties::get_text_indent() const
+ {
+ return m_css_text_indent;
+ }
+
+ inline void css_properties::set_text_indent(const css_length &mCssTextIndent)
+ {
+ m_css_text_indent = mCssTextIndent;
+ }
+
+ inline int css_properties::get_line_height() const
+ {
+ return m_line_height;
+ }
+
+ inline void css_properties::set_line_height(int mLineHeight)
+ {
+ m_line_height = mLineHeight;
+ }
+
+ inline list_style_type css_properties::get_list_style_type() const
+ {
+ return m_list_style_type;
+ }
+
+ inline void css_properties::set_list_style_type(list_style_type mListStyleType)
+ {
+ m_list_style_type = mListStyleType;
+ }
+
+ inline list_style_position css_properties::get_list_style_position() const
+ {
+ return m_list_style_position;
+ }
+
+ inline void css_properties::set_list_style_position(list_style_position mListStylePosition)
+ {
+ m_list_style_position = mListStylePosition;
+ }
+
+ inline string css_properties::get_list_style_image() const { return m_list_style_image; }
+ inline void css_properties::set_list_style_image(const string& url) { m_list_style_image = url; }
+
+ inline string css_properties::get_list_style_image_baseurl() const { return m_list_style_image_baseurl; }
+ inline void css_properties::set_list_style_image_baseurl(const string& url) { m_list_style_image_baseurl = url; }
+
+ inline const background &css_properties::get_bg() const
+ {
+ return m_bg;
+ }
+
+ inline void css_properties::set_bg(const background &mBg)
+ {
+ m_bg = mBg;
+ }
+
+ inline int css_properties::get_font_size() const
+ {
+ return (int)m_font_size.val();
+ }
+
+ inline void css_properties::set_font_size(int mFontSize)
+ {
+ m_font_size = (float)mFontSize;
+ }
+
+ inline uint_ptr css_properties::get_font() const
+ {
+ return m_font;
+ }
+
+ inline void css_properties::set_font(uint_ptr mFont)
+ {
+ m_font = mFont;
+ }
+
+ inline const font_metrics& css_properties::get_font_metrics() const
+ {
+ return m_font_metrics;
+ }
+
+ inline void css_properties::set_font_metrics(const font_metrics& mFontMetrics)
+ {
+ m_font_metrics = mFontMetrics;
+ }
+
+ inline text_transform css_properties::get_text_transform() const
+ {
+ return m_text_transform;
+ }
+
+ inline void css_properties::set_text_transform(text_transform mTextTransform)
+ {
+ m_text_transform = mTextTransform;
+ }
+
+ inline web_color css_properties::get_color() const { return m_color; }
+ inline void css_properties::set_color(web_color color) { m_color = color; }
+
+ inline string css_properties::get_cursor() const { return m_cursor; }
+ inline void css_properties::set_cursor(const string& cursor) { m_cursor = cursor; }
+
+ inline string css_properties::get_content() const { return m_content; }
+ inline void css_properties::set_content(const string& content) { m_content = content; }
+
+ inline border_collapse css_properties::get_border_collapse() const
+ {
+ return m_border_collapse;
+ }
+
+ inline void css_properties::set_border_collapse(border_collapse mBorderCollapse)
+ {
+ m_border_collapse = mBorderCollapse;
+ }
+
+ inline const css_length& css_properties::get_border_spacing_x() const
+ {
+ return m_css_border_spacing_x;
+ }
+
+ inline void css_properties::set_border_spacing_x(const css_length& mBorderSpacingX)
+ {
+ m_css_border_spacing_x = mBorderSpacingX;
+ }
+
+ inline const css_length& css_properties::get_border_spacing_y() const
+ {
+ return m_css_border_spacing_y;
+ }
+
+ inline void css_properties::set_border_spacing_y(const css_length& mBorderSpacingY)
+ {
+ m_css_border_spacing_y = mBorderSpacingY;
+ }
+
+ inline float css_properties::get_flex_grow() const
+ {
+ return m_flex_grow;
+ }
+
+ inline float css_properties::get_flex_shrink() const
+ {
+ return m_flex_shrink;
+ }
+
+ inline const css_length& css_properties::get_flex_basis() const
+ {
+ return m_flex_basis;
+ }
+
+ inline flex_direction css_properties::get_flex_direction() const
+ {
+ return m_flex_direction;
+ }
+
+ inline flex_wrap css_properties::get_flex_wrap() const
+ {
+ return m_flex_wrap;
+ }
+
+ inline flex_justify_content css_properties::get_flex_justify_content() const
+ {
+ return m_flex_justify_content;
+ }
+
+ inline flex_align_items css_properties::get_flex_align_items() const
+ {
+ return m_flex_align_items;
+ }
+
+ inline flex_align_self css_properties::get_flex_align_self() const
+ {
+ return m_flex_align_self;
+ }
+
+ inline flex_align_content css_properties::get_flex_align_content() const
+ {
+ return m_flex_align_content;
+ }
+}
+
+#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 e0a7ed445..6ace9bb07 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_selector.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/css_selector.cpp
@@ -2,190 +2,245 @@
#include "css_selector.h"
#include "document.h"
-void litehtml::css_element_selector::parse( const tstring& txt )
+void litehtml::css_element_selector::parse_nth_child_params(const string& param, int& num, int& off)
{
- tstring::size_type el_end = txt.find_first_of(_t(".#[:"));
- m_tag = txt.substr(0, el_end);
- litehtml::lcase(m_tag);
+ if (param == "odd")
+ {
+ num = 2;
+ off = 1;
+ }
+ else if (param == "even")
+ {
+ num = 2;
+ off = 0;
+ }
+ else
+ {
+ string_vector tokens;
+ split_string(param, tokens, " n", "n");
+
+ string s_num;
+ string s_off;
+
+ string s_int;
+ for (const auto& token : tokens)
+ {
+ if (token == "n")
+ {
+ s_num = s_int;
+ s_int.clear();
+ }
+ else
+ {
+ s_int += token;
+ }
+ }
+ s_off = s_int;
+
+ num = atoi(s_num.c_str());
+ off = atoi(s_off.c_str());
+ }
+}
+
+void litehtml::css_element_selector::parse( const string& txt )
+{
+ string::size_type el_end = txt.find_first_of(".#[:");
+ string tag = txt.substr(0, el_end);
+ litehtml::lcase(tag);
+ if (tag == "") tag = "*";
+ m_tag = _id(tag);
+
m_attrs.clear();
- while(el_end != tstring::npos)
+ while(el_end != string::npos)
{
- if(txt[el_end] == _t('.'))
+ if(txt[el_end] == '.')
+ {
+ css_attribute_selector attribute;
+
+ attribute.type = select_class;
+ string::size_type pos = txt.find_first_of(".#[:", el_end + 1);
+ string name = txt.substr(el_end + 1, pos - el_end - 1);
+ litehtml::lcase(name);
+ attribute.name = _id(name);
+ m_attrs.push_back(attribute);
+ el_end = pos;
+ } else if(txt[el_end] == '#')
{
css_attribute_selector attribute;
- tstring::size_type pos = txt.find_first_of(_t(".#[:"), el_end + 1);
- attribute.val = txt.substr(el_end + 1, pos - el_end - 1);
- split_string( attribute.val, attribute.class_val, _t(" ") );
- attribute.condition = select_equal;
- attribute.attribute = _t("class");
+ attribute.type = select_id;
+ string::size_type pos = txt.find_first_of(".#[:", el_end + 1);
+ string name = txt.substr(el_end + 1, pos - el_end - 1);
+ litehtml::lcase(name);
+ attribute.name = _id(name);
m_attrs.push_back(attribute);
el_end = pos;
- } else if(txt[el_end] == _t(':'))
+ } else if(txt[el_end] == ':')
{
css_attribute_selector attribute;
- if(txt[el_end + 1] == _t(':'))
+ if(txt[el_end + 1] == ':')
{
- tstring::size_type pos = txt.find_first_of(_t(".#[:"), el_end + 2);
- attribute.val = txt.substr(el_end + 2, pos - el_end - 2);
- attribute.condition = select_pseudo_element;
- litehtml::lcase(attribute.val);
- attribute.attribute = _t("pseudo-el");
+ attribute.type = select_pseudo_element;
+ string::size_type pos = txt.find_first_of(".#[:", el_end + 2);
+ string name = txt.substr(el_end + 2, pos - el_end - 2);
+ litehtml::lcase(name);
+ attribute.name = _id(name);
m_attrs.push_back(attribute);
el_end = pos;
} else
{
- tstring::size_type pos = txt.find_first_of(_t(".#[:("), el_end + 1);
- if(pos != tstring::npos && txt.at(pos) == _t('('))
+ string::size_type pos = txt.find_first_of(".#[:(", el_end + 1);
+ string name = txt.substr(el_end + 1, pos - el_end - 1);
+ lcase(name);
+ attribute.name = _id(name);
+ if(attribute.name == _after_ || attribute.name == _before_)
{
- pos = find_close_bracket(txt, pos);
- if(pos != tstring::npos)
- {
- pos++;
- } else
- {
- int iii = 0;
- iii++;
- }
- }
- if(pos != tstring::npos)
- {
- attribute.val = txt.substr(el_end + 1, pos - el_end - 1);
+ attribute.type = select_pseudo_element;
} else
{
- attribute.val = txt.substr(el_end + 1);
+ attribute.type = select_pseudo_class;
}
- litehtml::lcase(attribute.val);
- if(attribute.val == _t("after") || attribute.val == _t("before"))
+
+ string val;
+ if(pos != string::npos && txt.at(pos) == '(')
{
- attribute.condition = select_pseudo_element;
- } else
+ auto end = find_close_bracket(txt, pos);
+ val = txt.substr(pos + 1, end - pos - 1);
+ if (end != string::npos) pos = end + 1;
+ }
+
+ switch (attribute.name)
{
- attribute.condition = select_pseudo_class;
+ case _nth_child_:
+ case _nth_of_type_:
+ case _nth_last_child_:
+ case _nth_last_of_type_:
+ lcase(val);
+ parse_nth_child_params(val, attribute.a, attribute.b);
+ break;
+ case _not_:
+ attribute.sel = std::make_shared<css_element_selector>();
+ attribute.sel->parse(val);
+ break;
+ case _lang_:
+ trim(val);
+ lcase(val);
+ attribute.val = val;
+ break;
}
- attribute.attribute = _t("pseudo");
+
m_attrs.push_back(attribute);
el_end = pos;
}
- } else if(txt[el_end] == _t('#'))
+ } else if(txt[el_end] == '[')
{
css_attribute_selector attribute;
- tstring::size_type pos = txt.find_first_of(_t(".#[:"), el_end + 1);
- attribute.val = txt.substr(el_end + 1, pos - el_end - 1);
- attribute.condition = select_equal;
- attribute.attribute = _t("id");
- m_attrs.push_back(attribute);
- el_end = pos;
- } else if(txt[el_end] == _t('['))
- {
- css_attribute_selector attribute;
-
- tstring::size_type pos = txt.find_first_of(_t("]~=|$*^"), el_end + 1);
- tstring attr = txt.substr(el_end + 1, pos - el_end - 1);
+ string::size_type pos = txt.find_first_of("]~=|$*^", el_end + 1);
+ string attr = txt.substr(el_end + 1, pos - el_end - 1);
trim(attr);
litehtml::lcase(attr);
- if(pos != tstring::npos)
+ if(pos != string::npos)
{
- if(txt[pos] == _t(']'))
+ if(txt[pos] == ']')
{
- attribute.condition = select_exists;
- } else if(txt[pos] == _t('='))
+ attribute.type = select_exists;
+ } else if(txt[pos] == '=')
{
- attribute.condition = select_equal;
+ attribute.type = select_equal;
pos++;
- } else if(txt.substr(pos, 2) == _t("~="))
+ } else if(txt.substr(pos, 2) == "~=")
{
- attribute.condition = select_contain_str;
+ attribute.type = select_contain_str;
pos += 2;
- } else if(txt.substr(pos, 2) == _t("|="))
+ } else if(txt.substr(pos, 2) == "|=")
{
- attribute.condition = select_start_str;
+ attribute.type = select_start_str;
pos += 2;
- } else if(txt.substr(pos, 2) == _t("^="))
+ } else if(txt.substr(pos, 2) == "^=")
{
- attribute.condition = select_start_str;
+ attribute.type = select_start_str;
pos += 2;
- } else if(txt.substr(pos, 2) == _t("$="))
+ } else if(txt.substr(pos, 2) == "$=")
{
- attribute.condition = select_end_str;
+ attribute.type = select_end_str;
pos += 2;
- } else if(txt.substr(pos, 2) == _t("*="))
+ } else if(txt.substr(pos, 2) == "*=")
{
- attribute.condition = select_contain_str;
+ attribute.type = select_contain_str;
pos += 2;
} else
{
- attribute.condition = select_exists;
+ attribute.type = select_exists;
pos += 1;
}
- pos = txt.find_first_not_of(_t(" \t"), pos);
- if(pos != tstring::npos)
+ pos = txt.find_first_not_of(" \t", pos);
+ if(pos != string::npos)
{
- if(txt[pos] == _t('"'))
+ if(txt[pos] == '"')
{
- tstring::size_type pos2 = txt.find_first_of(_t("\""), pos + 1);
- attribute.val = txt.substr(pos + 1, pos2 == tstring::npos ? pos2 : (pos2 - pos - 1));
- pos = pos2 == tstring::npos ? pos2 : (pos2 + 1);
- } else if(txt[pos] == _t(']'))
+ 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 ++;
} else
{
- tstring::size_type pos2 = txt.find_first_of(_t("]"), pos + 1);
- attribute.val = txt.substr(pos, pos2 == tstring::npos ? pos2 : (pos2 - pos));
+ string::size_type pos2 = txt.find_first_of(']', pos + 1);
+ attribute.val = txt.substr(pos, pos2 == string::npos ? pos2 : (pos2 - pos));
trim(attribute.val);
- pos = pos2 == tstring::npos ? pos2 : (pos2 + 1);
+ pos = pos2 == string::npos ? pos2 : (pos2 + 1);
}
}
} else
{
- attribute.condition = select_exists;
+ attribute.type = select_exists;
}
- attribute.attribute = attr;
+ attribute.name = _id(attr);
m_attrs.push_back(attribute);
el_end = pos;
} else
{
el_end++;
}
- el_end = txt.find_first_of(_t(".#[:"), el_end);
+ el_end = txt.find_first_of(".#[:", el_end);
}
}
-bool litehtml::css_selector::parse( const tstring& text )
+bool litehtml::css_selector::parse( const string& text )
{
if(text.empty())
{
return false;
}
string_vector tokens;
- split_string(text, tokens, _t(""), _t(" \t>+~"), _t("(["));
+ split_string(text, tokens, "", " \t>+~", "([");
if(tokens.empty())
{
return false;
}
- tstring left;
- tstring right = tokens.back();
- tchar_t combinator = 0;
+ string left;
+ string right = tokens.back();
+ char combinator = 0;
tokens.pop_back();
- while(!tokens.empty() && (tokens.back() == _t(" ") || tokens.back() == _t("\t") || tokens.back() == _t("+") || tokens.back() == _t("~") || tokens.back() == _t(">")))
+ while(!tokens.empty() && (tokens.back() == " " || tokens.back() == "\t" || tokens.back() == "+" || tokens.back() == "~" || tokens.back() == ">"))
{
- if(combinator == _t(' ') || combinator == 0)
+ if(combinator == ' ' || combinator == 0)
{
combinator = tokens.back()[0];
}
tokens.pop_back();
}
- for(string_vector::const_iterator i = tokens.begin(); i != tokens.end(); i++)
+ for(const auto & token : tokens)
{
- left += *i;
+ left += token;
}
trim(left);
@@ -200,13 +255,13 @@ bool litehtml::css_selector::parse( const tstring& text )
switch(combinator)
{
- case _t('>'):
+ case '>':
m_combinator = combinator_child;
break;
- case _t('+'):
+ case '+':
m_combinator = combinator_adjacent_sibling;
break;
- case _t('~'):
+ case '~':
m_combinator = combinator_general_sibling;
break;
default:
@@ -214,11 +269,11 @@ bool litehtml::css_selector::parse( const tstring& text )
break;
}
- m_left = 0;
+ m_left = nullptr;
if(!left.empty())
{
- m_left = std::make_shared<css_selector>(media_query_list::ptr(0));
+ m_left = std::make_shared<css_selector>();
if(!m_left->parse(left))
{
return false;
@@ -230,24 +285,18 @@ bool litehtml::css_selector::parse( const tstring& text )
void litehtml::css_selector::calc_specificity()
{
- if(!m_right.m_tag.empty() && m_right.m_tag != _t("*"))
+ if(m_right.m_tag != star_id)
{
m_specificity.d = 1;
}
- for(css_attribute_selector::vector::iterator i = m_right.m_attrs.begin(); i != m_right.m_attrs.end(); i++)
+ for(const auto& attr : m_right.m_attrs)
{
- if(i->attribute == _t("id"))
+ if(attr.type == select_id)
{
m_specificity.b++;
} else
{
- if(i->attribute == _t("class"))
- {
- m_specificity.c += (int) i->class_val.size();
- } else
- {
- m_specificity.c++;
- }
+ m_specificity.c++;
}
}
if(m_left)
diff --git a/src/plugins/litehtml_viewer/litehtml/css_selector.h b/src/plugins/litehtml_viewer/litehtml/css_selector.h
index d9a027464..4fe7db9e5 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_selector.h
+++ b/src/plugins/litehtml_viewer/litehtml/css_selector.h
@@ -15,7 +15,7 @@ namespace litehtml
int c;
int d;
- selector_specificity(int va = 0, int vb = 0, int vc = 0, int vd = 0)
+ explicit selector_specificity(int va = 0, int vb = 0, int vc = 0, int vd = 0)
{
a = va;
b = vb;
@@ -117,31 +117,41 @@ namespace litehtml
//////////////////////////////////////////////////////////////////////////
- enum attr_select_condition
+ enum attr_select_type
{
+ select_class,
+ select_id,
+
select_exists,
select_equal,
select_contain_str,
select_start_str,
select_end_str,
+
select_pseudo_class,
select_pseudo_element,
};
//////////////////////////////////////////////////////////////////////////
+ class css_element_selector;
+
struct css_attribute_selector
{
typedef std::vector<css_attribute_selector> vector;
- tstring attribute;
- tstring val;
- string_vector class_val;
- attr_select_condition condition;
+ attr_select_type type;
+ string_id name; // .name, #name, [name], :name
+ string val; // [name=val], :lang(val)
+
+ std::shared_ptr<css_element_selector> sel; // :not(sel)
+ int a, b; // :nth-child(an+b)
css_attribute_selector()
{
- condition = select_exists;
+ type = select_class;
+ name = empty_id;
+ a = b = 0;
}
};
@@ -150,11 +160,12 @@ namespace litehtml
class css_element_selector
{
public:
- tstring m_tag;
+ string_id m_tag;
css_attribute_selector::vector m_attrs;
public:
- void parse(const tstring& txt);
+ void parse(const string& txt);
+ static void parse_nth_child_params(const string& param, int& num, int& off);
};
//////////////////////////////////////////////////////////////////////////
@@ -183,26 +194,24 @@ namespace litehtml
int m_order;
media_query_list::ptr m_media_query;
public:
- css_selector(media_query_list::ptr media)
+ explicit css_selector(const media_query_list::ptr& media = nullptr)
{
m_media_query = media;
m_combinator = combinator_descendant;
m_order = 0;
}
- ~css_selector()
- {
- }
+ ~css_selector() = default;
css_selector(const css_selector& val)
{
m_right = val.m_right;
if(val.m_left)
{
- m_left = std::make_shared<css_selector>(*val.m_left);
+ m_left = std::make_shared<css_selector>(*val.m_left);
} else
{
- m_left = 0;
+ m_left = nullptr;
}
m_combinator = val.m_combinator;
m_specificity = val.m_specificity;
@@ -210,7 +219,7 @@ namespace litehtml
m_media_query = val.m_media_query;
}
- bool parse(const tstring& text);
+ bool parse(const string& text);
void calc_specificity();
bool is_media_valid() const;
void add_media_to_doc(document* doc) const;
@@ -246,7 +255,7 @@ namespace litehtml
return (v1.m_specificity < v2.m_specificity);
}
- inline bool operator >(const css_selector::ptr& v1, const css_selector::ptr& v2)
+ inline bool operator > (const css_selector::ptr& v1, const css_selector::ptr& v2)
{
return (*v1 > *v2);
}
@@ -272,6 +281,19 @@ namespace litehtml
m_used = used;
m_selector = selector;
}
+
+ used_selector(const used_selector& val)
+ {
+ m_used = val.m_used;
+ m_selector = val.m_selector;
+ }
+
+ used_selector& operator=(const used_selector& val)
+ {
+ m_used = val.m_used;
+ m_selector = val.m_selector;
+ return *this;
+ }
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/document.cpp b/src/plugins/litehtml_viewer/litehtml/document.cpp
index 245411bf4..8623bff41 100644
--- a/src/plugins/litehtml_viewer/litehtml/document.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/document.cpp
@@ -21,43 +21,37 @@
#include "el_div.h"
#include "el_font.h"
#include "el_tr.h"
-#include "el_li.h"
-#include <math.h>
-#include <stdio.h>
+#include <cmath>
+#include <cstdio>
#include <algorithm>
#include "gumbo.h"
#include "utf8_strings.h"
+#include "render_item.h"
-litehtml::document::document(litehtml::document_container* objContainer, litehtml::context* ctx)
+litehtml::document::document(document_container* objContainer)
{
m_container = objContainer;
- m_context = ctx;
}
litehtml::document::~document()
{
- m_over_element = 0;
+ m_over_element = nullptr;
if(m_container)
{
- for(fonts_map::iterator f = m_fonts.begin(); f != m_fonts.end(); f++)
+ for(auto& font : m_fonts)
{
- m_container->delete_font(f->second.font);
+ m_container->delete_font(font.second.font);
}
}
}
-litehtml::document::ptr litehtml::document::createFromString( const tchar_t* str, litehtml::document_container* objPainter, litehtml::context* ctx, litehtml::css* user_styles)
-{
- return createFromUTF8(litehtml_to_utf8(str), objPainter, ctx, user_styles);
-}
-
-litehtml::document::ptr litehtml::document::createFromUTF8(const char* str, litehtml::document_container* objPainter, litehtml::context* ctx, litehtml::css* user_styles)
+litehtml::document::ptr litehtml::document::createFromString( const char* str, document_container* objPainter, const char* master_styles, const char* user_styles )
{
// parse document into GumboOutput
- GumboOutput* output = gumbo_parse((const char*) str);
+ GumboOutput* output = gumbo_parse(str);
// Create litehtml::document
- litehtml::document::ptr doc = std::make_shared<litehtml::document>(objPainter, ctx);
+ document::ptr doc = std::make_shared<document>(objPainter);
// Create litehtml::elements.
elements_vector root_elements;
@@ -69,30 +63,43 @@ litehtml::document::ptr litehtml::document::createFromUTF8(const char* str, lite
// Destroy GumboOutput
gumbo_destroy_output(&kGumboDefaultOptions, output);
+ if (master_styles && *master_styles)
+ {
+ doc->m_master_css.parse_stylesheet(master_styles, nullptr, doc, nullptr);
+ doc->m_master_css.sort_selectors();
+ }
+ if (user_styles && *user_styles)
+ {
+ doc->m_user_css.parse_stylesheet(user_styles, nullptr, doc, nullptr);
+ doc->m_user_css.sort_selectors();
+ }
+
// Let's process created elements tree
if (doc->m_root)
{
doc->container()->get_media_features(doc->m_media);
+ doc->m_root->set_pseudo_class(_root_, true);
+
// apply master CSS
- doc->m_root->apply_stylesheet(ctx->master_css());
+ doc->m_root->apply_stylesheet(doc->m_master_css);
// parse elements attributes
doc->m_root->parse_attributes();
// parse style sheets linked in document
media_query_list::ptr media;
- for (css_text::vector::iterator css = doc->m_css.begin(); css != doc->m_css.end(); css++)
+ for (const auto& css : doc->m_css)
{
- if (!css->media.empty())
+ if (!css.media.empty())
{
- media = media_query_list::create_from_string(css->media, doc);
+ media = media_query_list::create_from_string(css.media, doc);
}
else
{
- media = 0;
+ media = nullptr;
}
- doc->m_styles.parse_stylesheet(css->text.c_str(), css->baseurl.c_str(), doc, media);
+ doc->m_styles.parse_stylesheet(css.text.c_str(), css.baseurl.c_str(), doc, media);
}
// Sort css selectors using CSS rules.
doc->m_styles.sort_selectors();
@@ -107,77 +114,100 @@ litehtml::document::ptr litehtml::document::createFromUTF8(const char* str, lite
doc->m_root->apply_stylesheet(doc->m_styles);
// Apply user styles if any
- if (user_styles)
- {
- doc->m_root->apply_stylesheet(*user_styles);
- }
+ doc->m_root->apply_stylesheet(doc->m_user_css);
- // Parse applied styles in the elements
- doc->m_root->parse_styles();
+ // Initialize m_css
+ doc->m_root->compute_styles();
+
+ // Create rendering tree
+ doc->m_root_render = doc->m_root->create_render_item(nullptr);
// Now the m_tabular_elements is filled with tabular elements.
// We have to check the tabular elements for missing table elements
// and create the anonymous boxes in visual table layout
doc->fix_tables_layout();
- // Fanaly initialize elements
- doc->m_root->init();
+ // Finally initialize elements
+ // init() return pointer to the render_init element because it can change its type
+ doc->m_root_render = doc->m_root_render->init();
}
return doc;
}
-litehtml::uint_ptr litehtml::document::add_font( const tchar_t* name, int size, const tchar_t* weight, const tchar_t* style, const tchar_t* decoration, font_metrics* fm )
+litehtml::uint_ptr litehtml::document::add_font( const char* name, int size, const char* weight, const char* style, const char* decoration, font_metrics* fm )
{
uint_ptr ret = 0;
- if( !name || (name && !t_strcasecmp(name, _t("inherit"))) )
+ if(!name)
{
name = m_container->get_default_font_name();
}
- if(!size)
- {
- size = container()->get_default_font_size();
- }
-
- tchar_t strSize[20];
+ char strSize[20];
t_itoa(size, strSize, 20, 10);
- tstring key = name;
- key += _t(":");
+ string key = name;
+ key += ":";
key += strSize;
- key += _t(":");
+ key += ":";
key += weight;
- key += _t(":");
+ key += ":";
key += style;
- key += _t(":");
+ key += ":";
key += decoration;
if(m_fonts.find(key) == m_fonts.end())
{
- font_style fs = (font_style) value_index(style, font_style_strings, fontStyleNormal);
+ font_style fs = (font_style) value_index(style, font_style_strings, font_style_normal);
int fw = value_index(weight, font_weight_strings, -1);
if(fw >= 0)
{
switch(fw)
{
- case litehtml::fontWeightBold:
+ case litehtml::font_weight_bold:
fw = 700;
break;
- case litehtml::fontWeightBolder:
+ case litehtml::font_weight_bolder:
fw = 600;
break;
- case litehtml::fontWeightLighter:
+ case litehtml::font_weight_lighter:
+ fw = 300;
+ break;
+ case litehtml::font_weight_normal:
+ fw = 400;
+ break;
+ case litehtml::font_weight_100:
+ fw = 100;
+ break;
+ case litehtml::font_weight_200:
+ fw = 200;
+ break;
+ case litehtml::font_weight_300:
fw = 300;
break;
- default:
+ case litehtml::font_weight_400:
fw = 400;
break;
+ case litehtml::font_weight_500:
+ fw = 500;
+ break;
+ case litehtml::font_weight_600:
+ fw = 600;
+ break;
+ case litehtml::font_weight_700:
+ fw = 700;
+ break;
+ case litehtml::font_weight_800:
+ fw = 800;
+ break;
+ case litehtml::font_weight_900:
+ fw = 900;
+ break;
}
} else
{
- fw = t_atoi(weight);
+ fw = atoi(weight);
if(fw < 100)
{
fw = 400;
@@ -188,17 +218,17 @@ litehtml::uint_ptr litehtml::document::add_font( const tchar_t* name, int size,
if(decoration)
{
- std::vector<tstring> tokens;
- split_string(decoration, tokens, _t(" "));
- for(std::vector<tstring>::iterator i = tokens.begin(); i != tokens.end(); i++)
+ std::vector<string> tokens;
+ split_string(decoration, tokens, " ");
+ for(auto & token : tokens)
{
- if(!t_strcasecmp(i->c_str(), _t("underline")))
+ if(!t_strcasecmp(token.c_str(), "underline"))
{
decor |= font_decoration_underline;
- } else if(!t_strcasecmp(i->c_str(), _t("line-through")))
+ } else if(!t_strcasecmp(token.c_str(), "line-through"))
{
decor |= font_decoration_linethrough;
- } else if(!t_strcasecmp(i->c_str(), _t("overline")))
+ } else if(!t_strcasecmp(token.c_str(), "overline"))
{
decor |= font_decoration_overline;
}
@@ -218,32 +248,31 @@ litehtml::uint_ptr litehtml::document::add_font( const tchar_t* name, int size,
return ret;
}
-litehtml::uint_ptr litehtml::document::get_font( const tchar_t* name, int size, const tchar_t* weight, const tchar_t* style, const tchar_t* decoration, font_metrics* fm )
+litehtml::uint_ptr litehtml::document::get_font( const char* name, int size, const char* weight, const char* style, const char* decoration, font_metrics* fm )
{
- if( !name || (name && !t_strcasecmp(name, _t("inherit"))) )
+ if(!size)
{
- name = m_container->get_default_font_name();
+ return 0;
}
-
- if(!size)
+ if(!name)
{
- size = m_container->get_default_font_size();
+ name = m_container->get_default_font_name();
}
- tchar_t strSize[20];
+ char strSize[20];
t_itoa(size, strSize, 20, 10);
- tstring key = name;
- key += _t(":");
+ string key = name;
+ key += ":";
key += strSize;
- key += _t(":");
+ key += ":";
key += weight;
- key += _t(":");
+ key += ":";
key += style;
- key += _t(":");
+ key += ":";
key += decoration;
- fonts_map::iterator el = m_fonts.find(key);
+ auto el = m_fonts.find(key);
if(el != m_fonts.end())
{
@@ -261,21 +290,31 @@ int litehtml::document::render( int max_width, render_type rt )
int ret = 0;
if(m_root)
{
+ position client_rc;
+ m_container->get_client_rect(client_rc);
+ containing_block_context cb_context;
+ cb_context.width = max_width;
+ cb_context.width.type = containing_block_context::cbc_value_type_absolute;
+ cb_context.height = client_rc.height;
+ cb_context.height.type = containing_block_context::cbc_value_type_absolute;
+
if(rt == render_fixed_only)
{
m_fixed_boxes.clear();
- m_root->render_positioned(rt);
+ m_root_render->render_positioned(rt);
} else
{
- ret = m_root->render(0, 0, max_width);
- if(m_root->fetch_positioned())
+ ret = m_root_render->render(0, 0, cb_context);
+ if(m_root_render->fetch_positioned())
{
m_fixed_boxes.clear();
- m_root->render_positioned(rt);
+ m_root_render->render_positioned(rt);
}
m_size.width = 0;
m_size.height = 0;
- m_root->calc_document_size(m_size);
+ m_content_size.width = 0;
+ m_content_size.height = 0;
+ m_root_render->calc_document_size(m_size, m_content_size);
}
}
return ret;
@@ -283,14 +322,14 @@ int litehtml::document::render( int max_width, render_type rt )
void litehtml::document::draw( uint_ptr hdc, int x, int y, const position* clip )
{
- if(m_root)
+ if(m_root && m_root_render)
{
- m_root->draw(hdc, x, y, clip);
- m_root->draw_stacking_context(hdc, x, y, clip, true);
+ m_root->draw(hdc, x, y, clip, m_root_render);
+ m_root_render->draw_stacking_context(hdc, x, y, clip, true);
}
}
-int litehtml::document::cvt_units( const tchar_t* str, int fontSize, bool* is_percent/*= 0*/ ) const
+int litehtml::document::to_pixels( const char* str, int fontSize, bool* is_percent/*= 0*/ ) const
{
if(!str) return 0;
@@ -300,40 +339,35 @@ int litehtml::document::cvt_units( const tchar_t* str, int fontSize, bool* is_pe
{
*is_percent = true;
}
- return cvt_units(val, fontSize);
+ return to_pixels(val, fontSize);
}
-int litehtml::document::cvt_units( css_length& val, int fontSize, int size ) const
+int litehtml::document::to_pixels( const css_length& val, int fontSize, int size ) const
{
if(val.is_predefined())
{
return 0;
}
- int ret = 0;
+ int ret;
switch(val.units())
{
case css_units_percentage:
ret = val.calc_percent(size);
break;
case css_units_em:
- ret = round_f(val.val() * fontSize);
- val.set_value((float) ret, css_units_px);
+ ret = round_f(val.val() * (float) fontSize);
break;
case css_units_pt:
ret = m_container->pt_to_px((int) val.val());
- val.set_value((float) ret, css_units_px);
break;
case css_units_in:
ret = m_container->pt_to_px((int) (val.val() * 72));
- val.set_value((float) ret, css_units_px);
break;
case css_units_cm:
ret = m_container->pt_to_px((int) (val.val() * 0.3937 * 72));
- val.set_value((float) ret, css_units_px);
break;
case css_units_mm:
ret = m_container->pt_to_px((int) (val.val() * 0.3937 * 72) / 10);
- val.set_value((float) ret, css_units_px);
break;
case css_units_vw:
ret = (int)((double)m_media.width * (double)val.val() / 100.0);
@@ -348,8 +382,7 @@ int litehtml::document::cvt_units( css_length& val, int fontSize, int size ) con
ret = (int)((double)std::max(m_media.height, m_media.width) * (double)val.val() / 100.0);
break;
case css_units_rem:
- ret = (int) ((double) m_root->get_font_size() * (double) val.val());
- val.set_value((float) ret, css_units_px);
+ ret = (int) ((double) m_root->css().get_font_size() * (double) val.val());
break;
default:
ret = (int) val.val();
@@ -358,6 +391,38 @@ int litehtml::document::cvt_units( css_length& val, int fontSize, int size ) con
return ret;
}
+void litehtml::document::cvt_units( css_length& val, int fontSize, int size ) const
+{
+ if(val.is_predefined())
+ {
+ return;
+ }
+ int ret;
+ switch(val.units())
+ {
+ case css_units_em:
+ ret = round_f(val.val() * (float) fontSize);
+ val.set_value((float) ret, css_units_px);
+ break;
+ case css_units_pt:
+ ret = m_container->pt_to_px((int) val.val());
+ val.set_value((float) ret, css_units_px);
+ break;
+ case css_units_in:
+ ret = m_container->pt_to_px((int) (val.val() * 72));
+ val.set_value((float) ret, css_units_px);
+ break;
+ case css_units_cm:
+ ret = m_container->pt_to_px((int) (val.val() * 0.3937 * 72));
+ val.set_value((float) ret, css_units_px);
+ break;
+ case css_units_mm:
+ ret = m_container->pt_to_px((int) (val.val() * 0.3937 * 72) / 10);
+ val.set_value((float) ret, css_units_px);
+ break;
+ }
+}
+
int litehtml::document::width() const
{
return m_size.width;
@@ -368,7 +433,18 @@ int litehtml::document::height() const
return m_size.height;
}
-void litehtml::document::add_stylesheet( const tchar_t* str, const tchar_t* baseurl, const tchar_t* media )
+int litehtml::document::content_width() const
+{
+ return m_content_size.width;
+}
+
+int litehtml::document::content_height() const
+{
+ return m_content_size.height;
+}
+
+
+void litehtml::document::add_stylesheet( const char* str, const char* baseurl, const char* media )
{
if(str && str[0])
{
@@ -378,12 +454,12 @@ void litehtml::document::add_stylesheet( const tchar_t* str, const tchar_t* base
bool litehtml::document::on_mouse_over( int x, int y, int client_x, int client_y, position::vector& redraw_boxes )
{
- if(!m_root)
+ if(!m_root || !m_root_render)
{
return false;
}
- element::ptr over_el = m_root->get_element_by_point(x, y, client_x, client_y);
+ element::ptr over_el = m_root_render->get_element_by_point(x, y, client_x, client_y);
bool state_was_changed = false;
@@ -399,7 +475,7 @@ bool litehtml::document::on_mouse_over( int x, int y, int client_x, int client_y
m_over_element = over_el;
}
- const tchar_t* cursor = 0;
+ string cursor;
if(m_over_element)
{
@@ -407,21 +483,21 @@ bool litehtml::document::on_mouse_over( int x, int y, int client_x, int client_y
{
state_was_changed = true;
}
- cursor = m_over_element->get_cursor();
+ cursor = m_over_element->css().get_cursor();
}
- m_container->set_cursor(cursor ? cursor : _t("auto"));
+ m_container->set_cursor(cursor.c_str());
if(state_was_changed)
{
- return m_root->find_styles_changes(redraw_boxes, 0, 0);
+ return m_root->find_styles_changes(redraw_boxes);
}
return false;
}
bool litehtml::document::on_mouse_leave( position::vector& redraw_boxes )
{
- if(!m_root)
+ if(!m_root || !m_root_render)
{
return false;
}
@@ -429,7 +505,7 @@ bool litehtml::document::on_mouse_leave( position::vector& redraw_boxes )
{
if(m_over_element->on_mouse_leave())
{
- return m_root->find_styles_changes(redraw_boxes, 0, 0);
+ return m_root->find_styles_changes(redraw_boxes);
}
}
return false;
@@ -437,12 +513,12 @@ bool litehtml::document::on_mouse_leave( position::vector& redraw_boxes )
bool litehtml::document::on_lbutton_down( int x, int y, int client_x, int client_y, position::vector& redraw_boxes )
{
- if(!m_root)
+ if(!m_root || !m_root_render)
{
return false;
}
- element::ptr over_el = m_root->get_element_by_point(x, y, client_x, client_y);
+ element::ptr over_el = m_root_render->get_element_by_point(x, y, client_x, client_y);
bool state_was_changed = false;
@@ -465,7 +541,7 @@ bool litehtml::document::on_lbutton_down( int x, int y, int client_x, int client
}
}
- const tchar_t* cursor = 0;
+ string cursor;
if(m_over_element)
{
@@ -473,14 +549,14 @@ bool litehtml::document::on_lbutton_down( int x, int y, int client_x, int client
{
state_was_changed = true;
}
- cursor = m_over_element->get_cursor();
+ cursor = m_over_element->css().get_cursor();
}
- m_container->set_cursor(cursor ? cursor : _t("auto"));
+ m_container->set_cursor(cursor.c_str());
if(state_was_changed)
{
- return m_root->find_styles_changes(redraw_boxes, 0, 0);
+ return m_root->find_styles_changes(redraw_boxes);
}
return false;
@@ -488,7 +564,7 @@ bool litehtml::document::on_lbutton_down( int x, int y, int client_x, int client
bool litehtml::document::on_lbutton_up( int x, int y, int client_x, int client_y, position::vector& redraw_boxes )
{
- if(!m_root)
+ if(!m_root || !m_root_render)
{
return false;
}
@@ -496,13 +572,13 @@ bool litehtml::document::on_lbutton_up( int x, int y, int client_x, int client_y
{
if(m_over_element->on_lbutton_up())
{
- return m_root->find_styles_changes(redraw_boxes, 0, 0);
+ return m_root->find_styles_changes(redraw_boxes);
}
}
return false;
}
-litehtml::element::ptr litehtml::document::create_element(const tchar_t* tag_name, const string_map& attributes)
+litehtml::element::ptr litehtml::document::create_element(const char* tag_name, const string_map& attributes)
{
element::ptr newTag;
document::ptr this_doc = shared_from_this();
@@ -512,54 +588,51 @@ litehtml::element::ptr litehtml::document::create_element(const tchar_t* tag_nam
}
if(!newTag)
{
- if(!t_strcmp(tag_name, _t("br")))
+ if(!strcmp(tag_name, "br"))
{
newTag = std::make_shared<litehtml::el_break>(this_doc);
- } else if(!t_strcmp(tag_name, _t("p")))
+ } else if(!strcmp(tag_name, "p"))
{
newTag = std::make_shared<litehtml::el_para>(this_doc);
- } else if(!t_strcmp(tag_name, _t("img")))
+ } else if(!strcmp(tag_name, "img"))
{
newTag = std::make_shared<litehtml::el_image>(this_doc);
- } else if(!t_strcmp(tag_name, _t("table")))
+ } else if(!strcmp(tag_name, "table"))
{
newTag = std::make_shared<litehtml::el_table>(this_doc);
- } else if(!t_strcmp(tag_name, _t("td")) || !t_strcmp(tag_name, _t("th")))
+ } else if(!strcmp(tag_name, "td") || !strcmp(tag_name, "th"))
{
newTag = std::make_shared<litehtml::el_td>(this_doc);
- } else if(!t_strcmp(tag_name, _t("link")))
+ } else if(!strcmp(tag_name, "link"))
{
newTag = std::make_shared<litehtml::el_link>(this_doc);
- } else if(!t_strcmp(tag_name, _t("title")))
+ } else if(!strcmp(tag_name, "title"))
{
newTag = std::make_shared<litehtml::el_title>(this_doc);
- } else if(!t_strcmp(tag_name, _t("a")))
+ } else if(!strcmp(tag_name, "a"))
{
newTag = std::make_shared<litehtml::el_anchor>(this_doc);
- } else if(!t_strcmp(tag_name, _t("tr")))
+ } else if(!strcmp(tag_name, "tr"))
{
newTag = std::make_shared<litehtml::el_tr>(this_doc);
- } else if(!t_strcmp(tag_name, _t("style")))
+ } else if(!strcmp(tag_name, "style"))
{
newTag = std::make_shared<litehtml::el_style>(this_doc);
- } else if(!t_strcmp(tag_name, _t("base")))
+ } else if(!strcmp(tag_name, "base"))
{
newTag = std::make_shared<litehtml::el_base>(this_doc);
- } else if(!t_strcmp(tag_name, _t("body")))
+ } else if(!strcmp(tag_name, "body"))
{
newTag = std::make_shared<litehtml::el_body>(this_doc);
- } else if(!t_strcmp(tag_name, _t("div")))
+ } else if(!strcmp(tag_name, "div"))
{
newTag = std::make_shared<litehtml::el_div>(this_doc);
- } else if(!t_strcmp(tag_name, _t("script")))
+ } else if(!strcmp(tag_name, "script"))
{
newTag = std::make_shared<litehtml::el_script>(this_doc);
- } else if(!t_strcmp(tag_name, _t("font")))
+ } else if(!strcmp(tag_name, "font"))
{
newTag = std::make_shared<litehtml::el_font>(this_doc);
- } else if(!t_strcmp(tag_name, _t("li")))
- {
- newTag = std::make_shared<litehtml::el_li>(this_doc);
} else
{
newTag = std::make_shared<litehtml::html_tag>(this_doc);
@@ -569,9 +642,9 @@ litehtml::element::ptr litehtml::document::create_element(const tchar_t* tag_nam
if(newTag)
{
newTag->set_tagName(tag_name);
- for (string_map::const_iterator iter = attributes.begin(); iter != attributes.end(); iter++)
+ for (const auto & attribute : attributes)
{
- newTag->set_attr(iter->first.c_str(), iter->second.c_str());
+ newTag->set_attr(attribute.first.c_str(), attribute.second.c_str());
}
}
@@ -590,15 +663,12 @@ void litehtml::document::add_fixed_box( const position& pos )
bool litehtml::document::media_changed()
{
- if(!m_media_lists.empty())
+ container()->get_media_features(m_media);
+ if (update_media_lists(m_media))
{
- container()->get_media_features(m_media);
- if (update_media_lists(m_media))
- {
- m_root->refresh_styles();
- m_root->parse_styles();
- return true;
- }
+ m_root->refresh_styles();
+ m_root->compute_styles();
+ return true;
}
return false;
}
@@ -607,18 +677,18 @@ bool litehtml::document::lang_changed()
{
if(!m_media_lists.empty())
{
- tstring culture;
+ string culture;
container()->get_language(m_lang, culture);
if(!culture.empty())
{
- m_culture = m_lang + _t('-') + culture;
+ m_culture = m_lang + '-' + culture;
}
else
{
m_culture.clear();
}
m_root->refresh_styles();
- m_root->parse_styles();
+ m_root->compute_styles();
return true;
}
return false;
@@ -627,9 +697,9 @@ bool litehtml::document::lang_changed()
bool litehtml::document::update_media_lists(const media_features& features)
{
bool update_styles = false;
- for(media_query_list::vector::iterator iter = m_media_lists.begin(); iter != m_media_lists.end(); iter++)
+ for(auto & m_media_list : m_media_lists)
{
- if((*iter)->apply_media_features(features))
+ if(m_media_list->apply_media_features(features))
{
update_styles = true;
}
@@ -637,7 +707,7 @@ bool litehtml::document::update_media_lists(const media_features& features)
return update_styles;
}
-void litehtml::document::add_media_list( media_query_list::ptr list )
+void litehtml::document::add_media_list( const media_query_list::ptr& list )
{
if(list)
{
@@ -650,7 +720,7 @@ void litehtml::document::add_media_list( media_query_list::ptr list )
void litehtml::document::create_node(void* gnode, elements_vector& elements, bool parseTextNode)
{
- GumboNode* node = (GumboNode*)gnode;
+ auto* node = (GumboNode*)gnode;
switch (node->type)
{
case GUMBO_NODE_ELEMENT:
@@ -660,7 +730,7 @@ void litehtml::document::create_node(void* gnode, elements_vector& elements, boo
for (unsigned int i = 0; i < node->v.element.attributes.length; i++)
{
attr = (GumboAttribute*)node->v.element.attributes.data[i];
- attrs[tstring(litehtml_from_utf8(attr->name))] = litehtml_from_utf8(attr->value);
+ attrs[attr->name] = attr->value;
}
@@ -668,7 +738,7 @@ void litehtml::document::create_node(void* gnode, elements_vector& elements, boo
const char* tag = gumbo_normalized_tagname(node->v.element.tag);
if (tag[0])
{
- ret = create_element(litehtml_from_utf8(tag), attrs);
+ ret = create_element(tag, attrs);
}
else
{
@@ -677,7 +747,7 @@ void litehtml::document::create_node(void* gnode, elements_vector& elements, boo
std::string strA;
gumbo_tag_from_original_text(&node->v.element.original_tag);
strA.append(node->v.element.original_tag.data, node->v.element.original_tag.length);
- ret = create_element(litehtml_from_utf8(strA.c_str()), attrs);
+ ret = create_element(strA.c_str(), attrs);
}
}
if (!strcmp(tag, "script"))
@@ -704,68 +774,35 @@ void litehtml::document::create_node(void* gnode, elements_vector& elements, boo
break;
case GUMBO_NODE_TEXT:
{
- std::wstring str;
- std::wstring str_in = (const wchar_t*) (utf8_to_wchar(node->v.text.text));
if (!parseTextNode)
{
- elements.push_back(std::make_shared<el_text>(litehtml_from_wchar(str_in.c_str()), shared_from_this()));
- break;
+ elements.push_back(std::make_shared<el_text>(node->v.text.text, shared_from_this()));
}
- ucode_t c;
- for (size_t i = 0; i < str_in.length(); i++)
- {
- c = (ucode_t) str_in[i];
- if (c <= ' ' && (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f'))
- {
- if (!str.empty())
- {
- elements.push_back(std::make_shared<el_text>(litehtml_from_wchar(str.c_str()), shared_from_this()));
- str.clear();
- }
- str += c;
- elements.push_back(std::make_shared<el_space>(litehtml_from_wchar(str.c_str()), shared_from_this()));
- str.clear();
- }
- // CJK character range
- else if (c >= 0x4E00 && c <= 0x9FCC)
- {
- if (!str.empty())
- {
- elements.push_back(std::make_shared<el_text>(litehtml_from_wchar(str.c_str()), shared_from_this()));
- str.clear();
- }
- str += c;
- elements.push_back(std::make_shared<el_text>(litehtml_from_wchar(str.c_str()), shared_from_this()));
- str.clear();
- }
- else
- {
- str += c;
- }
- }
- if (!str.empty())
+ else
{
- elements.push_back(std::make_shared<el_text>(litehtml_from_wchar(str.c_str()), shared_from_this()));
+ m_container->split_text(node->v.text.text,
+ [this, &elements](const char* text) { elements.push_back(std::make_shared<el_text>(text, shared_from_this())); },
+ [this, &elements](const char* text) { elements.push_back(std::make_shared<el_space>(text, shared_from_this())); });
}
}
break;
case GUMBO_NODE_CDATA:
{
element::ptr ret = std::make_shared<el_cdata>(shared_from_this());
- ret->set_data(litehtml_from_utf8(node->v.text.text));
+ ret->set_data(node->v.text.text);
elements.push_back(ret);
}
break;
case GUMBO_NODE_COMMENT:
{
element::ptr ret = std::make_shared<el_comment>(shared_from_this());
- ret->set_data(litehtml_from_utf8(node->v.text.text));
+ ret->set_data(node->v.text.text);
elements.push_back(ret);
}
break;
case GUMBO_NODE_WHITESPACE:
{
- tstring str = litehtml_from_utf8(node->v.text.text);
+ string str = node->v.text.text;
for (size_t i = 0; i < str.length(); i++)
{
elements.push_back(std::make_shared<el_space>(str.substr(i, 1).c_str(), shared_from_this()));
@@ -779,36 +816,33 @@ void litehtml::document::create_node(void* gnode, elements_vector& elements, boo
void litehtml::document::fix_tables_layout()
{
- size_t i = 0;
- while (i < m_tabular_elements.size())
+ for (const auto& el_ptr : m_tabular_elements)
{
- element::ptr el_ptr = m_tabular_elements[i];
-
- switch (el_ptr->get_display())
+ switch (el_ptr->src_el()->css().get_display())
{
case display_inline_table:
case display_table:
- fix_table_children(el_ptr, display_table_row_group, _t("table-row-group"));
+ fix_table_children(el_ptr, display_table_row_group, "table-row-group");
break;
case display_table_footer_group:
case display_table_row_group:
case display_table_header_group:
{
- element::ptr parent = el_ptr->parent();
+ auto parent = el_ptr->parent();
if (parent)
{
- if (parent->get_display() != display_inline_table)
- fix_table_parent(el_ptr, display_table, _t("table"));
+ if (parent->src_el()->css().get_display() != display_inline_table)
+ fix_table_parent(el_ptr, display_table, "table");
}
- fix_table_children(el_ptr, display_table_row, _t("table-row"));
+ fix_table_children(el_ptr, display_table_row, "table-row");
}
break;
case display_table_row:
- fix_table_parent(el_ptr, display_table_row_group, _t("table-row-group"));
- fix_table_children(el_ptr, display_table_cell, _t("table-cell"));
+ fix_table_parent(el_ptr, display_table_row_group, "table-row-group");
+ fix_table_children(el_ptr, display_table_cell, "table-cell");
break;
case display_table_cell:
- fix_table_parent(el_ptr, display_table_row, _t("table-row"));
+ fix_table_parent(el_ptr, display_table_row, "table-row");
break;
// TODO: make table layout fix for table-caption, table-column etc. elements
case display_table_caption:
@@ -817,51 +851,61 @@ void litehtml::document::fix_tables_layout()
default:
break;
}
- i++;
}
}
-void litehtml::document::fix_table_children(element::ptr& el_ptr, style_display disp, const tchar_t* disp_str)
+void litehtml::document::fix_table_children(const std::shared_ptr<render_item>& el_ptr, style_display disp, const char* disp_str)
{
- elements_vector tmp;
- elements_vector::iterator first_iter = el_ptr->m_children.begin();
- elements_vector::iterator cur_iter = el_ptr->m_children.begin();
+ std::list<std::shared_ptr<render_item>> tmp;
+ auto first_iter = el_ptr->children().begin();
+ auto cur_iter = el_ptr->children().begin();
auto flush_elements = [&]()
{
- element::ptr annon_tag = std::make_shared<html_tag>(shared_from_this());
- style st;
- st.add_property(_t("display"), disp_str, 0, false);
- annon_tag->add_style(st);
- annon_tag->parent(el_ptr);
- annon_tag->parse_styles();
- std::for_each(tmp.begin(), tmp.end(),
- [&annon_tag](element::ptr& el)
- {
- annon_tag->appendChild(el);
- }
- );
- first_iter = el_ptr->m_children.insert(first_iter, annon_tag);
- cur_iter = first_iter + 1;
- while (cur_iter != el_ptr->m_children.end() && (*cur_iter)->parent() != el_ptr)
+ element::ptr annon_tag = std::make_shared<html_tag>(el_ptr->src_el(), string("display:") + disp_str);
+ std::shared_ptr<render_item> annon_ri;
+ if(annon_tag->css().get_display() == display_table_cell)
+ {
+ annon_tag->set_tagName("table_cell");
+ annon_ri = std::make_shared<render_item_block>(annon_tag);
+ } else if(annon_tag->css().get_display() == display_table_row)
+ {
+ annon_ri = std::make_shared<render_item_table_row>(annon_tag);
+ } else
+ {
+ annon_ri = std::make_shared<render_item_table_part>(annon_tag);
+ }
+ for(const auto& el : tmp)
+ {
+ annon_ri->add_child(el);
+ }
+ // add annon item as tabular for future processing
+ add_tabular(annon_ri);
+ annon_ri->parent(el_ptr);
+ first_iter = el_ptr->children().insert(first_iter, annon_ri);
+ cur_iter = std::next(first_iter);
+ while (cur_iter != el_ptr->children().end() && (*cur_iter)->parent() != el_ptr)
{
- cur_iter = el_ptr->m_children.erase(cur_iter);
+ cur_iter = el_ptr->children().erase(cur_iter);
}
first_iter = cur_iter;
tmp.clear();
};
- while (cur_iter != el_ptr->m_children.end())
+ while (cur_iter != el_ptr->children().end())
{
- if ((*cur_iter)->get_display() != disp)
+ if ((*cur_iter)->src_el()->css().get_display() != disp)
{
- if (!(*cur_iter)->is_white_space() || ((*cur_iter)->is_white_space() && !tmp.empty()))
+ if (!(*cur_iter)->src_el()->is_table_skip() || ((*cur_iter)->src_el()->is_table_skip() && !tmp.empty()))
{
- if (tmp.empty())
+ if (disp != display_table_row_group || (*cur_iter)->src_el()->css().get_display() != display_table_caption)
{
- first_iter = cur_iter;
+ if (tmp.empty())
+ {
+ first_iter = cur_iter;
+ }
+ tmp.push_back((*cur_iter));
}
- tmp.push_back((*cur_iter));
}
cur_iter++;
}
@@ -880,14 +924,14 @@ void litehtml::document::fix_table_children(element::ptr& el_ptr, style_display
}
}
-void litehtml::document::fix_table_parent(element::ptr& el_ptr, style_display disp, const tchar_t* disp_str)
+void litehtml::document::fix_table_parent(const std::shared_ptr<render_item>& el_ptr, style_display disp, const char* disp_str)
{
- element::ptr parent = el_ptr->parent();
+ auto parent = el_ptr->parent();
- if (parent->get_display() != disp)
+ if (parent->src_el()->css().get_display() != disp)
{
- elements_vector::iterator this_element = std::find_if(parent->m_children.begin(), parent->m_children.end(),
- [&](element::ptr& el)
+ auto this_element = std::find_if(parent->children().begin(), parent->children().end(),
+ [&](const std::shared_ptr<render_item>& el)
{
if (el == el_ptr)
{
@@ -896,19 +940,19 @@ void litehtml::document::fix_table_parent(element::ptr& el_ptr, style_display di
return false;
}
);
- if (this_element != parent->m_children.end())
+ if (this_element != parent->children().end())
{
- style_display el_disp = el_ptr->get_display();
- elements_vector::iterator first = this_element;
- elements_vector::iterator last = this_element;
- elements_vector::iterator cur = this_element;
+ style_display el_disp = el_ptr->src_el()->css().get_display();
+ auto first = this_element;
+ auto last = this_element;
+ auto cur = this_element;
// find first element with same display
while (true)
{
- if (cur == parent->m_children.begin()) break;
+ if (cur == parent->children().begin()) break;
cur--;
- if ((*cur)->is_white_space() || (*cur)->get_display() == el_disp)
+ if ((*cur)->src_el()->is_table_skip() || (*cur)->src_el()->css().get_display() == el_disp)
{
first = cur;
}
@@ -923,9 +967,9 @@ void litehtml::document::fix_table_parent(element::ptr& el_ptr, style_display di
while (true)
{
cur++;
- if (cur == parent->m_children.end()) break;
+ if (cur == parent->children().end()) break;
- if ((*cur)->is_white_space() || (*cur)->get_display() == el_disp)
+ if ((*cur)->src_el()->is_table_skip() || (*cur)->src_el()->css().get_display() == el_disp)
{
last = cur;
}
@@ -936,30 +980,33 @@ void litehtml::document::fix_table_parent(element::ptr& el_ptr, style_display di
}
// extract elements with the same display and wrap them with anonymous object
- element::ptr annon_tag = std::make_shared<html_tag>(shared_from_this());
- style st;
- st.add_property(_t("display"), disp_str, 0, false);
- annon_tag->add_style(st);
- annon_tag->parent(parent);
- annon_tag->parse_styles();
- std::for_each(first, last + 1,
- [&annon_tag](element::ptr& el)
+ element::ptr annon_tag = std::make_shared<html_tag>(parent->src_el(), string("display:") + disp_str);
+ std::shared_ptr<render_item> annon_ri;
+ if(annon_tag->css().get_display() == display_table || annon_tag->css().get_display() == display_inline_table)
+ {
+ annon_ri = std::make_shared<render_item_table>(annon_tag);
+ } else if(annon_tag->css().get_display() == display_table_row)
+ {
+ annon_ri = std::make_shared<render_item_table_row>(annon_tag);
+ } else
+ {
+ annon_ri = std::make_shared<render_item_table_part>(annon_tag);
+ }
+ std::for_each(first, std::next(last, 1),
+ [&annon_ri](std::shared_ptr<render_item>& el)
{
- annon_tag->appendChild(el);
+ annon_ri->add_child(el);
}
);
- first = parent->m_children.erase(first, last + 1);
- parent->m_children.insert(first, annon_tag);
+ first = parent->children().erase(first, std::next(last));
+ parent->children().insert(first, annon_ri);
+ add_tabular(annon_ri);
+ annon_ri->parent(parent);
}
}
}
-void litehtml::document::append_children_from_string(element& parent, const tchar_t* str)
-{
- append_children_from_utf8(parent, litehtml_to_utf8(str));
-}
-
-void litehtml::document::append_children_from_utf8(element& parent, const char* str)
+void litehtml::document::append_children_from_string(element& parent, const char* str)
{
// parent must belong to this document
if (parent.get_document().get() != this)
@@ -968,7 +1015,7 @@ void litehtml::document::append_children_from_utf8(element& parent, const char*
}
// parse document into GumboOutput
- GumboOutput* output = gumbo_parse((const char*) str);
+ GumboOutput* output = gumbo_parse(str);
// Create litehtml::elements.
elements_vector child_elements;
@@ -978,13 +1025,13 @@ void litehtml::document::append_children_from_utf8(element& parent, const char*
gumbo_destroy_output(&kGumboDefaultOptions, output);
// Let's process created elements tree
- for (litehtml::element::ptr child : child_elements)
+ for (const auto& child : child_elements)
{
// Add the child element to parent
parent.appendChild(child);
// apply master CSS
- child->apply_stylesheet(m_context->master_css());
+ child->apply_stylesheet(m_master_css);
// parse elements attributes
child->parse_attributes();
@@ -992,15 +1039,26 @@ void litehtml::document::append_children_from_utf8(element& parent, const char*
// Apply parsed styles.
child->apply_stylesheet(m_styles);
- // Parse applied styles in the elements
- child->parse_styles();
+ // Apply user styles if any
+ child->apply_stylesheet(m_user_css);
+
+ // Initialize m_css
+ child->compute_styles();
// Now the m_tabular_elements is filled with tabular elements.
// We have to check the tabular elements for missing table elements
// and create the anonymous boxes in visual table layout
fix_tables_layout();
- // Fanaly initialize elements
- child->init();
+ // Finally initialize elements
+ //child->init();
}
-}
\ No newline at end of file
+}
+
+void litehtml::document::dump(dumper& cout)
+{
+ if(m_root_render)
+ {
+ m_root_render->dump(cout);
+ }
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/document.h b/src/plugins/litehtml_viewer/litehtml/document.h
index cb297e991..11322f899 100644
--- a/src/plugins/litehtml_viewer/litehtml/document.h
+++ b/src/plugins/litehtml_viewer/litehtml/document.h
@@ -3,7 +3,7 @@
#include "style.h"
#include "types.h"
-#include "context.h"
+#include "master_css.h"
namespace litehtml
{
@@ -11,19 +11,17 @@ namespace litehtml
{
typedef std::vector<css_text> vector;
- tstring text;
- tstring baseurl;
- tstring media;
+ string text;
+ string baseurl;
+ string media;
- css_text()
- {
- }
+ css_text() = default;
- css_text(const tchar_t* txt, const tchar_t* url, const tchar_t* media_str)
+ css_text(const char* txt, const char* url, const char* media_str)
{
- text = txt ? txt : _t("");
- baseurl = url ? url : _t("");
- media = media_str ? media_str : _t("");
+ text = txt ? txt : "";
+ baseurl = url ? url : "";
+ media = media_str ? media_str : "";
}
css_text(const css_text& val)
@@ -34,19 +32,19 @@ namespace litehtml
}
};
- struct stop_tags_t
- {
- const litehtml::tchar_t* tags;
- const litehtml::tchar_t* stop_parent;
- };
-
- struct ommited_end_tags_t
- {
- const litehtml::tchar_t* tag;
- const litehtml::tchar_t* followed_tags;
- };
+ class dumper
+ {
+ public:
+ virtual ~dumper() {}
+ virtual void begin_node(const litehtml::string& descr) = 0;
+ virtual void end_node() = 0;
+ virtual void begin_attrs_group(const litehtml::string& descr) = 0;
+ virtual void end_attrs_group() = 0;
+ virtual void add_attr(const litehtml::string& name, const litehtml::string& value) = 0;
+ };
class html_tag;
+ class render_item;
class document : public std::enable_shared_from_this<document>
{
@@ -55,64 +53,69 @@ namespace litehtml
typedef std::weak_ptr<document> weak_ptr;
private:
std::shared_ptr<element> m_root;
+ std::shared_ptr<render_item> m_root_render;
document_container* m_container;
fonts_map m_fonts;
css_text::vector m_css;
litehtml::css m_styles;
litehtml::web_color m_def_color;
- litehtml::context* m_context;
+ litehtml::css m_master_css;
+ litehtml::css m_user_css;
litehtml::size m_size;
+ litehtml::size m_content_size;
position::vector m_fixed_boxes;
media_query_list::vector m_media_lists;
element::ptr m_over_element;
- elements_vector m_tabular_elements;
+ std::list<std::shared_ptr<render_item>> m_tabular_elements;
media_features m_media;
- tstring m_lang;
- tstring m_culture;
+ string m_lang;
+ string m_culture;
public:
- document(litehtml::document_container* objContainer, litehtml::context* ctx);
+ document(document_container* objContainer);
virtual ~document();
- litehtml::document_container* container() { return m_container; }
- uint_ptr get_font(const tchar_t* name, int size, const tchar_t* weight, const tchar_t* style, const tchar_t* decoration, font_metrics* fm);
+ document_container* container() { return m_container; }
+ uint_ptr get_font(const char* name, int size, const char* weight, const char* style, const char* decoration, font_metrics* fm);
int render(int max_width, render_type rt = render_all);
void draw(uint_ptr hdc, int x, int y, const position* clip);
web_color get_def_color() { return m_def_color; }
- int cvt_units(const tchar_t* str, int fontSize, bool* is_percent = 0) const;
- int cvt_units(css_length& val, int fontSize, int size = 0) const;
+ int to_pixels(const char* str, int fontSize, bool* is_percent = nullptr) const;
+ void cvt_units(css_length& val, int fontSize, int size = 0) const;
+ int to_pixels(const css_length& val, int fontSize, int size = 0) const;
int width() const;
int height() const;
- void add_stylesheet(const tchar_t* str, const tchar_t* baseurl, const tchar_t* media);
+ int content_width() const;
+ int content_height() const;
+ void add_stylesheet(const char* str, const char* baseurl, const char* media);
bool on_mouse_over(int x, int y, int client_x, int client_y, position::vector& redraw_boxes);
bool on_lbutton_down(int x, int y, int client_x, int client_y, position::vector& redraw_boxes);
bool on_lbutton_up(int x, int y, int client_x, int client_y, position::vector& redraw_boxes);
bool on_mouse_leave(position::vector& redraw_boxes);
- litehtml::element::ptr create_element(const tchar_t* tag_name, const string_map& attributes);
+ element::ptr create_element(const char* tag_name, const string_map& attributes);
element::ptr root();
const element::ptr over_element() const;
void get_fixed_boxes(position::vector& fixed_boxes);
void add_fixed_box(const position& pos);
- void add_media_list(media_query_list::ptr list);
+ void add_media_list(const media_query_list::ptr& list);
bool media_changed();
bool lang_changed();
- bool match_lang(const tstring & lang);
- void add_tabular(const element::ptr& el);
- const element::const_ptr get_over_element() const { return m_over_element; }
+ bool match_lang(const string& lang);
+ void add_tabular(const std::shared_ptr<render_item>& el);
+ element::const_ptr get_over_element() const { return m_over_element; }
- void append_children_from_string(element& parent, const tchar_t* str);
- void append_children_from_utf8(element& parent, const char* str);
+ void append_children_from_string(element& parent, const char* str);
+ void dump(dumper& cout);
- static litehtml::document::ptr createFromString(const tchar_t* str, litehtml::document_container* objPainter, litehtml::context* ctx, litehtml::css* user_styles = 0);
- static litehtml::document::ptr createFromUTF8(const char* str, litehtml::document_container* objPainter, litehtml::context* ctx, litehtml::css* user_styles = 0);
+ static litehtml::document::ptr createFromString(const char* str, litehtml::document_container* objPainter, const char* master_styles = litehtml::master_css, const char* user_styles = "");
private:
- litehtml::uint_ptr add_font(const tchar_t* name, int size, const tchar_t* weight, const tchar_t* style, const tchar_t* decoration, font_metrics* fm);
+ 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);
bool update_media_lists(const media_features& features);
void fix_tables_layout();
- void fix_table_children(element::ptr& el_ptr, style_display disp, const tchar_t* disp_str);
- void fix_table_parent(element::ptr& el_ptr, style_display disp, const tchar_t* disp_str);
+ void fix_table_children(const std::shared_ptr<render_item>& el_ptr, style_display disp, const char* disp_str);
+ void fix_table_parent(const std::shared_ptr<render_item> & el_ptr, style_display disp, const char* disp_str);
};
inline element::ptr document::root()
@@ -123,11 +126,11 @@ namespace litehtml
{
return m_over_element;
}
- inline void document::add_tabular(const element::ptr& el)
+ inline void document::add_tabular(const std::shared_ptr<render_item>& el)
{
m_tabular_elements.push_back(el);
}
- inline bool document::match_lang(const tstring & lang)
+ inline bool document::match_lang(const string& lang)
{
return lang == m_lang || lang == m_culture;
}
diff --git a/src/plugins/litehtml_viewer/litehtml/document_container.cpp b/src/plugins/litehtml_viewer/litehtml/document_container.cpp
new file mode 100644
index 000000000..d3802473e
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/document_container.cpp
@@ -0,0 +1,44 @@
+#include "html.h"
+#include "document_container.h"
+
+void litehtml::document_container::split_text(const char* text, const std::function<void(const char*)>& on_word, const std::function<void(const char*)>& on_space)
+{
+ std::wstring str;
+ std::wstring str_in = (const wchar_t*)utf8_to_wchar(text);
+ ucode_t c;
+ for (size_t i = 0; i < str_in.length(); i++)
+ {
+ c = (ucode_t)str_in[i];
+ if (c <= ' ' && (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f'))
+ {
+ if (!str.empty())
+ {
+ on_word(wchar_to_utf8(str.c_str()));
+ str.clear();
+ }
+ str += c;
+ on_space(wchar_to_utf8(str.c_str()));
+ str.clear();
+ }
+ // CJK character range
+ else if (c >= 0x4E00 && c <= 0x9FCC)
+ {
+ if (!str.empty())
+ {
+ on_word(wchar_to_utf8(str.c_str()));
+ str.clear();
+ }
+ str += c;
+ on_word(wchar_to_utf8(str.c_str()));
+ str.clear();
+ }
+ else
+ {
+ str += c;
+ }
+ }
+ if (!str.empty())
+ {
+ on_word(wchar_to_utf8(str.c_str()));
+ }
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/document_container.h b/src/plugins/litehtml_viewer/litehtml/document_container.h
new file mode 100644
index 000000000..391873c1a
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/document_container.h
@@ -0,0 +1,71 @@
+#ifndef LH_DOCUMENT_CONTAINER_H
+#define LH_DOCUMENT_CONTAINER_H
+
+#include "os_types.h"
+#include "types.h"
+#include "web_color.h"
+#include "background.h"
+#include "borders.h"
+#include "element.h"
+#include <memory>
+#include <functional>
+
+namespace litehtml
+{
+ struct list_marker
+ {
+ string image;
+ const char* baseurl;
+ list_style_type marker_type;
+ web_color color;
+ position pos;
+ int index;
+ uint_ptr font;
+ };
+
+ // call back interface to draw text, images and other elements
+ class document_container
+ {
+ public:
+ virtual litehtml::uint_ptr create_font(const char* faceName, int size, int weight, litehtml::font_style italic, unsigned int decoration, litehtml::font_metrics* fm) = 0;
+ virtual void delete_font(litehtml::uint_ptr hFont) = 0;
+ virtual int text_width(const char* text, litehtml::uint_ptr hFont) = 0;
+ virtual void draw_text(litehtml::uint_ptr hdc, const char* text, litehtml::uint_ptr hFont, litehtml::web_color color, const litehtml::position& pos) = 0;
+ virtual int pt_to_px(int pt) const = 0;
+ virtual int get_default_font_size() const = 0;
+ virtual const char* get_default_font_name() const = 0;
+ virtual void draw_list_marker(litehtml::uint_ptr hdc, const litehtml::list_marker& marker) = 0;
+ virtual void load_image(const char* src, const char* baseurl, bool redraw_on_ready) = 0;
+ virtual void get_image_size(const char* src, const char* baseurl, litehtml::size& sz) = 0;
+ // Note: regular <img> images are also drawn with draw_background
+ // bg is guaranteed to have at least one item.
+ // backgrounds in bg are in CSS order - the last one is the farthest from the user.
+ // only the last background has valid background-color.
+ virtual void draw_background(litehtml::uint_ptr hdc, const std::vector<litehtml::background_paint>& bg) = 0;
+ virtual void draw_borders(litehtml::uint_ptr hdc, const litehtml::borders& borders, const litehtml::position& draw_pos, bool root) = 0;
+
+ virtual void set_caption(const char* caption) = 0;
+ virtual void set_base_url(const char* base_url) = 0;
+ virtual void link(const std::shared_ptr<litehtml::document>& doc, const litehtml::element::ptr& el) = 0;
+ virtual void on_anchor_click(const char* url, const litehtml::element::ptr& el) = 0;
+ virtual void set_cursor(const char* cursor) = 0;
+ virtual void transform_text(litehtml::string& text, litehtml::text_transform tt) = 0;
+ virtual void import_css(litehtml::string& text, const litehtml::string& url, litehtml::string& baseurl) = 0;
+ virtual void set_clip(const litehtml::position& pos, const litehtml::border_radiuses& bdr_radius) = 0;
+ virtual void del_clip() = 0;
+ virtual void get_client_rect(litehtml::position& client) const = 0;
+ virtual litehtml::element::ptr create_element( const char* tag_name,
+ const litehtml::string_map& attributes,
+ const std::shared_ptr<litehtml::document>& doc) = 0;
+
+ virtual void get_media_features(litehtml::media_features& media) const = 0;
+ virtual void get_language(litehtml::string& language, litehtml::string& culture) const = 0;
+ virtual litehtml::string resolve_color(const litehtml::string& /*color*/) const { return litehtml::string(); }
+ virtual void split_text(const char* text, const std::function<void(const char*)>& on_word, const std::function<void(const char*)>& on_space);
+
+ protected:
+ ~document_container() = default;
+ };
+}
+
+#endif // LH_DOCUMENT_CONTAINER_H
diff --git a/src/plugins/litehtml_viewer/litehtml/el_anchor.cpp b/src/plugins/litehtml_viewer/litehtml/el_anchor.cpp
index a120eb15d..372e4afb5 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_anchor.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_anchor.cpp
@@ -6,14 +6,9 @@ litehtml::el_anchor::el_anchor(const std::shared_ptr<litehtml::document>& doc) :
{
}
-litehtml::el_anchor::~el_anchor()
-{
-
-}
-
void litehtml::el_anchor::on_click()
{
- const tchar_t* href = get_attr(_t("href"));
+ const char* href = get_attr("href");
if(href)
{
@@ -23,9 +18,9 @@ void litehtml::el_anchor::on_click()
void litehtml::el_anchor::apply_stylesheet( const litehtml::css& stylesheet )
{
- if( get_attr(_t("href")) )
+ if( get_attr("href") )
{
- m_pseudo_classes.push_back(_t("link"));
+ m_pseudo_classes.push_back(_link_);
}
html_tag::apply_stylesheet(stylesheet);
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_anchor.h b/src/plugins/litehtml_viewer/litehtml/el_anchor.h
index 140d19508..b33794c52 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_anchor.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_anchor.h
@@ -8,11 +8,10 @@ namespace litehtml
class el_anchor : public html_tag
{
public:
- el_anchor(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_anchor();
+ explicit el_anchor(const std::shared_ptr<litehtml::document>& doc);
- virtual void on_click() override;
- virtual void apply_stylesheet(const litehtml::css& stylesheet) override;
+ void on_click() override;
+ void apply_stylesheet(const litehtml::css& stylesheet) override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_base.cpp b/src/plugins/litehtml_viewer/litehtml/el_base.cpp
index dffc6afd0..baf025653 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_base.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_base.cpp
@@ -2,17 +2,12 @@
#include "el_base.h"
#include "document.h"
-litehtml::el_base::el_base(const std::shared_ptr<litehtml::document>& doc) : html_tag(doc)
+litehtml::el_base::el_base(const std::shared_ptr<document>& doc) : html_tag(doc)
{
}
-litehtml::el_base::~el_base()
-{
-
-}
-
void litehtml::el_base::parse_attributes()
{
- get_document()->container()->set_base_url(get_attr(_t("href")));
+ get_document()->container()->set_base_url(get_attr("href"));
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_base.h b/src/plugins/litehtml_viewer/litehtml/el_base.h
index 57ba87d4f..d7efb8064 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_base.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_base.h
@@ -8,10 +8,9 @@ namespace litehtml
class el_base : public html_tag
{
public:
- el_base(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_base();
+ explicit el_base(const std::shared_ptr<litehtml::document>& doc);
- virtual void parse_attributes() override;
+ void parse_attributes() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp b/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp
index bf0127d2f..4455642e8 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp
@@ -3,90 +3,104 @@
#include "el_text.h"
#include "el_space.h"
#include "el_image.h"
+#include "utf8_strings.h"
-litehtml::el_before_after_base::el_before_after_base(const std::shared_ptr<litehtml::document>& doc, bool before) : html_tag(doc)
+litehtml::el_before_after_base::el_before_after_base(const std::shared_ptr<document>& doc, bool before) : html_tag(doc)
{
- if(before)
- {
- set_tagName(_t("::before"));
- } else
- {
- set_tagName(_t("::after"));
- }
+ m_tag = before ? __tag_before_ : __tag_after_;
}
-litehtml::el_before_after_base::~el_before_after_base()
+void litehtml::el_before_after_base::add_style(const style& style)
{
+ html_tag::add_style(style);
-}
-
-void litehtml::el_before_after_base::add_style(const litehtml::style& st)
-{
- html_tag::add_style(st);
+ auto children = m_children;
+ m_children.clear();
- tstring content = get_style_property(_t("content"), false, _t(""));
- if(!content.empty())
+ const auto& content_property = style.get_property(_content_);
+ if(content_property.m_type == prop_type_string && !content_property.m_string.empty())
{
- int idx = value_index(content.c_str(), content_property_string);
+ int idx = value_index(content_property.m_string, content_property_string);
if(idx < 0)
{
- tstring fnc;
- tstring::size_type i = 0;
- while(i < content.length() && i != tstring::npos)
+ string fnc;
+ string::size_type i = 0;
+ while(i < content_property.m_string.length() && i != string::npos)
{
- if(content.at(i) == _t('"'))
+ if(content_property.m_string.at(i) == '"' || content_property.m_string.at(i) == '\'')
{
+ auto chr = content_property.m_string.at(i);
fnc.clear();
i++;
- tstring::size_type pos = content.find(_t('"'), i);
- tstring txt;
- if(pos == tstring::npos)
+ string::size_type pos = content_property.m_string.find(chr, i);
+ string txt;
+ if(pos == string::npos)
{
- txt = content.substr(i);
- i = tstring::npos;
+ txt = content_property.m_string.substr(i);
+ i = string::npos;
} else
{
- txt = content.substr(i, pos - i);
+ txt = content_property.m_string.substr(i, pos - i);
i = pos + 1;
}
add_text(txt);
- } else if(content.at(i) == _t('('))
+ } else if(content_property.m_string.at(i) == '(')
{
i++;
litehtml::trim(fnc);
litehtml::lcase(fnc);
- tstring::size_type pos = content.find(_t(')'), i);
- tstring params;
- if(pos == tstring::npos)
+ string::size_type pos = content_property.m_string.find(')', i);
+ string params;
+ if(pos == string::npos)
{
- params = content.substr(i);
- i = tstring::npos;
+ params = content_property.m_string.substr(i);
+ i = string::npos;
} else
{
- params = content.substr(i, pos - i);
+ params = content_property.m_string.substr(i, pos - i);
i = pos + 1;
}
add_function(fnc, params);
fnc.clear();
} else
{
- fnc += content.at(i);
+ fnc += content_property.m_string.at(i);
i++;
}
}
}
}
+
+ if(m_children.empty())
+ {
+ m_children = children;
+ }
}
-void litehtml::el_before_after_base::add_text( const tstring& txt )
+void litehtml::el_before_after_base::add_text( const string& txt )
{
- tstring word;
- tstring esc;
- for(tstring::size_type i = 0; i < txt.length(); i++)
+ string word;
+ string esc;
+
+ for(auto chr : txt)
{
- if( (txt.at(i) == _t(' ')) || (txt.at(i) == _t('\t')) || (txt.at(i) == _t('\\') && !esc.empty()) )
+ if(chr == '\\' ||
+ !esc.empty() && esc.length() < 5 && (chr >= '0' && chr <= '9' || chr >= 'A' && chr <= 'Z' || chr >= 'a' && chr <= 'z'))
+ {
+ if(!esc.empty() && chr == '\\')
+ {
+ word += convert_escape(esc.c_str() + 1);
+ esc.clear();
+ }
+ esc += chr;
+ } else
{
- if(esc.empty())
+ if(!esc.empty())
+ {
+ word += convert_escape(esc.c_str() + 1);
+ esc.clear();
+ }
+ if(isspace(chr))
{
if(!word.empty())
{
@@ -94,26 +108,13 @@ void litehtml::el_before_after_base::add_text( const tstring& txt )
appendChild(el);
word.clear();
}
-
- element::ptr el = std::make_shared<el_space>(txt.substr(i, 1).c_str(), get_document());
+ word += chr;
+ element::ptr el = std::make_shared<el_text>(word.c_str(), get_document());
appendChild(el);
+ word.clear();
} else
{
- word += convert_escape(esc.c_str() + 1);
- esc.clear();
- if(txt.at(i) == _t('\\'))
- {
- esc += txt.at(i);
- }
- }
- } else
- {
- if(!esc.empty() || txt.at(i) == _t('\\'))
- {
- esc += txt.at(i);
- } else
- {
- word += txt.at(i);
+ word += chr;
}
}
}
@@ -130,21 +131,21 @@ void litehtml::el_before_after_base::add_text( const tstring& txt )
}
}
-void litehtml::el_before_after_base::add_function( const tstring& fnc, const tstring& params )
+void litehtml::el_before_after_base::add_function( const string& fnc, const string& params )
{
- int idx = value_index(fnc.c_str(), _t("attr;counter;url"));
+ int idx = value_index(fnc, "attr;counter;url");
switch(idx)
{
// attr
case 0:
{
- tstring p_name = params;
+ string p_name = params;
trim(p_name);
lcase(p_name);
element::ptr el_parent = parent();
if (el_parent)
{
- const tchar_t* attr_value = el_parent->get_attr(p_name.c_str());
+ const char* attr_value = el_parent->get_attr(p_name.c_str());
if (attr_value)
{
add_text(attr_value);
@@ -158,18 +159,18 @@ void litehtml::el_before_after_base::add_function( const tstring& fnc, const tst
// url
case 2:
{
- tstring p_url = params;
+ string p_url = params;
trim(p_url);
if(!p_url.empty())
{
- if(p_url.at(0) == _t('\'') || p_url.at(0) == _t('\"'))
+ if(p_url.at(0) == '\'' || p_url.at(0) == '\"')
{
p_url.erase(0, 1);
}
}
if(!p_url.empty())
{
- if(p_url.at(p_url.length() - 1) == _t('\'') || p_url.at(p_url.length() - 1) == _t('\"'))
+ if(p_url.at(p_url.length() - 1) == '\'' || p_url.at(p_url.length() - 1) == '\"')
{
p_url.erase(p_url.length() - 1, 1);
}
@@ -177,9 +178,9 @@ void litehtml::el_before_after_base::add_function( const tstring& fnc, const tst
if(!p_url.empty())
{
element::ptr el = std::make_shared<el_image>(get_document());
- el->set_attr(_t("src"), p_url.c_str());
- el->set_attr(_t("style"), _t("display:inline-block"));
- el->set_tagName(_t("img"));
+ el->set_attr("src", p_url.c_str());
+ el->set_attr("style", "display:inline-block");
+ el->set_tagName("img");
appendChild(el);
el->parse_attributes();
}
@@ -188,10 +189,13 @@ void litehtml::el_before_after_base::add_function( const tstring& fnc, const tst
}
}
-litehtml::tchar_t litehtml::el_before_after_base::convert_escape( const tchar_t* txt )
+litehtml::string litehtml::el_before_after_base::convert_escape( const char* txt )
{
- tchar_t* sss = 0;
- return (tchar_t) t_strtol(txt, &sss, 16);
+ char* str_end;
+ wchar_t u_str[2];
+ u_str[0] = (wchar_t) strtol(txt, &str_end, 16);
+ 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 1bb55f315..ac966f395 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_before_after.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_before_after.h
@@ -8,21 +8,20 @@ namespace litehtml
class el_before_after_base : public html_tag
{
public:
- el_before_after_base(const std::shared_ptr<litehtml::document>& doc, bool before);
- virtual ~el_before_after_base();
+ el_before_after_base(const std::shared_ptr<document>& doc, bool before);
- virtual void add_style(const litehtml::style& st) override;
- virtual void apply_stylesheet(const litehtml::css& stylesheet) override;
+ void add_style(const style& style) override;
+ void apply_stylesheet(const litehtml::css& stylesheet) override;
private:
- void add_text(const tstring& txt);
- void add_function(const tstring& fnc, const tstring& params);
- tchar_t convert_escape(const tchar_t* txt);
+ void add_text(const string& txt);
+ void add_function(const string& fnc, const string& params);
+ static string convert_escape(const char* txt);
};
class el_before : public el_before_after_base
{
public:
- el_before(const std::shared_ptr<litehtml::document>& doc) : el_before_after_base(doc, true)
+ explicit el_before(const std::shared_ptr<document>& doc) : el_before_after_base(doc, true)
{
}
@@ -31,7 +30,7 @@ namespace litehtml
class el_after : public el_before_after_base
{
public:
- el_after(const std::shared_ptr<litehtml::document>& doc) : el_before_after_base(doc, false)
+ explicit el_after(const std::shared_ptr<document>& doc) : el_before_after_base(doc, false)
{
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_body.cpp b/src/plugins/litehtml_viewer/litehtml/el_body.cpp
index 61376d5d4..3d35f8f75 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_body.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_body.cpp
@@ -6,11 +6,6 @@ litehtml::el_body::el_body(const std::shared_ptr<litehtml::document>& doc) : lit
{
}
-litehtml::el_body::~el_body()
-{
-
-}
-
bool litehtml::el_body::is_body() const
{
return true;
diff --git a/src/plugins/litehtml_viewer/litehtml/el_body.h b/src/plugins/litehtml_viewer/litehtml/el_body.h
index d03d5df34..fb30e0c51 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_body.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_body.h
@@ -8,10 +8,9 @@ namespace litehtml
class el_body : public html_tag
{
public:
- el_body(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_body();
+ explicit el_body(const std::shared_ptr<litehtml::document>& doc);
- virtual bool is_body() const override;
+ bool is_body() const override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_break.cpp b/src/plugins/litehtml_viewer/litehtml/el_break.cpp
index 5523b4111..f13b2e3cf 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_break.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_break.cpp
@@ -6,11 +6,6 @@ litehtml::el_break::el_break(const std::shared_ptr<litehtml::document>& doc) : h
}
-litehtml::el_break::~el_break()
-{
-
-}
-
bool litehtml::el_break::is_break() const
{
return true;
diff --git a/src/plugins/litehtml_viewer/litehtml/el_break.h b/src/plugins/litehtml_viewer/litehtml/el_break.h
index 70fab321d..2a4d8fe45 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_break.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_break.h
@@ -8,11 +8,10 @@ namespace litehtml
class el_break : public html_tag
{
public:
- el_break(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_break();
+ explicit el_break(const std::shared_ptr<litehtml::document>& doc);
- virtual bool is_break() const override;
- };
+ bool is_break() const override;
+ };
}
#endif // LH_EL_BREAK_H
diff --git a/src/plugins/litehtml_viewer/litehtml/el_cdata.cpp b/src/plugins/litehtml_viewer/litehtml/el_cdata.cpp
index bb21eab10..e5948bff1 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_cdata.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_cdata.cpp
@@ -1,22 +1,17 @@
#include "html.h"
#include "el_cdata.h"
-litehtml::el_cdata::el_cdata(const std::shared_ptr<litehtml::document>& doc) : litehtml::element(doc)
+litehtml::el_cdata::el_cdata(const std::shared_ptr<document>& doc) : element(doc)
{
- m_skip = true;
+ //m_skip = true;
}
-litehtml::el_cdata::~el_cdata()
-{
-
-}
-
-void litehtml::el_cdata::get_text( tstring& text )
+void litehtml::el_cdata::get_text( string& text )
{
text += m_text;
}
-void litehtml::el_cdata::set_data( const tchar_t* data )
+void litehtml::el_cdata::set_data( const char* data )
{
if(data)
{
diff --git a/src/plugins/litehtml_viewer/litehtml/el_cdata.h b/src/plugins/litehtml_viewer/litehtml/el_cdata.h
index 33bdfe311..838cd92b1 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_cdata.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_cdata.h
@@ -7,13 +7,12 @@ namespace litehtml
{
class el_cdata : public element
{
- tstring m_text;
+ string m_text;
public:
- el_cdata(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_cdata();
+ explicit el_cdata(const std::shared_ptr<document>& doc);
- virtual void get_text(tstring& text) override;
- virtual void set_data(const tchar_t* data) override;
+ void get_text(string& text) override;
+ void set_data(const char* data) override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_comment.cpp b/src/plugins/litehtml_viewer/litehtml/el_comment.cpp
index 638c960f7..1ec934d04 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_comment.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_comment.cpp
@@ -1,22 +1,22 @@
#include "html.h"
#include "el_comment.h"
-litehtml::el_comment::el_comment(const std::shared_ptr<litehtml::document>& doc) : litehtml::element(doc)
+litehtml::el_comment::el_comment(const std::shared_ptr<document>& doc) : element(doc)
{
- m_skip = true;
+ //m_skip = true;
}
-litehtml::el_comment::~el_comment()
+bool litehtml::el_comment::is_comment() const
{
-
+ return true;
}
-void litehtml::el_comment::get_text( tstring& text )
+void litehtml::el_comment::get_text( string& text )
{
text += m_text;
}
-void litehtml::el_comment::set_data( const tchar_t* data )
+void litehtml::el_comment::set_data( const char* data )
{
if(data)
{
diff --git a/src/plugins/litehtml_viewer/litehtml/el_comment.h b/src/plugins/litehtml_viewer/litehtml/el_comment.h
index ceffd2c05..454ee4787 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_comment.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_comment.h
@@ -7,13 +7,18 @@ namespace litehtml
{
class el_comment : public element
{
- tstring m_text;
+ string m_text;
public:
- el_comment(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_comment();
+ explicit el_comment(const std::shared_ptr<document>& doc);
- virtual void get_text(tstring& text) override;
- virtual void set_data(const tchar_t* data) override;
+ bool is_comment() const override;
+ void get_text(string& text) override;
+ void set_data(const char* data) override;
+ std::shared_ptr<render_item> create_render_item(const std::shared_ptr<render_item>& parent_ri) override
+ {
+ // Comments are not rendered
+ return nullptr;
+ }
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_div.cpp b/src/plugins/litehtml_viewer/litehtml/el_div.cpp
index c4ee3c0db..983d45ab2 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_div.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_div.cpp
@@ -2,22 +2,17 @@
#include "el_div.h"
-litehtml::el_div::el_div(const std::shared_ptr<litehtml::document>& doc) : html_tag(doc)
-{
-
-}
-
-litehtml::el_div::~el_div()
+litehtml::el_div::el_div(const document::ptr& doc) : html_tag(doc)
{
}
void litehtml::el_div::parse_attributes()
{
- const tchar_t* str = get_attr(_t("align"));
+ const char* str = get_attr("align");
if(str)
{
- m_style.add_property(_t("text-align"), str, 0, false);
+ m_style.add_property(_text_align_, str);
}
html_tag::parse_attributes();
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_div.h b/src/plugins/litehtml_viewer/litehtml/el_div.h
index ece762f51..a2d031a32 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_div.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_div.h
@@ -8,10 +8,9 @@ namespace litehtml
class el_div : public html_tag
{
public:
- el_div(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_div();
+ explicit el_div(const std::shared_ptr<litehtml::document>& doc);
- virtual void parse_attributes() override;
+ void parse_attributes() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_font.cpp b/src/plugins/litehtml_viewer/litehtml/el_font.cpp
index da6bae984..3d5f6d9f7 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_font.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_font.cpp
@@ -2,55 +2,52 @@
#include "el_font.h"
-litehtml::el_font::el_font(const std::shared_ptr<litehtml::document>& doc) : html_tag(doc)
-{
-
-}
-
-litehtml::el_font::~el_font()
+litehtml::el_font::el_font(const std::shared_ptr<document>& doc) : html_tag(doc)
{
}
void litehtml::el_font::parse_attributes()
{
- const tchar_t* str = get_attr(_t("color"));
+ const char* str = get_attr("color");
if(str)
{
- m_style.add_property(_t("color"), str, 0, false);
+ m_style.add_property(_color_, str, "", false, get_document()->container());
}
- str = get_attr(_t("face"));
+ str = get_attr("face");
if(str)
{
- m_style.add_property(_t("font-face"), str, 0, false);
+ m_style.add_property(_font_family_, str);
}
- str = get_attr(_t("size"));
+ str = get_attr("size");
if(str)
{
- int sz = t_atoi(str);
+ int sz = atoi(str);
+ if(*str == '+' || *str == '-') sz = 3 + sz; // relative size
+
if(sz <= 1)
{
- m_style.add_property(_t("font-size"), _t("x-small"), 0, false);
+ m_style.add_property(_font_size_, "x-small");
} else if(sz >= 6)
{
- m_style.add_property(_t("font-size"), _t("xx-large"), 0, false);
+ m_style.add_property(_font_size_, "xx-large");
} else
{
switch(sz)
{
case 2:
- m_style.add_property(_t("font-size"), _t("small"), 0, false);
+ m_style.add_property(_font_size_, "small");
break;
case 3:
- m_style.add_property(_t("font-size"), _t("medium"), 0, false);
+ m_style.add_property(_font_size_, "medium");
break;
case 4:
- m_style.add_property(_t("font-size"), _t("large"), 0, false);
+ m_style.add_property(_font_size_, "large");
break;
case 5:
- m_style.add_property(_t("font-size"), _t("x-large"), 0, false);
+ m_style.add_property(_font_size_, "x-large");
break;
}
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_font.h b/src/plugins/litehtml_viewer/litehtml/el_font.h
index a0f391ec2..ccb894512 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_font.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_font.h
@@ -8,10 +8,9 @@ namespace litehtml
class el_font : public html_tag
{
public:
- el_font(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_font();
+ explicit el_font(const std::shared_ptr<litehtml::document>& doc);
- virtual void parse_attributes() override;
+ void parse_attributes() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_image.cpp b/src/plugins/litehtml_viewer/litehtml/el_image.cpp
index 62b3c4437..34b8a7aef 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_image.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_image.cpp
@@ -1,15 +1,10 @@
#include "html.h"
#include "el_image.h"
-#include "document.h"
+#include "render_item.h"
-litehtml::el_image::el_image(const std::shared_ptr<litehtml::document>& doc) : html_tag(doc)
+litehtml::el_image::el_image(const document::ptr& doc) : html_tag(doc)
{
- m_display = display_inline_block;
-}
-
-litehtml::el_image::~el_image( void )
-{
-
+ m_css.set_display(display_inline_block);
}
void litehtml::el_image::get_content_size( size& sz, int max_width )
@@ -17,196 +12,36 @@ void litehtml::el_image::get_content_size( size& sz, int max_width )
get_document()->container()->get_image_size(m_src.c_str(), 0, sz);
}
-int litehtml::el_image::calc_max_height(int image_height)
-{
- document::ptr doc = get_document();
- int percentSize = 0;
- if (m_css_max_height.units() == css_units_percentage)
- {
- auto el_parent = parent();
- if (el_parent)
- {
- if (!el_parent->get_predefined_height(percentSize))
- {
- return image_height;
- }
- }
- }
- return doc->cvt_units(m_css_max_height, m_font_size, percentSize);
-}
-
-int litehtml::el_image::line_height() const
-{
- return height();
-}
-
bool litehtml::el_image::is_replaced() const
{
return true;
}
-int litehtml::el_image::render( int x, int y, int max_width, bool second_pass )
-{
- int parent_width = max_width;
-
- calc_outlines(parent_width);
-
- m_pos.move_to(x, y);
-
- document::ptr doc = get_document();
-
- litehtml::size sz;
- doc->container()->get_image_size(m_src.c_str(), 0, sz);
-
- m_pos.width = sz.width;
- m_pos.height = sz.height;
-
- if(m_css_height.is_predefined() && m_css_width.is_predefined())
- {
- m_pos.height = sz.height;
- m_pos.width = sz.width;
-
- // check for max-width
- if(!m_css_max_width.is_predefined())
- {
- int max_width = doc->cvt_units(m_css_max_width, m_font_size, parent_width);
- if(m_pos.width > max_width)
- {
- m_pos.width = max_width;
- }
- if(sz.width)
- {
- m_pos.height = (int) ((float) m_pos.width * (float) sz.height / (float)sz.width);
- } else
- {
- m_pos.height = sz.height;
- }
- }
-
- // check for max-height
- if(!m_css_max_height.is_predefined())
- {
- int max_height = calc_max_height(sz.height);
- if(m_pos.height > max_height)
- {
- m_pos.height = max_height;
- }
- if(sz.height)
- {
- m_pos.width = (int) (m_pos.height * (float)sz.width / (float)sz.height);
- } else
- {
- m_pos.width = sz.width;
- }
- }
- } else if(!m_css_height.is_predefined() && m_css_width.is_predefined())
- {
- if (!get_predefined_height(m_pos.height))
- {
- m_pos.height = (int)m_css_height.val();
- }
-
- // check for max-height
- if(!m_css_max_height.is_predefined())
- {
- int max_height = calc_max_height(sz.height);
- if(m_pos.height > max_height)
- {
- m_pos.height = max_height;
- }
- }
-
- if(sz.height)
- {
- m_pos.width = (int) (m_pos.height * (float)sz.width / (float)sz.height);
- } else
- {
- m_pos.width = sz.width;
- }
- } else if(m_css_height.is_predefined() && !m_css_width.is_predefined())
- {
- m_pos.width = (int) m_css_width.calc_percent(parent_width);
-
- // check for max-width
- if(!m_css_max_width.is_predefined())
- {
- int max_width = doc->cvt_units(m_css_max_width, m_font_size, parent_width);
- if(m_pos.width > max_width)
- {
- m_pos.width = max_width;
- }
- }
-
- if(sz.width)
- {
- m_pos.height = (int) ((float) m_pos.width * (float) sz.height / (float)sz.width);
- } else
- {
- m_pos.height = sz.height;
- }
- } else
- {
- m_pos.width = (int) m_css_width.calc_percent(parent_width);
- m_pos.height = 0;
- if (!get_predefined_height(m_pos.height))
- {
- m_pos.height = (int)m_css_height.val();
- }
-
- // check for max-height
- if(!m_css_max_height.is_predefined())
- {
- int max_height = calc_max_height(sz.height);
- if(m_pos.height > max_height)
- {
- m_pos.height = max_height;
- }
- }
-
- // check for max-height
- if(!m_css_max_width.is_predefined())
- {
- int max_width = doc->cvt_units(m_css_max_width, m_font_size, parent_width);
- if(m_pos.width > max_width)
- {
- m_pos.width = max_width;
- }
- }
- }
-
- calc_auto_margins(parent_width);
-
- m_pos.x += content_margins_left();
- m_pos.y += content_margins_top();
-
- return m_pos.width + content_margins_left() + content_margins_right();
-}
-
void litehtml::el_image::parse_attributes()
{
- m_src = get_attr(_t("src"), _t(""));
+ m_src = get_attr("src", "");
- const tchar_t* attr_height = get_attr(_t("height"));
+ const char* attr_height = get_attr("height");
if(attr_height)
{
- m_style.add_property(_t("height"), attr_height, 0, false);
+ m_style.add_property(_height_, attr_height);
}
- const tchar_t* attr_width = get_attr(_t("width"));
+ const char* attr_width = get_attr("width");
if(attr_width)
{
- m_style.add_property(_t("width"), attr_width, 0, false);
+ m_style.add_property(_width_, attr_width);
}
}
-void litehtml::el_image::draw( uint_ptr hdc, int x, int y, const position* clip )
+void litehtml::el_image::draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri)
{
- position pos = m_pos;
+ position pos = ri->pos();
pos.x += x;
pos.y += y;
position el_pos = pos;
- el_pos += m_padding;
- el_pos += m_borders;
+ el_pos += ri->get_paddings();
+ el_pos += ri->get_borders();
// draw standard background here
if (el_pos.does_intersect(clip))
@@ -214,8 +49,8 @@ void litehtml::el_image::draw( uint_ptr hdc, int x, int y, const position* clip
const background* bg = get_background();
if (bg)
{
- background_paint bg_paint;
- init_background_paint(pos, bg_paint, bg);
+ std::vector<background_paint> bg_paint;
+ init_background_paint(pos, bg_paint, bg, ri);
get_document()->container()->draw_background(hdc, bg_paint);
}
@@ -230,15 +65,15 @@ void litehtml::el_image::draw( uint_ptr hdc, int x, int y, const position* clip
bg.clip_box = pos;
bg.origin_box = pos;
bg.border_box = pos;
- bg.border_box += m_padding;
- bg.border_box += m_borders;
+ bg.border_box += ri->get_paddings();
+ bg.border_box += ri->get_borders();
bg.repeat = background_repeat_no_repeat;
bg.image_size.width = pos.width;
bg.image_size.height = pos.height;
- bg.border_radius = m_css_borders.radius.calc_percents(bg.border_box.width, bg.border_box.height);
+ bg.border_radius = css().get_borders().radius.calc_percents(bg.border_box.width, bg.border_box.height);
bg.position_x = pos.x;
bg.position_y = pos.y;
- get_document()->container()->draw_background(hdc, bg);
+ get_document()->container()->draw_background(hdc, {bg});
}
}
@@ -246,28 +81,40 @@ void litehtml::el_image::draw( uint_ptr hdc, int x, int y, const position* clip
if (el_pos.does_intersect(clip))
{
position border_box = pos;
- border_box += m_padding;
- border_box += m_borders;
+ border_box += ri->get_paddings();
+ border_box += ri->get_borders();
- borders bdr = m_css_borders;
- bdr.radius = m_css_borders.radius.calc_percents(border_box.width, border_box.height);
+ borders bdr = css().get_borders();
+ bdr.radius = css().get_borders().radius.calc_percents(border_box.width, border_box.height);
- get_document()->container()->draw_borders(hdc, bdr, border_box, have_parent() ? false : true);
+ get_document()->container()->draw_borders(hdc, bdr, border_box, is_root());
}
}
-void litehtml::el_image::parse_styles( bool is_reparse /*= false*/ )
+void litehtml::el_image::compute_styles(bool recursive)
{
- html_tag::parse_styles(is_reparse);
+ html_tag::compute_styles(recursive);
if(!m_src.empty())
{
- if(!m_css_height.is_predefined() && !m_css_width.is_predefined())
+ if(!css().get_height().is_predefined() && !css().get_width().is_predefined())
{
- get_document()->container()->load_image(m_src.c_str(), 0, true);
+ get_document()->container()->load_image(m_src.c_str(), nullptr, true);
} else
{
- get_document()->container()->load_image(m_src.c_str(), 0, false);
+ get_document()->container()->load_image(m_src.c_str(), nullptr, false);
}
}
}
+
+litehtml::string litehtml::el_image::dump_get_name()
+{
+ return "img src=\"" + m_src + "\"";
+}
+
+std::shared_ptr<litehtml::render_item> litehtml::el_image::create_render_item(const std::shared_ptr<render_item>& parent_ri)
+{
+ auto ret = std::make_shared<render_item_image>(shared_from_this());
+ ret->parent(parent_ri);
+ return ret;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_image.h b/src/plugins/litehtml_viewer/litehtml/el_image.h
index fa13d3c1d..2b7394081 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_image.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_image.h
@@ -8,20 +8,21 @@ namespace litehtml
class el_image : public html_tag
{
- tstring m_src;
+ string m_src;
public:
- el_image(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_image(void);
+ el_image(const document::ptr& doc);
+
+ bool is_replaced() const override;
+ void parse_attributes() override;
+ void compute_styles(bool recursive = true) override;
+ void draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri) override;
+ void get_content_size(size& sz, int max_width) override;
+ string dump_get_name() override;
+
+ std::shared_ptr<render_item> create_render_item(const std::shared_ptr<render_item>& parent_ri) override;
- virtual int line_height() const override;
- virtual bool is_replaced() const override;
- virtual int render(int x, int y, int max_width, bool second_pass = false) override;
- virtual void parse_attributes() override;
- virtual void parse_styles(bool is_reparse = false) override;
- virtual void draw(uint_ptr hdc, int x, int y, const position* clip) override;
- virtual void get_content_size(size& sz, int max_width) override;
private:
- int calc_max_height(int image_height);
+// int calc_max_height(int image_height);
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_li.cpp b/src/plugins/litehtml_viewer/litehtml/el_li.cpp
deleted file mode 100644
index 9f2f484fe..000000000
--- a/src/plugins/litehtml_viewer/litehtml/el_li.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "html.h"
-#include "el_li.h"
-#include "document.h"
-
-litehtml::el_li::el_li(const std::shared_ptr<litehtml::document>& doc) : litehtml::html_tag(doc)
-{
-}
-
-litehtml::el_li::~el_li()
-{
-
-}
-
-int litehtml::el_li::render(int x, int y, int max_width, bool second_pass)
-{
- if (m_list_style_type >= list_style_type_armenian && !m_index_initialized)
- {
- if (auto p = parent())
- {
- tchar_t val[2] = { 1, 0 };
- for (int i = 0, n = (int)p->get_children_count(); i < n; ++i)
- {
- auto child = p->get_child(i);
- if (child.get() == this)
- {
- set_attr(_t("list_index"), val);
- break;
- }
- else if (!t_strcmp(child->get_tagName(), _t("li")))
- ++val[0];
- }
- }
-
- m_index_initialized = true;
- }
-
- return html_tag::render(x, y, max_width, second_pass);
-}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_li.h b/src/plugins/litehtml_viewer/litehtml/el_li.h
deleted file mode 100644
index 3451c4f1d..000000000
--- a/src/plugins/litehtml_viewer/litehtml/el_li.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef LH_EL_LI_H
-#define LH_EL_LI_H
-
-#include "html_tag.h"
-
-namespace litehtml
-{
- class el_li : public html_tag
- {
- public:
- el_li(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_li();
-
- virtual int render(int x, int y, int max_width, bool second_pass = false) override;
-
- private:
- bool m_index_initialized = false;
- };
-}
-
-#endif // LH_EL_LI_H
diff --git a/src/plugins/litehtml_viewer/litehtml/el_link.cpp b/src/plugins/litehtml_viewer/litehtml/el_link.cpp
index 01561ab6c..aa3bc7659 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_link.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_link.cpp
@@ -3,12 +3,7 @@
#include "document.h"
-litehtml::el_link::el_link(const std::shared_ptr<litehtml::document>& doc) : litehtml::html_tag(doc)
-{
-
-}
-
-litehtml::el_link::~el_link()
+litehtml::el_link::el_link(const std::shared_ptr<document>& doc) : litehtml::html_tag(doc)
{
}
@@ -19,15 +14,15 @@ void litehtml::el_link::parse_attributes()
document::ptr doc = get_document();
- const tchar_t* rel = get_attr(_t("rel"));
- if(rel && !t_strcmp(rel, _t("stylesheet")))
+ const char* rel = get_attr("rel");
+ if(rel && !strcmp(rel, "stylesheet"))
{
- const tchar_t* media = get_attr(_t("media"));
- const tchar_t* href = get_attr(_t("href"));
+ const char* media = get_attr("media");
+ const char* href = get_attr("href");
if(href && href[0])
{
- tstring css_text;
- tstring css_baseurl;
+ string css_text;
+ string css_baseurl;
doc->container()->import_css(css_text, href, css_baseurl);
if(!css_text.empty())
{
diff --git a/src/plugins/litehtml_viewer/litehtml/el_link.h b/src/plugins/litehtml_viewer/litehtml/el_link.h
index 6795760ba..0da3513dc 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_link.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_link.h
@@ -8,11 +8,10 @@ namespace litehtml
class el_link : public html_tag
{
public:
- el_link(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_link();
+ explicit el_link(const std::shared_ptr<litehtml::document>& doc);
protected:
- virtual void parse_attributes() override;
+ void parse_attributes() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_para.cpp b/src/plugins/litehtml_viewer/litehtml/el_para.cpp
index 0986e5c73..5d7915135 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_para.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_para.cpp
@@ -2,21 +2,16 @@
#include "el_para.h"
#include "document.h"
-litehtml::el_para::el_para(const std::shared_ptr<litehtml::document>& doc) : litehtml::html_tag(doc)
+litehtml::el_para::el_para(const std::shared_ptr<document>& doc) : html_tag(doc)
{
}
-litehtml::el_para::~el_para()
-{
-
-}
-
void litehtml::el_para::parse_attributes()
{
- const tchar_t* str = get_attr(_t("align"));
+ const char* str = get_attr("align");
if(str)
{
- m_style.add_property(_t("text-align"), str, 0, false);
+ m_style.add_property(_text_align_, str);
}
html_tag::parse_attributes();
diff --git a/src/plugins/litehtml_viewer/litehtml/el_para.h b/src/plugins/litehtml_viewer/litehtml/el_para.h
index 82e964ba1..32ad53758 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_para.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_para.h
@@ -8,10 +8,9 @@ namespace litehtml
class el_para : public html_tag
{
public:
- el_para(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_para();
+ explicit el_para(const std::shared_ptr<litehtml::document>& doc);
- virtual void parse_attributes() override;
+ void parse_attributes() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_script.cpp b/src/plugins/litehtml_viewer/litehtml/el_script.cpp
index 603a46d58..4b598a137 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_script.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_script.cpp
@@ -3,12 +3,7 @@
#include "document.h"
-litehtml::el_script::el_script(const std::shared_ptr<litehtml::document>& doc) : litehtml::element(doc)
-{
-
-}
-
-litehtml::el_script::~el_script()
+litehtml::el_script::el_script(const std::shared_ptr<document>& doc) : element(doc)
{
}
@@ -24,7 +19,12 @@ bool litehtml::el_script::appendChild(const ptr &el)
return true;
}
-const litehtml::tchar_t* litehtml::el_script::get_tagName() const
+litehtml::string_id litehtml::el_script::tag() const
+{
+ return _script_;
+}
+
+const char* litehtml::el_script::get_tagName() const
{
- return _t("script");
+ return "script";
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_script.h b/src/plugins/litehtml_viewer/litehtml/el_script.h
index b8fed3697..e0a037405 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_script.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_script.h
@@ -7,14 +7,14 @@ namespace litehtml
{
class el_script : public element
{
- tstring m_text;
+ string m_text;
public:
- el_script(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_script();
+ explicit el_script(const std::shared_ptr<document>& doc);
- virtual void parse_attributes() override;
- virtual bool appendChild(const ptr &el) override;
- virtual const tchar_t* get_tagName() const override;
+ void parse_attributes() override;
+ bool appendChild(const ptr &el) override;
+ string_id tag() const override;
+ const char* get_tagName() const override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_space.cpp b/src/plugins/litehtml_viewer/litehtml/el_space.cpp
index 5178255f1..f5e3818ca 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_space.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_space.cpp
@@ -2,18 +2,13 @@
#include "document.h"
#include "el_space.h"
-litehtml::el_space::el_space(const tchar_t* text, const std::shared_ptr<litehtml::document>& doc) : el_text(text, doc)
+litehtml::el_space::el_space(const char* text, const std::shared_ptr<document>& doc) : el_text(text, doc)
{
}
-litehtml::el_space::~el_space()
-{
-
-}
-
bool litehtml::el_space::is_white_space() const
{
- white_space ws = get_white_space();
+ white_space ws = css().get_white_space();
if( ws == white_space_normal ||
ws == white_space_nowrap ||
ws == white_space_pre_line )
@@ -25,15 +20,25 @@ bool litehtml::el_space::is_white_space() const
bool litehtml::el_space::is_break() const
{
- white_space ws = get_white_space();
+ white_space ws = css().get_white_space();
if( ws == white_space_pre ||
ws == white_space_pre_line ||
ws == white_space_pre_wrap)
{
- if(m_text == _t("\n"))
+ if(m_text == "\n")
{
return true;
}
}
return false;
}
+
+bool litehtml::el_space::is_space() const
+{
+ return true;
+}
+
+litehtml::string litehtml::el_space::dump_get_name()
+{
+ return "space: \"" + get_escaped_string(m_text) + "\"";
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_space.h b/src/plugins/litehtml_viewer/litehtml/el_space.h
index 35ce88512..46a292ebc 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_space.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_space.h
@@ -9,11 +9,12 @@ namespace litehtml
class el_space : public el_text
{
public:
- el_space(const tchar_t* text, const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_space();
+ el_space(const char* text, const std::shared_ptr<document>& doc);
- virtual bool is_white_space() const override;
- virtual bool is_break() const override;
+ bool is_white_space() const override;
+ bool is_break() const override;
+ bool is_space() const override;
+ string dump_get_name() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_style.cpp b/src/plugins/litehtml_viewer/litehtml/el_style.cpp
index 1b1bb0e0f..cc2f0bab6 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_style.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_style.cpp
@@ -3,25 +3,20 @@
#include "document.h"
-litehtml::el_style::el_style(const std::shared_ptr<litehtml::document>& doc) : litehtml::element(doc)
-{
-
-}
-
-litehtml::el_style::~el_style()
+litehtml::el_style::el_style(const std::shared_ptr<document>& doc) : element(doc)
{
}
void litehtml::el_style::parse_attributes()
{
- tstring text;
+ string text;
for(auto& el : m_children)
{
el->get_text(text);
}
- get_document()->add_stylesheet( text.c_str(), 0, get_attr(_t("media")) );
+ get_document()->add_stylesheet( text.c_str(), nullptr, get_attr("media") );
}
bool litehtml::el_style::appendChild(const ptr &el)
@@ -30,7 +25,12 @@ bool litehtml::el_style::appendChild(const ptr &el)
return true;
}
-const litehtml::tchar_t* litehtml::el_style::get_tagName() const
+litehtml::string_id litehtml::el_style::tag() const
+{
+ return _style_;
+}
+
+const char* litehtml::el_style::get_tagName() const
{
- return _t("style");
+ return "style";
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_style.h b/src/plugins/litehtml_viewer/litehtml/el_style.h
index 8407b4b91..b6258932d 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_style.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_style.h
@@ -9,12 +9,12 @@ namespace litehtml
{
elements_vector m_children;
public:
- el_style(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_style();
+ explicit el_style(const std::shared_ptr<document>& doc);
- virtual void parse_attributes() override;
- virtual bool appendChild(const ptr &el) override;
- virtual const tchar_t* get_tagName() const override;
+ void parse_attributes() override;
+ bool appendChild(const ptr &el) override;
+ string_id tag() const override;
+ const char* get_tagName() const override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_table.cpp b/src/plugins/litehtml_viewer/litehtml/el_table.cpp
index 06d77be7d..d0c711c4d 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_table.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_table.cpp
@@ -2,106 +2,70 @@
#include "el_table.h"
#include "document.h"
#include "iterators.h"
-#include <algorithm>
-litehtml::el_table::el_table(const std::shared_ptr<litehtml::document>& doc) : html_tag(doc)
+litehtml::el_table::el_table(const std::shared_ptr<document>& doc) : html_tag(doc)
{
- m_border_spacing_x = 0;
- m_border_spacing_y = 0;
- m_border_collapse = border_collapse_separate;
}
-litehtml::el_table::~el_table()
-{
-
-}
-
-bool litehtml::el_table::appendChild(const litehtml::element::ptr& el)
+bool litehtml::el_table::appendChild(const element::ptr& el)
{
if(!el) return false;
- if(!t_strcmp(el->get_tagName(), _t("tbody")) || !t_strcmp(el->get_tagName(), _t("thead")) || !t_strcmp(el->get_tagName(), _t("tfoot")))
+ if( el->tag() == _tbody_ ||
+ el->tag() == _thead_ ||
+ el->tag() == _tfoot_ ||
+ el->tag() == _caption_)
{
return html_tag::appendChild(el);
}
return false;
}
-void litehtml::el_table::parse_styles(bool is_reparse)
-{
- html_tag::parse_styles(is_reparse);
-
- m_border_collapse = (border_collapse) value_index(get_style_property(_t("border-collapse"), true, _t("separate")), border_collapse_strings, border_collapse_separate);
-
- if(m_border_collapse == border_collapse_separate)
- {
- m_css_border_spacing_x.fromString(get_style_property(_t("-litehtml-border-spacing-x"), true, _t("0px")));
- m_css_border_spacing_y.fromString(get_style_property(_t("-litehtml-border-spacing-y"), true, _t("0px")));
-
- int fntsz = get_font_size();
- document::ptr doc = get_document();
- m_border_spacing_x = doc->cvt_units(m_css_border_spacing_x, fntsz);
- m_border_spacing_y = doc->cvt_units(m_css_border_spacing_y, fntsz);
- } else
- {
- m_border_spacing_x = 0;
- m_border_spacing_y = 0;
- m_padding.bottom = 0;
- m_padding.top = 0;
- m_padding.left = 0;
- m_padding.right = 0;
- m_css_padding.bottom.set_value(0, css_units_px);
- m_css_padding.top.set_value(0, css_units_px);
- m_css_padding.left.set_value(0, css_units_px);
- m_css_padding.right.set_value(0, css_units_px);
- }
-}
-
void litehtml::el_table::parse_attributes()
{
- const tchar_t* str = get_attr(_t("width"));
+ const char* str = get_attr("width");
if(str)
{
- m_style.add_property(_t("width"), str, 0, false);
+ m_style.add_property(_width_, str);
}
- str = get_attr(_t("align"));
+ str = get_attr("align");
if(str)
{
- int align = value_index(str, _t("left;center;right"));
+ int align = value_index(str, "left;center;right");
switch(align)
{
case 1:
- m_style.add_property(_t("margin-left"), _t("auto"), 0, false);
- m_style.add_property(_t("margin-right"), _t("auto"), 0, false);
+ m_style.add_property(_margin_left_, "auto");
+ m_style.add_property(_margin_right_, "auto");
break;
case 2:
- m_style.add_property(_t("margin-left"), _t("auto"), 0, false);
- m_style.add_property(_t("margin-right"), _t("0"), 0, false);
+ m_style.add_property(_margin_left_, "auto");
+ m_style.add_property(_margin_right_, "0");
break;
}
}
- str = get_attr(_t("cellspacing"));
+ str = get_attr("cellspacing");
if(str)
{
- tstring val = str;
- val += _t(" ");
+ string val = str;
+ val += " ";
val += str;
- m_style.add_property(_t("border-spacing"), val.c_str(), 0, false);
+ m_style.add_property(_border_spacing_, val);
}
- str = get_attr(_t("border"));
+ str = get_attr("border");
if(str)
{
- m_style.add_property(_t("border-width"), str, 0, false);
+ m_style.add_property(_border_width_, str);
}
- str = get_attr(_t("bgcolor"));
+ str = get_attr("bgcolor");
if (str)
{
- m_style.add_property(_t("background-color"), str, 0, false);
+ m_style.add_property(_background_color_, str, "", false, get_document()->container());
}
html_tag::parse_attributes();
diff --git a/src/plugins/litehtml_viewer/litehtml/el_table.h b/src/plugins/litehtml_viewer/litehtml/el_table.h
index f1ef97315..38352503b 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_table.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_table.h
@@ -15,12 +15,10 @@ namespace litehtml
class el_table : public html_tag
{
public:
- el_table(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_table();
+ explicit el_table(const std::shared_ptr<litehtml::document>& doc);
- virtual bool appendChild(const litehtml::element::ptr& el) override;
- virtual void parse_styles(bool is_reparse = false) override;
- virtual void parse_attributes() override;
+ bool appendChild(const litehtml::element::ptr& el) override;
+ void parse_attributes() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_td.cpp b/src/plugins/litehtml_viewer/litehtml/el_td.cpp
index ca214402d..679d9212a 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_td.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_td.cpp
@@ -2,48 +2,42 @@
#include "el_td.h"
-litehtml::el_td::el_td(const std::shared_ptr<litehtml::document>& doc) : html_tag(doc)
-{
-
-}
-
-litehtml::el_td::~el_td()
+litehtml::el_td::el_td(const std::shared_ptr<document>& doc) : html_tag(doc)
{
}
void litehtml::el_td::parse_attributes()
{
- const tchar_t* str = get_attr(_t("width"));
+ const char* str = get_attr("width");
if(str)
{
- m_style.add_property(_t("width"), str, 0, false);
+ m_style.add_property(_width_, str);
}
- str = get_attr(_t("background"));
+ str = get_attr("background");
if(str)
{
- tstring url = _t("url('");
+ string url = "url('";
url += str;
- url += _t("')");
- m_style.add_property(_t("background-image"), url.c_str(), 0, false);
+ url += "')";
+ m_style.add_property(_background_image_, url);
}
- str = get_attr(_t("align"));
+ str = get_attr("align");
if(str)
{
- m_style.add_property(_t("text-align"), str, 0, false);
+ m_style.add_property(_text_align_, str);
}
- str = get_attr(_t("bgcolor"));
+ str = get_attr("bgcolor");
if (str)
{
- m_style.add_property(_t("background-color"), str, 0, false);
+ m_style.add_property(_background_color_, str, "", false, get_document()->container());
}
- str = get_attr(_t("valign"));
+ str = get_attr("valign");
if(str)
{
- m_style.add_property(_t("vertical-align"), str, 0, false);
+ m_style.add_property(_vertical_align_, str);
}
html_tag::parse_attributes();
}
-
diff --git a/src/plugins/litehtml_viewer/litehtml/el_td.h b/src/plugins/litehtml_viewer/litehtml/el_td.h
index 5dce950a4..03d21c1c7 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_td.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_td.h
@@ -8,10 +8,9 @@ namespace litehtml
class el_td : public html_tag
{
public:
- el_td(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_td();
+ explicit el_td(const std::shared_ptr<litehtml::document>& doc);
- virtual void parse_attributes() override;
+ void parse_attributes() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_text.cpp b/src/plugins/litehtml_viewer/litehtml/el_text.cpp
index 9fad2a45a..a22224a35 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_text.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_text.cpp
@@ -1,21 +1,16 @@
#include "html.h"
#include "el_text.h"
-#include "document.h"
+#include "render_item.h"
-litehtml::el_text::el_text(const tchar_t* text, const std::shared_ptr<litehtml::document>& doc) : element(doc)
+litehtml::el_text::el_text(const char* text, const document::ptr& doc) : element(doc)
{
if(text)
{
m_text = text;
}
- m_text_transform = text_transform_none;
m_use_transformed = false;
m_draw_spaces = true;
-}
-
-litehtml::el_text::~el_text()
-{
-
+ css_w().set_display(display_inline_text);
}
void litehtml::el_text::get_content_size( size& sz, int max_width )
@@ -23,60 +18,77 @@ void litehtml::el_text::get_content_size( size& sz, int max_width )
sz = m_size;
}
-void litehtml::el_text::get_text( tstring& text )
+void litehtml::el_text::get_text( string& text )
{
text += m_text;
}
-const litehtml::tchar_t* litehtml::el_text::get_style_property( const tchar_t* name, bool inherited, const tchar_t* def /*= 0*/ )
-{
- if(inherited)
- {
- element::ptr el_parent = parent();
- if (el_parent)
- {
- return el_parent->get_style_property(name, inherited, def);
- }
- }
- return def;
-}
-
-void litehtml::el_text::parse_styles(bool is_reparse)
+void litehtml::el_text::compute_styles(bool recursive)
{
- m_text_transform = (text_transform) value_index(get_style_property(_t("text-transform"), true, _t("none")), text_transform_strings, text_transform_none);
- if(m_text_transform != text_transform_none)
+ element::ptr el_parent = parent();
+ if (el_parent)
+ {
+ css_w().set_line_height(el_parent->css().get_line_height());
+ css_w().set_font(el_parent->css().get_font());
+ css_w().set_font_metrics(el_parent->css().get_font_metrics());
+ css_w().set_white_space(el_parent->css().get_white_space());
+ css_w().set_text_transform(el_parent->css().get_text_transform());
+ }
+ css_w().set_display(display_inline_text);
+ css_w().set_float(float_none);
+
+ if(m_css.get_text_transform() != text_transform_none)
{
m_transformed_text = m_text;
m_use_transformed = true;
- get_document()->container()->transform_text(m_transformed_text, m_text_transform);
+ get_document()->container()->transform_text(m_transformed_text, m_css.get_text_transform());
+ } else
+ {
+ m_use_transformed = false;
}
+ element::ptr p = parent();
+ while(p && p->css().get_display() == display_inline)
+ {
+ if(p->css().get_position() == element_position_relative)
+ {
+ css_w().set_offsets(p->css().get_offsets());
+ css_w().set_position(element_position_relative);
+ break;
+ }
+ p = p->parent();
+ }
+ if(p)
+ {
+ css_w().set_position(element_position_static);
+ }
+
if(is_white_space())
{
- m_transformed_text = _t(" ");
+ m_transformed_text = " ";
m_use_transformed = true;
} else
{
- if(m_text == _t("\t"))
+ if(m_text == "\t")
{
- m_transformed_text = _t(" ");
+ m_transformed_text = " ";
m_use_transformed = true;
}
- if(m_text == _t("\n") || m_text == _t("\r"))
+ if(m_text == "\n" || m_text == "\r")
{
- m_transformed_text = _t("");
+ m_transformed_text = "";
m_use_transformed = true;
}
}
font_metrics fm;
uint_ptr font = 0;
- element::ptr el_parent = parent();
if (el_parent)
{
- font = el_parent->get_font(&fm);
+ font = el_parent->css().get_font();
+ fm = el_parent->css().get_font_metrics();
}
- if(is_break())
+ if(is_break() || !font)
{
m_size.height = 0;
m_size.width = 0;
@@ -88,24 +100,14 @@ void litehtml::el_text::parse_styles(bool is_reparse)
m_draw_spaces = fm.draw_spaces;
}
-int litehtml::el_text::get_base_line()
-{
- element::ptr el_parent = parent();
- if (el_parent)
- {
- return el_parent->get_base_line();
- }
- return 0;
-}
-
-void litehtml::el_text::draw( uint_ptr hdc, int x, int y, const position* clip )
+void litehtml::el_text::draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri)
{
if(is_white_space() && !m_draw_spaces)
{
return;
}
- position pos = m_pos;
+ position pos = ri->pos();
pos.x += x;
pos.y += y;
@@ -116,73 +118,23 @@ void litehtml::el_text::draw( uint_ptr hdc, int x, int y, const position* clip )
{
document::ptr doc = get_document();
- uint_ptr font = el_parent->get_font();
- litehtml::web_color color = el_parent->get_color(_t("color"), true, doc->get_def_color());
- doc->container()->draw_text(hdc, m_use_transformed ? m_transformed_text.c_str() : m_text.c_str(), font, color, pos);
+ uint_ptr font = el_parent->css().get_font();
+ if(font)
+ {
+ web_color color = el_parent->css().get_color();
+ doc->container()->draw_text(hdc, m_use_transformed ? m_transformed_text.c_str() : m_text.c_str(), font,
+ color, pos);
+ }
}
}
}
-int litehtml::el_text::line_height() const
-{
- element::ptr el_parent = parent();
- if (el_parent)
- {
- return el_parent->line_height();
- }
- return 0;
-}
-
-litehtml::uint_ptr litehtml::el_text::get_font( font_metrics* fm /*= 0*/ )
-{
- element::ptr el_parent = parent();
- if (el_parent)
- {
- return el_parent->get_font(fm);
- }
- return 0;
-}
-
-litehtml::style_display litehtml::el_text::get_display() const
-{
- return display_inline_text;
-}
-
-litehtml::white_space litehtml::el_text::get_white_space() const
+litehtml::string litehtml::el_text::dump_get_name()
{
- element::ptr el_parent = parent();
- if (el_parent) return el_parent->get_white_space();
- return white_space_normal;
+ return "text: \"" + get_escaped_string(m_text) + "\"";
}
-litehtml::element_position litehtml::el_text::get_element_position(css_offsets* offsets) const
+std::vector<std::tuple<litehtml::string, litehtml::string>> litehtml::el_text::dump_get_attrs()
{
- element::ptr p = parent();
- while(p && p->get_display() == display_inline)
- {
- if(p->get_element_position() == element_position_relative)
- {
- if(offsets)
- {
- *offsets = p->get_css_offsets();
- }
- return element_position_relative;
- }
- p = p->parent();
- }
- return element_position_static;
-}
-
-litehtml::css_offsets litehtml::el_text::get_css_offsets() const
-{
- element::ptr p = parent();
- while(p && p->get_display() == display_inline)
- {
- if(p->get_element_position() == element_position_relative)
- {
- return p->get_css_offsets();
- }
- p = p->parent();
- }
- return css_offsets();
+ return std::vector<std::tuple<string, string>>();
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_text.h b/src/plugins/litehtml_viewer/litehtml/el_text.h
index d2149deb2..4b8a442f3 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_text.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_text.h
@@ -8,30 +8,23 @@ namespace litehtml
class el_text : public element
{
protected:
- tstring m_text;
- tstring m_transformed_text;
+ string m_text;
+ string m_transformed_text;
size m_size;
- text_transform m_text_transform;
bool m_use_transformed;
bool m_draw_spaces;
public:
- el_text(const tchar_t* text, const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_text();
+ el_text(const char* text, const document::ptr& doc);
- virtual void get_text(tstring& text) override;
- virtual const tchar_t* get_style_property(const tchar_t* name, bool inherited, const tchar_t* def = 0) override;
- virtual void parse_styles(bool is_reparse) override;
- virtual int get_base_line() override;
- virtual void draw(uint_ptr hdc, int x, int y, const position* clip) override;
- virtual int line_height() const override;
- virtual uint_ptr get_font(font_metrics* fm = 0) override;
- virtual style_display get_display() const override;
- virtual white_space get_white_space() const override;
- virtual element_position get_element_position(css_offsets* offsets = 0) const override;
- virtual css_offsets get_css_offsets() const override;
+ void get_text(string& text) override;
+ void compute_styles(bool recursive) override;
+ bool is_text() const override { return true; }
+ void draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri) override;
+ string dump_get_name() override;
+ std::vector<std::tuple<string, string>> dump_get_attrs() override;
protected:
- virtual void get_content_size(size& sz, int max_width) override;
+ void get_content_size(size& sz, int max_width) override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_title.cpp b/src/plugins/litehtml_viewer/litehtml/el_title.cpp
index 7a9590d18..f0e42311b 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_title.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_title.cpp
@@ -2,19 +2,15 @@
#include "el_title.h"
#include "document.h"
-litehtml::el_title::el_title(const std::shared_ptr<litehtml::document>& doc) : litehtml::html_tag(doc)
-{
-
-}
-
-litehtml::el_title::~el_title()
+litehtml::el_title::el_title(const std::shared_ptr<document>& doc) : html_tag(doc)
{
}
void litehtml::el_title::parse_attributes()
{
- tstring text;
+ string text;
get_text(text);
get_document()->container()->set_caption(text.c_str());
}
+
diff --git a/src/plugins/litehtml_viewer/litehtml/el_title.h b/src/plugins/litehtml_viewer/litehtml/el_title.h
index 20dc8cdd6..201186a4a 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_title.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_title.h
@@ -8,11 +8,10 @@ namespace litehtml
class el_title : public html_tag
{
public:
- el_title(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_title();
+ explicit el_title(const std::shared_ptr<litehtml::document>& doc);
protected:
- virtual void parse_attributes() override;
+ void parse_attributes() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/el_tr.cpp b/src/plugins/litehtml_viewer/litehtml/el_tr.cpp
index 0ef0675b5..f10997654 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_tr.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_tr.cpp
@@ -2,50 +2,27 @@
#include "el_tr.h"
-litehtml::el_tr::el_tr(const std::shared_ptr<litehtml::document>& doc) : html_tag(doc)
-{
-
-}
-
-litehtml::el_tr::~el_tr()
+litehtml::el_tr::el_tr(const std::shared_ptr<document>& doc) : html_tag(doc)
{
}
void litehtml::el_tr::parse_attributes()
{
- const tchar_t* str = get_attr(_t("align"));
+ const char* str = get_attr("align");
if(str)
{
- m_style.add_property(_t("text-align"), str, 0, false);
+ m_style.add_property(_text_align_, str);
}
- str = get_attr(_t("valign"));
+ str = get_attr("valign");
if(str)
{
- m_style.add_property(_t("vertical-align"), str, 0, false);
+ m_style.add_property(_vertical_align_, str);
}
- str = get_attr(_t("bgcolor"));
+ str = get_attr("bgcolor");
if (str)
{
- m_style.add_property(_t("background-color"), str, 0, false);
+ m_style.add_property(_background_color_, str, "", false, get_document()->container());
}
html_tag::parse_attributes();
}
-
-void litehtml::el_tr::get_inline_boxes( position::vector& boxes )
-{
- position pos;
- for(auto& el : m_children)
- {
- if(el->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/el_tr.h b/src/plugins/litehtml_viewer/litehtml/el_tr.h
index 0fbb6c28d..49c0b9a9b 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_tr.h
+++ b/src/plugins/litehtml_viewer/litehtml/el_tr.h
@@ -8,11 +8,9 @@ namespace litehtml
class el_tr : public html_tag
{
public:
- el_tr(const std::shared_ptr<litehtml::document>& doc);
- virtual ~el_tr();
+ explicit el_tr(const std::shared_ptr<litehtml::document>& doc);
- virtual void parse_attributes() override;
- virtual void get_inline_boxes(position::vector& boxes) override;
+ void parse_attributes() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/element.cpp b/src/plugins/litehtml_viewer/litehtml/element.cpp
index 67a500236..2438b1325 100644
--- a/src/plugins/litehtml_viewer/litehtml/element.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/element.cpp
@@ -1,410 +1,330 @@
#include "html.h"
#include "element.h"
#include "document.h"
+#include "render_item.h"
+#include "el_before_after.h"
+
+namespace litehtml
+{
#define LITEHTML_EMPTY_FUNC {}
#define LITEHTML_RETURN_FUNC(ret) {return ret;}
-litehtml::element::element(const std::shared_ptr<litehtml::document>& doc) : m_doc(doc)
+element::element(const document::ptr& doc) : m_doc(doc)
{
- m_box = 0;
- m_skip = false;
}
-litehtml::element::~element()
+position element::get_placement() const
{
-
-}
-
-
-bool litehtml::element::is_point_inside( int x, int y )
-{
- if(get_display() != display_inline && get_display() != display_table_row)
+ position pos;
+ bool is_first = true;
+ for(const auto& ri_el : m_renders)
{
- position pos = m_pos;
- pos += m_padding;
- pos += m_borders;
- if(pos.is_point_inside(x, y))
- {
- return true;
- } else
+ auto ri = ri_el.lock();
+ if(ri)
{
- return false;
- }
- } else
- {
- position::vector boxes;
- get_inline_boxes(boxes);
- for(position::vector::iterator box = boxes.begin(); box != boxes.end(); box++)
- {
- if(box->is_point_inside(x, y))
+ position ri_pos = ri_el.lock()->get_placement();
+ if(is_first)
{
- return true;
+ is_first = false;
+ pos = ri_pos;
+ } else
+ {
+ if(pos.x < ri_pos.x)
+ {
+ pos.x = ri_pos.x;
+ }
+ if(pos.y < ri_pos.y)
+ {
+ pos.y = ri_pos.y;
+ }
}
}
}
- return false;
+ return pos;
}
-litehtml::web_color litehtml::element::get_color( const tchar_t* prop_name, bool inherited, const litehtml::web_color& def_color )
+bool element::is_inline_box() const
{
- const tchar_t* clrstr = get_style_property(prop_name, inherited, 0);
- if(!clrstr)
+ if( css().get_display() == display_inline ||
+ css().get_display() == display_inline_table ||
+ css().get_display() == display_inline_block ||
+ css().get_display() == display_inline_text ||
+ css().get_display() == display_inline_flex)
{
- return def_color;
+ return true;
}
- return web_color::from_string(clrstr, get_document()->container());
+ return false;
}
-litehtml::position litehtml::element::get_placement() const
+bool element::is_ancestor(const ptr &el) const
{
- litehtml::position pos = m_pos;
- element::ptr cur_el = parent();
- while(cur_el)
+ element::ptr el_parent = parent();
+ while(el_parent && el_parent != el)
{
- pos.x += cur_el->m_pos.x;
- pos.y += cur_el->m_pos.y;
- cur_el = cur_el->parent();
+ el_parent = el_parent->parent();
}
- return pos;
-}
-
-bool litehtml::element::is_inline_box() const
-{
- style_display d = get_display();
- if( d == display_inline ||
- d == display_inline_table ||
- d == display_inline_block ||
- d == display_inline_text)
+ if(el_parent)
{
return true;
}
return false;
}
-bool litehtml::element::collapse_top_margin() const
+bool element::is_table_skip() const
{
- if(!m_borders.top && !m_padding.top && in_normal_flow() && get_float() == float_none && m_margins.top >= 0 && have_parent())
- {
- return true;
- }
- return false;
+ return is_space() || is_comment() || css().get_display() == display_none;
}
-bool litehtml::element::collapse_bottom_margin() const
+string element::dump_get_name()
{
- if(!m_borders.bottom && !m_padding.bottom && in_normal_flow() && get_float() == float_none && m_margins.bottom >= 0 && have_parent())
- {
- return true;
- }
- return false;
+ return "element";
}
-bool litehtml::element::get_predefined_height(int& p_height) const
+std::vector<std::tuple<string, string>> element::dump_get_attrs()
{
- css_length h = get_css_height();
- if(h.is_predefined())
- {
- p_height = m_pos.height;
- return false;
- }
- if(h.units() == css_units_percentage)
- {
- element::ptr el_parent = parent();
- if (!el_parent)
- {
- position client_pos;
- get_document()->container()->get_client_rect(client_pos);
- p_height = h.calc_percent(client_pos.height);
- return true;
- } else
- {
- int ph = 0;
- if (el_parent->get_predefined_height(ph))
- {
- p_height = h.calc_percent(ph);
- if (is_body())
- {
- p_height -= content_margins_height();
- }
- return true;
- } else
- {
- p_height = m_pos.height;
- return false;
- }
- }
- }
- p_height = get_document()->cvt_units(h, get_font_size());
- return true;
+ return m_css.dump_get_attrs();
}
-void litehtml::element::calc_document_size( litehtml::size& sz, int x /*= 0*/, int y /*= 0*/ )
+void element::dump(dumper& cout)
{
- if(is_visible())
+ cout.begin_node(dump_get_name());
+
+ auto attrs = dump_get_attrs();
+ if(!attrs.empty())
{
- sz.width = std::max(sz.width, x + right());
- sz.height = std::max(sz.height, y + bottom());
+ cout.begin_attrs_group("attributes");
+ for (const auto &attr: attrs)
+ {
+ cout.add_attr(std::get<0>(attr), std::get<1>(attr));
+ }
+ cout.end_attrs_group();
}
-}
-void litehtml::element::get_redraw_box(litehtml::position& pos, int x /*= 0*/, int y /*= 0*/)
-{
- if(is_visible())
+ if(!m_children.empty())
{
- int p_left = std::min(pos.left(), x + m_pos.left() - m_padding.left - m_borders.left);
- int p_right = std::max(pos.right(), x + m_pos.right() + m_padding.left + m_borders.left);
- int p_top = std::min(pos.top(), y + m_pos.top() - m_padding.top - m_borders.top);
- int p_bottom = std::max(pos.bottom(), y + m_pos.bottom() + m_padding.bottom + m_borders.bottom);
-
- pos.x = p_left;
- pos.y = p_top;
- pos.width = p_right - p_left;
- pos.height = p_bottom - p_top;
+ cout.begin_attrs_group("children");
+ for (const auto &el: m_children)
+ {
+ el->dump(cout);
+ }
+ cout.end_attrs_group();
}
+
+ cout.end_node();
}
-int litehtml::element::calc_width(int defVal) const
+std::shared_ptr<render_item> element::create_render_item(const std::shared_ptr<render_item>& parent_ri)
{
- css_length w = get_css_width();
- if(w.is_predefined())
+ std::shared_ptr<render_item> ret;
+
+ if(css().get_display() == display_table_column ||
+ css().get_display() == display_table_column_group ||
+ css().get_display() == display_table_footer_group ||
+ css().get_display() == display_table_header_group ||
+ css().get_display() == display_table_row_group)
+ {
+ ret = std::make_shared<render_item_table_part>(shared_from_this());
+ } else if(css().get_display() == display_table_row)
{
- return defVal;
+ ret = std::make_shared<render_item_table_row>(shared_from_this());
+ } else if(css().get_display() == display_block ||
+ css().get_display() == display_table_cell ||
+ css().get_display() == display_table_caption ||
+ css().get_display() == display_list_item ||
+ css().get_display() == display_inline_block)
+ {
+ ret = std::make_shared<render_item_block>(shared_from_this());
+ } else if(css().get_display() == display_table || css().get_display() == display_inline_table)
+ {
+ ret = std::make_shared<render_item_table>(shared_from_this());
+ } else if(css().get_display() == display_inline || css().get_display() == display_inline_text)
+ {
+ ret = std::make_shared<render_item_inline>(shared_from_this());
+ } else if(css().get_display() == display_flex || css().get_display() == display_inline_flex)
+ {
+ ret = std::make_shared<render_item_flex>(shared_from_this());
}
- if(w.units() == css_units_percentage)
+ if(ret)
{
- element::ptr el_parent = parent();
- if (!el_parent)
+ if (css().get_display() == display_table ||
+ css().get_display() == display_inline_table ||
+ css().get_display() == display_table_caption ||
+ css().get_display() == display_table_cell ||
+ css().get_display() == display_table_column ||
+ css().get_display() == display_table_column_group ||
+ css().get_display() == display_table_footer_group ||
+ css().get_display() == display_table_header_group ||
+ css().get_display() == display_table_row ||
+ css().get_display() == display_table_row_group)
{
- position client_pos;
- get_document()->container()->get_client_rect(client_pos);
- return w.calc_percent(client_pos.width);
- } else
+ get_document()->add_tabular(ret);
+ }
+
+ ret->parent(parent_ri);
+ for(const auto& el : m_children)
{
- int pw = el_parent->calc_width(defVal);
- if (is_body())
+ auto ri = el->create_render_item(ret);
+ if(ri)
{
- pw -= content_margins_width();
+ ret->add_child(ri);
}
- return w.calc_percent(pw);
}
}
- return get_document()->cvt_units(w, get_font_size());
-}
-
-bool litehtml::element::is_ancestor(const ptr &el) const
-{
- element::ptr el_parent = parent();
- while(el_parent && el_parent != el)
- {
- el_parent = el_parent->parent();
- }
- if(el_parent)
- {
- return true;
- }
- return false;
+ return ret;
}
-int litehtml::element::get_inline_shift_left()
+bool element::requires_styles_update()
{
- int ret = 0;
- element::ptr el_parent = parent();
- if (el_parent)
+ for (const auto& used_style : m_used_styles)
{
- if (el_parent->get_display() == display_inline)
+ if(used_style->m_selector->is_media_valid())
{
- style_display disp = get_display();
-
- if (disp == display_inline_text || disp == display_inline_block)
+ int res = select(*(used_style->m_selector), true);
+ if( (res == select_no_match && used_style->m_used) || (res == select_match && !used_style->m_used) )
{
- element::ptr el = shared_from_this();
- while (el_parent && el_parent->get_display() == display_inline)
- {
- if (el_parent->is_first_child_inline(el))
- {
- ret += el_parent->padding_left() + el_parent->border_left() + el_parent->margin_left();
- }
- el = el_parent;
- el_parent = el_parent->parent();
- }
+ return true;
}
}
}
+ return false;
+}
- return ret;
+void element::add_render(const std::shared_ptr<render_item>& ri)
+{
+ m_renders.push_back(ri);
}
-int litehtml::element::get_inline_shift_right()
+bool element::find_styles_changes( position::vector& redraw_boxes)
{
- int ret = 0;
- element::ptr el_parent = parent();
- if (el_parent)
+ if(css().get_display() == display_inline_text)
{
- if (el_parent->get_display() == display_inline)
- {
- style_display disp = get_display();
+ return false;
+ }
+
+ bool ret = false;
- if (disp == display_inline_text || disp == display_inline_block)
+ if(requires_styles_update())
+ {
+ auto fetch_boxes = [&](const std::shared_ptr<element>& el)
{
- element::ptr el = shared_from_this();
- while (el_parent && el_parent->get_display() == display_inline)
+ for(const auto& weak_ri : el->m_renders)
{
- if (el_parent->is_last_child_inline(el))
+ auto ri = weak_ri.lock();
+ if(ri)
{
- ret += el_parent->padding_right() + el_parent->border_right() + el_parent->margin_right();
+ position::vector boxes;
+ ri->get_rendering_boxes(boxes);
+ for (auto &box: boxes)
+ {
+ redraw_boxes.push_back(box);
+ }
}
- el = el_parent;
- el_parent = el_parent->parent();
}
- }
+ };
+ fetch_boxes(shared_from_this());
+ for (auto& el : m_children)
+ {
+ fetch_boxes(el);
}
- }
+ refresh_styles();
+ compute_styles();
+ ret = true;
+ }
+ for (auto& el : m_children)
+ {
+ if(el->find_styles_changes(redraw_boxes))
+ {
+ ret = true;
+ }
+ }
return ret;
}
-void litehtml::element::apply_relative_shift(int parent_width)
+element::ptr element::_add_before_after(int type, const style& style)
{
- css_offsets offsets;
- if (get_element_position(&offsets) == element_position_relative)
+ if(style.get_property(_content_).m_type != prop_type_invalid)
{
- element::ptr parent_ptr = parent();
- if (!offsets.left.is_predefined())
+ element::ptr el;
+ if(type == 0)
{
- m_pos.x += offsets.left.calc_percent(parent_width);
- }
- else if (!offsets.right.is_predefined())
+ el = std::make_shared<el_before>(get_document());
+ m_children.insert(m_children.begin(), el);
+ } else
{
- m_pos.x -= offsets.right.calc_percent(parent_width);
+ el = std::make_shared<el_after>(get_document());
+ m_children.insert(m_children.end(), el);
}
- if (!offsets.top.is_predefined())
- {
- int h = 0;
-
- if (offsets.top.units() == css_units_percentage)
- {
- element::ptr el_parent = parent();
- if (el_parent)
- {
- el_parent->get_predefined_height(h);
- }
- }
+ el->parent(shared_from_this());
+ return el;
+ }
+ return nullptr;
+}
- m_pos.y += offsets.top.calc_percent(h);
- }
- else if (!offsets.bottom.is_predefined())
- {
- int h = 0;
- if (offsets.top.units() == css_units_percentage)
- {
- element::ptr el_parent = parent();
- if (el_parent)
- {
- el_parent->get_predefined_height(h);
- }
- }
+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())
+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)
+element::ptr element::find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo /*= true*/, bool* is_pseudo /*= 0*/) LITEHTML_RETURN_FUNC(nullptr)
+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)
+void element::clearRecursive() LITEHTML_EMPTY_FUNC
+string_id element::id() const LITEHTML_RETURN_FUNC(empty_id)
+string_id element::tag() const LITEHTML_RETURN_FUNC(empty_id)
+const char* element::get_tagName() const LITEHTML_RETURN_FUNC("")
+void element::set_tagName( const char* tag ) LITEHTML_EMPTY_FUNC
+void element::set_data( const char* data ) LITEHTML_EMPTY_FUNC
+void element::set_attr( const char* name, const char* val ) LITEHTML_EMPTY_FUNC
+void element::apply_stylesheet( const litehtml::css& stylesheet ) LITEHTML_EMPTY_FUNC
+void element::refresh_styles() LITEHTML_EMPTY_FUNC
+void element::on_click() LITEHTML_EMPTY_FUNC
+void element::compute_styles( bool recursive ) LITEHTML_EMPTY_FUNC
+const char* element::get_attr( const char* name, const char* def /*= 0*/ ) const LITEHTML_RETURN_FUNC(def)
+bool element::is_white_space() const LITEHTML_RETURN_FUNC(false)
+bool element::is_space() const LITEHTML_RETURN_FUNC(false)
+bool element::is_comment() const LITEHTML_RETURN_FUNC(false)
+bool element::is_body() const LITEHTML_RETURN_FUNC(false)
+bool element::is_break() const LITEHTML_RETURN_FUNC(false)
+bool element::is_text() const LITEHTML_RETURN_FUNC(false)
- m_pos.y -= offsets.bottom.calc_percent(h);
- }
- }
-}
+bool element::on_mouse_over() LITEHTML_RETURN_FUNC(false)
+bool element::on_mouse_leave() LITEHTML_RETURN_FUNC(false)
+bool element::on_lbutton_down() LITEHTML_RETURN_FUNC(false)
+bool element::on_lbutton_up() LITEHTML_RETURN_FUNC(false)
+bool element::set_pseudo_class( string_id cls, bool add ) LITEHTML_RETURN_FUNC(false)
+bool element::set_class( const char* pclass, bool add ) LITEHTML_RETURN_FUNC(false)
+bool element::is_replaced() const LITEHTML_RETURN_FUNC(false)
+void element::draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri) LITEHTML_EMPTY_FUNC
+void element::draw_background(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri) LITEHTML_EMPTY_FUNC
+int element::get_enum_property (string_id name, bool inherited, int defval, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC(0)
+css_length element::get_length_property (string_id name, bool inherited, css_length defval, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC(0)
+web_color element::get_color_property (string_id name, bool inherited, web_color defval, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC(web_color())
+string element::get_string_property (string_id name, bool inherited, const string& defval, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC("")
+float element::get_number_property (string_id name, bool inherited, float defval, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC(0)
+string_vector element::get_string_vector_property (string_id name, bool inherited, const string_vector& default_value, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC({})
+int_vector element::get_int_vector_property (string_id name, bool inherited, const int_vector& default_value, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC({})
+length_vector element::get_length_vector_property (string_id name, bool inherited, const length_vector& default_value, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC({})
+size_vector element::get_size_vector_property (string_id name, bool inherited, const size_vector& default_value, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC({})
+string element::get_custom_property (string_id name, const string& defval) const LITEHTML_RETURN_FUNC("")
+void element::get_text( string& text ) LITEHTML_EMPTY_FUNC
+void element::parse_attributes() LITEHTML_EMPTY_FUNC
+int element::select(const string& selector) LITEHTML_RETURN_FUNC(select_no_match)
+int element::select(const css_selector& selector, bool apply_pseudo) LITEHTML_RETURN_FUNC(select_no_match)
+int element::select( const css_element_selector& selector, bool apply_pseudo /*= true*/ ) LITEHTML_RETURN_FUNC(select_no_match)
+element::ptr element::find_ancestor(const css_selector& selector, bool apply_pseudo, bool* is_pseudo) LITEHTML_RETURN_FUNC(nullptr)
-void litehtml::element::calc_auto_margins(int parent_width) LITEHTML_EMPTY_FUNC
-const litehtml::background* litehtml::element::get_background(bool own_only) LITEHTML_RETURN_FUNC(0)
-litehtml::element::ptr litehtml::element::get_element_by_point(int x, int y, int client_x, int client_y) LITEHTML_RETURN_FUNC(0)
-litehtml::element::ptr litehtml::element::get_child_by_point(int x, int y, int client_x, int client_y, draw_flag flag, int zindex) LITEHTML_RETURN_FUNC(0)
-void litehtml::element::get_line_left_right( int y, int def_right, int& ln_left, int& ln_right ) LITEHTML_EMPTY_FUNC
-void litehtml::element::add_style( const litehtml::style& st ) LITEHTML_EMPTY_FUNC
-void litehtml::element::select_all(const css_selector& selector, litehtml::elements_vector& res) LITEHTML_EMPTY_FUNC
-litehtml::elements_vector litehtml::element::select_all(const litehtml::css_selector& selector) LITEHTML_RETURN_FUNC(litehtml::elements_vector())
-litehtml::elements_vector litehtml::element::select_all(const litehtml::tstring& selector) LITEHTML_RETURN_FUNC(litehtml::elements_vector())
-litehtml::element::ptr litehtml::element::select_one( const css_selector& selector ) LITEHTML_RETURN_FUNC(0)
-litehtml::element::ptr litehtml::element::select_one( const tstring& selector ) LITEHTML_RETURN_FUNC(0)
-litehtml::element::ptr litehtml::element::find_adjacent_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo /*= true*/, bool* is_pseudo /*= 0*/) LITEHTML_RETURN_FUNC(0)
-litehtml::element::ptr litehtml::element::find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo /*= true*/, bool* is_pseudo /*= 0*/) LITEHTML_RETURN_FUNC(0)
-bool litehtml::element::is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::is_nth_child(const element::ptr&, int num, int off, bool of_type) const LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::is_only_child(const element::ptr& el, bool of_type) const LITEHTML_RETURN_FUNC(false)
-litehtml::overflow litehtml::element::get_overflow() const LITEHTML_RETURN_FUNC(overflow_visible)
-void litehtml::element::draw_children( uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex ) LITEHTML_EMPTY_FUNC
-void litehtml::element::draw_stacking_context( uint_ptr hdc, int x, int y, const position* clip, bool with_positioned ) LITEHTML_EMPTY_FUNC
-void litehtml::element::render_positioned(render_type rt) LITEHTML_EMPTY_FUNC
-int litehtml::element::get_zindex() const LITEHTML_RETURN_FUNC(0)
-bool litehtml::element::fetch_positioned() LITEHTML_RETURN_FUNC(false)
-litehtml::visibility litehtml::element::get_visibility() const LITEHTML_RETURN_FUNC(visibility_visible)
-void litehtml::element::apply_vertical_align() LITEHTML_EMPTY_FUNC
-void litehtml::element::set_css_width( css_length& w ) LITEHTML_EMPTY_FUNC
-litehtml::element::ptr litehtml::element::get_child( int idx ) const LITEHTML_RETURN_FUNC(0)
-size_t litehtml::element::get_children_count() const LITEHTML_RETURN_FUNC(0)
-void litehtml::element::calc_outlines( int parent_width ) LITEHTML_EMPTY_FUNC
-litehtml::css_length litehtml::element::get_css_width() const LITEHTML_RETURN_FUNC(css_length())
-litehtml::css_length litehtml::element::get_css_height() const LITEHTML_RETURN_FUNC(css_length())
-litehtml::element_clear litehtml::element::get_clear() const LITEHTML_RETURN_FUNC(clear_none)
-litehtml::css_length litehtml::element::get_css_left() const LITEHTML_RETURN_FUNC(css_length())
-litehtml::css_length litehtml::element::get_css_right() const LITEHTML_RETURN_FUNC(css_length())
-litehtml::css_length litehtml::element::get_css_top() const LITEHTML_RETURN_FUNC(css_length())
-litehtml::css_length litehtml::element::get_css_bottom() const LITEHTML_RETURN_FUNC(css_length())
-litehtml::css_offsets litehtml::element::get_css_offsets() const LITEHTML_RETURN_FUNC(css_offsets())
-litehtml::vertical_align litehtml::element::get_vertical_align() const LITEHTML_RETURN_FUNC(va_baseline)
-int litehtml::element::place_element(const ptr &el, int max_width) LITEHTML_RETURN_FUNC(0)
-int litehtml::element::render_inline(const ptr &container, int max_width) LITEHTML_RETURN_FUNC(0)
-void litehtml::element::add_positioned(const ptr &el) LITEHTML_EMPTY_FUNC
-int litehtml::element::find_next_line_top( int top, int width, int def_right ) LITEHTML_RETURN_FUNC(0)
-litehtml::element_float litehtml::element::get_float() const LITEHTML_RETURN_FUNC(float_none)
-void litehtml::element::add_float(const ptr &el, int x, int y) LITEHTML_EMPTY_FUNC
-void litehtml::element::update_floats(int dy, const ptr &parent) LITEHTML_EMPTY_FUNC
-int litehtml::element::get_line_left( int y ) LITEHTML_RETURN_FUNC(0)
-int litehtml::element::get_line_right( int y, int def_right ) LITEHTML_RETURN_FUNC(def_right)
-int litehtml::element::get_left_floats_height() const LITEHTML_RETURN_FUNC(0)
-int litehtml::element::get_right_floats_height() const LITEHTML_RETURN_FUNC(0)
-int litehtml::element::get_floats_height(element_float el_float) const LITEHTML_RETURN_FUNC(0)
-bool litehtml::element::is_floats_holder() const LITEHTML_RETURN_FUNC(false)
-void litehtml::element::get_content_size( size& sz, int max_width ) LITEHTML_EMPTY_FUNC
-void litehtml::element::init() LITEHTML_EMPTY_FUNC
-int litehtml::element::render( int x, int y, int max_width, bool second_pass ) LITEHTML_RETURN_FUNC(0)
-bool litehtml::element::appendChild(const ptr &el) LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::removeChild(const ptr &el) LITEHTML_RETURN_FUNC(false)
-void litehtml::element::clearRecursive() LITEHTML_EMPTY_FUNC
-const litehtml::tchar_t* litehtml::element::get_tagName() const LITEHTML_RETURN_FUNC(_t(""))
-void litehtml::element::set_tagName( const tchar_t* tag ) LITEHTML_EMPTY_FUNC
-void litehtml::element::set_data( const tchar_t* data ) LITEHTML_EMPTY_FUNC
-void litehtml::element::set_attr( const tchar_t* name, const tchar_t* val ) LITEHTML_EMPTY_FUNC
-void litehtml::element::apply_stylesheet( const litehtml::css& stylesheet ) LITEHTML_EMPTY_FUNC
-void litehtml::element::refresh_styles() LITEHTML_EMPTY_FUNC
-void litehtml::element::on_click() LITEHTML_EMPTY_FUNC
-void litehtml::element::init_font() LITEHTML_EMPTY_FUNC
-void litehtml::element::get_inline_boxes( position::vector& boxes ) LITEHTML_EMPTY_FUNC
-void litehtml::element::parse_styles( bool is_reparse /*= false*/ ) LITEHTML_EMPTY_FUNC
-const litehtml::tchar_t* litehtml::element::get_attr( const tchar_t* name, const tchar_t* def /*= 0*/ ) const LITEHTML_RETURN_FUNC(def)
-bool litehtml::element::is_white_space() const LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::is_body() const LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::is_break() const LITEHTML_RETURN_FUNC(false)
-int litehtml::element::get_base_line() LITEHTML_RETURN_FUNC(0)
-bool litehtml::element::on_mouse_over() LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::on_mouse_leave() LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::on_lbutton_down() LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::on_lbutton_up() LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::find_styles_changes( position::vector& redraw_boxes, int x, int y ) LITEHTML_RETURN_FUNC(false)
-const litehtml::tchar_t* litehtml::element::get_cursor() LITEHTML_RETURN_FUNC(0)
-litehtml::white_space litehtml::element::get_white_space() const LITEHTML_RETURN_FUNC(white_space_normal)
-litehtml::style_display litehtml::element::get_display() const LITEHTML_RETURN_FUNC(display_none)
-bool litehtml::element::set_pseudo_class( const tchar_t* pclass, bool add ) LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::set_class( const tchar_t* pclass, bool add ) LITEHTML_RETURN_FUNC(false)
-litehtml::element_position litehtml::element::get_element_position(css_offsets* offsets) const LITEHTML_RETURN_FUNC(element_position_static)
-bool litehtml::element::is_replaced() const LITEHTML_RETURN_FUNC(false)
-int litehtml::element::line_height() const LITEHTML_RETURN_FUNC(0)
-void litehtml::element::draw( uint_ptr hdc, int x, int y, const position* clip ) LITEHTML_EMPTY_FUNC
-void litehtml::element::draw_background( uint_ptr hdc, int x, int y, const position* clip ) LITEHTML_EMPTY_FUNC
-const litehtml::tchar_t* litehtml::element::get_style_property( const tchar_t* name, bool inherited, const tchar_t* def /*= 0*/ ) LITEHTML_RETURN_FUNC(0)
-litehtml::uint_ptr litehtml::element::get_font( font_metrics* fm /*= 0*/ ) LITEHTML_RETURN_FUNC(0)
-int litehtml::element::get_font_size() const LITEHTML_RETURN_FUNC(0)
-void litehtml::element::get_text( tstring& text ) LITEHTML_EMPTY_FUNC
-void litehtml::element::parse_attributes() LITEHTML_EMPTY_FUNC
-int litehtml::element::select( const css_selector& selector, bool apply_pseudo) LITEHTML_RETURN_FUNC(select_no_match)
-int litehtml::element::select( const css_element_selector& selector, bool apply_pseudo /*= true*/ ) LITEHTML_RETURN_FUNC(select_no_match)
-litehtml::element::ptr litehtml::element::find_ancestor(const css_selector& selector, bool apply_pseudo, bool* is_pseudo) LITEHTML_RETURN_FUNC(0)
-bool litehtml::element::is_first_child_inline(const element::ptr& el) const LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::is_last_child_inline(const element::ptr& el) LITEHTML_RETURN_FUNC(false)
-bool litehtml::element::have_inline_child() const LITEHTML_RETURN_FUNC(false)
+} // namespace litehtml
\ No newline at end of file
diff --git a/src/plugins/litehtml_viewer/litehtml/element.h b/src/plugins/litehtml_viewer/litehtml/element.h
index 5b91e28a3..2fa160c2c 100644
--- a/src/plugins/litehtml_viewer/litehtml/element.h
+++ b/src/plugins/litehtml_viewer/litehtml/element.h
@@ -2,341 +2,166 @@
#define LH_ELEMENT_H
#include <memory>
+#include <tuple>
+#include <list>
#include "stylesheet.h"
#include "css_offsets.h"
+#include "css_margins.h"
+#include "css_properties.h"
namespace litehtml
{
- class box;
+ class line_box;
+ class dumper;
+ class render_item;
class element : public std::enable_shared_from_this<element>
{
- friend class block_box;
friend class line_box;
friend class html_tag;
friend class el_table;
friend class document;
public:
- typedef std::shared_ptr<litehtml::element> ptr;
- typedef std::shared_ptr<const litehtml::element> const_ptr;
- typedef std::weak_ptr<litehtml::element> weak_ptr;
+ typedef std::shared_ptr<element> ptr;
+ typedef std::shared_ptr<const element> const_ptr;
+ typedef std::weak_ptr<element> weak_ptr;
protected:
- std::weak_ptr<element> m_parent;
- std::weak_ptr<litehtml::document> m_doc;
- litehtml::box* m_box;
- elements_vector m_children;
- position m_pos;
- margins m_margins;
- margins m_padding;
- margins m_borders;
- bool m_skip;
-
+ std::weak_ptr<element> m_parent;
+ std::weak_ptr<document> m_doc;
+ elements_vector 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);
+ element::ptr _add_before_after(int type, const style& style);
public:
- element(const std::shared_ptr<litehtml::document>& doc);
- virtual ~element();
-
- // returns refer to m_pos member;
- position& get_position();
-
- int left() const;
- int right() const;
- int top() const;
- int bottom() const;
- int height() const;
- int width() const;
-
- int content_margins_top() const;
- int content_margins_bottom() const;
- int content_margins_left() const;
- int content_margins_right() const;
- int content_margins_width() const;
- int content_margins_height() const;
+ explicit element(const std::shared_ptr<document>& doc);
+ virtual ~element() = default;
- int margin_top() const;
- int margin_bottom() const;
- int margin_left() const;
- int margin_right() const;
- margins get_margins() const;
-
- int padding_top() const;
- int padding_bottom() const;
- int padding_left() const;
- int padding_right() const;
- margins get_paddings() const;
-
- int border_top() const;
- int border_bottom() const;
- int border_left() const;
- int border_right() const;
- margins get_borders() const;
+ const css_properties& css() const;
+ css_properties& css_w();
bool in_normal_flow() const;
- litehtml::web_color get_color(const tchar_t* prop_name, bool inherited, const litehtml::web_color& def_color = litehtml::web_color());
bool is_inline_box() const;
+ bool is_block_box() const;
position get_placement() const;
- bool collapse_top_margin() const;
- bool collapse_bottom_margin() const;
bool is_positioned() const;
+ bool is_float() const;
- bool skip();
- void skip(bool val);
bool have_parent() const;
+ bool is_root() const;
element::ptr parent() const;
- void parent(element::ptr par);
- bool is_visible() const;
- int calc_width(int defVal) const;
- int get_inline_shift_left();
- int get_inline_shift_right();
- void apply_relative_shift(int parent_width);
+ void parent(const element::ptr& par);
+ // returns true for elements inside a table (but outside cells) that don't participate in table rendering
+ bool is_table_skip() const;
std::shared_ptr<document> get_document() const;
- virtual elements_vector select_all(const tstring& selector);
+ virtual elements_vector select_all(const string& selector);
virtual elements_vector select_all(const css_selector& selector);
- virtual element::ptr select_one(const tstring& selector);
+ virtual element::ptr select_one(const string& selector);
virtual element::ptr select_one(const css_selector& selector);
- virtual int render(int x, int y, int max_width, bool second_pass = false);
- virtual int render_inline(const ptr &container, int max_width);
- virtual int place_element(const ptr &el, int max_width);
- virtual void calc_outlines( int parent_width );
- virtual void calc_auto_margins(int parent_width);
- virtual void apply_vertical_align();
- virtual bool fetch_positioned();
- virtual void render_positioned(render_type rt = render_all);
-
virtual bool appendChild(const ptr &el);
virtual bool removeChild(const ptr &el);
virtual void clearRecursive();
- virtual const tchar_t* get_tagName() const;
- virtual void set_tagName(const tchar_t* tag);
- virtual void set_data(const tchar_t* data);
- virtual element_float get_float() const;
- virtual vertical_align get_vertical_align() const;
- virtual element_clear get_clear() const;
+ virtual string_id id() const;
+ virtual string_id tag() const;
+ 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 overflow get_overflow() const;
- virtual css_length get_css_left() const;
- virtual css_length get_css_right() const;
- virtual css_length get_css_top() const;
- virtual css_length get_css_bottom() const;
- virtual css_offsets get_css_offsets() const;
- virtual css_length get_css_width() const;
- virtual void set_css_width(css_length& w);
- virtual css_length get_css_height() const;
-
- virtual void set_attr(const tchar_t* name, const tchar_t* val);
- virtual const tchar_t* get_attr(const tchar_t* name, const tchar_t* def = 0) const;
+ virtual void set_attr(const char* name, const char* val);
+ virtual const char* get_attr(const char* name, const char* def = nullptr) const;
virtual void apply_stylesheet(const litehtml::css& stylesheet);
virtual void refresh_styles();
virtual bool is_white_space() const;
+ virtual bool is_space() const;
+ virtual bool is_comment() const;
virtual bool is_body() const;
virtual bool is_break() const;
- virtual int get_base_line();
+ virtual bool is_text() const;
+
virtual bool on_mouse_over();
virtual bool on_mouse_leave();
virtual bool on_lbutton_down();
virtual bool on_lbutton_up();
virtual void on_click();
- virtual bool find_styles_changes(position::vector& redraw_boxes, int x, int y);
- virtual const tchar_t* get_cursor();
- virtual void init_font();
- virtual bool is_point_inside(int x, int y);
- virtual bool set_pseudo_class(const tchar_t* pclass, bool add);
- virtual bool set_class(const tchar_t* pclass, bool add);
+ virtual bool set_pseudo_class(string_id cls, bool add);
+ virtual bool set_class(const char* pclass, bool add);
virtual bool is_replaced() const;
- virtual int line_height() const;
- virtual white_space get_white_space() const;
- virtual style_display get_display() const;
- virtual visibility get_visibility() const;
- virtual element_position get_element_position(css_offsets* offsets = 0) const;
- virtual void get_inline_boxes(position::vector& boxes);
- virtual void parse_styles(bool is_reparse = false);
- virtual void draw(uint_ptr hdc, int x, int y, const position* clip);
- virtual void draw_background( uint_ptr hdc, int x, int y, const position* clip );
- virtual const tchar_t* get_style_property(const tchar_t* name, bool inherited, const tchar_t* def = 0);
- virtual uint_ptr get_font(font_metrics* fm = 0);
- virtual int get_font_size() const;
- virtual void get_text(tstring& text);
+ virtual void compute_styles(bool recursive = true);
+ virtual void draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item>& ri);
+ virtual void draw_background(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri);
+ virtual int get_enum_property (string_id name, bool inherited, int default_value, uint_ptr css_properties_member_offset) const;
+ virtual css_length get_length_property(string_id name, bool inherited, css_length default_value, uint_ptr css_properties_member_offset) const;
+ virtual web_color get_color_property (string_id name, bool inherited, web_color default_value, uint_ptr css_properties_member_offset) const;
+ virtual string get_string_property(string_id name, bool inherited, const string& default_value, uint_ptr css_properties_member_offset) const;
+ virtual float get_number_property(string_id name, bool inherited, float default_value, uint_ptr css_properties_member_offset) const;
+ virtual string_vector get_string_vector_property(string_id name, bool inherited, const string_vector& default_value, uint_ptr css_properties_member_offset) const;
+ virtual int_vector get_int_vector_property (string_id name, bool inherited, const int_vector& default_value, uint_ptr css_properties_member_offset) const;
+ virtual length_vector get_length_vector_property(string_id name, bool inherited, const length_vector& default_value, uint_ptr css_properties_member_offset) const;
+ virtual size_vector get_size_vector_property (string_id name, bool inherited, const size_vector& default_value, uint_ptr css_properties_member_offset) const;
+ virtual string get_custom_property(string_id name, const string& default_value) const;
+
+ virtual void get_text(string& text);
virtual void parse_attributes();
+ virtual int select(const string& selector);
virtual int select(const css_selector& selector, bool apply_pseudo = true);
virtual int select(const css_element_selector& selector, bool apply_pseudo = true);
- virtual element::ptr find_ancestor(const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = 0);
+ virtual element::ptr find_ancestor(const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr);
virtual bool is_ancestor(const ptr &el) const;
- virtual element::ptr find_adjacent_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = 0);
- virtual element::ptr find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = 0);
- virtual bool is_first_child_inline(const element::ptr& el) const;
- virtual bool is_last_child_inline(const element::ptr& el);
- virtual bool have_inline_child() const;
+ 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 void init();
virtual bool is_floats_holder() const;
- virtual int get_floats_height(element_float el_float = float_none) const;
- virtual int get_left_floats_height() const;
- virtual int get_right_floats_height() const;
- virtual int get_line_left(int y);
- virtual int get_line_right(int y, int def_right);
- virtual void get_line_left_right(int y, int def_right, int& ln_left, int& ln_right);
- virtual void add_float(const ptr &el, int x, int y);
virtual void update_floats(int dy, const ptr &parent);
- virtual void add_positioned(const ptr &el);
- virtual int find_next_line_top(int top, int width, int def_right);
- virtual int get_zindex() const;
- virtual void draw_stacking_context(uint_ptr hdc, int x, int y, const position* clip, bool with_positioned);
- virtual void draw_children( uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex );
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;
- virtual bool get_predefined_height(int& p_height) const;
- virtual void calc_document_size(litehtml::size& sz, int x = 0, int y = 0);
- virtual void get_redraw_box(litehtml::position& pos, int x = 0, int y = 0);
- virtual void add_style(const litehtml::style& st);
- virtual element::ptr get_element_by_point(int x, int y, int client_x, int client_y);
- virtual element::ptr get_child_by_point(int x, int y, int client_x, int client_y, draw_flag flag, int zindex);
+ virtual void add_style(const style& style);
virtual const background* get_background(bool own_only = false);
+
+ virtual string dump_get_name();
+ virtual std::vector<std::tuple<string, string>> dump_get_attrs();
+ void dump(litehtml::dumper& cout);
+
+ std::tuple<element::ptr, element::ptr, element::ptr> split_inlines();
+ virtual std::shared_ptr<render_item> create_render_item(const std::shared_ptr<render_item>& parent_ri);
+ bool requires_styles_update();
+ void add_render(const std::shared_ptr<render_item>& ri);
+ bool find_styles_changes( position::vector& redraw_boxes);
+ element::ptr add_pseudo_before(const style& style)
+ {
+ return _add_before_after(0, style);
+ }
+ element::ptr add_pseudo_after(const style& style)
+ {
+ return _add_before_after(1, style);
+ }
};
//////////////////////////////////////////////////////////////////////////
// INLINE FUNCTIONS //
//////////////////////////////////////////////////////////////////////////
- inline int litehtml::element::right() const
- {
- return left() + width();
- }
-
- inline int litehtml::element::left() const
- {
- return m_pos.left() - margin_left() - m_padding.left - m_borders.left;
- }
-
- inline int litehtml::element::top() const
- {
- return m_pos.top() - margin_top() - m_padding.top - m_borders.top;
- }
-
- inline int litehtml::element::bottom() const
- {
- return top() + height();
- }
-
- inline int litehtml::element::height() const
- {
- return m_pos.height + margin_top() + margin_bottom() + m_padding.height() + m_borders.height();
- }
-
- inline int litehtml::element::width() const
- {
- return m_pos.width + margin_left() + margin_right() + m_padding.width() + m_borders.width();
- }
-
- inline int litehtml::element::content_margins_top() const
- {
- return margin_top() + m_padding.top + m_borders.top;
- }
-
- inline int litehtml::element::content_margins_bottom() const
- {
- return margin_bottom() + m_padding.bottom + m_borders.bottom;
- }
-
- inline int litehtml::element::content_margins_left() const
- {
- return margin_left() + m_padding.left + m_borders.left;
- }
-
- inline int litehtml::element::content_margins_right() const
- {
- return margin_right() + m_padding.right + m_borders.right;
- }
-
- inline int litehtml::element::content_margins_width() const
- {
- return content_margins_left() + content_margins_right();
- }
-
- inline int litehtml::element::content_margins_height() const
- {
- return content_margins_top() + content_margins_bottom();
- }
-
- inline litehtml::margins litehtml::element::get_paddings() const
- {
- return m_padding;
- }
-
- inline litehtml::margins litehtml::element::get_borders() const
- {
- return m_borders;
- }
-
- inline int litehtml::element::padding_top() const
- {
- return m_padding.top;
- }
-
- inline int litehtml::element::padding_bottom() const
- {
- return m_padding.bottom;
- }
-
- inline int litehtml::element::padding_left() const
- {
- return m_padding.left;
- }
-
- inline int litehtml::element::padding_right() const
- {
- return m_padding.right;
- }
-
inline bool litehtml::element::in_normal_flow() const
{
- if(get_element_position() != element_position_absolute && get_display() != display_none)
+ if(css().get_position() != element_position_absolute && css().get_display() != display_none)
{
return true;
}
return false;
}
- inline int litehtml::element::border_top() const
- {
- return m_borders.top;
- }
-
- inline int litehtml::element::border_bottom() const
- {
- return m_borders.bottom;
- }
-
- inline int litehtml::element::border_left() const
- {
- return m_borders.left;
- }
-
- inline int litehtml::element::border_right() const
- {
- return m_borders.right;
- }
-
- inline bool litehtml::element::skip()
+ inline bool litehtml::element::is_root() const
{
- return m_skip;
- }
-
- inline void litehtml::element::skip(bool val)
- {
- m_skip = val;
- }
-
- inline bool litehtml::element::have_parent() const
- {
- return !m_parent.expired();
+ return m_parent.expired();
}
inline element::ptr litehtml::element::parent() const
@@ -344,60 +169,47 @@ namespace litehtml
return m_parent.lock();
}
- inline void litehtml::element::parent(element::ptr par)
+ inline void litehtml::element::parent(const element::ptr& par)
{
m_parent = par;
}
- inline int litehtml::element::margin_top() const
- {
- return m_margins.top;
- }
-
- inline int litehtml::element::margin_bottom() const
- {
- return m_margins.bottom;
- }
-
- inline int litehtml::element::margin_left() const
- {
- return m_margins.left;
- }
-
- inline int litehtml::element::margin_right() const
+ inline bool litehtml::element::is_positioned() const
{
- return m_margins.right;
+ return (css().get_position() > element_position_static);
}
- inline litehtml::margins litehtml::element::get_margins() const
+ inline bool litehtml::element::is_float() const
{
- margins ret;
- ret.left = margin_left();
- ret.right = margin_right();
- ret.top = margin_top();
- ret.bottom = margin_bottom();
-
- return ret;
+ return (css().get_float() != float_none);
}
- inline bool litehtml::element::is_positioned() const
+ inline std::shared_ptr<document> element::get_document() const
{
- return (get_element_position() > element_position_static);
+ return m_doc.lock();
}
- inline bool litehtml::element::is_visible() const
+ inline const css_properties& element::css() const
{
- return !(m_skip || get_display() == display_none || get_visibility() != visibility_visible);
+ return m_css;
}
- inline position& litehtml::element::get_position()
+ inline css_properties& element::css_w()
{
- return m_pos;
+ return m_css;
}
- inline std::shared_ptr<document> element::get_document() const
+ inline bool element::is_block_box() const
{
- return m_doc.lock();
+ if (css().get_display() == display_block ||
+ css().get_display() == display_flex ||
+ css().get_display() == display_table ||
+ css().get_display() == display_list_item ||
+ css().get_display() == display_flex)
+ {
+ return true;
+ }
+ return false;
}
}
diff --git a/src/plugins/litehtml_viewer/litehtml/html.cpp b/src/plugins/litehtml_viewer/litehtml/html.cpp
index d61da5dba..9695180a7 100644
--- a/src/plugins/litehtml_viewer/litehtml/html.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/html.cpp
@@ -1,33 +1,38 @@
#include "html.h"
#include "types.h"
-#include "html_tag.h"
+#include "utf8_strings.h"
-void litehtml::trim(tstring &s)
+void litehtml::trim(string &s)
{
- tstring::size_type pos = s.find_first_not_of(_t(" \n\r\t"));
- if(pos != tstring::npos)
+ string::size_type pos = s.find_first_not_of(" \n\r\t");
+ if(pos != string::npos)
{
s.erase(s.begin(), s.begin() + pos);
}
- pos = s.find_last_not_of(_t(" \n\r\t"));
- if(pos != tstring::npos)
+ else
+ {
+ s = "";
+ return;
+ }
+ pos = s.find_last_not_of(" \n\r\t");
+ if(pos != string::npos)
{
s.erase(s.begin() + pos + 1, s.end());
}
}
-void litehtml::lcase(tstring &s)
+void litehtml::lcase(string &s)
{
- for(tstring::iterator i = s.begin(); i != s.end(); i++)
+ for(char & i : s)
{
- (*i) = t_tolower(*i);
+ i = t_tolower(i);
}
}
-litehtml::tstring::size_type litehtml::find_close_bracket(const tstring &s, tstring::size_type off, tchar_t open_b, tchar_t close_b)
+litehtml::string::size_type litehtml::find_close_bracket(const string &s, string::size_type off, char open_b, char close_b)
{
int cnt = 0;
- for(tstring::size_type i = off; i < s.length(); i++)
+ for(string::size_type i = off; i < s.length(); i++)
{
if(s[i] == open_b)
{
@@ -41,10 +46,23 @@ litehtml::tstring::size_type litehtml::find_close_bracket(const tstring &s, tstr
}
}
}
- return tstring::npos;
+ return string::npos;
+}
+
+litehtml::string litehtml::index_value(int index, const string& strings, char delim)
+{
+ std::vector<string> vals;
+ string delims;
+ delims.push_back(delim);
+ split_string(strings, vals, delims);
+ if(index >= 0 && index < vals.size())
+ {
+ return vals[index];
+ }
+ return std::to_string(index);
}
-int litehtml::value_index( const tstring& val, const tstring& strings, int defValue, tchar_t delim )
+int litehtml::value_index( const string& val, const string& strings, int defValue, char delim )
{
if(val.empty() || strings.empty() || !delim)
{
@@ -52,12 +70,12 @@ int litehtml::value_index( const tstring& val, const tstring& strings, int defVa
}
int idx = 0;
- tstring::size_type delim_start = 0;
- tstring::size_type delim_end = strings.find(delim, delim_start);
- tstring::size_type item_len = 0;
+ string::size_type delim_start = 0;
+ string::size_type delim_end = strings.find(delim, delim_start);
+ string::size_type item_len;
while(true)
{
- if(delim_end == tstring::npos)
+ if(delim_end == string::npos)
{
item_len = strings.length() - delim_start;
} else
@@ -73,7 +91,7 @@ int litehtml::value_index( const tstring& val, const tstring& strings, int defVa
}
idx++;
delim_start = delim_end;
- if(delim_start == tstring::npos) break;
+ if(delim_start == string::npos) break;
delim_start++;
if(delim_start == strings.length()) break;
delim_end = strings.find(delim, delim_start);
@@ -81,7 +99,7 @@ int litehtml::value_index( const tstring& val, const tstring& strings, int defVa
return defValue;
}
-bool litehtml::value_in_list( const tstring& val, const tstring& strings, tchar_t delim )
+bool litehtml::value_in_list( const string& val, const string& strings, char delim )
{
int idx = value_index(val, strings, -1, delim);
if(idx >= 0)
@@ -91,45 +109,45 @@ bool litehtml::value_in_list( const tstring& val, const tstring& strings, tchar_
return false;
}
-void litehtml::split_string(const tstring& str, string_vector& tokens, const tstring& delims, const tstring& delims_preserve, const tstring& quote)
+void litehtml::split_string(const string& str, string_vector& tokens, const string& delims, const string& delims_preserve, const string& quote)
{
if(str.empty() || (delims.empty() && delims_preserve.empty()))
{
return;
}
- tstring all_delims = delims + delims_preserve + quote;
+ string all_delims = delims + delims_preserve + quote;
- tstring::size_type token_start = 0;
- tstring::size_type token_end = str.find_first_of(all_delims, token_start);
- tstring::size_type token_len = 0;
- tstring token;
+ string::size_type token_start = 0;
+ string::size_type token_end = str.find_first_of(all_delims, token_start);
+ string::size_type token_len;
+ string token;
while(true)
{
- while( token_end != tstring::npos && quote.find_first_of(str[token_end]) != tstring::npos )
+ while( token_end != string::npos && quote.find_first_of(str[token_end]) != string::npos )
{
- if(str[token_end] == _t('('))
+ if(str[token_end] == '(')
{
- token_end = find_close_bracket(str, token_end, _t('('), _t(')'));
- } else if(str[token_end] == _t('['))
+ token_end = find_close_bracket(str, token_end, '(', ')');
+ } else if(str[token_end] == '[')
{
- token_end = find_close_bracket(str, token_end, _t('['), _t(']'));
- } else if(str[token_end] == _t('{'))
+ token_end = find_close_bracket(str, token_end, '[', ']');
+ } else if(str[token_end] == '{')
{
- token_end = find_close_bracket(str, token_end, _t('{'), _t('}'));
+ token_end = find_close_bracket(str, token_end, '{', '}');
} else
{
token_end = str.find_first_of(str[token_end], token_end + 1);
}
- if(token_end != tstring::npos)
+ if(token_end != string::npos)
{
token_end = str.find_first_of(all_delims, token_end + 1);
}
}
- if(token_end == tstring::npos)
+ if(token_end == string::npos)
{
- token_len = tstring::npos;
+ token_len = string::npos;
} else
{
token_len = token_end - token_start;
@@ -140,30 +158,122 @@ void litehtml::split_string(const tstring& str, string_vector& tokens, const tst
{
tokens.push_back( token );
}
- if(token_end != tstring::npos && !delims_preserve.empty() && delims_preserve.find_first_of(str[token_end]) != tstring::npos)
+ if(token_end != string::npos && !delims_preserve.empty() && delims_preserve.find_first_of(str[token_end]) != string::npos)
{
tokens.push_back( str.substr(token_end, 1) );
}
token_start = token_end;
- if(token_start == tstring::npos) break;
+ if(token_start == string::npos) break;
token_start++;
if(token_start == str.length()) break;
token_end = str.find_first_of(all_delims, token_start);
}
}
-void litehtml::join_string(tstring& str, const string_vector& tokens, const tstring& delims)
+void litehtml::join_string(string& str, const string_vector& tokens, const string& delims)
{
- tstringstream ss;
- for(size_t i=0; i<tokens.size(); ++i)
+ str = "";
+ for (size_t i = 0; i < tokens.size(); i++)
{
- if(i != 0)
+ if (i != 0)
{
- ss << delims;
+ str += delims;
}
- ss << tokens[i];
+ str += tokens[i];
+ }
+}
+
+int litehtml::t_strcasecmp(const char *s1, const char *s2)
+{
+ int i, d, c;
+
+ for (i = 0;; i++)
+ {
+ c = t_tolower((unsigned char)s1[i]);
+ d = c - t_tolower((unsigned char)s2[i]);
+ if (d < 0)
+ return -1;
+ else if (d > 0)
+ return 1;
+ else if (c == 0)
+ return 0;
+ }
+}
+
+int litehtml::t_strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ int i, d, c;
+
+ for (i = 0; i < n; i++)
+ {
+ c = t_tolower((unsigned char)s1[i]);
+ d = c - t_tolower((unsigned char)s2[i]);
+ if (d < 0)
+ return -1;
+ else if (d > 0)
+ return 1;
+ else if (c == 0)
+ return 0;
}
- str = ss.str();
+ return 0;
+}
+
+litehtml::string litehtml::get_escaped_string(const string& in_str)
+{
+ string ret;
+ for (auto ch : in_str)
+ {
+ switch (ch)
+ {
+ case '\'':
+ ret += "\\'";
+ break;
+
+ case '\"':
+ ret += "\\\"";
+ break;
+
+ case '\?':
+ ret += "\\?";
+ break;
+
+ case '\\':
+ ret += "\\\\";
+ break;
+
+ case '\a':
+ ret += "\\a";
+ break;
+
+ case '\b':
+ ret += "\\b";
+ break;
+
+ case '\f':
+ ret += "\\f";
+ break;
+
+ case '\n':
+ ret += "\\n";
+ break;
+
+ case '\r':
+ ret += "\\r";
+ break;
+
+ case '\t':
+ ret += "\\t";
+ break;
+
+ case '\v':
+ ret += "\\v";
+ break;
+
+ default:
+ ret += ch;
+ }
+ }
+ return ret;
}
diff --git a/src/plugins/litehtml_viewer/litehtml/html.h b/src/plugins/litehtml_viewer/litehtml/html.h
index 20457f155..b184ac30a 100644
--- a/src/plugins/litehtml_viewer/litehtml/html.h
+++ b/src/plugins/litehtml_viewer/litehtml/html.h
@@ -8,73 +8,50 @@
#include <map>
#include <cstring>
#include <algorithm>
-#include <sstream>
-#include <cstdint>
+#include <functional>
#include "os_types.h"
+#include "string_id.h"
#include "types.h"
+#include "utf8_strings.h"
#include "background.h"
#include "borders.h"
-#include "html_tag.h"
#include "web_color.h"
#include "media_query.h"
+#include "html_tag.h"
+#include "document_container.h"
+#include "document.h"
namespace litehtml
{
- struct list_marker
- {
- tstring image;
- const tchar_t* baseurl;
- list_style_type marker_type;
- web_color color;
- position pos;
- int index;
- uint_ptr font;
- };
+ void trim(string &s);
+ void lcase(string &s);
+ int value_index(const string& val, const string& strings, int defValue = -1, char delim = ';');
+ string index_value(int index, const string& strings, char delim = ';');
+ bool value_in_list(const string& val, const string& strings, char delim = ';');
+ string::size_type find_close_bracket(const string &s, string::size_type off, char open_b = '(', char close_b = ')');
+ void split_string(const string& str, string_vector& tokens, const string& delims, const string& delims_preserve = "", const string& quote = "\"");
+ void join_string(string& str, const string_vector& tokens, const string& delims);
+ double t_strtod(const char* string, char** endPtr = nullptr);
+ string get_escaped_string(const string& in_str);
- // call back interface to draw text, images and other elements
- class document_container
+ int t_strcasecmp(const char *s1, const char *s2);
+ int t_strncasecmp(const char *s1, const char *s2, size_t n);
+
+ inline int t_isdigit(int c)
{
- public:
- virtual litehtml::uint_ptr create_font(const litehtml::tchar_t* faceName, int size, int weight, litehtml::font_style italic, unsigned int decoration, litehtml::font_metrics* fm) = 0;
- virtual void delete_font(litehtml::uint_ptr hFont) = 0;
- virtual int text_width(const litehtml::tchar_t* text, litehtml::uint_ptr hFont) = 0;
- virtual void draw_text(litehtml::uint_ptr hdc, const litehtml::tchar_t* text, litehtml::uint_ptr hFont, litehtml::web_color color, const litehtml::position& pos) = 0;
- virtual int pt_to_px(int pt) = 0;
- virtual int get_default_font_size() const = 0;
- virtual const litehtml::tchar_t* get_default_font_name() const = 0;
- virtual void draw_list_marker(litehtml::uint_ptr hdc, const litehtml::list_marker& marker) = 0;
- virtual void load_image(const litehtml::tchar_t* src, const litehtml::tchar_t* baseurl, bool redraw_on_ready) = 0;
- virtual void get_image_size(const litehtml::tchar_t* src, const litehtml::tchar_t* baseurl, litehtml::size& sz) = 0;
- virtual void draw_background(litehtml::uint_ptr hdc, const litehtml::background_paint& bg) = 0;
- virtual void draw_borders(litehtml::uint_ptr hdc, const litehtml::borders& borders, const litehtml::position& draw_pos, bool root) = 0;
-
- virtual void set_caption(const litehtml::tchar_t* caption) = 0;
- virtual void set_base_url(const litehtml::tchar_t* base_url) = 0;
- virtual void link(const std::shared_ptr<litehtml::document>& doc, const litehtml::element::ptr& el) = 0;
- virtual void on_anchor_click(const litehtml::tchar_t* url, const litehtml::element::ptr& el) = 0;
- virtual void set_cursor(const litehtml::tchar_t* cursor) = 0;
- virtual void transform_text(litehtml::tstring& text, litehtml::text_transform tt) = 0;
- virtual void import_css(litehtml::tstring& text, const litehtml::tstring& url, litehtml::tstring& baseurl) = 0;
- virtual void set_clip(const litehtml::position& pos, const litehtml::border_radiuses& bdr_radius, bool valid_x, bool valid_y) = 0;
- virtual void del_clip() = 0;
- virtual void get_client_rect(litehtml::position& client) const = 0;
- virtual std::shared_ptr<litehtml::element> create_element(const litehtml::tchar_t *tag_name,
- const litehtml::string_map &attributes,
- const std::shared_ptr<litehtml::document> &doc) = 0;
-
- virtual void get_media_features(litehtml::media_features& media) const = 0;
- virtual void get_language(litehtml::tstring& language, litehtml::tstring & culture) const = 0;
- virtual litehtml::tstring resolve_color(const litehtml::tstring& color) const { return litehtml::tstring(); }
- };
+ return (c >= '0' && c <= '9');
+ }
- void trim(tstring &s);
- void lcase(tstring &s);
- int value_index(const tstring& val, const tstring& strings, int defValue = -1, tchar_t delim = _t(';'));
- bool value_in_list(const tstring& val, const tstring& strings, tchar_t delim = _t(';'));
- tstring::size_type find_close_bracket(const tstring &s, tstring::size_type off, tchar_t open_b = _t('('), tchar_t close_b = _t(')'));
- void split_string(const tstring& str, string_vector& tokens, const tstring& delims, const tstring& delims_preserve = _t(""), const tstring& quote = _t("\""));
- void join_string(tstring& str, const string_vector& tokens, const tstring& delims);
+ inline int t_isalpha(int c)
+ {
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
+ }
+ inline int t_tolower(int c)
+ {
+ return (c >= 'A' && c <= 'Z' ? c + 'a' - 'A' : c);
+ }
+
inline int round_f(float val)
{
int int_val = (int) val;
@@ -94,6 +71,16 @@ namespace litehtml
}
return int_val;
}
+
+ inline float t_strtof(const string& str, char** endPtr = nullptr)
+ {
+ return (float)t_strtod(str.c_str(), endPtr);
+ }
+
+ inline int baseline_align(int line_height, int line_base_line, int height, int baseline)
+ {
+ return (line_height - line_base_line) - (height - baseline);
+ }
}
#endif // LH_HTML_H
diff --git a/src/plugins/litehtml_viewer/litehtml/html_tag.cpp b/src/plugins/litehtml_viewer/litehtml/html_tag.cpp
index a992d68a2..d1e7302e4 100644
--- a/src/plugins/litehtml_viewer/litehtml/html_tag.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/html_tag.cpp
@@ -8,35 +8,25 @@
#include <locale>
#include "el_before_after.h"
#include "num_cvt.h"
+#include "line_box.h"
+#include <stack>
+#include "render_item.h"
-litehtml::html_tag::html_tag(const std::shared_ptr<litehtml::document>& doc) : litehtml::element(doc)
+litehtml::html_tag::html_tag(const std::shared_ptr<document>& doc) : element(doc)
{
- m_box_sizing = box_sizing_content_box;
- m_z_index = 0;
- m_overflow = overflow_visible;
- m_box = 0;
- m_text_align = text_align_left;
- m_el_position = element_position_static;
- m_display = display_inline;
- m_vertical_align = va_baseline;
- m_list_style_type = list_style_type_none;
- m_list_style_position = list_style_position_outside;
- m_float = float_none;
- m_clear = clear_none;
- m_font = 0;
- m_font_size = 0;
- m_white_space = white_space_normal;
- m_lh_predefined = false;
- m_line_height = 0;
- m_visibility = visibility_visible;
- m_border_spacing_x = 0;
- m_border_spacing_y = 0;
- m_border_collapse = border_collapse_separate;
+ m_tag = empty_id;
+ m_id = empty_id;
}
-litehtml::html_tag::~html_tag()
+litehtml::html_tag::html_tag(const element::ptr& parent, const string& style) : element(parent->get_document()),
+ m_tag(empty_id),
+ m_id(empty_id)
{
-
+ litehtml::style st;
+ st.add(style);
+ add_style(st);
+ this->parent(parent);
+ compute_styles();
}
bool litehtml::html_tag::appendChild(const element::ptr &el)
@@ -71,34 +61,59 @@ void litehtml::html_tag::clearRecursive()
m_children.clear();
}
+litehtml::string_id litehtml::html_tag::id() const
+{
+ return m_id;
+}
+
+litehtml::string_id litehtml::html_tag::tag() const
+{
+ return m_tag;
+}
+
+const char* litehtml::html_tag::get_tagName() const
+{
+ return _s(m_tag).c_str();
+}
-const litehtml::tchar_t* litehtml::html_tag::get_tagName() const
+void litehtml::html_tag::set_tagName( const char* _tag )
{
- return m_tag.c_str();
+ string tag = _tag;
+ lcase(tag);
+ m_tag = _id(tag);
}
-void litehtml::html_tag::set_attr( const tchar_t* name, const tchar_t* val )
+void litehtml::html_tag::set_attr( const char* _name, const char* _val )
{
- if(name && val)
+ if(_name && _val)
{
- tstring s_val = name;
- for(size_t i = 0; i < s_val.length(); i++)
+ string name = _name;
+ lcase(name);
+ m_attrs[name] = _val;
+
+ if( name == "class" )
{
- s_val[i] = std::tolower(s_val[i], std::locale::classic());
+ string val = _val;
+ // class names are matched case-insensitively in quirks mode
+ // we match them case-insensitively in all modes (same for id)
+ lcase(val);
+ m_str_classes.resize( 0 );
+ split_string( val, m_str_classes, " " );
+ m_classes.clear();
+ for (auto& cls : m_str_classes) m_classes.push_back(_id(cls));
}
- m_attrs[s_val] = val;
-
- if( t_strcasecmp( name, _t("class") ) == 0 )
+ else if (name == "id")
{
- m_class_values.resize( 0 );
- split_string( val, m_class_values, _t(" ") );
+ string val = _val;
+ lcase(val);
+ m_id = _id(val);
}
}
}
-const litehtml::tchar_t* litehtml::html_tag::get_attr( const tchar_t* name, const tchar_t* def ) const
+const char* litehtml::html_tag::get_attr( const char* name, const char* def ) const
{
- string_map::const_iterator attr = m_attrs.find(name);
+ auto attr = m_attrs.find(name);
if(attr != m_attrs.end())
{
return attr->second.c_str();
@@ -106,9 +121,9 @@ const litehtml::tchar_t* litehtml::html_tag::get_attr( const tchar_t* name, cons
return def;
}
-litehtml::elements_vector litehtml::html_tag::select_all( const tstring& selector )
+litehtml::elements_vector litehtml::html_tag::select_all( const string& selector )
{
- css_selector sel(media_query_list::ptr(0));
+ css_selector sel;
sel.parse(selector);
return select_all(sel);
@@ -135,9 +150,9 @@ void litehtml::html_tag::select_all(const css_selector& selector, elements_vecto
}
-litehtml::element::ptr litehtml::html_tag::select_one( const tstring& selector )
+litehtml::element::ptr litehtml::html_tag::select_one( const string& selector )
{
- css_selector sel(media_query_list::ptr(0));
+ css_selector sel;
sel.parse(selector);
return select_one(sel);
@@ -158,15 +173,28 @@ litehtml::element::ptr litehtml::html_tag::select_one( const css_selector& selec
return res;
}
}
- return 0;
+ return nullptr;
}
void litehtml::html_tag::apply_stylesheet( const litehtml::css& stylesheet )
{
- remove_before_after();
-
for(const auto& sel : stylesheet.selectors())
{
+ // optimization
+ {
+ const auto& r = sel->m_right;
+ if (r.m_tag != star_id && r.m_tag != m_tag)
+ continue;
+
+ if (!r.m_attrs.empty())
+ {
+ const auto& attr = r.m_attrs[0];
+ if (attr.type == select_class &&
+ std::find(m_classes.begin(), m_classes.end(), attr.name) == m_classes.end())
+ continue;
+ }
+ }
+
int apply = select(*sel, false);
if(apply != select_no_match)
@@ -181,14 +209,14 @@ void litehtml::html_tag::apply_stylesheet( const litehtml::css& stylesheet )
{
if(apply & select_match_with_after)
{
- element::ptr el = get_element_after();
+ 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();
+ element::ptr el = get_element_before(*sel->m_style, true);
if(el)
{
el->add_style(*sel->m_style);
@@ -202,14 +230,14 @@ void litehtml::html_tag::apply_stylesheet( const litehtml::css& stylesheet )
}
} else if(apply & select_match_with_after)
{
- element::ptr el = get_element_after();
+ 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();
+ element::ptr el = get_element_before(*sel->m_style, true);
if(el)
{
el->add_style(*sel->m_style);
@@ -226,7 +254,7 @@ void litehtml::html_tag::apply_stylesheet( const litehtml::css& stylesheet )
for(auto& el : m_children)
{
- if(el->get_display() != display_inline_text)
+ if(el->css().get_display() != display_inline_text)
{
el->apply_stylesheet(stylesheet);
}
@@ -236,7 +264,7 @@ void litehtml::html_tag::apply_stylesheet( const litehtml::css& stylesheet )
void litehtml::html_tag::get_content_size( size& sz, int max_width )
{
sz.height = 0;
- if(m_display == display_block)
+ if(m_css.get_display() == display_block)
{
sz.width = max_width;
} else
@@ -245,351 +273,154 @@ void litehtml::html_tag::get_content_size( size& sz, int max_width )
}
}
-void litehtml::html_tag::draw( uint_ptr hdc, int x, int y, const position* clip )
+void litehtml::html_tag::draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri)
{
- position pos = m_pos;
+ position pos = ri->pos();
pos.x += x;
pos.y += y;
- draw_background(hdc, x, y, clip);
+ draw_background(hdc, x, y, clip, ri);
- if(m_display == display_list_item && m_list_style_type != list_style_type_none)
+ if(m_css.get_display() == display_list_item && m_css.get_list_style_type() != list_style_type_none)
{
- if(m_overflow > overflow_visible)
+ if(m_css.get_overflow() > overflow_visible)
{
position border_box = pos;
- border_box += m_padding;
- border_box += m_borders;
+ border_box += ri->get_paddings();
+ border_box += ri->get_borders();
- border_radiuses bdr_radius = m_css_borders.radius.calc_percents(border_box.width, border_box.height);
+ border_radiuses bdr_radius = m_css.get_borders().radius.calc_percents(border_box.width, border_box.height);
- bdr_radius -= m_borders;
- bdr_radius -= m_padding;
+ bdr_radius -= ri->get_borders();
+ bdr_radius -= ri->get_paddings();
- get_document()->container()->set_clip(pos, bdr_radius, true, true);
+ get_document()->container()->set_clip(pos, bdr_radius);
}
draw_list_marker(hdc, pos);
- if(m_overflow > overflow_visible)
+ if(m_css.get_overflow() > overflow_visible)
{
get_document()->container()->del_clip();
}
}
}
-litehtml::uint_ptr litehtml::html_tag::get_font(font_metrics* fm)
+litehtml::string litehtml::html_tag::get_custom_property(string_id name, const string& default_value) const
{
- if(fm)
- {
- *fm = m_font_metrics;
- }
- return m_font;
-}
+ const property_value& value = m_style.get_property(name);
-const litehtml::tchar_t* litehtml::html_tag::get_style_property( const tchar_t* name, bool inherited, const tchar_t* def /*= 0*/ )
-{
- const tchar_t* ret = m_style.get_property(name);
- element::ptr el_parent = parent();
- if (el_parent)
+ if (value.m_type == prop_type_string)
{
- if ( ( ret && !t_strcasecmp(ret, _t("inherit")) ) || (!ret && inherited) )
- {
- ret = el_parent->get_style_property(name, inherited, def);
- }
+ return value.m_string;
}
-
- if(!ret)
+ else if (auto _parent = parent())
{
- ret = def;
+ return _parent->get_custom_property(name, default_value);
}
-
- return ret;
+ return default_value;
}
-void litehtml::html_tag::parse_styles(bool is_reparse)
+template<class Type, litehtml::property_type property_value_type, Type litehtml::property_value::* property_value_member>
+const Type& litehtml::html_tag::get_property_impl(string_id name, bool inherited, const Type& default_value, uint_ptr css_properties_member_offset) const
{
- const tchar_t* style = get_attr(_t("style"));
-
- if(style)
- {
- m_style.add(style, NULL);
- }
+ const property_value& value = m_style.get_property(name);
- init_font();
- document::ptr doc = get_document();
-
- m_el_position = (element_position) value_index(get_style_property(_t("position"), false, _t("static")), element_position_strings, element_position_fixed);
- m_text_align = (text_align) value_index(get_style_property(_t("text-align"), true, _t("left")), text_align_strings, text_align_left);
- m_overflow = (overflow) value_index(get_style_property(_t("overflow"), false, _t("visible")), overflow_strings, overflow_visible);
- m_white_space = (white_space) value_index(get_style_property(_t("white-space"), true, _t("normal")), white_space_strings, white_space_normal);
- m_display = (style_display) value_index(get_style_property(_t("display"), false, _t("inline")), style_display_strings, display_inline);
- m_visibility = (visibility) value_index(get_style_property(_t("visibility"), true, _t("visible")), visibility_strings, visibility_visible);
- m_box_sizing = (box_sizing) value_index(get_style_property(_t("box-sizing"), false, _t("content-box")), box_sizing_strings, box_sizing_content_box);
-
- if(m_el_position != element_position_static)
- {
- const tchar_t* val = get_style_property(_t("z-index"), false, 0);
- if(val)
- {
- m_z_index = t_atoi(val);
- }
- }
-
- const tchar_t* va = get_style_property(_t("vertical-align"), true, _t("baseline"));
- m_vertical_align = (vertical_align) value_index(va, vertical_align_strings, va_baseline);
-
- const tchar_t* fl = get_style_property(_t("float"), false, _t("none"));
- m_float = (element_float) value_index(fl, element_float_strings, float_none);
-
- m_clear = (element_clear) value_index(get_style_property(_t("clear"), false, _t("none")), element_clear_strings, clear_none);
-
- if (m_float != float_none)
- {
- // reset display in to block for floating elements
- if (m_display != display_none)
- {
- m_display = display_block;
- }
- }
- else if (m_display == display_table ||
- m_display == display_inline_table ||
- m_display == display_table_caption ||
- m_display == display_table_cell ||
- m_display == display_table_column ||
- m_display == display_table_column_group ||
- m_display == display_table_footer_group ||
- m_display == display_table_header_group ||
- m_display == display_table_row ||
- m_display == display_table_row_group)
+ if (value.m_type == property_value_type)
{
- doc->add_tabular(shared_from_this());
+ return value.*property_value_member;
}
- // fix inline boxes with absolute/fixed positions
- else if (m_display != display_none && is_inline_box())
+ else if (inherited || value.m_type == prop_type_inherit)
{
- if (m_el_position == element_position_absolute || m_el_position == element_position_fixed)
+ if (auto _parent = parent())
{
- m_display = display_block;
+ return *(Type*)((byte*)&_parent->css() + css_properties_member_offset);
}
+ return default_value;
}
+ // value must be invalid here
+ //assert(value.m_type == prop_type_invalid);
+ return default_value;
+}
- m_css_text_indent.fromString( get_style_property(_t("text-indent"), true, _t("0")), _t("0"));
-
- m_css_width.fromString( get_style_property(_t("width"), false, _t("auto")), _t("auto"));
- m_css_height.fromString( get_style_property(_t("height"), false, _t("auto")), _t("auto"));
-
- doc->cvt_units(m_css_width, m_font_size);
- doc->cvt_units(m_css_height, m_font_size);
-
- m_css_min_width.fromString( get_style_property(_t("min-width"), false, _t("0")));
- m_css_min_height.fromString( get_style_property(_t("min-height"), false, _t("0")));
-
- m_css_max_width.fromString( get_style_property(_t("max-width"), false, _t("none")), _t("none"));
- m_css_max_height.fromString( get_style_property(_t("max-height"), false, _t("none")), _t("none"));
-
- doc->cvt_units(m_css_min_width, m_font_size);
- doc->cvt_units(m_css_min_height, m_font_size);
-
- m_css_offsets.left.fromString( get_style_property(_t("left"), false, _t("auto")), _t("auto"));
- m_css_offsets.right.fromString( get_style_property(_t("right"), false, _t("auto")), _t("auto"));
- m_css_offsets.top.fromString( get_style_property(_t("top"), false, _t("auto")), _t("auto"));
- m_css_offsets.bottom.fromString( get_style_property(_t("bottom"), false, _t("auto")), _t("auto"));
-
- doc->cvt_units(m_css_offsets.left, m_font_size);
- doc->cvt_units(m_css_offsets.right, m_font_size);
- doc->cvt_units(m_css_offsets.top, m_font_size);
- doc->cvt_units(m_css_offsets.bottom, m_font_size);
-
- m_css_margins.left.fromString( get_style_property(_t("margin-left"), false, _t("0")), _t("auto"));
- m_css_margins.right.fromString( get_style_property(_t("margin-right"), false, _t("0")), _t("auto"));
- m_css_margins.top.fromString( get_style_property(_t("margin-top"), false, _t("0")), _t("auto"));
- m_css_margins.bottom.fromString( get_style_property(_t("margin-bottom"), false, _t("0")), _t("auto"));
-
- m_css_padding.left.fromString( get_style_property(_t("padding-left"), false, _t("0")), _t(""));
- m_css_padding.right.fromString( get_style_property(_t("padding-right"), false, _t("0")), _t(""));
- m_css_padding.top.fromString( get_style_property(_t("padding-top"), false, _t("0")), _t(""));
- m_css_padding.bottom.fromString( get_style_property(_t("padding-bottom"), false, _t("0")), _t(""));
-
- m_css_borders.left.width.fromString( get_style_property(_t("border-left-width"), false, _t("medium")), border_width_strings);
- m_css_borders.right.width.fromString( get_style_property(_t("border-right-width"), false, _t("medium")), border_width_strings);
- m_css_borders.top.width.fromString( get_style_property(_t("border-top-width"), false, _t("medium")), border_width_strings);
- m_css_borders.bottom.width.fromString( get_style_property(_t("border-bottom-width"), false, _t("medium")), border_width_strings);
-
- m_css_borders.left.color = web_color::from_string(get_style_property(_t("border-left-color"), false, _t("")), doc->container());
- m_css_borders.left.style = (border_style) value_index(get_style_property(_t("border-left-style"), false, _t("none")), border_style_strings, border_style_none);
-
- m_css_borders.right.color = web_color::from_string(get_style_property(_t("border-right-color"), false, _t("")), doc->container());
- m_css_borders.right.style = (border_style) value_index(get_style_property(_t("border-right-style"), false, _t("none")), border_style_strings, border_style_none);
-
- m_css_borders.top.color = web_color::from_string(get_style_property(_t("border-top-color"), false, _t("")), doc->container());
- m_css_borders.top.style = (border_style) value_index(get_style_property(_t("border-top-style"), false, _t("none")), border_style_strings, border_style_none);
-
- m_css_borders.bottom.color = web_color::from_string(get_style_property(_t("border-bottom-color"), false, _t("")), doc->container());
- m_css_borders.bottom.style = (border_style) value_index(get_style_property(_t("border-bottom-style"), false, _t("none")), border_style_strings, border_style_none);
-
- m_css_borders.radius.top_left_x.fromString(get_style_property(_t("border-top-left-radius-x"), false, _t("0")));
- m_css_borders.radius.top_left_y.fromString(get_style_property(_t("border-top-left-radius-y"), false, _t("0")));
-
- m_css_borders.radius.top_right_x.fromString(get_style_property(_t("border-top-right-radius-x"), false, _t("0")));
- m_css_borders.radius.top_right_y.fromString(get_style_property(_t("border-top-right-radius-y"), false, _t("0")));
-
- m_css_borders.radius.bottom_right_x.fromString(get_style_property(_t("border-bottom-right-radius-x"), false, _t("0")));
- m_css_borders.radius.bottom_right_y.fromString(get_style_property(_t("border-bottom-right-radius-y"), false, _t("0")));
-
- m_css_borders.radius.bottom_left_x.fromString(get_style_property(_t("border-bottom-left-radius-x"), false, _t("0")));
- m_css_borders.radius.bottom_left_y.fromString(get_style_property(_t("border-bottom-left-radius-y"), false, _t("0")));
-
- doc->cvt_units(m_css_borders.radius.bottom_left_x, m_font_size);
- doc->cvt_units(m_css_borders.radius.bottom_left_y, m_font_size);
- doc->cvt_units(m_css_borders.radius.bottom_right_x, m_font_size);
- doc->cvt_units(m_css_borders.radius.bottom_right_y, m_font_size);
- doc->cvt_units(m_css_borders.radius.top_left_x, m_font_size);
- doc->cvt_units(m_css_borders.radius.top_left_y, m_font_size);
- doc->cvt_units(m_css_borders.radius.top_right_x, m_font_size);
- doc->cvt_units(m_css_borders.radius.top_right_y, m_font_size);
-
- doc->cvt_units(m_css_text_indent, m_font_size);
-
- m_margins.left = doc->cvt_units(m_css_margins.left, m_font_size);
- m_margins.right = doc->cvt_units(m_css_margins.right, m_font_size);
- m_margins.top = doc->cvt_units(m_css_margins.top, m_font_size);
- m_margins.bottom = doc->cvt_units(m_css_margins.bottom, m_font_size);
-
- m_padding.left = doc->cvt_units(m_css_padding.left, m_font_size);
- m_padding.right = doc->cvt_units(m_css_padding.right, m_font_size);
- m_padding.top = doc->cvt_units(m_css_padding.top, m_font_size);
- m_padding.bottom = doc->cvt_units(m_css_padding.bottom, m_font_size);
-
- m_borders.left = doc->cvt_units(m_css_borders.left.width, m_font_size);
- m_borders.right = doc->cvt_units(m_css_borders.right.width, m_font_size);
- m_borders.top = doc->cvt_units(m_css_borders.top.width, m_font_size);
- m_borders.bottom = doc->cvt_units(m_css_borders.bottom.width, m_font_size);
-
- css_length line_height;
- line_height.fromString(get_style_property(_t("line-height"), true, _t("normal")), _t("normal"));
- if(line_height.is_predefined())
- {
- m_line_height = m_font_metrics.height;
- m_lh_predefined = true;
- } else if(line_height.units() == css_units_none)
- {
- m_line_height = (int) (line_height.val() * m_font_size);
- m_lh_predefined = false;
- } else
- {
- m_line_height = doc->cvt_units(line_height, m_font_size, m_font_size);
- m_lh_predefined = false;
- }
-
-
- if(m_display == display_list_item)
- {
- const tchar_t* list_type = get_style_property(_t("list-style-type"), true, _t("disc"));
- m_list_style_type = (list_style_type) value_index(list_type, list_style_type_strings, list_style_type_disc);
-
- const tchar_t* list_pos = get_style_property(_t("list-style-position"), true, _t("outside"));
- m_list_style_position = (list_style_position) value_index(list_pos, list_style_position_strings, list_style_position_outside);
-
- const tchar_t* list_image = get_style_property(_t("list-style-image"), true, 0);
- if(list_image && list_image[0])
- {
- tstring url;
- css::parse_css_url(list_image, url);
-
- const tchar_t* list_image_baseurl = get_style_property(_t("list-style-image-baseurl"), true, 0);
- doc->container()->load_image(url.c_str(), list_image_baseurl, true);
- }
+int litehtml::html_tag::get_enum_property(string_id name, bool inherited, int default_value, uint_ptr css_properties_member_offset) const
+{
+ return get_property_impl<int, prop_type_enum_item, &property_value::m_enum_item>(name, inherited, default_value, css_properties_member_offset);
+}
- }
+litehtml::css_length litehtml::html_tag::get_length_property(string_id name, bool inherited, css_length default_value, uint_ptr css_properties_member_offset) const
+{
+ return get_property_impl<css_length, prop_type_length, &property_value::m_length>(name, inherited, default_value, css_properties_member_offset);
+}
- parse_background();
+litehtml::web_color litehtml::html_tag::get_color_property(string_id name, bool inherited, web_color default_value, uint_ptr css_properties_member_offset) const
+{
+ return get_property_impl<web_color, prop_type_color, &property_value::m_color>(name, inherited, default_value, css_properties_member_offset);
+}
- if(!is_reparse)
- {
- for(auto& el : m_children)
- {
- el->parse_styles();
- }
- }
+litehtml::string litehtml::html_tag::get_string_property(string_id name, bool inherited, const string& default_value, uint_ptr css_properties_member_offset) const
+{
+ return get_property_impl<string, prop_type_string, &property_value::m_string>(name, inherited, default_value, css_properties_member_offset);
}
-int litehtml::html_tag::render( int x, int y, int max_width, bool second_pass )
+float litehtml::html_tag::get_number_property(string_id name, bool inherited, float default_value, uint_ptr css_properties_member_offset) const
{
- if (m_display == display_table || m_display == display_inline_table)
- {
- return render_table(x, y, max_width, second_pass);
- }
+ return get_property_impl<float, prop_type_number, &property_value::m_number>(name, inherited, default_value, css_properties_member_offset);
+}
- return render_box(x, y, max_width, second_pass);
+litehtml::string_vector litehtml::html_tag::get_string_vector_property(string_id name, bool inherited, const string_vector& default_value, uint_ptr css_properties_member_offset) const
+{
+ return get_property_impl<string_vector, prop_type_string_vector, &property_value::m_string_vector>(name, inherited, default_value, css_properties_member_offset);
}
-bool litehtml::html_tag::is_white_space() const
+litehtml::int_vector litehtml::html_tag::get_int_vector_property(string_id name, bool inherited, const int_vector& default_value, uint_ptr css_properties_member_offset) const
{
- return false;
+ return get_property_impl<int_vector, prop_type_enum_item_vector, &property_value::m_enum_item_vector>(name, inherited, default_value, css_properties_member_offset);
}
-int litehtml::html_tag::get_font_size() const
+litehtml::length_vector litehtml::html_tag::get_length_vector_property(string_id name, bool inherited, const length_vector& default_value, uint_ptr css_properties_member_offset) const
{
- return m_font_size;
+ return get_property_impl<length_vector, prop_type_length_vector, &property_value::m_length_vector>(name, inherited, default_value, css_properties_member_offset);
}
-int litehtml::html_tag::get_base_line()
+litehtml::size_vector litehtml::html_tag::get_size_vector_property(string_id name, bool inherited, const size_vector& default_value, uint_ptr css_properties_member_offset) const
{
- if(is_replaced())
- {
- return 0;
- }
- int bl = 0;
- if(!m_boxes.empty())
- {
- bl = m_boxes.back()->baseline() + content_margins_bottom();
- }
- return bl;
+ return get_property_impl<size_vector, prop_type_size_vector, &property_value::m_size_vector>(name, inherited, default_value, css_properties_member_offset);
}
-void litehtml::html_tag::init()
+void litehtml::html_tag::compute_styles(bool recursive)
{
- if (m_display == display_table || m_display == display_inline_table)
+ const char* style = get_attr("style");
+ document::ptr doc = get_document();
+
+ if (style)
{
- if (m_grid)
- {
- m_grid->clear();
- }
- else
- {
- m_grid = std::unique_ptr<table_grid>(new table_grid());
- }
+ m_style.add(style, "", doc->container());
+ }
- go_inside_table table_selector;
- table_rows_selector row_selector;
- table_cells_selector cell_selector;
+ m_style.subst_vars(this);
- elements_iterator row_iter(shared_from_this(), &table_selector, &row_selector);
+ m_css.compute(this, doc);
- element::ptr row = row_iter.next(false);
- while (row)
+ if (recursive)
+ {
+ for (const auto& el : m_children)
{
- m_grid->begin_row(row);
-
- elements_iterator cell_iter(row, &table_selector, &cell_selector);
- element::ptr cell = cell_iter.next();
- while (cell)
- {
- m_grid->add_cell(cell);
-
- cell = cell_iter.next(false);
- }
- row = row_iter.next(false);
+ el->compute_styles();
}
-
- m_grid->finish();
}
+}
- for (auto& el : m_children)
- {
- el->init();
- }
+bool litehtml::html_tag::is_white_space() const
+{
+ return false;
+}
+
+int litehtml::html_tag::select(const string& selector)
+{
+ css_selector sel;
+ sel.parse(selector);
+ return select(sel, true);
}
int litehtml::html_tag::select(const css_selector& selector, bool apply_pseudo)
@@ -680,107 +511,34 @@ int litehtml::html_tag::select(const css_selector& selector, bool apply_pseudo)
int litehtml::html_tag::select(const css_element_selector& selector, bool apply_pseudo)
{
- if(!selector.m_tag.empty() && selector.m_tag != _t("*"))
+ if(selector.m_tag != star_id && selector.m_tag != m_tag)
{
- if(selector.m_tag != m_tag)
- {
- return select_no_match;
- }
+ return select_no_match;
}
int res = select_match;
- element::ptr el_parent = parent();
- for(css_attribute_selector::vector::const_iterator i = selector.m_attrs.begin(); i != selector.m_attrs.end(); i++)
+ for(const auto& attr : selector.m_attrs)
{
- const tchar_t* attr_value = get_attr(i->attribute.c_str());
- switch(i->condition)
+ switch(attr.type)
{
- case select_exists:
- if(!attr_value)
- {
- return select_no_match;
- }
- break;
- case select_equal:
- if(!attr_value)
- {
- return select_no_match;
- } else
- {
- if(i->attribute == _t("class"))
- {
- const string_vector & tokens1 = m_class_values;
- const string_vector & tokens2 = i->class_val;
- bool found = true;
- for(string_vector::const_iterator str1 = tokens2.begin(); str1 != tokens2.end() && found; str1++)
- {
- bool f = false;
- for(string_vector::const_iterator str2 = tokens1.begin(); str2 != tokens1.end() && !f; str2++)
- {
- if( !t_strcasecmp(str1->c_str(), str2->c_str()) )
- {
- f = true;
- }
- }
- if(!f)
- {
- found = false;
- }
- }
- if(!found)
- {
- return select_no_match;
- }
- } else
- {
- if( t_strcasecmp(i->val.c_str(), attr_value) )
- {
- return select_no_match;
- }
- }
- }
- break;
- case select_contain_str:
- if(!attr_value)
- {
- return select_no_match;
- } else if(!t_strstr(attr_value, i->val.c_str()))
- {
- return select_no_match;
- }
- break;
- case select_start_str:
- if(!attr_value)
- {
- return select_no_match;
- } else if(t_strncmp(attr_value, i->val.c_str(), i->val.length()))
+ case select_class:
+ if (std::find(m_classes.begin(), m_classes.end(), attr.name) == m_classes.end())
{
return select_no_match;
}
break;
- case select_end_str:
- if(!attr_value)
+ case select_id:
+ if (attr.name != m_id)
{
return select_no_match;
- } else if(t_strncmp(attr_value, i->val.c_str(), i->val.length()))
- {
- const tchar_t* s = attr_value + t_strlen(attr_value) - i->val.length() - 1;
- if(s < attr_value)
- {
- return select_no_match;
- }
- if(i->val != s)
- {
- return select_no_match;
- }
}
break;
case select_pseudo_element:
- if(i->val == _t("after"))
+ if(attr.name == _after_)
{
res |= select_match_with_after;
- } else if(i->val == _t("before"))
+ } else if(attr.name == _before_)
{
res |= select_match_with_before;
} else
@@ -791,3970 +549,1130 @@ int litehtml::html_tag::select(const css_element_selector& selector, bool apply_
case select_pseudo_class:
if(apply_pseudo)
{
- if (!el_parent) return select_no_match;
-
- tstring selector_param;
- tstring selector_name;
-
- tstring::size_type begin = i->val.find_first_of(_t('('));
- tstring::size_type end = (begin == tstring::npos) ? tstring::npos : find_close_bracket(i->val, begin);
- if(begin != tstring::npos && end != tstring::npos)
+ if (select_pseudoclass(attr) == select_no_match)
{
- selector_param = i->val.substr(begin + 1, end - begin - 1);
- }
- if(begin != tstring::npos)
- {
- selector_name = i->val.substr(0, begin);
- litehtml::trim(selector_name);
- } else
- {
- selector_name = i->val;
- }
-
- int selector = value_index(selector_name.c_str(), pseudo_class_strings);
-
- switch(selector)
- {
- case pseudo_class_only_child:
- if (!el_parent->is_only_child(shared_from_this(), false))
- {
- return select_no_match;
- }
- break;
- case pseudo_class_only_of_type:
- if (!el_parent->is_only_child(shared_from_this(), true))
- {
- return select_no_match;
- }
- break;
- case pseudo_class_first_child:
- if (!el_parent->is_nth_child(shared_from_this(), 0, 1, false))
- {
- return select_no_match;
- }
- break;
- case pseudo_class_first_of_type:
- if (!el_parent->is_nth_child(shared_from_this(), 0, 1, true))
- {
- return select_no_match;
- }
- break;
- case pseudo_class_last_child:
- if (!el_parent->is_nth_last_child(shared_from_this(), 0, 1, false))
- {
- return select_no_match;
- }
- break;
- case pseudo_class_last_of_type:
- if (!el_parent->is_nth_last_child(shared_from_this(), 0, 1, true))
- {
- return select_no_match;
- }
- break;
- case pseudo_class_nth_child:
- case pseudo_class_nth_of_type:
- case pseudo_class_nth_last_child:
- case pseudo_class_nth_last_of_type:
- {
- if(selector_param.empty()) return select_no_match;
-
- int num = 0;
- int off = 0;
-
- parse_nth_child_params(selector_param, num, off);
- if(!num && !off) return select_no_match;
- switch(selector)
- {
- case pseudo_class_nth_child:
- if (!el_parent->is_nth_child(shared_from_this(), num, off, false))
- {
- return select_no_match;
- }
- break;
- case pseudo_class_nth_of_type:
- if (!el_parent->is_nth_child(shared_from_this(), num, off, true))
- {
- return select_no_match;
- }
- break;
- case pseudo_class_nth_last_child:
- if (!el_parent->is_nth_last_child(shared_from_this(), num, off, false))
- {
- return select_no_match;
- }
- break;
- case pseudo_class_nth_last_of_type:
- if (!el_parent->is_nth_last_child(shared_from_this(), num, off, true))
- {
- return select_no_match;
- }
- break;
- }
-
- }
- break;
- case pseudo_class_not:
- {
- css_element_selector sel;
- sel.parse(selector_param);
- if(select(sel, apply_pseudo))
- {
- return select_no_match;
- }
- }
- break;
- case pseudo_class_lang:
- {
- trim( selector_param );
-
- if( !get_document()->match_lang( selector_param ) )
- {
- return select_no_match;
- }
- }
- break;
- default:
- if(std::find(m_pseudo_classes.begin(), m_pseudo_classes.end(), i->val) == m_pseudo_classes.end())
- {
- return select_no_match;
- }
- break;
+ return select_no_match;
}
} else
{
res |= select_match_pseudo_class;
}
break;
+ default:
+ if (select_attribute(attr) == select_no_match)
+ {
+ return select_no_match;
+ }
}
}
return res;
}
-litehtml::element::ptr litehtml::html_tag::find_ancestor(const css_selector& selector, bool apply_pseudo, bool* is_pseudo)
+int litehtml::html_tag::select_pseudoclass(const css_attribute_selector& sel)
{
element::ptr el_parent = parent();
- if (!el_parent)
- {
- return nullptr;
- }
- int res = el_parent->select(selector, apply_pseudo);
- if(res != select_no_match)
+
+ switch (sel.name)
{
- if(is_pseudo)
+ case _only_child_:
+ if (!el_parent || !el_parent->is_only_child(shared_from_this(), false))
{
- if(res & select_match_pseudo_class)
- {
- *is_pseudo = true;
- } else
- {
- *is_pseudo = false;
- }
+ return select_no_match;
}
- return el_parent;
- }
- return el_parent->find_ancestor(selector, apply_pseudo, is_pseudo);
-}
-
-int litehtml::html_tag::get_floats_height(element_float el_float) const
-{
- if(is_floats_holder())
- {
- int h = 0;
-
- bool process = false;
-
- for(const auto& fb : m_floats_left)
+ break;
+ case _only_of_type_:
+ if (!el_parent || !el_parent->is_only_child(shared_from_this(), true))
{
- 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 select_no_match;
+ }
+ break;
+ case _first_child_:
+ if (!el_parent || !el_parent->is_nth_child(shared_from_this(), 0, 1, false))
+ {
+ return select_no_match;
+ }
+ break;
+ case _first_of_type_:
+ if (!el_parent || !el_parent->is_nth_child(shared_from_this(), 0, 1, true))
+ {
+ return select_no_match;
+ }
+ break;
+ case _last_child_:
+ if (!el_parent || !el_parent->is_nth_last_child(shared_from_this(), 0, 1, false))
+ {
+ return select_no_match;
+ }
+ break;
+ case _last_of_type_:
+ if (!el_parent || !el_parent->is_nth_last_child(shared_from_this(), 0, 1, true))
+ {
+ return select_no_match;
}
+ break;
+ case _nth_child_:
+ case _nth_of_type_:
+ case _nth_last_child_:
+ case _nth_last_of_type_:
+ {
+ if (!el_parent) return select_no_match;
+ int num = sel.a;
+ int off = sel.b;
+ if (!num && !off) return select_no_match;
- for(const auto fb : m_floats_right)
+ switch (sel.name)
{
- process = false;
- switch(el_float)
+ case _nth_child_:
+ if (!el_parent->is_nth_child(shared_from_this(), num, off, false))
{
- 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;
+ return select_no_match;
}
- if(process)
+ break;
+ case _nth_of_type_:
+ if (!el_parent->is_nth_child(shared_from_this(), num, off, true))
{
- if(el_float == float_none)
- {
- h = std::max(h, fb.pos.bottom());
- } else
- {
- h = std::max(h, fb.pos.top());
- }
+ return select_no_match;
}
- }
-
- return h;
- }
- element::ptr el_parent = parent();
- if (el_parent)
- {
- int h = el_parent->get_floats_height(el_float);
- return h - m_pos.y;
- }
- return 0;
-}
-
-int litehtml::html_tag::get_left_floats_height() const
-{
- if(is_floats_holder())
- {
- int h = 0;
- if(!m_floats_left.empty())
- {
- for (const auto& fb : m_floats_left)
+ break;
+ case _nth_last_child_:
+ if (!el_parent->is_nth_last_child(shared_from_this(), num, off, false))
{
- h = std::max(h, fb.pos.bottom());
+ return select_no_match;
}
- }
- return h;
- }
- element::ptr el_parent = parent();
- if (el_parent)
- {
- int h = el_parent->get_left_floats_height();
- return h - m_pos.y;
- }
- return 0;
-}
-
-int litehtml::html_tag::get_right_floats_height() const
-{
- if(is_floats_holder())
- {
- int h = 0;
- if(!m_floats_right.empty())
- {
- for(const auto& fb : m_floats_right)
+ break;
+ case _nth_last_of_type_:
+ if (!el_parent->is_nth_last_child(shared_from_this(), num, off, true))
{
- h = std::max(h, fb.pos.bottom());
+ return select_no_match;
}
+ break;
}
- return h;
- }
- element::ptr el_parent = parent();
- if (el_parent)
- {
- int h = el_parent->get_right_floats_height();
- return h - m_pos.y;
- }
- return 0;
-}
-int litehtml::html_tag::get_line_left( int y )
-{
- if(is_floats_holder())
- {
- if(m_cahe_line_left.is_valid && m_cahe_line_left.hash == y)
+ }
+ break;
+ case _not_:
+ if (select(*sel.sel, true))
{
- return m_cahe_line_left.val;
+ return select_no_match;
}
-
- int w = 0;
- for(const auto& fb : m_floats_left)
+ break;
+ case _lang_:
+ if (!get_document()->match_lang(sel.val))
{
- if (y >= fb.pos.top() && y < fb.pos.bottom())
- {
- w = std::max(w, fb.pos.right());
- if (w < fb.pos.right())
- {
- break;
- }
- }
+ return select_no_match;
}
- m_cahe_line_left.set_value(y, w);
- return w;
- }
- element::ptr el_parent = parent();
- if (el_parent)
- {
- int w = el_parent->get_line_left(y + m_pos.y);
- if (w < 0)
+ break;
+ default:
+ if (std::find(m_pseudo_classes.begin(), m_pseudo_classes.end(), sel.name) == m_pseudo_classes.end())
{
- w = 0;
+ return select_no_match;
}
- return w - (w ? m_pos.x : 0);
+ break;
}
- return 0;
+ return select_match;
}
-int litehtml::html_tag::get_line_right( int y, int def_right )
+int litehtml::html_tag::select_attribute(const css_attribute_selector& sel)
{
- if(is_floats_holder())
+ const char* attr_value = get_attr(_s(sel.name).c_str());
+
+ switch (sel.type)
{
- if(m_cahe_line_right.is_valid && m_cahe_line_right.hash == y)
+ case select_exists:
+ if (!attr_value)
{
- if(m_cahe_line_right.is_default)
- {
- return def_right;
- } else
- {
- return std::min(m_cahe_line_right.val, def_right);
- }
+ return select_no_match;
}
-
- int w = def_right;
- m_cahe_line_right.is_default = true;
- for(const auto& fb : m_floats_right)
+ break;
+ case select_equal:
+ if (!attr_value || strcmp(attr_value, sel.val.c_str()))
{
- if(y >= fb.pos.top() && y < fb.pos.bottom())
- {
- w = std::min(w, fb.pos.left());
- m_cahe_line_right.is_default = false;
- if(w > fb.pos.left())
- {
- break;
- }
- }
+ return select_no_match;
}
- m_cahe_line_right.set_value(y, w);
- return w;
- }
- element::ptr 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::html_tag::get_line_left_right( int y, int def_right, int& ln_left, int& ln_right )
-{
- if(is_floats_holder())
- {
- ln_left = get_line_left(y);
- ln_right = get_line_right(y, def_right);
- } else
- {
- element::ptr el_parent = parent();
- if (el_parent)
+ break;
+ case select_contain_str:
+ if (!attr_value || !strstr(attr_value, sel.val.c_str()))
{
- el_parent->get_line_left_right(y + m_pos.y, def_right + m_pos.x, ln_left, ln_right);
+ return select_no_match;
}
- 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;
- }
- }
- }
-}
-
-int litehtml::html_tag::fix_line_width( int max_width, element_float flt )
-{
- int ret_width = 0;
- if(!m_boxes.empty())
- {
- elements_vector els;
- m_boxes.back()->get_elements(els);
- bool was_cleared = false;
- if(!els.empty() && els.front()->get_clear() != clear_none)
+ break;
+ case select_start_str:
+ if (!attr_value || strncmp(attr_value, sel.val.c_str(), sel.val.length()))
{
- if(els.front()->get_clear() == clear_both)
- {
- was_cleared = true;
- } else
- {
- if( (flt == float_left && els.front()->get_clear() == clear_left) ||
- (flt == float_right && els.front()->get_clear() == clear_right) )
- {
- was_cleared = true;
- }
- }
+ return select_no_match;
}
-
- if(!was_cleared)
+ break;
+ case select_end_str:
+ if (!attr_value)
{
- m_boxes.pop_back();
-
- for(elements_vector::iterator i = els.begin(); i != els.end(); i++)
- {
- int rw = place_element((*i), max_width);
- if(rw > ret_width)
- {
- ret_width = rw;
- }
- }
- } else
+ return select_no_match;
+ }
+ else if (strncmp(attr_value, sel.val.c_str(), sel.val.length()))
{
- int line_top = 0;
- if(m_boxes.back()->get_type() == box_line)
- {
- line_top = m_boxes.back()->top();
- } else
- {
- line_top = m_boxes.back()->bottom();
- }
-
- int line_left = 0;
- int line_right = max_width;
- get_line_left_right(line_top, max_width, line_left, line_right);
-
- if(m_boxes.back()->get_type() == box_line)
+ const char* s = attr_value + strlen(attr_value) - sel.val.length() - 1;
+ if (s < attr_value)
{
- if(m_boxes.size() == 1 && m_list_style_type != list_style_type_none && m_list_style_position == list_style_position_inside)
- {
- int sz_font = get_font_size();
- line_left += sz_font;
- }
-
- if(m_css_text_indent.val() != 0)
- {
- bool line_box_found = false;
- for(box::vector::iterator iter = m_boxes.begin(); iter < m_boxes.end(); iter++)
- {
- if((*iter)->get_type() == box_line)
- {
- line_box_found = true;
- break;
- }
- }
- if(!line_box_found)
- {
- line_left += m_css_text_indent.calc_percent(max_width);
- }
- }
-
+ return select_no_match;
}
-
- elements_vector els;
- m_boxes.back()->new_width(line_left, line_right, els);
- for(auto& el : els)
+ if (sel.val != s)
{
- int rw = place_element(el, max_width);
- if(rw > ret_width)
- {
- ret_width = rw;
- }
+ return select_no_match;
}
}
+ break;
}
-
- return ret_width;
+ return select_match;
}
-void litehtml::html_tag::add_float(const element::ptr &el, int x, int y)
+litehtml::element::ptr litehtml::html_tag::find_ancestor(const css_selector& selector, bool apply_pseudo, bool* is_pseudo)
{
- if(is_floats_holder())
+ element::ptr el_parent = parent();
+ if (!el_parent)
{
- 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->get_float();
- fb.clear_floats = el->get_clear();
- fb.el = el;
-
- if(fb.float_side == float_left)
- {
- if(m_floats_left.empty())
- {
- m_floats_left.push_back(fb);
- } else
- {
- bool inserted = false;
- for(floated_box::vector::iterator 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_cahe_line_left.invalidate();
- } else if(fb.float_side == float_right)
+ return nullptr;
+ }
+ int res = el_parent->select(selector, apply_pseudo);
+ if(res != select_no_match)
+ {
+ if(is_pseudo)
{
- if(m_floats_right.empty())
+ if(res & select_match_pseudo_class)
{
- m_floats_right.push_back(std::move(fb));
+ *is_pseudo = true;
} else
{
- bool inserted = false;
- for(floated_box::vector::iterator 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);
- }
+ *is_pseudo = false;
}
- m_cahe_line_right.invalidate();
- }
- } else
- {
- element::ptr el_parent = parent();
- if (el_parent)
- {
- el_parent->add_float(el, x + m_pos.x, y + m_pos.y);
}
+ return el_parent;
}
+ return el_parent->find_ancestor(selector, apply_pseudo, is_pseudo);
}
-int litehtml::html_tag::find_next_line_top( int top, int width, int def_right )
+void litehtml::html_tag::parse_attributes()
{
- if(is_floats_holder())
+ for(auto& el : m_children)
{
- 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;
+ el->parse_attributes();
}
- element::ptr el_parent = parent();
- if (el_parent)
+}
+
+void litehtml::html_tag::get_text( string& text )
+{
+ for (auto& el : m_children)
{
- 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;
+ el->get_text(text);
}
- return 0;
}
-void litehtml::html_tag::parse_background()
+bool litehtml::html_tag::is_body() const
{
- // parse background-color
- m_bg.m_color = get_color(_t("background-color"), false, web_color(0, 0, 0, 0));
-
- // parse background-position
- const tchar_t* str = get_style_property(_t("background-position"), false, _t("0% 0%"));
- if(str)
- {
- string_vector res;
- split_string(str, res, _t(" \t"));
- if(res.size() > 0)
- {
- if(res.size() == 1)
- {
- if( value_in_list(res[0].c_str(), _t("left;right;center")) )
- {
- m_bg.m_position.x.fromString(res[0], _t("left;right;center"));
- m_bg.m_position.y.set_value(50, css_units_percentage);
- } else if( value_in_list(res[0].c_str(), _t("top;bottom;center")) )
- {
- m_bg.m_position.y.fromString(res[0], _t("top;bottom;center"));
- m_bg.m_position.x.set_value(50, css_units_percentage);
- } else
- {
- m_bg.m_position.x.fromString(res[0], _t("left;right;center"));
- m_bg.m_position.y.set_value(50, css_units_percentage);
- }
- } else
- {
- if(value_in_list(res[0].c_str(), _t("left;right")))
- {
- m_bg.m_position.x.fromString(res[0], _t("left;right;center"));
- m_bg.m_position.y.fromString(res[1], _t("top;bottom;center"));
- } else if(value_in_list(res[0].c_str(), _t("top;bottom")))
- {
- m_bg.m_position.x.fromString(res[1], _t("left;right;center"));
- m_bg.m_position.y.fromString(res[0], _t("top;bottom;center"));
- } else if(value_in_list(res[1].c_str(), _t("left;right")))
- {
- m_bg.m_position.x.fromString(res[1], _t("left;right;center"));
- m_bg.m_position.y.fromString(res[0], _t("top;bottom;center"));
- }else if(value_in_list(res[1].c_str(), _t("top;bottom")))
- {
- m_bg.m_position.x.fromString(res[0], _t("left;right;center"));
- m_bg.m_position.y.fromString(res[1], _t("top;bottom;center"));
- } else
- {
- m_bg.m_position.x.fromString(res[0], _t("left;right;center"));
- m_bg.m_position.y.fromString(res[1], _t("top;bottom;center"));
- }
- }
-
- if(m_bg.m_position.x.is_predefined())
- {
- switch(m_bg.m_position.x.predef())
- {
- case 0:
- m_bg.m_position.x.set_value(0, css_units_percentage);
- break;
- case 1:
- m_bg.m_position.x.set_value(100, css_units_percentage);
- break;
- case 2:
- m_bg.m_position.x.set_value(50, css_units_percentage);
- break;
- }
- }
- if(m_bg.m_position.y.is_predefined())
- {
- switch(m_bg.m_position.y.predef())
- {
- case 0:
- m_bg.m_position.y.set_value(0, css_units_percentage);
- break;
- case 1:
- m_bg.m_position.y.set_value(100, css_units_percentage);
- break;
- case 2:
- m_bg.m_position.y.set_value(50, css_units_percentage);
- break;
- }
- }
- } else
- {
- m_bg.m_position.x.set_value(0, css_units_percentage);
- m_bg.m_position.y.set_value(0, css_units_percentage);
- }
- } else
- {
- m_bg.m_position.y.set_value(0, css_units_percentage);
- m_bg.m_position.x.set_value(0, css_units_percentage);
- }
-
- str = get_style_property(_t("background-size"), false, _t("auto"));
- if(str)
- {
- string_vector res;
- split_string(str, res, _t(" \t"));
- if(!res.empty())
- {
- m_bg.m_position.width.fromString(res[0], background_size_strings);
- if(res.size() > 1)
- {
- m_bg.m_position.height.fromString(res[1], background_size_strings);
- } else
- {
- m_bg.m_position.height.predef(background_size_auto);
- }
- } else
- {
- m_bg.m_position.width.predef(background_size_auto);
- m_bg.m_position.height.predef(background_size_auto);
- }
- }
-
- document::ptr doc = get_document();
-
- doc->cvt_units(m_bg.m_position.x, m_font_size);
- doc->cvt_units(m_bg.m_position.y, m_font_size);
- doc->cvt_units(m_bg.m_position.width, m_font_size);
- doc->cvt_units(m_bg.m_position.height, m_font_size);
-
- // parse background_attachment
- m_bg.m_attachment = (background_attachment) value_index(
- get_style_property(_t("background-attachment"), false, _t("scroll")),
- background_attachment_strings,
- background_attachment_scroll);
-
- // parse background_attachment
- m_bg.m_repeat = (background_repeat) value_index(
- get_style_property(_t("background-repeat"), false, _t("repeat")),
- background_repeat_strings,
- background_repeat_repeat);
-
- // parse background_clip
- m_bg.m_clip = (background_box) value_index(
- get_style_property(_t("background-clip"), false, _t("border-box")),
- background_box_strings,
- background_box_border);
-
- // parse background_origin
- m_bg.m_origin = (background_box) value_index(
- get_style_property(_t("background-origin"), false, _t("padding-box")),
- background_box_strings,
- background_box_content);
-
- // parse background-image
- css::parse_css_url(get_style_property(_t("background-image"), false, _t("")), m_bg.m_image);
- m_bg.m_baseurl = get_style_property(_t("background-image-baseurl"), false, _t(""));
-
- if(!m_bg.m_image.empty())
- {
- doc->container()->load_image(m_bg.m_image.c_str(), m_bg.m_baseurl.empty() ? 0 : m_bg.m_baseurl.c_str(), true);
- }
-}
-
-void litehtml::html_tag::add_positioned(const element::ptr &el)
-{
- if (m_el_position != element_position_static || (!have_parent()))
- {
- m_positioned.push_back(el);
- } else
- {
- element::ptr el_parent = parent();
- if (el_parent)
- {
- el_parent->add_positioned(el);
- }
- }
-}
-
-void litehtml::html_tag::calc_outlines( int parent_width )
-{
- m_padding.left = m_css_padding.left.calc_percent(parent_width);
- m_padding.right = m_css_padding.right.calc_percent(parent_width);
-
- m_borders.left = m_css_borders.left.width.calc_percent(parent_width);
- m_borders.right = m_css_borders.right.width.calc_percent(parent_width);
-
- m_margins.left = m_css_margins.left.calc_percent(parent_width);
- m_margins.right = m_css_margins.right.calc_percent(parent_width);
-
- m_margins.top = m_css_margins.top.calc_percent(parent_width);
- m_margins.bottom = m_css_margins.bottom.calc_percent(parent_width);
-
- m_padding.top = m_css_padding.top.calc_percent(parent_width);
- m_padding.bottom = m_css_padding.bottom.calc_percent(parent_width);
-}
-
-void litehtml::html_tag::calc_auto_margins(int parent_width)
-{
- if (get_element_position() != element_position_absolute && (m_display == display_block || m_display == display_table))
- {
- if (m_css_margins.left.is_predefined() && m_css_margins.right.is_predefined())
- {
- int el_width = m_pos.width + m_borders.left + m_borders.right + m_padding.left + m_padding.right;
- if (el_width <= parent_width)
- {
- m_margins.left = (parent_width - el_width) / 2;
- m_margins.right = (parent_width - el_width) - m_margins.left;
- }
- else
- {
- m_margins.left = 0;
- m_margins.right = 0;
- }
- }
- else if (m_css_margins.left.is_predefined() && !m_css_margins.right.is_predefined())
- {
- int el_width = m_pos.width + m_borders.left + m_borders.right + m_padding.left + m_padding.right + m_margins.right;
- m_margins.left = parent_width - el_width;
- if (m_margins.left < 0) m_margins.left = 0;
- }
- else if (!m_css_margins.left.is_predefined() && m_css_margins.right.is_predefined())
- {
- int el_width = m_pos.width + m_borders.left + m_borders.right + m_padding.left + m_padding.right + m_margins.left;
- m_margins.right = parent_width - el_width;
- if (m_margins.right < 0) m_margins.right = 0;
- }
- }
-}
-
-void litehtml::html_tag::parse_attributes()
-{
- for(auto& el : m_children)
- {
- el->parse_attributes();
- }
-}
-
-void litehtml::html_tag::get_text( tstring& text )
-{
- for (auto& el : m_children)
- {
- el->get_text(text);
- }
-}
-
-bool litehtml::html_tag::is_body() const
-{
- return false;
-}
-
-void litehtml::html_tag::set_data( const tchar_t* data )
-{
-
-}
-
-void litehtml::html_tag::get_inline_boxes( position::vector& boxes )
-{
- litehtml::box* old_box = 0;
- position pos;
- for(auto& el : m_children)
- {
- if(!el->skip())
- {
- if(el->m_box)
- {
- if(el->m_box != old_box)
- {
- if(old_box)
- {
- if(boxes.empty())
- {
- pos.x -= m_padding.left + m_borders.left;
- pos.width += m_padding.left + m_borders.left;
- }
- boxes.push_back(pos);
- }
- old_box = el->m_box;
- pos.x = el->left() + el->margin_left();
- pos.y = el->top() - m_padding.top - m_borders.top;
- pos.width = 0;
- pos.height = 0;
- }
- pos.width = el->right() - pos.x - el->margin_right() - el->margin_left();
- pos.height = std::max(pos.height, el->height() + m_padding.top + m_padding.bottom + m_borders.top + m_borders.bottom);
- } else if(el->get_display() == display_inline)
- {
- position::vector sub_boxes;
- el->get_inline_boxes(sub_boxes);
- if(!sub_boxes.empty())
- {
- sub_boxes.rbegin()->width += el->margin_right();
- if(boxes.empty())
- {
- if(m_padding.left + m_borders.left > 0)
- {
- position padding_box = (*sub_boxes.begin());
- padding_box.x -= m_padding.left + m_borders.left + el->margin_left();
- padding_box.width = m_padding.left + m_borders.left + el->margin_left();
- boxes.push_back(padding_box);
- }
- }
-
- sub_boxes.rbegin()->width += el->margin_right();
-
- boxes.insert(boxes.end(), sub_boxes.begin(), sub_boxes.end());
- }
- }
- }
- }
- if(pos.width || pos.height)
- {
- if(boxes.empty())
- {
- pos.x -= m_padding.left + m_borders.left;
- pos.width += m_padding.left + m_borders.left;
- }
- boxes.push_back(pos);
- }
- if(!boxes.empty())
- {
- if(m_padding.right + m_borders.right > 0)
- {
- boxes.back().width += m_padding.right + m_borders.right;
- }
- }
-}
-
-bool litehtml::html_tag::on_mouse_over()
-{
- bool ret = false;
-
- element::ptr el = shared_from_this();
- while(el)
- {
- if(el->set_pseudo_class(_t("hover"), true))
- {
- ret = true;
- }
- el = el->parent();
- }
-
- return ret;
-}
-
-bool litehtml::html_tag::find_styles_changes( position::vector& redraw_boxes, int x, int y )
-{
- if(m_display == display_inline_text)
- {
- return false;
- }
-
- bool ret = false;
- bool apply = false;
- for (used_selector::vector::iterator iter = m_used_styles.begin(); iter != m_used_styles.end() && !apply; iter++)
- {
- if((*iter)->m_selector->is_media_valid())
- {
- int res = select(*((*iter)->m_selector), true);
- if( (res == select_no_match && (*iter)->m_used) || (res == select_match && !(*iter)->m_used) )
- {
- apply = true;
- }
- }
- }
-
- if(apply)
- {
- if(m_display == display_inline || m_display == display_table_row)
- {
- position::vector boxes;
- get_inline_boxes(boxes);
- for(position::vector::iterator pos = boxes.begin(); pos != boxes.end(); pos++)
- {
- pos->x += x;
- pos->y += y;
- redraw_boxes.push_back(*pos);
- }
- } else
- {
- position pos = m_pos;
- if(m_el_position != element_position_fixed)
- {
- pos.x += x;
- pos.y += y;
- }
- pos += m_padding;
- pos += m_borders;
- redraw_boxes.push_back(pos);
- }
-
- ret = true;
- refresh_styles();
- parse_styles();
- }
- for (auto& el : m_children)
- {
- if(!el->skip())
- {
- if(m_el_position != element_position_fixed)
- {
- if(el->find_styles_changes(redraw_boxes, x + m_pos.x, y + m_pos.y))
- {
- ret = true;
- }
- } else
- {
- if(el->find_styles_changes(redraw_boxes, m_pos.x, m_pos.y))
- {
- ret = true;
- }
- }
- }
- }
- return ret;
-}
-
-bool litehtml::html_tag::on_mouse_leave()
-{
- bool ret = false;
-
- element::ptr el = shared_from_this();
- while(el)
- {
- if(el->set_pseudo_class(_t("hover"), false))
- {
- ret = true;
- }
- if(el->set_pseudo_class(_t("active"), false))
- {
- ret = true;
- }
- el = el->parent();
- }
-
- return ret;
-}
-
-bool litehtml::html_tag::on_lbutton_down()
-{
- bool ret = false;
-
- element::ptr el = shared_from_this();
- while (el)
- {
- if (el->set_pseudo_class(_t("active"), true))
- {
- ret = true;
- }
- el = el->parent();
- }
-
- return ret;
-}
-
-bool litehtml::html_tag::on_lbutton_up()
-{
- bool ret = false;
-
- element::ptr el = shared_from_this();
- while (el)
- {
- if (el->set_pseudo_class(_t("active"), false))
- {
- ret = true;
- }
- el = el->parent();
- }
-
- on_click();
-
- return ret;
-}
-
-void litehtml::html_tag::on_click()
-{
- if (have_parent())
- {
- element::ptr el_parent = parent();
- if (el_parent)
- {
- el_parent->on_click();
- }
- }
-}
-
-const litehtml::tchar_t* litehtml::html_tag::get_cursor()
-{
- return get_style_property(_t("cursor"), true, 0);
-}
-
-static const int font_size_table[8][7] =
-{
- { 9, 9, 9, 9, 11, 14, 18},
- { 9, 9, 9, 10, 12, 15, 20},
- { 9, 9, 9, 11, 13, 17, 22},
- { 9, 9, 10, 12, 14, 18, 24},
- { 9, 9, 10, 13, 16, 20, 26},
- { 9, 9, 11, 14, 17, 21, 28},
- { 9, 10, 12, 15, 17, 23, 30},
- { 9, 10, 13, 16, 18, 24, 32}
-};
-
-
-void litehtml::html_tag::init_font()
-{
- // initialize font size
- const tchar_t* str = get_style_property(_t("font-size"), false, 0);
-
- int parent_sz = 0;
- int doc_font_size = get_document()->container()->get_default_font_size();
- element::ptr el_parent = parent();
- if (el_parent)
- {
- parent_sz = el_parent->get_font_size();
- } else
- {
- parent_sz = doc_font_size;
- }
-
-
- if(!str)
- {
- m_font_size = parent_sz;
- } else
- {
- m_font_size = parent_sz;
-
- css_length sz;
- sz.fromString(str, font_size_strings);
- if(sz.is_predefined())
- {
- int idx_in_table = doc_font_size - 9;
- if(idx_in_table >= 0 && idx_in_table <= 7)
- {
- if(sz.predef() >= fontSize_xx_small && sz.predef() <= fontSize_xx_large)
- {
- m_font_size = font_size_table[idx_in_table][sz.predef()];
- } else
- {
- m_font_size = doc_font_size;
- }
- } else
- {
- switch(sz.predef())
- {
- case fontSize_xx_small:
- m_font_size = doc_font_size * 3 / 5;
- break;
- case fontSize_x_small:
- m_font_size = doc_font_size * 3 / 4;
- break;
- case fontSize_small:
- m_font_size = doc_font_size * 8 / 9;
- break;
- case fontSize_large:
- m_font_size = doc_font_size * 6 / 5;
- break;
- case fontSize_x_large:
- m_font_size = doc_font_size * 3 / 2;
- break;
- case fontSize_xx_large:
- m_font_size = doc_font_size * 2;
- break;
- default:
- m_font_size = doc_font_size;
- break;
- }
- }
- } else
- {
- if(sz.units() == css_units_percentage)
- {
- m_font_size = sz.calc_percent(parent_sz);
- } else if(sz.units() == css_units_none)
- {
- m_font_size = parent_sz;
- } else
- {
- m_font_size = get_document()->cvt_units(sz, parent_sz);
- }
- }
- }
-
- // initialize font
- const tchar_t* name = get_style_property(_t("font-family"), true, _t("inherit"));
- const tchar_t* weight = get_style_property(_t("font-weight"), true, _t("normal"));
- const tchar_t* style = get_style_property(_t("font-style"), true, _t("normal"));
- const tchar_t* decoration = get_style_property(_t("text-decoration"), true, _t("none"));
-
- m_font = get_document()->get_font(name, m_font_size, weight, style, decoration, &m_font_metrics);
-}
-
-bool litehtml::html_tag::is_break() const
-{
- return false;
-}
-
-void litehtml::html_tag::set_tagName( const tchar_t* tag )
-{
- tstring s_val = tag;
- for(size_t i = 0; i < s_val.length(); i++)
- {
- s_val[i] = std::tolower(s_val[i], std::locale::classic());
- }
- m_tag = s_val;
-}
-
-void litehtml::html_tag::draw_background( uint_ptr hdc, int x, int y, const position* clip )
-{
- position pos = m_pos;
- pos.x += x;
- pos.y += y;
-
- position el_pos = pos;
- el_pos += m_padding;
- el_pos += m_borders;
-
- if(m_display != display_inline && m_display != display_table_row)
- {
- if(el_pos.does_intersect(clip))
- {
- const background* bg = get_background();
- if(bg)
- {
- background_paint bg_paint;
- init_background_paint(pos, bg_paint, bg);
-
- get_document()->container()->draw_background(hdc, bg_paint);
- }
- position border_box = pos;
- border_box += m_padding;
- border_box += m_borders;
-
- borders bdr = m_css_borders;
- bdr.radius = m_css_borders.radius.calc_percents(border_box.width, border_box.height);
-
- get_document()->container()->draw_borders(hdc, bdr, border_box, have_parent() ? false : true);
- }
- } else
- {
- const background* bg = get_background();
-
- position::vector boxes;
- get_inline_boxes(boxes);
-
- background_paint bg_paint;
- position content_box;
-
- for(position::vector::iterator box = boxes.begin(); box != boxes.end(); box++)
- {
- box->x += x;
- box->y += y;
-
- if(box->does_intersect(clip))
- {
- content_box = *box;
- content_box -= m_borders;
- content_box -= m_padding;
-
- if(bg)
- {
- init_background_paint(content_box, bg_paint, bg);
- }
-
- css_borders bdr;
-
- // set left borders radius for the first box
- if(box == boxes.begin())
- {
- bdr.radius.bottom_left_x = m_css_borders.radius.bottom_left_x;
- bdr.radius.bottom_left_y = m_css_borders.radius.bottom_left_y;
- bdr.radius.top_left_x = m_css_borders.radius.top_left_x;
- bdr.radius.top_left_y = m_css_borders.radius.top_left_y;
- }
-
- // set right borders radius for the last box
- if(box == boxes.end() - 1)
- {
- bdr.radius.bottom_right_x = m_css_borders.radius.bottom_right_x;
- bdr.radius.bottom_right_y = m_css_borders.radius.bottom_right_y;
- bdr.radius.top_right_x = m_css_borders.radius.top_right_x;
- bdr.radius.top_right_y = m_css_borders.radius.top_right_y;
- }
-
-
- bdr.top = m_css_borders.top;
- bdr.bottom = m_css_borders.bottom;
- if(box == boxes.begin())
- {
- bdr.left = m_css_borders.left;
- }
- if(box == boxes.end() - 1)
- {
- bdr.right = m_css_borders.right;
- }
-
-
- if(bg)
- {
- bg_paint.border_radius = bdr.radius.calc_percents(bg_paint.border_box.width, bg_paint.border_box.width);
- get_document()->container()->draw_background(hdc, bg_paint);
- }
- borders b = bdr;
- b.radius = bdr.radius.calc_percents(box->width, box->height);
- get_document()->container()->draw_borders(hdc, b, *box, false);
- }
- }
- }
-}
-
-int litehtml::html_tag::render_inline(const element::ptr &container, int max_width)
-{
- int ret_width = 0;
- int rw = 0;
-
- white_space ws = get_white_space();
- bool skip_spaces = false;
- if (ws == white_space_normal ||
- ws == white_space_nowrap ||
- ws == white_space_pre_line)
- {
- skip_spaces = true;
- }
- bool was_space = false;
-
- for (auto& el : m_children)
- {
- // skip spaces to make rendering a bit faster
- if (skip_spaces)
- {
- if (el->is_white_space())
- {
- if (was_space)
- {
- el->skip(true);
- continue;
- }
- else
- {
- was_space = true;
- }
- }
- else
- {
- was_space = false;
- }
- }
-
- rw = container->place_element( el, max_width );
- if(rw > ret_width)
- {
- ret_width = rw;
- }
- }
- return ret_width;
-}
-
-int litehtml::html_tag::place_element(const element::ptr &el, int max_width)
-{
- if(el->get_display() == display_none) return 0;
-
- if(el->get_display() == display_inline)
- {
- return el->render_inline(shared_from_this(), max_width);
- }
-
- element_position el_position = el->get_element_position();
-
- if(el_position == element_position_absolute || el_position == element_position_fixed)
- {
- int line_top = 0;
- if(!m_boxes.empty())
- {
- if(m_boxes.back()->get_type() == box_line)
- {
- line_top = m_boxes.back()->top();
- if(!m_boxes.back()->is_empty())
- {
- line_top += line_height();
- }
- } else
- {
- line_top = m_boxes.back()->bottom();
- }
- }
-
- el->render(0, line_top, max_width);
- el->m_pos.x += el->content_margins_left();
- el->m_pos.y += el->content_margins_top();
-
- return 0;
- }
-
- int ret_width = 0;
-
- switch(el->get_float())
- {
- case float_left:
- {
- int line_top = 0;
- if(!m_boxes.empty())
- {
- if(m_boxes.back()->get_type() == box_line)
- {
- line_top = m_boxes.back()->top();
- } else
- {
- line_top = m_boxes.back()->bottom();
- }
- }
- line_top = get_cleared_top(el, line_top);
- int line_left = 0;
- int line_right = max_width;
- get_line_left_right(line_top, max_width, line_left, line_right);
-
- el->render(line_left, line_top, line_right);
- if(el->right() > line_right)
- {
- int new_top = find_next_line_top(el->top(), el->width(), max_width);
- el->m_pos.x = get_line_left(new_top) + el->content_margins_left();
- el->m_pos.y = new_top + el->content_margins_top();
- }
- add_float(el, 0, 0);
- ret_width = fix_line_width(max_width, float_left);
- if(!ret_width)
- {
- ret_width = el->right();
- }
- }
- break;
- case float_right:
- {
- int line_top = 0;
- if(!m_boxes.empty())
- {
- if(m_boxes.back()->get_type() == box_line)
- {
- line_top = m_boxes.back()->top();
- } else
- {
- line_top = m_boxes.back()->bottom();
- }
- }
- line_top = get_cleared_top(el, line_top);
- int line_left = 0;
- int line_right = max_width;
- get_line_left_right(line_top, max_width, line_left, line_right);
-
- el->render(0, line_top, line_right);
-
- if(line_left + el->width() > line_right)
- {
- int new_top = find_next_line_top(el->top(), el->width(), max_width);
- el->m_pos.x = get_line_right(new_top, max_width) - el->width() + el->content_margins_left();
- el->m_pos.y = new_top + el->content_margins_top();
- } else
- {
- el->m_pos.x = line_right - el->width() + el->content_margins_left();
- }
- add_float(el, 0, 0);
- ret_width = fix_line_width(max_width, float_right);
-
- if(!ret_width)
- {
- line_left = 0;
- line_right = max_width;
- get_line_left_right(line_top, max_width, line_left, line_right);
-
- ret_width = ret_width + (max_width - line_right);
- }
- }
- break;
- default:
- {
- line_context line_ctx;
- line_ctx.top = 0;
- if (!m_boxes.empty())
- {
- line_ctx.top = m_boxes.back()->top();
- }
- line_ctx.left = 0;
- line_ctx.right = max_width;
- line_ctx.fix_top();
- get_line_left_right(line_ctx.top, max_width, line_ctx.left, line_ctx.right);
-
- switch(el->get_display())
- {
- case display_inline_block:
- case display_inline_table:
- ret_width = el->render(line_ctx.left, line_ctx.top, line_ctx.right);
- break;
- case display_block:
- if(el->is_replaced() || el->is_floats_holder())
- {
- element::ptr el_parent = el->parent();
- el->m_pos.width = el->get_css_width().calc_percent(line_ctx.right - line_ctx.left);
- el->m_pos.height = el->get_css_height().calc_percent(el_parent ? el_parent->m_pos.height : 0);
- }
- el->calc_outlines(line_ctx.right - line_ctx.left);
- break;
- case display_inline_text:
- {
- litehtml::size sz;
- el->get_content_size(sz, line_ctx.right);
- el->m_pos = sz;
- }
- break;
- default:
- ret_width = 0;
- break;
- }
-
- bool add_box = true;
- if(!m_boxes.empty())
- {
- if(m_boxes.back()->can_hold(el, m_white_space))
- {
- add_box = false;
- }
- }
- if(add_box)
- {
- new_box(el, max_width, line_ctx);
- } else if(!m_boxes.empty())
- {
- line_ctx.top = m_boxes.back()->top();
- }
-
- if (line_ctx.top != line_ctx.calculatedTop)
- {
- line_ctx.left = 0;
- line_ctx.right = max_width;
- line_ctx.fix_top();
- get_line_left_right(line_ctx.top, max_width, line_ctx.left, line_ctx.right);
- }
-
- if(!el->is_inline_box())
- {
- if(m_boxes.size() == 1)
- {
- if(collapse_top_margin())
- {
- int shift = el->margin_top();
- if(shift >= 0)
- {
- line_ctx.top -= shift;
- m_boxes.back()->y_shift(-shift);
- }
- }
- } else
- {
- int shift = 0;
- int prev_margin = m_boxes[m_boxes.size() - 2]->bottom_margin();
-
- if(prev_margin > el->margin_top())
- {
- shift = el->margin_top();
- } else
- {
- shift = prev_margin;
- }
- if(shift >= 0)
- {
- line_ctx.top -= shift;
- m_boxes.back()->y_shift(-shift);
- }
- }
- }
-
- switch(el->get_display())
- {
- case display_table:
- case display_list_item:
- ret_width = el->render(line_ctx.left, line_ctx.top, line_ctx.width());
- break;
- case display_block:
- case display_table_cell:
- case display_table_caption:
- case display_table_row:
- if(el->is_replaced() || el->is_floats_holder())
- {
- ret_width = el->render(line_ctx.left, line_ctx.top, line_ctx.width()) + line_ctx.left + (max_width - line_ctx.right);
- } else
- {
- ret_width = el->render(0, line_ctx.top, max_width);
- }
- break;
- default:
- ret_width = 0;
- break;
- }
-
- m_boxes.back()->add_element(el);
-
- if(el->is_inline_box() && !el->skip())
- {
- ret_width = el->right() + (max_width - line_ctx.right);
- }
- }
- break;
- }
-
- return ret_width;
-}
-
-bool litehtml::html_tag::set_pseudo_class( const tchar_t* pclass, bool add )
-{
- bool ret = false;
- if(add)
- {
- if(std::find(m_pseudo_classes.begin(), m_pseudo_classes.end(), pclass) == m_pseudo_classes.end())
- {
- m_pseudo_classes.push_back(pclass);
- ret = true;
- }
- } else
- {
- string_vector::iterator pi = std::find(m_pseudo_classes.begin(), m_pseudo_classes.end(), pclass);
- if(pi != m_pseudo_classes.end())
- {
- m_pseudo_classes.erase(pi);
- ret = true;
- }
- }
- return ret;
-}
-
-bool litehtml::html_tag::set_class( const tchar_t* pclass, bool add )
-{
- string_vector classes;
- bool changed = false;
-
- split_string( pclass, classes, _t(" ") );
-
- if(add)
- {
- for( auto & _class : classes )
- {
- if(std::find(m_class_values.begin(), m_class_values.end(), _class) == m_class_values.end())
- {
- m_class_values.push_back( std::move( _class ) );
- changed = true;
- }
- }
- } else
- {
- for( const auto & _class : classes )
- {
- auto end = std::remove(m_class_values.begin(), m_class_values.end(), _class);
-
- if(end != m_class_values.end())
- {
- m_class_values.erase(end, m_class_values.end());
- changed = true;
- }
- }
- }
-
- if( changed )
- {
- tstring class_string;
- join_string(class_string, m_class_values, _t(" "));
- set_attr(_t("class"), class_string.c_str());
-
- return true;
- }
- else
- {
- return false;
- }
-
-}
-
-int litehtml::html_tag::line_height() const
-{
- return m_line_height;
-}
-
-bool litehtml::html_tag::is_replaced() const
-{
- return false;
-}
-
-int litehtml::html_tag::finish_last_box(bool end_of_render)
-{
- int line_top = 0;
-
- if(!m_boxes.empty())
- {
- m_boxes.back()->finish(end_of_render);
-
- if(m_boxes.back()->is_empty())
- {
- line_top = m_boxes.back()->top();
- m_boxes.pop_back();
- }
-
- if(!m_boxes.empty())
- {
- line_top = m_boxes.back()->bottom();
- }
- }
- return line_top;
-}
-
-int litehtml::html_tag::new_box(const element::ptr &el, int max_width, line_context& line_ctx)
-{
- line_ctx.top = get_cleared_top(el, finish_last_box());
-
- line_ctx.left = 0;
- line_ctx.right = max_width;
- line_ctx.fix_top();
- get_line_left_right(line_ctx.top, max_width, line_ctx.left, line_ctx.right);
-
- if(el->is_inline_box() || el->is_floats_holder())
- {
- if (el->width() > line_ctx.right - line_ctx.left)
- {
- line_ctx.top = find_next_line_top(line_ctx.top, el->width(), max_width);
- line_ctx.left = 0;
- line_ctx.right = max_width;
- line_ctx.fix_top();
- get_line_left_right(line_ctx.top, max_width, line_ctx.left, line_ctx.right);
- }
- }
-
- int first_line_margin = 0;
- if(m_boxes.empty() && m_list_style_type != list_style_type_none && m_list_style_position == list_style_position_inside)
- {
- int sz_font = get_font_size();
- first_line_margin = sz_font;
- }
-
- if(el->is_inline_box())
- {
- int text_indent = 0;
- if(m_css_text_indent.val() != 0)
- {
- bool line_box_found = false;
- for(box::vector::iterator iter = m_boxes.begin(); iter != m_boxes.end(); iter++)
- {
- if((*iter)->get_type() == box_line)
- {
- line_box_found = true;
- break;
- }
- }
- if(!line_box_found)
- {
- text_indent = m_css_text_indent.calc_percent(max_width);
- }
- }
-
- font_metrics fm;
- get_font(&fm);
- m_boxes.emplace_back(std::unique_ptr<line_box>(new line_box(line_ctx.top, line_ctx.left + first_line_margin + text_indent, line_ctx.right, line_height(), fm, m_text_align)));
- } else
- {
- m_boxes.emplace_back(std::unique_ptr<block_box>(new block_box(line_ctx.top, line_ctx.left, line_ctx.right)));
- }
-
- return line_ctx.top;
-}
-
-int litehtml::html_tag::get_cleared_top(const element::ptr &el, int line_top) const
-{
- switch(el->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();
- if(fh && fh > line_top)
- {
- line_top = fh;
- }
- }
- break;
- default:
- if(el->get_float() != float_none)
- {
- int fh = get_floats_height(el->get_float());
- if(fh && fh > line_top)
- {
- line_top = fh;
- }
- }
- break;
- }
- return line_top;
-}
-
-litehtml::style_display litehtml::html_tag::get_display() const
-{
- return m_display;
-}
-
-litehtml::element_float litehtml::html_tag::get_float() const
-{
- return m_float;
-}
-
-bool litehtml::html_tag::is_floats_holder() const
-{
- if( m_display == display_inline_block ||
- m_display == display_table_cell ||
- !have_parent() ||
- is_body() ||
- m_float != float_none ||
- m_el_position == element_position_absolute ||
- m_el_position == element_position_fixed ||
- m_overflow > overflow_visible)
- {
- return true;
- }
- return false;
-}
-
-bool litehtml::html_tag::is_first_child_inline(const element::ptr& el) const
-{
- if(!m_children.empty())
- {
- for (const auto& this_el : m_children)
- {
- if (!this_el->is_white_space())
- {
- if (el == this_el)
- {
- return true;
- }
- if (this_el->get_display() == display_inline)
- {
- if (this_el->have_inline_child())
- {
- return false;
- }
- } else
- {
- return false;
- }
- }
- }
- }
- return false;
-}
-
-bool litehtml::html_tag::is_last_child_inline(const element::ptr& el)
-{
- if(!m_children.empty())
- {
- for (auto this_el = m_children.rbegin(); this_el < m_children.rend(); ++this_el)
- {
- if (!(*this_el)->is_white_space())
- {
- if (el == (*this_el))
- {
- return true;
- }
- if ((*this_el)->get_display() == display_inline)
- {
- if ((*this_el)->have_inline_child())
- {
- return false;
- }
- } else
- {
- return false;
- }
- }
- }
- }
- return false;
-}
-
-litehtml::white_space litehtml::html_tag::get_white_space() const
-{
- return m_white_space;
-}
-
-litehtml::vertical_align litehtml::html_tag::get_vertical_align() const
-{
- return m_vertical_align;
-}
-
-litehtml::css_length litehtml::html_tag::get_css_left() const
-{
- return m_css_offsets.left;
-}
-
-litehtml::css_length litehtml::html_tag::get_css_right() const
-{
- return m_css_offsets.right;
-}
-
-litehtml::css_length litehtml::html_tag::get_css_top() const
-{
- return m_css_offsets.top;
-}
-
-litehtml::css_length litehtml::html_tag::get_css_bottom() const
-{
- return m_css_offsets.bottom;
-}
-
-
-litehtml::css_offsets litehtml::html_tag::get_css_offsets() const
-{
- return m_css_offsets;
-}
-
-litehtml::element_clear litehtml::html_tag::get_clear() const
-{
- return m_clear;
-}
-
-litehtml::css_length litehtml::html_tag::get_css_width() const
-{
- return m_css_width;
-}
-
-litehtml::css_length litehtml::html_tag::get_css_height() const
-{
- return m_css_height;
-}
-
-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::set_css_width( css_length& w )
-{
- m_css_width = w;
-}
-
-void litehtml::html_tag::apply_vertical_align()
-{
- if(!m_boxes.empty())
- {
- int add = 0;
- int content_height = m_boxes.back()->bottom();
-
- if(m_pos.height > content_height)
- {
- switch(m_vertical_align)
- {
- case va_middle:
- add = (m_pos.height - content_height) / 2;
- break;
- case va_bottom:
- add = m_pos.height - content_height;
- break;
- default:
- add = 0;
- break;
- }
- }
-
- if(add)
- {
- for(size_t i = 0; i < m_boxes.size(); i++)
- {
- m_boxes[i]->y_shift(add);
- }
- }
- }
-}
-
-litehtml::element_position litehtml::html_tag::get_element_position(css_offsets* offsets) const
-{
- if(offsets && m_el_position != element_position_static)
- {
- *offsets = m_css_offsets;
- }
- return m_el_position;
-}
-
-void litehtml::html_tag::init_background_paint(position pos, background_paint &bg_paint, const background* bg)
-{
- if(!bg) return;
-
- bg_paint = *bg;
- position content_box = pos;
- position padding_box = pos;
- padding_box += m_padding;
- position border_box = padding_box;
- border_box += m_borders;
-
- switch(bg->m_clip)
- {
- case litehtml::background_box_padding:
- bg_paint.clip_box = padding_box;
- break;
- case litehtml::background_box_content:
- bg_paint.clip_box = content_box;
- break;
- default:
- bg_paint.clip_box = border_box;
- break;
- }
-
- switch(bg->m_origin)
- {
- case litehtml::background_box_border:
- bg_paint.origin_box = border_box;
- break;
- case litehtml::background_box_content:
- bg_paint.origin_box = content_box;
- break;
- default:
- bg_paint.origin_box = padding_box;
- break;
- }
-
- if(!bg_paint.image.empty())
- {
- get_document()->container()->get_image_size(bg_paint.image.c_str(), bg_paint.baseurl.c_str(), bg_paint.image_size);
- if(bg_paint.image_size.width && bg_paint.image_size.height)
- {
- litehtml::size img_new_sz = bg_paint.image_size;
- double img_ar_width = (double) bg_paint.image_size.width / (double) bg_paint.image_size.height;
- double img_ar_height = (double) bg_paint.image_size.height / (double) bg_paint.image_size.width;
-
-
- if(bg->m_position.width.is_predefined())
- {
- switch(bg->m_position.width.predef())
- {
- case litehtml::background_size_contain:
- if( (int) ((double) bg_paint.origin_box.width * img_ar_height) <= bg_paint.origin_box.height )
- {
- img_new_sz.width = bg_paint.origin_box.width;
- img_new_sz.height = (int) ((double) bg_paint.origin_box.width * img_ar_height);
- } else
- {
- img_new_sz.height = bg_paint.origin_box.height;
- img_new_sz.width = (int) ((double) bg_paint.origin_box.height * img_ar_width);
- }
- break;
- case litehtml::background_size_cover:
- if( (int) ((double) bg_paint.origin_box.width * img_ar_height) >= bg_paint.origin_box.height )
- {
- img_new_sz.width = bg_paint.origin_box.width;
- img_new_sz.height = (int) ((double) bg_paint.origin_box.width * img_ar_height);
- } else
- {
- img_new_sz.height = bg_paint.origin_box.height;
- img_new_sz.width = (int) ((double) bg_paint.origin_box.height * img_ar_width);
- }
- break;
- break;
- case litehtml::background_size_auto:
- if(!bg->m_position.height.is_predefined())
- {
- img_new_sz.height = bg->m_position.height.calc_percent(bg_paint.origin_box.height);
- img_new_sz.width = (int) ((double) img_new_sz.height * img_ar_width);
- }
- break;
- }
- } else
- {
- img_new_sz.width = bg->m_position.width.calc_percent(bg_paint.origin_box.width);
- if(bg->m_position.height.is_predefined())
- {
- img_new_sz.height = (int) ((double) img_new_sz.width * img_ar_height);
- } else
- {
- img_new_sz.height = bg->m_position.height.calc_percent(bg_paint.origin_box.height);
- }
- }
-
- bg_paint.image_size = img_new_sz;
- bg_paint.position_x = bg_paint.origin_box.x + (int) bg->m_position.x.calc_percent(bg_paint.origin_box.width - bg_paint.image_size.width);
- bg_paint.position_y = bg_paint.origin_box.y + (int) bg->m_position.y.calc_percent(bg_paint.origin_box.height - bg_paint.image_size.height);
- }
-
- }
- bg_paint.border_radius = m_css_borders.radius.calc_percents(border_box.width, border_box.height);
- bg_paint.border_box = border_box;
- bg_paint.is_root = have_parent() ? false : true;
-}
-
-litehtml::visibility litehtml::html_tag::get_visibility() const
-{
- return m_visibility;
-}
-
-void litehtml::html_tag::draw_list_marker( uint_ptr hdc, const position &pos )
-{
- list_marker lm;
-
- const tchar_t* list_image = get_style_property(_t("list-style-image"), true, 0);
- size img_size;
- if(list_image)
- {
- css::parse_css_url(list_image, lm.image);
- lm.baseurl = get_style_property(_t("list-style-image-baseurl"), true, 0);
- get_document()->container()->get_image_size(lm.image.c_str(), lm.baseurl, img_size);
- } else
- {
- lm.baseurl = 0;
- }
-
- int ln_height = line_height();
- int sz_font = get_font_size();
- lm.pos.x = pos.x;
- lm.pos.width = sz_font - sz_font * 2 / 3;
- lm.color = get_color(_t("color"), true, web_color(0, 0, 0));
- lm.marker_type = m_list_style_type;
- lm.font = get_font();
-
- if (m_list_style_type >= list_style_type_armenian)
- {
- lm.pos.y = pos.y;
- lm.pos.height = pos.height;
- lm.index = get_attr(_t("list_index"), _t(""))[0];
- }
- else
- {
- lm.pos.height = sz_font - sz_font * 2 / 3;
- lm.pos.y = pos.y + ln_height / 2 - lm.pos.height / 2;
- lm.index = -1;
- }
-
- if(img_size.width && img_size.height)
- {
- if(lm.pos.y + img_size.height > pos.y + pos.height)
- {
- lm.pos.y = pos.y + pos.height - img_size.height;
- }
- if(img_size.width > lm.pos.width)
- {
- lm.pos.x -= img_size.width - lm.pos.width;
- }
-
- lm.pos.width = img_size.width;
- lm.pos.height = img_size.height;
- }
-
- if (m_list_style_position == list_style_position_outside)
- {
- if (m_list_style_type >= list_style_type_armenian)
- {
- auto tw_space = get_document()->container()->text_width(_t(" "), lm.font);
- lm.pos.x = pos.x - tw_space * 2;
- lm.pos.width = tw_space;
- }
- else
- {
- lm.pos.x -= sz_font;
- }
- }
-
- if (m_list_style_type >= list_style_type_armenian)
- {
- auto marker_text = get_list_marker_text(lm.index);
- lm.pos.height = ln_height;
- if (marker_text.empty())
- {
- get_document()->container()->draw_list_marker(hdc, lm);
- }
- else
- {
- marker_text += _t(".");
- auto tw = get_document()->container()->text_width(marker_text.c_str(), lm.font);
- auto text_pos = lm.pos;
- text_pos.move_to(text_pos.right() - tw, text_pos.y);
- text_pos.width = tw;
- get_document()->container()->draw_text(hdc, marker_text.c_str(), lm.font, lm.color, text_pos);
- }
- }
- else
- {
- get_document()->container()->draw_list_marker(hdc, lm);
- }
-}
-
-litehtml::tstring litehtml::html_tag::get_list_marker_text(int index)
-{
- switch (m_list_style_type)
- {
- case litehtml::list_style_type_decimal:
- return t_to_string(index);
- case litehtml::list_style_type_decimal_leading_zero:
- {
- auto txt = t_to_string(index);
- if (txt.length() == 1)
- {
- txt = _t("0") + txt;
- }
- return txt;
- }
- case litehtml::list_style_type_lower_latin:
- case litehtml::list_style_type_lower_alpha:
- return num_cvt::to_latin_lower(index);
- case litehtml::list_style_type_lower_greek:
- return num_cvt::to_greek_lower(index);
- case litehtml::list_style_type_upper_alpha:
- case litehtml::list_style_type_upper_latin:
- return num_cvt::to_latin_upper(index);
- case litehtml::list_style_type_lower_roman:
- return num_cvt::to_roman_lower(index);
- case litehtml::list_style_type_upper_roman:
- return num_cvt::to_roman_upper(index);
- case litehtml::list_style_type_armenian:
- break;
- case litehtml::list_style_type_georgian:
- break;
- case litehtml::list_style_type_hebrew:
- break;
- case litehtml::list_style_type_hiragana:
- break;
- case litehtml::list_style_type_hiragana_iroha:
- break;
- case litehtml::list_style_type_katakana:
- break;
- case litehtml::list_style_type_katakana_iroha:
- break;
- default:
- break;
- }
- return _t("");
-}
-
-void litehtml::html_tag::draw_children( uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex )
-{
- if (m_display == display_table || m_display == display_inline_table)
- {
- draw_children_table(hdc, x, y, clip, flag, zindex);
- }
- else
- {
- draw_children_box(hdc, x, y, clip, flag, zindex);
- }
-}
-
-bool litehtml::html_tag::fetch_positioned()
-{
- bool ret = false;
-
- m_positioned.clear();
-
- litehtml::element_position el_pos;
-
- for(auto& el : m_children)
- {
- el_pos = el->get_element_position();
- if (el_pos != element_position_static)
- {
- add_positioned(el);
- }
- if (!ret && (el_pos == element_position_absolute || el_pos == element_position_fixed))
- {
- ret = true;
- }
- if(el->fetch_positioned())
- {
- ret = true;
- }
- }
- return ret;
-}
-
-int litehtml::html_tag::get_zindex() const
-{
- return m_z_index;
-}
-
-void litehtml::html_tag::render_positioned(render_type rt)
-{
- position wnd_position;
- get_document()->container()->get_client_rect(wnd_position);
-
- element_position el_position;
- bool process;
- for (auto& el : m_positioned)
- {
- el_position = el->get_element_position();
-
- process = false;
- if(el->get_display() != display_none)
- {
- if(el_position == element_position_absolute)
- {
- if(rt != render_fixed_only)
- {
- process = true;
- }
- } else if(el_position == element_position_fixed)
- {
- if(rt != render_no_fixed)
- {
- process = true;
- }
- }
- }
-
- if(process)
- {
- int parent_height = 0;
- int parent_width = 0;
- if(el_position == element_position_fixed)
- {
- parent_height = wnd_position.height;
- parent_width = wnd_position.width;
- } else
- {
- element::ptr el_parent = el->parent();
- if(el_parent)
- {
- parent_height = el_parent->height();
- parent_width = el_parent->width();
- }
- }
-
- css_length css_left = el->get_css_left();
- css_length css_right = el->get_css_right();
- css_length css_top = el->get_css_top();
- css_length css_bottom = el->get_css_bottom();
-
- bool need_render = false;
-
- css_length el_w = el->get_css_width();
- css_length el_h = el->get_css_height();
-
- int new_width = -1;
- int new_height = -1;
- if(el_w.units() == css_units_percentage && parent_width)
- {
- new_width = el_w.calc_percent(parent_width);
- if(el->m_pos.width != new_width)
- {
- need_render = true;
- el->m_pos.width = new_width;
- }
- }
-
- if(el_h.units() == css_units_percentage && parent_height)
- {
- new_height = el_h.calc_percent(parent_height);
- if(el->m_pos.height != new_height)
- {
- need_render = true;
- el->m_pos.height = new_height;
- }
- }
-
- bool cvt_x = false;
- bool cvt_y = false;
-
- if(el_position == element_position_fixed)
- {
- if(!css_left.is_predefined() || !css_right.is_predefined())
- {
- if(!css_left.is_predefined() && css_right.is_predefined())
- {
- el->m_pos.x = css_left.calc_percent(parent_width) + el->content_margins_left();
- } else if(css_left.is_predefined() && !css_right.is_predefined())
- {
- el->m_pos.x = parent_width - css_right.calc_percent(parent_width) - el->m_pos.width - el->content_margins_right();
- } else
- {
- el->m_pos.x = css_left.calc_percent(parent_width) + el->content_margins_left();
- el->m_pos.width = parent_width - css_left.calc_percent(parent_width) - css_right.calc_percent(parent_width) - (el->content_margins_left() + el->content_margins_right());
- need_render = true;
- }
- }
-
- if(!css_top.is_predefined() || !css_bottom.is_predefined())
- {
- if(!css_top.is_predefined() && css_bottom.is_predefined())
- {
- el->m_pos.y = css_top.calc_percent(parent_height) + el->content_margins_top();
- } else if(css_top.is_predefined() && !css_bottom.is_predefined())
- {
- el->m_pos.y = parent_height - css_bottom.calc_percent(parent_height) - el->m_pos.height - el->content_margins_bottom();
- } else
- {
- el->m_pos.y = css_top.calc_percent(parent_height) + el->content_margins_top();
- el->m_pos.height = parent_height - css_top.calc_percent(parent_height) - css_bottom.calc_percent(parent_height) - (el->content_margins_top() + el->content_margins_bottom());
- need_render = true;
- }
- }
- } else
- {
- if(!css_left.is_predefined() || !css_right.is_predefined())
- {
- if(!css_left.is_predefined() && css_right.is_predefined())
- {
- el->m_pos.x = css_left.calc_percent(parent_width) + el->content_margins_left() - m_padding.left;
- } else if(css_left.is_predefined() && !css_right.is_predefined())
- {
- el->m_pos.x = m_pos.width + m_padding.right - css_right.calc_percent(parent_width) - el->m_pos.width - el->content_margins_right();
- } else
- {
- el->m_pos.x = css_left.calc_percent(parent_width) + el->content_margins_left() - m_padding.left;
- el->m_pos.width = m_pos.width + m_padding.left + m_padding.right - css_left.calc_percent(parent_width) - css_right.calc_percent(parent_width) - (el->content_margins_left() + el->content_margins_right());
- if (new_width != -1)
- {
- el->m_pos.x += (el->m_pos.width - new_width) / 2;
- el->m_pos.width = new_width;
- }
- need_render = true;
- }
- cvt_x = true;
- }
-
- if(!css_top.is_predefined() || !css_bottom.is_predefined())
- {
- if(!css_top.is_predefined() && css_bottom.is_predefined())
- {
- el->m_pos.y = css_top.calc_percent(parent_height) + el->content_margins_top() - m_padding.top;
- } else if(css_top.is_predefined() && !css_bottom.is_predefined())
- {
- el->m_pos.y = m_pos.height + m_padding.bottom - css_bottom.calc_percent(parent_height) - el->m_pos.height - el->content_margins_bottom();
- } else
- {
- el->m_pos.y = css_top.calc_percent(parent_height) + el->content_margins_top() - m_padding.top;
- el->m_pos.height = m_pos.height + m_padding.top + m_padding.bottom - css_top.calc_percent(parent_height) - css_bottom.calc_percent(parent_height) - (el->content_margins_top() + el->content_margins_bottom());
- if (new_height != -1)
- {
- el->m_pos.y += (el->m_pos.height - new_height) / 2;
- el->m_pos.height = new_height;
- }
- need_render = true;
- }
- cvt_y = true;
- }
- }
-
- if(cvt_x || cvt_y)
- {
- int offset_x = 0;
- int offset_y = 0;
- element::ptr cur_el = el->parent();
- element::ptr this_el = shared_from_this();
- while(cur_el && cur_el != this_el)
- {
- offset_x += cur_el->m_pos.x;
- offset_y += cur_el->m_pos.y;
- cur_el = cur_el->parent();
- }
- if(cvt_x) el->m_pos.x -= offset_x;
- if(cvt_y) el->m_pos.y -= offset_y;
- }
-
- if(need_render)
- {
- position pos = el->m_pos;
- el->render(el->left(), el->top(), el->width(), true);
- el->m_pos = pos;
- }
-
- if(el_position == element_position_fixed)
- {
- position fixed_pos;
- el->get_redraw_box(fixed_pos);
- get_document()->add_fixed_box(fixed_pos);
- }
- }
-
- el->render_positioned();
- }
-
- if(!m_positioned.empty())
- {
- std::stable_sort(m_positioned.begin(), m_positioned.end(), [](const litehtml::element::ptr& _Left, const litehtml::element::ptr& _Right)
- {
- return (_Left->get_zindex() < _Right->get_zindex());
- });
- }
-}
-
-void litehtml::html_tag::draw_stacking_context( uint_ptr hdc, int x, int y, const position* clip, bool with_positioned )
-{
- if(!is_visible()) return;
-
- std::map<int, bool> zindexes;
- if(with_positioned)
- {
- for(elements_vector::iterator i = m_positioned.begin(); i != m_positioned.end(); i++)
- {
- zindexes[(*i)->get_zindex()];
- }
-
- for(std::map<int, bool>::iterator idx = zindexes.begin(); idx != zindexes.end(); idx++)
- {
- if(idx->first < 0)
- {
- draw_children(hdc, x, y, clip, draw_positioned, idx->first);
- }
- }
- }
- draw_children(hdc, x, y, clip, draw_block, 0);
- draw_children(hdc, x, y, clip, draw_floats, 0);
- draw_children(hdc, x, y, clip, draw_inlines, 0);
- if(with_positioned)
- {
- for(std::map<int, bool>::iterator idx = zindexes.begin(); idx != zindexes.end(); idx++)
- {
- if(idx->first == 0)
- {
- draw_children(hdc, x, y, clip, draw_positioned, idx->first);
- }
- }
-
- for(std::map<int, bool>::iterator idx = zindexes.begin(); idx != zindexes.end(); idx++)
- {
- if(idx->first > 0)
- {
- draw_children(hdc, x, y, clip, draw_positioned, idx->first);
- }
- }
- }
-}
-
-litehtml::overflow litehtml::html_tag::get_overflow() const
-{
- return m_overflow;
-}
-
-bool litehtml::html_tag::is_nth_child(const element::ptr& el, int num, int off, bool of_type) const
-{
- int idx = 1;
- for(const auto& child : m_children)
- {
- if(child->get_display() != display_inline_text)
- {
- if( (!of_type) || (of_type && !t_strcmp(el->get_tagName(), child->get_tagName())) )
- {
- if(el == child)
- {
- if(num != 0)
- {
- if((idx - off) >= 0 && (idx - off) % num == 0)
- {
- return true;
- }
-
- } else if(idx == off)
- {
- return true;
- }
- return false;
- }
- idx++;
- }
- if(el == child) break;
- }
- }
- return false;
-}
-
-bool litehtml::html_tag::is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const
-{
- int idx = 1;
- for(elements_vector::const_reverse_iterator child = m_children.rbegin(); child != m_children.rend(); child++)
- {
- if((*child)->get_display() != display_inline_text)
- {
- if( !of_type || (of_type && !t_strcmp(el->get_tagName(), (*child)->get_tagName())) )
- {
- if(el == (*child))
- {
- if(num != 0)
- {
- if((idx - off) >= 0 && (idx - off) % num == 0)
- {
- return true;
- }
-
- } else if(idx == off)
- {
- return true;
- }
- return false;
- }
- idx++;
- }
- if(el == (*child)) break;
- }
- }
- return false;
-}
-
-void litehtml::html_tag::parse_nth_child_params( tstring param, int &num, int &off )
-{
- if(param == _t("odd"))
- {
- num = 2;
- off = 1;
- } else if(param == _t("even"))
- {
- num = 2;
- off = 0;
- } else
- {
- string_vector tokens;
- split_string(param, tokens, _t(" n"), _t("n"));
-
- tstring s_num;
- tstring s_off;
-
- tstring s_int;
- for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
- {
- if((*tok) == _t("n"))
- {
- s_num = s_int;
- s_int.clear();
- } else
- {
- s_int += (*tok);
- }
- }
- s_off = s_int;
-
- num = t_atoi(s_num.c_str());
- off = t_atoi(s_off.c_str());
- }
-}
-
-void litehtml::html_tag::calc_document_size( litehtml::size& sz, int x /*= 0*/, int y /*= 0*/ )
-{
- if(is_visible() && m_el_position != element_position_fixed)
- {
- element::calc_document_size(sz, x, y);
-
- if(m_overflow == overflow_visible)
- {
- for(auto& el : m_children)
- {
- el->calc_document_size(sz, x + m_pos.x, y + m_pos.y);
- }
- }
-
- // root element (<html>) must to cover entire window
- if(!have_parent())
- {
- position client_pos;
- get_document()->container()->get_client_rect(client_pos);
- m_pos.height = std::max(sz.height, client_pos.height) - content_margins_top() - content_margins_bottom();
- m_pos.width = std::max(sz.width, client_pos.width) - content_margins_left() - content_margins_right();
- }
- }
-}
-
-
-void litehtml::html_tag::get_redraw_box(litehtml::position& pos, int x /*= 0*/, int y /*= 0*/)
-{
- if(is_visible())
- {
- element::get_redraw_box(pos, x, y);
-
- if(m_overflow == overflow_visible)
- {
- for(auto& el : m_children)
- {
- if(el->get_element_position() != element_position_fixed)
- {
- el->get_redraw_box(pos, x + m_pos.x, y + m_pos.y);
- }
- }
- }
- }
-}
-
-litehtml::element::ptr litehtml::html_tag::find_adjacent_sibling( const element::ptr& el, const css_selector& selector, bool apply_pseudo /*= true*/, bool* is_pseudo /*= 0*/ )
-{
- element::ptr ret;
- for(auto& e : m_children)
- {
- if(e->get_display() != display_inline_text)
- {
- if(e == el)
- {
- if(ret)
- {
- int res = ret->select(selector, apply_pseudo);
- if(res != select_no_match)
- {
- if(is_pseudo)
- {
- if(res & select_match_pseudo_class)
- {
- *is_pseudo = true;
- } else
- {
- *is_pseudo = false;
- }
- }
- return ret;
- }
- }
- return 0;
- } else
- {
- ret = e;
- }
- }
- }
- return 0;
-}
-
-litehtml::element::ptr litehtml::html_tag::find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo /*= true*/, bool* is_pseudo /*= 0*/)
-{
- element::ptr ret = 0;
- for(auto& e : m_children)
- {
- if(e->get_display() != display_inline_text)
- {
- if(e == el)
- {
- return ret;
- } else if(!ret)
- {
- int res = e->select(selector, apply_pseudo);
- if(res != select_no_match)
- {
- if(is_pseudo)
- {
- if(res & select_match_pseudo_class)
- {
- *is_pseudo = true;
- } else
- {
- *is_pseudo = false;
- }
- }
- ret = e;
- }
- }
- }
- }
- return 0;
-}
-
-bool litehtml::html_tag::is_only_child(const element::ptr& el, bool of_type) const
-{
- int child_count = 0;
- for(const auto& child : m_children)
- {
- if(child->get_display() != display_inline_text)
- {
- if( !of_type || (of_type && !t_strcmp(el->get_tagName(), child->get_tagName())) )
- {
- child_count++;
- }
- if(child_count > 1) break;
- }
- }
- if(child_count > 1)
- {
- return false;
- }
- return true;
+ return false;
}
-void litehtml::html_tag::update_floats(int dy, const element::ptr &parent)
+void litehtml::html_tag::set_data( const char* /*data*/ )
{
- if(is_floats_holder())
- {
- bool reset_cache = false;
- for(floated_box::vector::reverse_iterator fb = m_floats_left.rbegin(); fb != m_floats_left.rend(); fb++)
- {
- if(fb->el->is_ancestor(parent))
- {
- reset_cache = true;
- fb->pos.y += dy;
- }
- }
- if(reset_cache)
- {
- m_cahe_line_left.invalidate();
- }
- reset_cache = false;
- for(floated_box::vector::reverse_iterator fb = m_floats_right.rbegin(); fb != m_floats_right.rend(); fb++)
- {
- if(fb->el->is_ancestor(parent))
- {
- reset_cache = true;
- fb->pos.y += dy;
- }
- }
- if(reset_cache)
- {
- m_cahe_line_right.invalidate();
- }
- } else
+
+}
+
+bool litehtml::html_tag::on_mouse_over()
+{
+ bool ret = false;
+
+ element::ptr el = shared_from_this();
+ while(el)
{
- element::ptr el_parent = this->parent();
- if (el_parent)
+ if(el->set_pseudo_class(_hover_, true))
{
- el_parent->update_floats(dy, parent);
+ ret = true;
}
+ el = el->parent();
}
+
+ return ret;
}
-void litehtml::html_tag::remove_before_after()
+bool litehtml::html_tag::on_mouse_leave()
{
- if(!m_children.empty())
+ bool ret = false;
+
+ element::ptr el = shared_from_this();
+ while(el)
{
- if( !t_strcmp(m_children.front()->get_tagName(), _t("::before")) )
+ if(el->set_pseudo_class(_hover_, false))
{
- m_children.erase(m_children.begin());
+ ret = true;
}
- }
- if(!m_children.empty())
- {
- if( !t_strcmp(m_children.back()->get_tagName(), _t("::after")) )
+ if(el->set_pseudo_class(_active_, false))
{
- m_children.erase(m_children.end() - 1);
+ ret = true;
}
+ el = el->parent();
}
+
+ return ret;
}
-litehtml::element::ptr litehtml::html_tag::get_element_before()
+bool litehtml::html_tag::on_lbutton_down()
{
- if(!m_children.empty())
+ bool ret = false;
+
+ element::ptr el = shared_from_this();
+ while (el)
{
- if( !t_strcmp(m_children.front()->get_tagName(), _t("::before")) )
+ if (el->set_pseudo_class(_active_, true))
{
- return m_children.front();
+ ret = true;
}
+ el = el->parent();
}
- element::ptr el = std::make_shared<el_before>(get_document());
- el->parent(shared_from_this());
- m_children.insert(m_children.begin(), el);
- return el;
+
+ return ret;
}
-litehtml::element::ptr litehtml::html_tag::get_element_after()
+bool litehtml::html_tag::on_lbutton_up()
{
- if(!m_children.empty())
+ bool ret = false;
+
+ element::ptr el = shared_from_this();
+ while (el)
{
- if( !t_strcmp(m_children.back()->get_tagName(), _t("::after")) )
+ if (el->set_pseudo_class(_active_, false))
{
- return m_children.back();
+ ret = true;
}
+ el = el->parent();
}
- element::ptr el = std::make_shared<el_after>(get_document());
- appendChild(el);
- return el;
-}
-void litehtml::html_tag::add_style( const litehtml::style& st )
-{
- m_style.combine(st);
+ on_click();
+
+ return ret;
}
-bool litehtml::html_tag::have_inline_child() const
+void litehtml::html_tag::on_click()
{
- if(!m_children.empty())
+ if (!is_root())
{
- for(const auto& el : m_children)
+ element::ptr el_parent = parent();
+ if (el_parent)
{
- if(!el->is_white_space())
- {
- return true;
- }
+ el_parent->on_click();
}
}
- return false;
}
-void litehtml::html_tag::refresh_styles()
+bool litehtml::html_tag::is_break() const
{
- remove_before_after();
+ return false;
+}
- for (auto& el : m_children)
- {
- if(el->get_display() != display_inline_text)
- {
- el->refresh_styles();
- }
- }
+void litehtml::html_tag::draw_background(uint_ptr hdc, int x, int y, const position *clip,
+ const std::shared_ptr<render_item> &ri)
+{
+ position pos = ri->pos();
+ pos.x += x;
+ pos.y += y;
- m_style.clear();
+ position el_pos = pos;
+ el_pos += ri->get_paddings();
+ el_pos += ri->get_margins();
- for (auto& usel : m_used_styles)
+ if(m_css.get_display() != display_inline && m_css.get_display() != display_table_row)
{
- usel->m_used = false;
-
- if(usel->m_selector->is_media_valid())
+ if(el_pos.does_intersect(clip) || is_root())
{
- int apply = select(*usel->m_selector, false);
+ auto v_offset = ri->get_draw_vertical_offset();
+ pos.y += v_offset;
+ pos.height -= v_offset;
- if(apply != select_no_match)
+ const background* bg = get_background();
+ if(bg)
{
- if(apply & select_match_pseudo_class)
- {
- if(select(*usel->m_selector, true))
- {
- if(apply & select_match_with_after)
- {
- element::ptr el = get_element_after();
- if(el)
- {
- el->add_style(*usel->m_selector->m_style);
- }
- } else if(apply & select_match_with_before)
- {
- element::ptr el = get_element_before();
- if(el)
- {
- el->add_style(*usel->m_selector->m_style);
- }
- }
- else
- {
- add_style(*usel->m_selector->m_style);
- usel->m_used = true;
- }
- }
- } else if(apply & select_match_with_after)
+ std::vector<background_paint> bg_paint;
+ init_background_paint(pos, bg_paint, bg, ri);
+ if(is_root())
{
- element::ptr el = get_element_after();
- if(el)
- {
- el->add_style(*usel->m_selector->m_style);
- }
- } else if(apply & select_match_with_before)
- {
- element::ptr el = get_element_before();
- if(el)
+ for(auto& b : bg_paint)
{
- el->add_style(*usel->m_selector->m_style);
+ b.clip_box = *clip;
+ b.border_box = *clip;
}
- } else
- {
- add_style(*usel->m_selector->m_style);
- usel->m_used = true;
}
- }
- }
- }
-}
-litehtml::element::ptr litehtml::html_tag::get_child_by_point(int x, int y, int client_x, int client_y, draw_flag flag, int zindex)
-{
- element::ptr ret = 0;
+ get_document()->container()->draw_background(hdc, bg_paint);
+ }
+ position border_box = pos;
+ border_box += ri->get_paddings();
+ border_box += ri->get_borders();
- if(m_overflow > overflow_visible)
- {
- if(!m_pos.is_point_inside(x, y))
- {
- return ret;
+ borders bdr = m_css.get_borders();
+ if(bdr.is_visible())
+ {
+ bdr.radius = m_css.get_borders().radius.calc_percents(border_box.width, border_box.height);
+ get_document()->container()->draw_borders(hdc, bdr, border_box, is_root());
+ }
}
- }
+ } else
+ {
+ const background* bg = get_background();
- position pos = m_pos;
- pos.x = x - pos.x;
- pos.y = y - pos.y;
+ position::vector boxes;
+ ri->get_inline_boxes(boxes);
- for(elements_vector::reverse_iterator i = m_children.rbegin(); i != m_children.rend() && !ret; i++)
- {
- element::ptr el = (*i);
+ std::vector<background_paint> bg_paint;
+ position content_box;
- if(el->is_visible() && el->get_display() != display_inline_text)
+ for(auto box = boxes.begin(); box != boxes.end(); box++)
{
- switch(flag)
+ box->x += x;
+ box->y += y;
+
+ if(box->does_intersect(clip))
{
- case draw_positioned:
- if(el->is_positioned() && el->get_zindex() == zindex)
+ content_box = *box;
+ content_box -= ri->get_borders();
+ content_box -= ri->get_paddings();
+
+ if(bg)
{
- if(el->get_element_position() == element_position_fixed)
- {
- ret = el->get_element_by_point(client_x, client_y, client_x, client_y);
- if(!ret && (*i)->is_point_inside(client_x, client_y))
- {
- ret = (*i);
- }
- } else
- {
- ret = el->get_element_by_point(pos.x, pos.y, client_x, client_y);
- if(!ret && (*i)->is_point_inside(pos.x, pos.y))
- {
- ret = (*i);
- }
- }
- el = 0;
+ init_background_paint(content_box, bg_paint, bg, ri);
}
- break;
- case draw_block:
- if(!el->is_inline_box() && el->get_float() == float_none && !el->is_positioned())
+
+ css_borders bdr;
+
+ // set left borders radius for the first box
+ if(box == boxes.begin())
{
- if(el->is_point_inside(pos.x, pos.y))
- {
- ret = el;
- }
+ bdr.radius.bottom_left_x = m_css.get_borders().radius.bottom_left_x;
+ bdr.radius.bottom_left_y = m_css.get_borders().radius.bottom_left_y;
+ bdr.radius.top_left_x = m_css.get_borders().radius.top_left_x;
+ bdr.radius.top_left_y = m_css.get_borders().radius.top_left_y;
}
- break;
- case draw_floats:
- if(el->get_float() != float_none && !el->is_positioned())
+
+ // set right borders radius for the last box
+ if(box == boxes.end() - 1)
{
- ret = el->get_element_by_point(pos.x, pos.y, client_x, client_y);
+ bdr.radius.bottom_right_x = m_css.get_borders().radius.bottom_right_x;
+ bdr.radius.bottom_right_y = m_css.get_borders().radius.bottom_right_y;
+ bdr.radius.top_right_x = m_css.get_borders().radius.top_right_x;
+ bdr.radius.top_right_y = m_css.get_borders().radius.top_right_y;
+ }
- if(!ret && (*i)->is_point_inside(pos.x, pos.y))
- {
- ret = (*i);
- }
- el = 0;
+
+ bdr.top = m_css.get_borders().top;
+ bdr.bottom = m_css.get_borders().bottom;
+ if(box == boxes.begin())
+ {
+ bdr.left = m_css.get_borders().left;
}
- break;
- case draw_inlines:
- if(el->is_inline_box() && el->get_float() == float_none && !el->is_positioned())
+ if(box == boxes.end() - 1)
{
- if(el->get_display() == display_inline_block)
- {
- ret = el->get_element_by_point(pos.x, pos.y, client_x, client_y);
- el = 0;
- }
- if(!ret && (*i)->is_point_inside(pos.x, pos.y))
- {
- ret = (*i);
- }
+ bdr.right = m_css.get_borders().right;
}
- break;
- default:
- break;
- }
- if(el && !el->is_positioned())
- {
- if(flag == draw_positioned)
+ if(bg)
{
- element::ptr child = el->get_child_by_point(pos.x, pos.y, client_x, client_y, flag, zindex);
- if(child)
+ for (auto& bgp : bg_paint)
{
- ret = child;
+ bgp.border_radius = bdr.radius.calc_percents(bgp.border_box.width, bgp.border_box.width);
}
- } else
+ get_document()->container()->draw_background(hdc, bg_paint);
+ }
+ if(bdr.is_visible())
{
- if( el->get_float() == float_none &&
- el->get_display() != display_inline_block)
- {
- element::ptr child = el->get_child_by_point(pos.x, pos.y, client_x, client_y, flag, zindex);
- if(child)
- {
- ret = child;
- }
- }
+ borders b = bdr;
+ b.radius = bdr.radius.calc_percents(box->width, box->height);
+ get_document()->container()->draw_borders(hdc, b, *box, false);
}
}
}
}
-
- return ret;
}
-litehtml::element::ptr litehtml::html_tag::get_element_by_point(int x, int y, int client_x, int client_y)
+bool litehtml::html_tag::set_pseudo_class( string_id cls, bool add )
{
- if(!is_visible()) return 0;
-
- element::ptr ret;
-
- std::map<int, bool> zindexes;
-
- for(elements_vector::iterator i = m_positioned.begin(); i != m_positioned.end(); i++)
- {
- zindexes[(*i)->get_zindex()];
- }
-
- for(std::map<int, bool>::iterator idx = zindexes.begin(); idx != zindexes.end() && !ret; idx++)
- {
- if(idx->first > 0)
- {
- ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, idx->first);
- }
- }
- if(ret) return ret;
-
- for(std::map<int, bool>::iterator idx = zindexes.begin(); idx != zindexes.end() && !ret; idx++)
- {
- if(idx->first == 0)
- {
- ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, idx->first);
- }
- }
- if(ret) return ret;
-
- ret = get_child_by_point(x, y, client_x, client_y, draw_inlines, 0);
- if(ret) return ret;
-
- ret = get_child_by_point(x, y, client_x, client_y, draw_floats, 0);
- if(ret) return ret;
-
- ret = get_child_by_point(x, y, client_x, client_y, draw_block, 0);
- if(ret) return ret;
-
-
- for(std::map<int, bool>::iterator idx = zindexes.begin(); idx != zindexes.end() && !ret; idx++)
- {
- if(idx->first < 0)
- {
- ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, idx->first);
- }
- }
- if(ret) return ret;
-
- if(m_el_position == element_position_fixed)
+ bool ret = false;
+ if(add)
{
- if(is_point_inside(client_x, client_y))
+ if(std::find(m_pseudo_classes.begin(), m_pseudo_classes.end(), cls) == m_pseudo_classes.end())
{
- ret = shared_from_this();
+ m_pseudo_classes.push_back(cls);
+ ret = true;
}
} else
{
- if(is_point_inside(x, y))
+ auto pi = std::find(m_pseudo_classes.begin(), m_pseudo_classes.end(), cls);
+ if(pi != m_pseudo_classes.end())
{
- ret = shared_from_this();
+ m_pseudo_classes.erase(pi);
+ ret = true;
}
}
-
return ret;
}
-const litehtml::background* litehtml::html_tag::get_background(bool own_only)
+bool litehtml::html_tag::set_class( const char* pclass, bool add )
{
- if(own_only)
- {
- // return own background with check for empty one
- if(m_bg.m_image.empty() && !m_bg.m_color.alpha)
- {
- return 0;
- }
- return &m_bg;
- }
+ string_vector classes;
+ bool changed = false;
+
+ split_string( pclass, classes, " " );
- if(m_bg.m_image.empty() && !m_bg.m_color.alpha)
+ if(add)
{
- // if this is root element (<html>) try to get background from body
- if (!have_parent())
+ for( auto & _class : classes )
{
- for (const auto& el : m_children)
+ if(std::find(m_str_classes.begin(), m_str_classes.end(), _class) == m_str_classes.end())
{
- if( el->is_body() )
- {
- // return own body background
- return el->get_background(true);
- }
- }
- }
- return 0;
- }
-
- if(is_body())
+ m_str_classes.push_back( std::move( _class ) );
+ changed = true;
+ }
+ }
+ } else
{
- element::ptr el_parent = parent();
- if (el_parent)
+ for( const auto & _class : classes )
{
- if (!el_parent->get_background(true))
+ auto end = std::remove(m_str_classes.begin(), m_str_classes.end(), _class);
+
+ if(end != m_str_classes.end())
{
- // parent of body will draw background for body
- return 0;
+ m_str_classes.erase(end, m_str_classes.end());
+ changed = true;
}
}
}
- return &m_bg;
+ if( changed )
+ {
+ string class_string;
+ join_string(class_string, m_str_classes, " ");
+ set_attr("class", class_string.c_str());
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+
}
-int litehtml::html_tag::render_box(int x, int y, int max_width, bool second_pass /*= false*/)
+bool litehtml::html_tag::is_replaced() const
{
- int parent_width = max_width;
-
- if (max_width <= 0)
- return 0;
+ return false;
+}
- calc_outlines(parent_width);
+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;
+}
- m_pos.clear();
- m_pos.move_to(x, y);
+size_t litehtml::html_tag::get_children_count() const
+{
+ return m_children.size();
+}
- m_pos.x += content_margins_left();
- m_pos.y += content_margins_top();
+litehtml::element::ptr litehtml::html_tag::get_child( int idx ) const
+{
+ return m_children[idx];
+}
- int ret_width = 0;
- def_value<int> block_width(0);
+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() };
+ if (!bg) return;
- if (m_display != display_table_cell && !m_css_width.is_predefined())
- {
- int w = calc_width(parent_width);
-
- if (m_box_sizing == box_sizing_border_box)
- {
- w -= m_padding.width() + m_borders.width();
- }
- ret_width = max_width = block_width = w;
- }
- else
- {
- if (max_width)
- {
- max_width -= content_margins_left() + content_margins_right();
- }
- }
+ int bg_count = std::max((int)bg->m_image.size(), 1);
+ bg_paint.resize(bg_count);
- // check for max-width (on the first pass only)
- if (!m_css_max_width.is_predefined() && !second_pass)
+ for (int i = 0; i < bg_count; i++)
{
- int mw = get_document()->cvt_units(m_css_max_width, m_font_size, parent_width);
- if (m_box_sizing == box_sizing_border_box)
- {
- mw -= m_padding.left + m_borders.left + m_padding.right + m_borders.right;
- }
- if (max_width > mw)
- {
- max_width = mw;
- }
+ init_one_background_paint(i, pos, bg_paint[i], bg, ri);
}
- m_floats_left.clear();
- m_floats_right.clear();
- m_boxes.clear();
- m_cahe_line_left.invalidate();
- m_cahe_line_right.invalidate();
-
- element_position el_position;
+ bg_paint.back().color = bg->m_color;
+}
- int block_height = 0;
+void litehtml::html_tag::init_one_background_paint(int i, position pos, background_paint& bg_paint, const background* bg, const std::shared_ptr<render_item>& ri)
+{
+ bg_paint.image = i < bg->m_image.size() ? bg->m_image[i] : "";
+ bg_paint.baseurl = bg->m_baseurl;
+ bg_paint.attachment = i < bg->m_attachment.size() ? (background_attachment)bg->m_attachment[i] : background_attachment_scroll;
+ bg_paint.repeat = i < bg->m_repeat.size() ? (background_repeat)bg->m_repeat[i] : background_repeat_repeat;
+ int clip = i < bg->m_clip.size() ? bg->m_clip[i] : background_box_border;
+ int origin = i < bg->m_origin.size() ? bg->m_origin[i] : background_box_padding;
+ const css_size auto_auto(css_length::predef_value(background_size_auto), css_length::predef_value(background_size_auto));
+ css_size size = i < bg->m_size.size() ? bg->m_size[i] : auto_auto;
+ css_length position_x = i < bg->m_position_x.size() ? bg->m_position_x[i] : css_length(0, css_units_percentage);
+ css_length position_y = i < bg->m_position_y.size() ? bg->m_position_y[i] : css_length(0, css_units_percentage);
- m_pos.height = 0;
+ position content_box = pos;
+ position padding_box = pos;
+ padding_box += ri->get_paddings();
+ position border_box = padding_box;
+ border_box += ri->get_borders();
- if (get_predefined_height(block_height))
+ switch(clip)
{
- m_pos.height = block_height;
+ case background_box_padding:
+ bg_paint.clip_box = padding_box;
+ break;
+ case background_box_content:
+ bg_paint.clip_box = content_box;
+ break;
+ default:
+ bg_paint.clip_box = border_box;
+ break;
}
- white_space ws = get_white_space();
- bool skip_spaces = false;
- if (ws == white_space_normal ||
- ws == white_space_nowrap ||
- ws == white_space_pre_line)
+ switch(origin)
{
- skip_spaces = true;
+ case background_box_border:
+ bg_paint.origin_box = border_box;
+ break;
+ case background_box_content:
+ bg_paint.origin_box = content_box;
+ break;
+ default:
+ bg_paint.origin_box = padding_box;
+ break;
}
- bool was_space = false;
-
- for (auto el : m_children)
+ if(!bg_paint.image.empty())
{
- // we don't need process absolute and fixed positioned element on the second pass
- if (second_pass)
+ get_document()->container()->get_image_size(bg_paint.image.c_str(), bg_paint.baseurl.c_str(), bg_paint.image_size);
+ if(bg_paint.image_size.width && bg_paint.image_size.height)
{
- el_position = el->get_element_position();
- if ((el_position == element_position_absolute || el_position == element_position_fixed)) continue;
- }
+ litehtml::size img_new_sz = bg_paint.image_size;
+ double img_ar_width = (double) bg_paint.image_size.width / (double) bg_paint.image_size.height;
+ double img_ar_height = (double) bg_paint.image_size.height / (double) bg_paint.image_size.width;
- // skip spaces to make rendering a bit faster
- if (skip_spaces)
- {
- if (el->is_white_space())
+
+ if(size.width.is_predefined())
{
- if (was_space)
+ switch(size.width.predef())
{
- el->skip(true);
- continue;
+ case background_size_contain:
+ if( (int) ((double) bg_paint.origin_box.width * img_ar_height) <= bg_paint.origin_box.height )
+ {
+ img_new_sz.width = bg_paint.origin_box.width;
+ img_new_sz.height = (int) ((double) bg_paint.origin_box.width * img_ar_height);
+ } else
+ {
+ img_new_sz.height = bg_paint.origin_box.height;
+ img_new_sz.width = (int) ((double) bg_paint.origin_box.height * img_ar_width);
+ }
+ break;
+ case background_size_cover:
+ if( (int) ((double) bg_paint.origin_box.width * img_ar_height) >= bg_paint.origin_box.height )
+ {
+ img_new_sz.width = bg_paint.origin_box.width;
+ img_new_sz.height = (int) ((double) bg_paint.origin_box.width * img_ar_height);
+ } else
+ {
+ img_new_sz.height = bg_paint.origin_box.height;
+ img_new_sz.width = (int) ((double) bg_paint.origin_box.height * img_ar_width);
+ }
+ break;
+ break;
+ case background_size_auto:
+ if(!size.height.is_predefined())
+ {
+ img_new_sz.height = size.height.calc_percent(bg_paint.origin_box.height);
+ img_new_sz.width = (int) ((double) img_new_sz.height * img_ar_width);
+ }
+ break;
}
- else
+ } else
+ {
+ img_new_sz.width = size.width.calc_percent(bg_paint.origin_box.width);
+ if(size.height.is_predefined())
+ {
+ img_new_sz.height = (int) ((double) img_new_sz.width * img_ar_height);
+ } else
{
- was_space = true;
+ img_new_sz.height = size.height.calc_percent(bg_paint.origin_box.height);
}
}
- else
- {
- was_space = false;
- }
- }
- // place element into rendering flow
- int rw = place_element(el, max_width);
- if (rw > ret_width)
- {
- ret_width = rw;
+ bg_paint.image_size = img_new_sz;
+ bg_paint.position_x = bg_paint.origin_box.x + (int) position_x.calc_percent(bg_paint.origin_box.width - bg_paint.image_size.width);
+ bg_paint.position_y = bg_paint.origin_box.y + (int) position_y.calc_percent(bg_paint.origin_box.height - bg_paint.image_size.height);
}
}
+ bg_paint.border_radius = m_css.get_borders().radius.calc_percents(border_box.width, border_box.height);
+ bg_paint.border_box = border_box;
+ bg_paint.is_root = is_root();
+}
- finish_last_box(true);
+void litehtml::html_tag::draw_list_marker( uint_ptr hdc, const position& pos )
+{
+ list_marker lm;
- if (block_width.is_default() && is_inline_box())
+ size img_size;
+ if (css().get_list_style_image() != "")
{
- m_pos.width = ret_width;
- }
- else
+ lm.image = css().get_list_style_image();
+ lm.baseurl = css().get_list_style_image_baseurl().c_str();
+ get_document()->container()->get_image_size(lm.image.c_str(), lm.baseurl, img_size);
+ } else
{
- m_pos.width = max_width;
+ lm.baseurl = nullptr;
}
- calc_auto_margins(parent_width);
- if (!m_boxes.empty())
- {
- if (collapse_top_margin())
- {
- int old_top = m_margins.top;
- m_margins.top = std::max(m_boxes.front()->top_margin(), m_margins.top);
- if (m_margins.top != old_top)
- {
- update_floats(m_margins.top - old_top, shared_from_this());
- }
- }
- if (collapse_bottom_margin())
- {
- m_margins.bottom = std::max(m_boxes.back()->bottom_margin(), m_margins.bottom);
- m_pos.height = m_boxes.back()->bottom() - m_boxes.back()->bottom_margin();
- }
- else
- {
- m_pos.height = m_boxes.back()->bottom();
- }
- }
+ int ln_height = css().get_line_height();
+ int sz_font = css().get_font_size();
+ lm.pos.x = pos.x;
+ lm.pos.width = sz_font - sz_font * 2 / 3;
+ lm.color = css().get_color();
+ lm.marker_type = css().get_list_style_type();
+ lm.font = css().get_font();
- // add the floats height to the block height
- if (is_floats_holder())
+ if (css().get_list_style_type() >= list_style_type_armenian)
{
- int floats_height = get_floats_height();
- if (floats_height > m_pos.height)
- {
- m_pos.height = floats_height;
- }
+ lm.pos.y = pos.y;
+ lm.pos.height = pos.height;
+ lm.index = atoi(get_attr("list_index", "0"));
}
-
- // calculate the final position
-
- m_pos.move_to(x, y);
- m_pos.x += content_margins_left();
- m_pos.y += content_margins_top();
-
- if (get_predefined_height(block_height))
+ else
{
- m_pos.height = block_height;
+ lm.pos.height = sz_font - sz_font * 2 / 3;
+ lm.pos.y = pos.y + ln_height / 2 - lm.pos.height / 2;
+ lm.index = -1;
}
- int min_height = 0;
- if (!m_css_min_height.is_predefined() && m_css_min_height.units() == css_units_percentage)
+ if(img_size.width && img_size.height)
{
- element::ptr el_parent = parent();
- if (el_parent)
+ if(lm.pos.y + img_size.height > pos.y + pos.height)
{
- if (el_parent->get_predefined_height(block_height))
- {
- min_height = m_css_min_height.calc_percent(block_height);
- }
+ lm.pos.y = pos.y + pos.height - img_size.height;
}
- }
- else
- {
- min_height = (int)m_css_min_height.val();
- }
- if (min_height != 0 && m_box_sizing == box_sizing_border_box)
- {
- min_height -= m_padding.top + m_borders.top + m_padding.bottom + m_borders.bottom;
- if (min_height < 0) min_height = 0;
- }
-
- if (m_display == display_list_item)
- {
- const tchar_t* list_image = get_style_property(_t("list-style-image"), true, 0);
- if (list_image)
+ if(img_size.width > lm.pos.width)
{
- tstring url;
- css::parse_css_url(list_image, url);
-
- size sz;
- const tchar_t* list_image_baseurl = get_style_property(_t("list-style-image-baseurl"), true, 0);
- get_document()->container()->get_image_size(url.c_str(), list_image_baseurl, sz);
- if (min_height < sz.height)
- {
- min_height = sz.height;
- }
+ lm.pos.x -= img_size.width - lm.pos.width;
}
+ lm.pos.width = img_size.width;
+ lm.pos.height = img_size.height;
}
- if (min_height > m_pos.height)
- {
- m_pos.height = min_height;
- }
-
- int min_width = m_css_min_width.calc_percent(parent_width);
-
- if (min_width != 0 && m_box_sizing == box_sizing_border_box)
- {
- min_width -= m_padding.left + m_borders.left + m_padding.right + m_borders.right;
- if (min_width < 0) min_width = 0;
- }
-
- if (min_width != 0)
+ if (m_css.get_list_style_position() == list_style_position_outside)
{
- if (min_width > m_pos.width)
+ if (m_css.get_list_style_type() >= list_style_type_armenian)
{
- m_pos.width = min_width;
+ if(lm.font)
+ {
+ auto tw_space = get_document()->container()->text_width(" ", lm.font);
+ lm.pos.x = pos.x - tw_space * 2;
+ lm.pos.width = tw_space;
+ } else
+ {
+ lm.pos.width = 0;
+ }
}
- if (min_width > ret_width)
+ else
{
- ret_width = min_width;
+ lm.pos.x -= sz_font;
}
}
- ret_width += content_margins_left() + content_margins_right();
-
- // re-render with new width
- if (ret_width < max_width && !second_pass && have_parent())
+ if (m_css.get_list_style_type() >= list_style_type_armenian)
{
- if (m_display == display_inline_block ||
- (m_css_width.is_predefined() &&
- (m_float != float_none ||
- m_display == display_table ||
- m_el_position == element_position_absolute ||
- m_el_position == element_position_fixed
- ))
- )
+ auto marker_text = get_list_marker_text(lm.index);
+ lm.pos.height = ln_height;
+ if (marker_text.empty())
{
- render(x, y, ret_width, true);
- m_pos.width = ret_width - (content_margins_left() + content_margins_right());
+ get_document()->container()->draw_list_marker(hdc, lm);
}
- }
-
- if (is_floats_holder() && !second_pass)
- {
- for (const auto& fb : m_floats_left)
+ else
{
- if (fb.el)
+ if(lm.font)
{
- fb.el->apply_relative_shift(fb.el->parent()->calc_width(m_pos.width));
+ marker_text += ".";
+ auto tw = get_document()->container()->text_width(marker_text.c_str(), lm.font);
+ auto text_pos = lm.pos;
+ text_pos.move_to(text_pos.right() - tw, text_pos.y);
+ text_pos.width = tw;
+ get_document()->container()->draw_text(hdc, marker_text.c_str(), lm.font, lm.color, text_pos);
}
}
}
-
-
- return ret_width;
-}
-
-int litehtml::html_tag::render_table(int x, int y, int max_width, bool second_pass /*= false*/)
-{
- if (!m_grid) return 0;
-
- int parent_width = max_width;
-
- calc_outlines(parent_width);
-
- m_pos.clear();
- m_pos.move_to(x, y);
-
- m_pos.x += content_margins_left();
- m_pos.y += content_margins_top();
-
- def_value<int> block_width(0);
-
- if (!m_css_width.is_predefined())
- {
- max_width = block_width = calc_width(parent_width) - m_padding.width() - m_borders.width();
- }
- else
- {
- if (max_width)
- {
- max_width -= content_margins_left() + content_margins_right();
- }
- }
-
- // Calculate table spacing
- int table_width_spacing = 0;
- if (m_border_collapse == border_collapse_separate)
- {
- table_width_spacing = m_border_spacing_x * (m_grid->cols_count() + 1);
- }
else
{
- table_width_spacing = 0;
-
- if (m_grid->cols_count())
- {
- table_width_spacing -= std::min(border_left(), m_grid->column(0).border_left);
- table_width_spacing -= std::min(border_right(), m_grid->column(m_grid->cols_count() - 1).border_right);
- }
-
- for (int col = 1; col < m_grid->cols_count(); col++)
- {
- table_width_spacing -= std::min(m_grid->column(col).border_left, m_grid->column(col - 1).border_right);
- }
+ get_document()->container()->draw_list_marker(hdc, lm);
}
+}
-
- // Calculate the minimum content width (MCW) of each cell: the formatted content may span any number of lines but may not overflow the cell box.
- // If the specified 'width' (W) of the cell is greater than MCW, W is the minimum cell width. A value of 'auto' means that MCW is the minimum
- // cell width.
- //
- // Also, calculate the "maximum" cell width of each cell: formatting the content without breaking lines other than where explicit line breaks occur.
-
- if (m_grid->cols_count() == 1 && !block_width.is_default())
+litehtml::string litehtml::html_tag::get_list_marker_text(int index)
+{
+ switch (m_css.get_list_style_type())
{
- for (int row = 0; row < m_grid->rows_count(); row++)
+ case litehtml::list_style_type_decimal:
+ return std::to_string(index);
+ case litehtml::list_style_type_decimal_leading_zero:
{
- table_cell* cell = m_grid->cell(0, row);
- if (cell && cell->el)
+ auto txt = std::to_string(index);
+ if (txt.length() == 1)
{
- cell->min_width = cell->max_width = cell->el->render(0, 0, max_width - table_width_spacing);
- cell->el->m_pos.width = cell->min_width - cell->el->content_margins_left() - cell->el->content_margins_right();
+ txt = "0" + txt;
}
+ return txt;
}
+ case litehtml::list_style_type_lower_latin:
+ case litehtml::list_style_type_lower_alpha:
+ return num_cvt::to_latin_lower(index);
+ case litehtml::list_style_type_lower_greek:
+ return num_cvt::to_greek_lower(index);
+ case litehtml::list_style_type_upper_alpha:
+ case litehtml::list_style_type_upper_latin:
+ return num_cvt::to_latin_upper(index);
+ case litehtml::list_style_type_lower_roman:
+ return num_cvt::to_roman_lower(index);
+ case litehtml::list_style_type_upper_roman:
+ return num_cvt::to_roman_upper(index);
+ default:
+ return "";
+// case litehtml::list_style_type_armenian:
+// case litehtml::list_style_type_georgian:
+// case litehtml::list_style_type_hebrew:
+// case litehtml::list_style_type_hiragana:
+// case litehtml::list_style_type_hiragana_iroha:
+// case litehtml::list_style_type_katakana:
+// case litehtml::list_style_type_katakana_iroha:
+// case litehtml::list_style_type_none:
+// case litehtml::list_style_type_circle:
+// case litehtml::list_style_type_disc:
+// case litehtml::list_style_type_square:
+// case litehtml::list_style_type_cjk_ideographic:
+// break;
}
- else
+}
+
+bool litehtml::html_tag::is_nth_child(const element::ptr& el, int num, int off, bool of_type) const
+{
+ int idx = 1;
+ for(const auto& child : m_children)
{
- for (int row = 0; row < m_grid->rows_count(); row++)
+ if(child->css().get_display() != display_inline_text)
{
- for (int col = 0; col < m_grid->cols_count(); col++)
+ if( (!of_type) || (of_type && el->tag() == child->tag()) )
{
- table_cell* cell = m_grid->cell(col, row);
- if (cell && cell->el)
+ if(el == child)
{
- if (!m_grid->column(col).css_width.is_predefined() && m_grid->column(col).css_width.units() != css_units_percentage)
+ if(num != 0)
{
- int css_w = m_grid->column(col).css_width.calc_percent(block_width);
- int el_w = cell->el->render(0, 0, css_w);
- cell->min_width = cell->max_width = std::max(css_w, el_w);
- cell->el->m_pos.width = cell->min_width - cell->el->content_margins_left() - cell->el->content_margins_right();
- }
- else
+ if((idx - off) >= 0 && (idx - off) % num == 0)
+ {
+ return true;
+ }
+
+ } else if(idx == off)
{
- // calculate minimum content width
- cell->min_width = cell->el->render(0, 0, 1);
- // calculate maximum content width
- cell->max_width = cell->el->render(0, 0, max_width - table_width_spacing);
+ return true;
}
+ return false;
}
+ idx++;
}
+ if(el == child) break;
}
}
+ return false;
+}
- // For each column, determine a maximum and minimum column width from the cells that span only that column.
- // The minimum is that required by the cell with the largest minimum cell width (or the column 'width', whichever is larger).
- // The maximum is that required by the cell with the largest maximum cell width (or the column 'width', whichever is larger).
-
- for (int col = 0; col < m_grid->cols_count(); col++)
- {
- m_grid->column(col).max_width = 0;
- m_grid->column(col).min_width = 0;
- for (int row = 0; row < m_grid->rows_count(); row++)
- {
- if (m_grid->cell(col, row)->colspan <= 1)
- {
- m_grid->column(col).max_width = std::max(m_grid->column(col).max_width, m_grid->cell(col, row)->max_width);
- m_grid->column(col).min_width = std::max(m_grid->column(col).min_width, m_grid->cell(col, row)->min_width);
- }
- }
- }
-
- // For each cell that spans more than one column, increase the minimum widths of the columns it spans so that together,
- // they are at least as wide as the cell. Do the same for the maximum widths.
- // If possible, widen all spanned columns by approximately the same amount.
-
- for (int col = 0; col < m_grid->cols_count(); col++)
+bool litehtml::html_tag::is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const
+{
+ int idx = 1;
+ for(auto child = m_children.rbegin(); child != m_children.rend(); child++)
{
- for (int row = 0; row < m_grid->rows_count(); row++)
+ if((*child)->css().get_display() != display_inline_text)
{
- if (m_grid->cell(col, row)->colspan > 1)
+ if( !of_type || (of_type && el->tag() == (*child)->tag()) )
{
- int max_total_width = m_grid->column(col).max_width;
- int min_total_width = m_grid->column(col).min_width;
- for (int col2 = col + 1; col2 < col + m_grid->cell(col, row)->colspan; col2++)
- {
- max_total_width += m_grid->column(col2).max_width;
- min_total_width += m_grid->column(col2).min_width;
- }
- if (min_total_width < m_grid->cell(col, row)->min_width)
- {
- m_grid->distribute_min_width(m_grid->cell(col, row)->min_width - min_total_width, col, col + m_grid->cell(col, row)->colspan - 1);
- }
- if (max_total_width < m_grid->cell(col, row)->max_width)
+ if(el == (*child))
{
- m_grid->distribute_max_width(m_grid->cell(col, row)->max_width - max_total_width, col, col + m_grid->cell(col, row)->colspan - 1);
+ if(num != 0)
+ {
+ if((idx - off) >= 0 && (idx - off) % num == 0)
+ {
+ return true;
+ }
+
+ } else if(idx == off)
+ {
+ return true;
+ }
+ return false;
}
+ idx++;
}
+ if(el == (*child)) break;
}
}
+ return false;
+}
- // If the 'table' or 'inline-table' element's 'width' property has a computed value (W) other than 'auto', the used width is the
- // greater of W, CAPMIN, and the minimum width required by all the columns plus cell spacing or borders (MIN).
- // If the used width is greater than MIN, the extra width should be distributed over the columns.
- //
- // If the 'table' or 'inline-table' element has 'width: auto', the used width is the greater of the table's containing block width,
- // CAPMIN, and MIN. However, if either CAPMIN or the maximum width required by the columns plus cell spacing or borders (MAX) is
- // less than that of the containing block, use max(MAX, CAPMIN).
-
-
- int table_width = 0;
- int min_table_width = 0;
- int max_table_width = 0;
-
- if (!block_width.is_default())
- {
- table_width = m_grid->calc_table_width(block_width - table_width_spacing, false, min_table_width, max_table_width);
- }
- else
- {
- table_width = m_grid->calc_table_width(max_width - table_width_spacing, true, min_table_width, max_table_width);
- }
-
- min_table_width += table_width_spacing;
- max_table_width += table_width_spacing;
- table_width += table_width_spacing;
- m_grid->calc_horizontal_positions(m_borders, m_border_collapse, m_border_spacing_x);
-
- bool row_span_found = false;
-
- // render cells with computed width
- for (int row = 0; row < m_grid->rows_count(); row++)
+litehtml::element::ptr litehtml::html_tag::find_adjacent_sibling( const element::ptr& el, const css_selector& selector, bool apply_pseudo /*= true*/, bool* is_pseudo /*= 0*/ )
+{
+ element::ptr ret;
+ for(auto& e : m_children)
{
- m_grid->row(row).height = 0;
- for (int col = 0; col < m_grid->cols_count(); col++)
+ if(e->css().get_display() != display_inline_text)
{
- table_cell* cell = m_grid->cell(col, row);
- if (cell->el)
+ if(e == el)
{
- int span_col = col + cell->colspan - 1;
- if (span_col >= m_grid->cols_count())
- {
- span_col = m_grid->cols_count() - 1;
- }
- int cell_width = m_grid->column(span_col).right - m_grid->column(col).left;
-
- if (cell->el->m_pos.width != cell_width - cell->el->content_margins_left() - cell->el->content_margins_right())
- {
- cell->el->render(m_grid->column(col).left, 0, cell_width);
- cell->el->m_pos.width = cell_width - cell->el->content_margins_left() - cell->el->content_margins_right();
- }
- else
- {
- cell->el->m_pos.x = m_grid->column(col).left + cell->el->content_margins_left();
- }
-
- if (cell->rowspan <= 1)
- {
- m_grid->row(row).height = std::max(m_grid->row(row).height, cell->el->height());
- }
- else
+ if(ret)
{
- row_span_found = true;
+ int res = ret->select(selector, apply_pseudo);
+ if(res != select_no_match)
+ {
+ if(is_pseudo)
+ {
+ if(res & select_match_pseudo_class)
+ {
+ *is_pseudo = true;
+ } else
+ {
+ *is_pseudo = false;
+ }
+ }
+ return ret;
+ }
}
-
+ return nullptr;
+ } else
+ {
+ ret = e;
}
}
}
+ return nullptr;
+}
- if (row_span_found)
+litehtml::element::ptr litehtml::html_tag::find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo /*= true*/, bool* is_pseudo /*= 0*/)
+{
+ element::ptr ret = nullptr;
+ for(auto& e : m_children)
{
- for (int col = 0; col < m_grid->cols_count(); col++)
+ if(e->css().get_display() != display_inline_text)
{
- for (int row = 0; row < m_grid->rows_count(); row++)
+ if(e == el)
+ {
+ return ret;
+ } else if(!ret)
{
- table_cell* cell = m_grid->cell(col, row);
- if (cell->el)
+ int res = e->select(selector, apply_pseudo);
+ if(res != select_no_match)
{
- int span_row = row + cell->rowspan - 1;
- if (span_row >= m_grid->rows_count())
- {
- span_row = m_grid->rows_count() - 1;
- }
- if (span_row != row)
+ if(is_pseudo)
{
- int h = 0;
- for (int i = row; i <= span_row; i++)
+ if(res & select_match_pseudo_class)
{
- h += m_grid->row(i).height;
- }
- if (h < cell->el->height())
+ *is_pseudo = true;
+ } else
{
- m_grid->row(span_row).height += cell->el->height() - h;
+ *is_pseudo = false;
}
}
+ ret = e;
}
}
}
}
+ return nullptr;
+}
- // Calculate vertical table spacing
- int table_height_spacing = 0;
- if (m_border_collapse == border_collapse_separate)
- {
- table_height_spacing = m_border_spacing_y * (m_grid->rows_count() + 1);
- }
- else
- {
- table_height_spacing = 0;
-
- if (m_grid->rows_count())
- {
- table_height_spacing -= std::min(border_top(), m_grid->row(0).border_top);
- table_height_spacing -= std::min(border_bottom(), m_grid->row(m_grid->rows_count() - 1).border_bottom);
- }
-
- for (int row = 1; row < m_grid->rows_count(); row++)
- {
- table_height_spacing -= std::min(m_grid->row(row).border_top, m_grid->row(row - 1).border_bottom);
- }
- }
-
-
- // calculate block height
- int block_height = 0;
- if (get_predefined_height(block_height))
- {
- block_height -= m_padding.height() + m_borders.height();
- }
-
- // calculate minimum height from m_css_min_height
- int min_height = 0;
- if (!m_css_min_height.is_predefined() && m_css_min_height.units() == css_units_percentage)
+bool litehtml::html_tag::is_only_child(const element::ptr& el, bool of_type) const
+{
+ int child_count = 0;
+ for(const auto& child : m_children)
{
- element::ptr el_parent = parent();
- if (el_parent)
+ if(child->css().get_display() != display_inline_text)
{
- int parent_height = 0;
- if (el_parent->get_predefined_height(parent_height))
+ if( !of_type || (of_type && el->tag() == child->tag()) )
{
- min_height = m_css_min_height.calc_percent(parent_height);
+ child_count++;
}
+ if(child_count > 1) break;
}
}
- else
+ if(child_count > 1)
{
- min_height = (int)m_css_min_height.val();
+ return false;
}
+ return true;
+}
- int minimum_table_height = std::max(block_height, min_height);
-
- m_grid->calc_rows_height(minimum_table_height - table_height_spacing, m_border_spacing_y);
- m_grid->calc_vertical_positions(m_borders, m_border_collapse, m_border_spacing_y);
-
- int table_height = 0;
-
- // place cells vertically
- for (int col = 0; col < m_grid->cols_count(); col++)
+litehtml::element::ptr litehtml::html_tag::get_element_before(const style& style, bool create)
+{
+ if(!m_children.empty())
{
- for (int row = 0; row < m_grid->rows_count(); row++)
+ if( m_children.front()->tag() == __tag_before_ )
{
- table_cell* cell = m_grid->cell(col, row);
- if (cell->el)
- {
- int span_row = row + cell->rowspan - 1;
- if (span_row >= m_grid->rows_count())
- {
- span_row = m_grid->rows_count() - 1;
- }
- cell->el->m_pos.y = m_grid->row(row).top + cell->el->content_margins_top();
- cell->el->m_pos.height = m_grid->row(span_row).bottom - m_grid->row(row).top - cell->el->content_margins_top() - cell->el->content_margins_bottom();
- table_height = std::max(table_height, m_grid->row(span_row).bottom);
- cell->el->apply_vertical_align();
- }
+ return m_children.front();
}
}
+ if(create)
+ {
+ return add_pseudo_before(style);
+ }
+ return nullptr;
+}
- if (m_border_collapse == border_collapse_collapse)
+litehtml::element::ptr litehtml::html_tag::get_element_after(const style& style, bool create)
+{
+ if(!m_children.empty())
{
- if (m_grid->rows_count())
+ if( m_children.back()->tag() == __tag_after_ )
{
- table_height -= std::min(border_bottom(), m_grid->row(m_grid->rows_count() - 1).border_bottom);
+ return m_children.back();
}
}
- else
+ if(create)
{
- table_height += m_border_spacing_y;
+ return add_pseudo_after(style);
}
-
- m_pos.width = table_width;
-
- calc_auto_margins(parent_width);
-
- m_pos.move_to(x, y);
- m_pos.x += content_margins_left();
- m_pos.y += content_margins_top();
- m_pos.width = table_width;
- m_pos.height = table_height;
-
- return max_table_width;
+ return nullptr;
}
-void litehtml::html_tag::draw_children_box(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex)
+void litehtml::html_tag::add_style(const style& style)
{
- position pos = m_pos;
- pos.x += x;
- pos.y += y;
-
- document::ptr doc = get_document();
+ m_style.combine(style);
+}
- if (m_overflow > overflow_visible)
+void litehtml::html_tag::refresh_styles()
+{
+ for (auto& el : m_children)
{
- position border_box = pos;
- border_box += m_padding;
- border_box += m_borders;
-
- border_radiuses bdr_radius = m_css_borders.radius.calc_percents(border_box.width, border_box.height);
-
- bdr_radius -= m_borders;
- bdr_radius -= m_padding;
-
- doc->container()->set_clip(pos, bdr_radius, true, true);
+ if(el->css().get_display() != display_inline_text)
+ {
+ el->refresh_styles();
+ }
}
- position browser_wnd;
- doc->container()->get_client_rect(browser_wnd);
+ m_style.clear();
- element::ptr el;
- for (auto& item : m_children)
+ for (auto& usel : m_used_styles)
{
- el = item;
- if (el->is_visible())
+ usel->m_used = false;
+
+ if(usel->m_selector->is_media_valid())
{
- switch (flag)
+ int apply = select(*usel->m_selector, false);
+
+ if(apply != select_no_match)
{
- case draw_positioned:
- if (el->is_positioned() && el->get_zindex() == zindex)
+ if(apply & select_match_pseudo_class)
{
- if (el->get_element_position() == element_position_fixed)
- {
- el->draw(hdc, browser_wnd.x, browser_wnd.y, clip);
- el->draw_stacking_context(hdc, browser_wnd.x, browser_wnd.y, clip, true);
- }
- else
+ if(select(*usel->m_selector, true))
{
- el->draw(hdc, pos.x, pos.y, clip);
- el->draw_stacking_context(hdc, pos.x, pos.y, clip, true);
+ if(apply & select_match_with_after)
+ {
+ element::ptr el = get_element_after(*usel->m_selector->m_style, false);
+ if(el)
+ {
+ el->add_style(*usel->m_selector->m_style);
+ }
+ } else if(apply & select_match_with_before)
+ {
+ element::ptr el = get_element_before(*usel->m_selector->m_style, false);
+ if(el)
+ {
+ el->add_style(*usel->m_selector->m_style);
+ }
+ }
+ else
+ {
+ add_style(*usel->m_selector->m_style);
+ usel->m_used = true;
+ }
}
- el = 0;
- }
- break;
- case draw_block:
- if (!el->is_inline_box() && el->get_float() == float_none && !el->is_positioned())
- {
- el->draw(hdc, pos.x, pos.y, clip);
- }
- break;
- case draw_floats:
- if (el->get_float() != float_none && !el->is_positioned())
- {
- el->draw(hdc, pos.x, pos.y, clip);
- el->draw_stacking_context(hdc, pos.x, pos.y, clip, false);
- el = 0;
- }
- break;
- case draw_inlines:
- if (el->is_inline_box() && el->get_float() == float_none && !el->is_positioned())
+ } else if(apply & select_match_with_after)
{
- el->draw(hdc, pos.x, pos.y, clip);
- if (el->get_display() == display_inline_block)
+ element::ptr el = get_element_after(*usel->m_selector->m_style, false);
+ if(el)
{
- el->draw_stacking_context(hdc, pos.x, pos.y, clip, false);
- el = 0;
+ el->add_style(*usel->m_selector->m_style);
}
- }
- break;
- default:
- break;
- }
-
- if (el)
- {
- if (flag == draw_positioned)
+ } else if(apply & select_match_with_before)
{
- if (!el->is_positioned())
+ element::ptr el = get_element_before(*usel->m_selector->m_style, false);
+ if(el)
{
- el->draw_children(hdc, pos.x, pos.y, clip, flag, zindex);
+ el->add_style(*usel->m_selector->m_style);
}
- }
- else
+ } else
{
- if (el->get_float() == float_none &&
- el->get_display() != display_inline_block &&
- !el->is_positioned())
- {
- el->draw_children(hdc, pos.x, pos.y, clip, flag, zindex);
- }
+ add_style(*usel->m_selector->m_style);
+ usel->m_used = true;
}
}
}
}
-
- if (m_overflow > overflow_visible)
- {
- doc->container()->del_clip();
- }
}
-void litehtml::html_tag::draw_children_table(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex)
+const litehtml::background* litehtml::html_tag::get_background(bool own_only)
{
- if (!m_grid) return;
-
- position pos = m_pos;
- pos.x += x;
- pos.y += y;
- for (int row = 0; row < m_grid->rows_count(); row++)
+ if(own_only)
{
- if (flag == draw_block)
+ // return own background with check for empty one
+ if(m_css.get_bg().is_empty())
{
- m_grid->row(row).el_row->draw_background(hdc, pos.x, pos.y, clip);
+ return nullptr;
}
- for (int col = 0; col < m_grid->cols_count(); col++)
+ return &m_css.get_bg();
+ }
+
+ if(m_css.get_bg().is_empty())
+ {
+ // if this is root element (<html>) try to get background from body
+ if (is_root())
{
- table_cell* cell = m_grid->cell(col, row);
- if (cell->el)
+ for (const auto& el : m_children)
{
- if (flag == draw_block)
+ if( el->is_body() )
{
- cell->el->draw(hdc, pos.x, pos.y, clip);
+ // return own body background
+ return el->get_background(true);
}
- cell->el->draw_children(hdc, pos.x, pos.y, clip, flag, zindex);
}
}
+ return nullptr;
+ }
+
+ if(is_body())
+ {
+ element::ptr el_parent = parent();
+ if (el_parent)
+ {
+ if (!el_parent->get_background(true))
+ {
+ // parent of body will draw background for body
+ return nullptr;
+ }
+ }
+ }
+
+ return &m_css.get_bg();
+}
+
+litehtml::string litehtml::html_tag::dump_get_name()
+{
+ if(m_tag == empty_id)
+ {
+ return "anon [html_tag]";
}
+ return _s(m_tag) + " [html_tag]";
}
diff --git a/src/plugins/litehtml_viewer/litehtml/html_tag.h b/src/plugins/litehtml_viewer/litehtml/html_tag.h
index 3379a719b..71b9cb345 100644
--- a/src/plugins/litehtml_viewer/litehtml/html_tag.h
+++ b/src/plugins/litehtml_viewer/litehtml/html_tag.h
@@ -8,232 +8,120 @@
#include "borders.h"
#include "css_selector.h"
#include "stylesheet.h"
-#include "box.h"
+#include "line_box.h"
#include "table.h"
namespace litehtml
{
- struct line_context
- {
- int calculatedTop;
- int top;
- int left;
- int right;
-
- int width()
- {
- return right - left;
- }
- void fix_top()
- {
- calculatedTop = top;
- }
- };
class html_tag : public element
{
friend class elements_iterator;
friend class el_table;
friend class table_grid;
- friend class block_box;
friend class line_box;
public:
- typedef std::shared_ptr<litehtml::html_tag> ptr;
+ typedef std::shared_ptr<html_tag> ptr;
protected:
- box::vector m_boxes;
- string_vector m_class_values;
- tstring m_tag;
+ string_id m_tag;
+ string_id m_id;
+ string_vector m_str_classes;
+ std::vector<string_id> m_classes;
litehtml::style m_style;
string_map m_attrs;
- vertical_align m_vertical_align;
- text_align m_text_align;
- style_display m_display;
- list_style_type m_list_style_type;
- list_style_position m_list_style_position;
- white_space m_white_space;
- element_float m_float;
- element_clear m_clear;
- floated_box::vector m_floats_left;
- floated_box::vector m_floats_right;
- elements_vector m_positioned;
- background m_bg;
- element_position m_el_position;
- int m_line_height;
- bool m_lh_predefined;
- string_vector m_pseudo_classes;
- used_selector::vector m_used_styles;
-
- uint_ptr m_font;
- int m_font_size;
- font_metrics m_font_metrics;
-
- css_margins m_css_margins;
- css_margins m_css_padding;
- css_borders m_css_borders;
- css_length m_css_width;
- css_length m_css_height;
- css_length m_css_min_width;
- css_length m_css_min_height;
- css_length m_css_max_width;
- css_length m_css_max_height;
- css_offsets m_css_offsets;
- css_length m_css_text_indent;
-
- overflow m_overflow;
- visibility m_visibility;
- int m_z_index;
- box_sizing m_box_sizing;
-
- int_int_cache m_cahe_line_left;
- int_int_cache m_cahe_line_right;
-
- // data for table rendering
- std::unique_ptr<table_grid> m_grid;
- css_length m_css_border_spacing_x;
- css_length m_css_border_spacing_y;
- int m_border_spacing_x;
- int m_border_spacing_y;
- border_collapse m_border_collapse;
-
- virtual void select_all(const css_selector& selector, elements_vector& res) override;
+ std::vector<string_id> m_pseudo_classes;
+
+ void select_all(const css_selector& selector, elements_vector& res) override;
public:
- html_tag(const std::shared_ptr<litehtml::document>& doc);
- virtual ~html_tag();
-
- /* render functions */
-
- virtual int render(int x, int y, int max_width, bool second_pass = false) override;
-
- virtual int render_inline(const element::ptr &container, int max_width) override;
- virtual int place_element(const element::ptr &el, int max_width) override;
- virtual bool fetch_positioned() override;
- virtual void render_positioned(render_type rt = render_all) override;
-
- int new_box(const element::ptr &el, int max_width, line_context& line_ctx);
-
- int get_cleared_top(const element::ptr &el, int line_top) const;
- int finish_last_box(bool end_of_render = false);
-
- virtual bool appendChild(const element::ptr &el) override;
- virtual bool removeChild(const element::ptr &el) override;
- virtual void clearRecursive() override;
- virtual const tchar_t* get_tagName() const override;
- virtual void set_tagName(const tchar_t* tag) override;
- virtual void set_data(const tchar_t* data) override;
- virtual element_float get_float() const override;
- virtual vertical_align get_vertical_align() const override;
- virtual css_length get_css_left() const override;
- virtual css_length get_css_right() const override;
- virtual css_length get_css_top() const override;
- virtual css_length get_css_bottom() const override;
- virtual css_length get_css_width() const override;
- virtual css_offsets get_css_offsets() const override;
- virtual void set_css_width(css_length& w) override;
- virtual css_length get_css_height() const override;
- virtual element_clear get_clear() const override;
- virtual size_t get_children_count() const override;
- virtual element::ptr get_child(int idx) const override;
- virtual element_position get_element_position(css_offsets* offsets = 0) const override;
- virtual overflow get_overflow() const override;
-
- virtual void set_attr(const tchar_t* name, const tchar_t* val) override;
- virtual const tchar_t* get_attr(const tchar_t* name, const tchar_t* def = 0) const override;
- virtual void apply_stylesheet(const litehtml::css& stylesheet) override;
- virtual void refresh_styles() override;
-
- virtual bool is_white_space() const override;
- virtual bool is_body() const override;
- virtual bool is_break() const override;
- virtual int get_base_line() override;
- virtual bool on_mouse_over() override;
- virtual bool on_mouse_leave() override;
- virtual bool on_lbutton_down() override;
- virtual bool on_lbutton_up() override;
- virtual void on_click() override;
- virtual bool find_styles_changes(position::vector& redraw_boxes, int x, int y) override;
- virtual const tchar_t* get_cursor() override;
- virtual void init_font() override;
- virtual bool set_pseudo_class(const tchar_t* pclass, bool add) override;
- virtual bool set_class(const tchar_t* pclass, bool add) override;
- virtual bool is_replaced() const override;
- virtual int line_height() const override;
- virtual white_space get_white_space() const override;
- virtual style_display get_display() const override;
- virtual visibility get_visibility() const override;
- virtual void parse_styles(bool is_reparse = false) override;
- virtual void draw(uint_ptr hdc, int x, int y, const position* clip) override;
- virtual void draw_background(uint_ptr hdc, int x, int y, const position* clip) override;
-
- virtual const tchar_t* get_style_property(const tchar_t* name, bool inherited, const tchar_t* def = 0) override;
- virtual uint_ptr get_font(font_metrics* fm = 0) override;
- virtual int get_font_size() const override;
-
- elements_vector& children();
- virtual void calc_outlines(int parent_width) override;
- virtual void calc_auto_margins(int parent_width) override;
-
- virtual int select(const css_selector& selector, bool apply_pseudo = true) override;
- virtual int select(const css_element_selector& selector, bool apply_pseudo = true) override;
-
- virtual elements_vector select_all(const tstring& selector) override;
- virtual elements_vector select_all(const css_selector& selector) override;
-
- virtual element::ptr select_one(const tstring& selector) override;
- virtual element::ptr select_one(const css_selector& selector) override;
-
- virtual element::ptr find_ancestor(const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = 0) override;
- virtual element::ptr find_adjacent_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = 0) override;
- virtual element::ptr find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = 0) override;
- virtual void get_text(tstring& text) override;
- virtual void parse_attributes() override;
-
- virtual bool is_first_child_inline(const element::ptr& el) const override;
- virtual bool is_last_child_inline(const element::ptr& el) override;
- virtual bool have_inline_child() const override;
- virtual void get_content_size(size& sz, int max_width) override;
- virtual void init() override;
- virtual void get_inline_boxes(position::vector& boxes) override;
- virtual bool is_floats_holder() const override;
- virtual int get_floats_height(element_float el_float = float_none) const override;
- virtual int get_left_floats_height() const override;
- virtual int get_right_floats_height() const override;
- virtual int get_line_left(int y) override;
- virtual int get_line_right(int y, int def_right) override;
- virtual void get_line_left_right(int y, int def_right, int& ln_left, int& ln_right) override;
- virtual void add_float(const element::ptr &el, int x, int y) override;
- virtual void update_floats(int dy, const element::ptr &parent) override;
- virtual void add_positioned(const element::ptr &el) override;
- virtual int find_next_line_top(int top, int width, int def_right) override;
- virtual void apply_vertical_align() override;
- virtual void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override;
- virtual int get_zindex() const override;
- virtual void draw_stacking_context(uint_ptr hdc, int x, int y, const position* clip, bool with_positioned) override;
- virtual void calc_document_size(litehtml::size& sz, int x = 0, int y = 0) override;
- virtual void get_redraw_box(litehtml::position& pos, int x = 0, int y = 0) override;
- virtual void add_style(const litehtml::style& st) override;
- virtual element::ptr get_element_by_point(int x, int y, int client_x, int client_y) override;
- virtual element::ptr get_child_by_point(int x, int y, int client_x, int client_y, draw_flag flag, int zindex) override;
-
- virtual bool is_nth_child(const element::ptr& el, int num, int off, bool of_type) const override;
- virtual bool is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const override;
- virtual bool is_only_child(const element::ptr& el, bool of_type) const override;
- virtual const background* get_background(bool own_only = false) override;
+ explicit html_tag(const std::shared_ptr<document>& doc);
+ // constructor for anonymous wrapper boxes
+ explicit html_tag(const element::ptr& parent, const string& style = "display: block");
+
+ bool appendChild(const element::ptr &el) override;
+ bool removeChild(const element::ptr &el) override;
+ void clearRecursive() override;
+ string_id tag() const override;
+ string_id id() const override;
+ 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;
+ void apply_stylesheet(const litehtml::css& stylesheet) override;
+ void refresh_styles() override;
+
+ bool is_white_space() const override;
+ bool is_body() const override;
+ bool is_break() const override;
+
+ bool on_mouse_over() override;
+ bool on_mouse_leave() override;
+ bool on_lbutton_down() override;
+ bool on_lbutton_up() override;
+ void on_click() override;
+ bool set_pseudo_class(string_id cls, bool add) override;
+ bool set_class(const char* pclass, bool add) override;
+ bool is_replaced() const override;
+ void compute_styles(bool recursive = true) override;
+ void draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri) override;
+ void draw_background(uint_ptr hdc, int x, int y, const position *clip,
+ const std::shared_ptr<render_item> &ri) override;
+
+ template<class Type, property_type property_value_type, Type property_value::* property_value_member>
+ const Type& get_property_impl (string_id name, bool inherited, const Type& default_value, uint_ptr css_properties_member_offset) const;
+ int get_enum_property (string_id name, bool inherited, int default_value, uint_ptr css_properties_member_offset) const override;
+ css_length get_length_property(string_id name, bool inherited, css_length default_value, uint_ptr css_properties_member_offset) const override;
+ web_color get_color_property (string_id name, bool inherited, web_color default_value, uint_ptr css_properties_member_offset) const override;
+ string get_string_property(string_id name, bool inherited, const string& default_value, uint_ptr css_properties_member_offset) const override;
+ float get_number_property(string_id name, bool inherited, float default_value, uint_ptr css_properties_member_offset) const override;
+ string_vector get_string_vector_property(string_id name, bool inherited, const string_vector& default_value, uint_ptr css_properties_member_offset) const override;
+ int_vector get_int_vector_property (string_id name, bool inherited, const int_vector& default_value, uint_ptr css_properties_member_offset) const override;
+ length_vector get_length_vector_property(string_id name, bool inherited, const length_vector& default_value, uint_ptr css_properties_member_offset) const override;
+ 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();
+
+ int select(const string& selector) override;
+ int select(const css_selector& selector, bool apply_pseudo = true) override;
+ int select(const css_element_selector& selector, bool apply_pseudo = true) override;
+ 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;
+
+ element::ptr select_one(const string& selector) override;
+ element::ptr select_one(const css_selector& selector) override;
+
+ element::ptr find_ancestor(const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr) override;
+ element::ptr find_adjacent_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr) override;
+ element::ptr find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr) override;
+ void get_text(string& text) override;
+ 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;
+ bool is_nth_last_child(const element::ptr& el, int num, int off, bool of_type) const override;
+ bool is_only_child(const element::ptr& el, bool of_type) const override;
+ const background* get_background(bool own_only = false) override;
+
+ string dump_get_name() override;
protected:
- void draw_children_box(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex);
- void draw_children_table(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex);
- int render_box(int x, int y, int max_width, bool second_pass = false);
- int render_table(int x, int y, int max_width, bool second_pass = false);
- int fix_line_width(int max_width, element_float flt);
- void parse_background();
- void init_background_paint( position pos, background_paint &bg_paint, const background* bg );
- void draw_list_marker( uint_ptr hdc, const position &pos );
- tstring get_list_marker_text(int index);
- void parse_nth_child_params( tstring param, int &num, int &off );
- void remove_before_after();
- litehtml::element::ptr get_element_before();
- litehtml::element::ptr get_element_after();
+ void init_background_paint(position pos, std::vector<background_paint>& bg_paint, const background* bg, const std::shared_ptr<render_item>& ri);
+ void init_one_background_paint(int i, position pos, background_paint& bg_paint, const background* bg, const std::shared_ptr<render_item>& ri);
+ void draw_list_marker( uint_ptr hdc, const position &pos );
+ string get_list_marker_text(int index);
+ element::ptr get_element_before(const style& style, bool create);
+ element::ptr get_element_after(const style& style, bool create);
};
/************************************************************************/
diff --git a/src/plugins/litehtml_viewer/litehtml/iterators.cpp b/src/plugins/litehtml_viewer/litehtml/iterators.cpp
index 9d6a623d8..5b3238ad2 100644
--- a/src/plugins/litehtml_viewer/litehtml/iterators.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/iterators.cpp
@@ -1,92 +1,99 @@
#include "html.h"
#include "iterators.h"
#include "html_tag.h"
+#include "render_item.h"
+#include <iterator>
-litehtml::element::ptr litehtml::elements_iterator::next(bool ret_parent)
+litehtml::elements_iterator::elements_iterator(bool return_parents, iterator_selector* go_inside, iterator_selector* select) :
+ m_return_parent(return_parents),
+ m_go_inside(go_inside),
+ m_select(select)
{
- next_idx();
-
- while(m_idx < (int) m_el->get_children_count())
- {
- element::ptr el = m_el->get_child(m_idx);
- if( el->get_children_count() && m_go_inside && m_go_inside->select(el) )
- {
- stack_item si;
- si.idx = m_idx;
- si.el = m_el;
- m_stack.push_back(si);
- m_el = el;
- m_idx = -1;
- if(ret_parent)
- {
- return el;
- }
- next_idx();
- } else
- {
- if( !m_select || (m_select && m_select->select(m_el->get_child(m_idx))) )
- {
- return m_el->get_child(m_idx);
- } else
- {
- next_idx();
- }
- }
- }
+}
- return 0;
+bool litehtml::elements_iterator::go_inside(const std::shared_ptr<render_item>& el)
+{
+ return /*!el->children().empty() &&*/ m_go_inside && m_go_inside->select(el);
}
-void litehtml::elements_iterator::next_idx()
+void litehtml::elements_iterator::process(const std::shared_ptr<render_item>& container, const std::function<void (std::shared_ptr<render_item>&, iterator_item_type)>& func)
{
- m_idx++;
- while(m_idx >= (int) m_el->get_children_count() && m_stack.size())
- {
- stack_item si = m_stack.back();
- m_stack.pop_back();
- m_idx = si.idx;
- m_el = si.el;
- m_idx++;
- continue;
- }
+ for(auto& el : container->children())
+ {
+ if(go_inside(el))
+ {
+ if(m_return_parent)
+ {
+ // call function for parent
+ func(el, iterator_item_type_start_parent);
+ }
+ // go inside element and process its items
+ process(el, func);
+ if(m_return_parent)
+ {
+ // call function for parent
+ func(el, iterator_item_type_end_parent);
+ }
+ } else
+ {
+ // call function for element
+ if(!m_select || m_select->select(el))
+ {
+ func(el, iterator_item_type_child);
+ }
+ }
+ }
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
-bool litehtml::go_inside_inline::select(const element::ptr& el)
+bool litehtml::go_inside_inline::select(const std::shared_ptr<render_item>& el)
{
- if(el->get_display() == display_inline || el->get_display() == display_inline_text)
+ if(el->src_el()->css().get_display() == display_inline && el->src_el()->css().get_float() == float_none)
{
return true;
}
return false;
}
-bool litehtml::go_inside_table::select(const element::ptr& el)
+bool litehtml::inline_selector::select(const std::shared_ptr<render_item>& el)
+{
+ if(el->src_el()->css().get_display() == display_inline_text ||
+ el->src_el()->css().get_display() == display_inline_table ||
+ el->src_el()->css().get_display() == display_inline_block ||
+ el->src_el()->css().get_display() == display_inline_flex ||
+ el->src_el()->css().get_float() != float_none)
+ {
+ return true;
+ }
+ return false;
+}
+
+bool litehtml::go_inside_table::select(const std::shared_ptr<render_item>& el)
{
- if( el->get_display() == display_table_row_group ||
- el->get_display() == display_table_header_group ||
- el->get_display() == display_table_footer_group)
+ if( el->src_el()->css().get_display() == display_table_row_group ||
+ el->src_el()->css().get_display() == display_table_header_group ||
+ el->src_el()->css().get_display() == display_table_footer_group)
{
return true;
}
return false;
}
-bool litehtml::table_rows_selector::select(const element::ptr& el)
+bool litehtml::table_rows_selector::select(const std::shared_ptr<render_item>& el)
{
- if( el->get_display() == display_table_row)
+ if( el->src_el()->css().get_display() == display_table_row)
{
return true;
}
return false;
}
-bool litehtml::table_cells_selector::select(const element::ptr& el)
+bool litehtml::table_cells_selector::select(const std::shared_ptr<render_item>& el)
{
- if( el->get_display() == display_table_cell)
+ if( el->src_el()->css().get_display() == display_table_cell)
{
return true;
}
diff --git a/src/plugins/litehtml_viewer/litehtml/iterators.h b/src/plugins/litehtml_viewer/litehtml/iterators.h
index 53f23c337..b1a678d7b 100644
--- a/src/plugins/litehtml_viewer/litehtml/iterators.h
+++ b/src/plugins/litehtml_viewer/litehtml/iterators.h
@@ -2,88 +2,82 @@
#define LH_ITERATORS_H
#include "types.h"
+#include <list>
+#include <functional>
namespace litehtml
{
- class element;
+ class render_item;
class iterator_selector
{
public:
- virtual bool select(const element::ptr& el) = 0;
+ virtual bool select(const std::shared_ptr<render_item>& el) = 0;
+
+ protected:
+ ~iterator_selector() = default;
+ };
+
+ enum iterator_item_type
+ {
+ iterator_item_type_child,
+ iterator_item_type_start_parent,
+ iterator_item_type_end_parent
};
class elements_iterator
{
private:
- struct stack_item
- {
- int idx;
- element::ptr el;
- stack_item()
- {
+ iterator_selector* m_go_inside;
+ iterator_selector* m_select;
+ bool m_return_parent;
- }
- stack_item(const stack_item& val)
- {
- idx = val.idx;
- el = val.el;
- }
- stack_item(stack_item&& val)
- {
- idx = val.idx;
- el = std::move(val.el);
- }
- };
+ /**
+ * Checks if iterator should go inside the element
+ *
+ * @param el element to check
+ * @return true to go inside
+ */
+ bool go_inside(const std::shared_ptr<render_item>& el);
- std::vector<stack_item> m_stack;
- element::ptr m_el;
- int m_idx;
- iterator_selector* m_go_inside;
- iterator_selector* m_select;
public:
+ elements_iterator(bool return_parents, iterator_selector* go_inside, iterator_selector* select);
+ ~elements_iterator() = default;
- elements_iterator(const element::ptr& el, iterator_selector* go_inside, iterator_selector* select)
- {
- m_el = el;
- m_idx = -1;
- m_go_inside = go_inside;
- m_select = select;
- }
-
- ~elements_iterator()
- {
-
- }
-
- element::ptr next(bool ret_parent = true);
+ void process(const std::shared_ptr<render_item>& container, const std::function<void (std::shared_ptr<render_item>&, iterator_item_type)>& func);
private:
void next_idx();
};
- class go_inside_inline : public iterator_selector
+ class go_inside_inline final : public iterator_selector
{
public:
- virtual bool select(const element::ptr& el);
+ bool select(const std::shared_ptr<render_item>& el) override;
};
- class go_inside_table : public iterator_selector
+ class inline_selector final : public iterator_selector
+ {
+ public:
+ bool select(const std::shared_ptr<render_item>& el) override;
+ };
+
+ class go_inside_table final : public iterator_selector
{
public:
- virtual bool select(const element::ptr& el);
+ bool select(const std::shared_ptr<render_item>& el) override;
};
- class table_rows_selector : public iterator_selector
+ class table_rows_selector final : public iterator_selector
{
public:
- virtual bool select(const element::ptr& el);
+ bool select(const std::shared_ptr<render_item>& el) override;
};
- class table_cells_selector : public iterator_selector
+ class table_cells_selector final : public iterator_selector
{
public:
- virtual bool select(const element::ptr& el);
+ bool select(const std::shared_ptr<render_item>& el) override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/line_box.cpp b/src/plugins/litehtml_viewer/litehtml/line_box.cpp
new file mode 100644
index 000000000..269dd4672
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/line_box.cpp
@@ -0,0 +1,698 @@
+#include "html.h"
+#include "line_box.h"
+#include "element.h"
+#include "render_item.h"
+#include <algorithm>
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void litehtml::line_box_item::place_to(int x, int y)
+{
+ m_element->pos().x = x + m_element->content_offset_left();
+ m_element->pos().y = y + m_element->content_offset_top();
+}
+
+litehtml::position& litehtml::line_box_item::pos()
+{
+ return m_element->pos();
+}
+
+
+int litehtml::line_box_item::width() const
+{
+ return m_element->width();
+}
+
+int litehtml::line_box_item::top() const
+{
+ return m_element->top();
+}
+
+int litehtml::line_box_item::bottom() const
+{
+ return m_element->bottom();
+}
+
+int litehtml::line_box_item::right() const
+{
+ return m_element->right();
+}
+
+int litehtml::line_box_item::left() const
+{
+ return m_element->left();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+litehtml::lbi_start::lbi_start(const std::shared_ptr<render_item>& element) : line_box_item(element)
+{
+ m_pos.height = m_element->src_el()->css().get_font_metrics().height;
+ m_pos.width = m_element->content_offset_left();
+}
+
+void litehtml::lbi_start::place_to(int x, int y)
+{
+ m_pos.x = x + m_element->content_offset_left();
+ m_pos.y = y;
+}
+
+int litehtml::lbi_start::width() const
+{
+ return m_pos.width;
+}
+
+int litehtml::lbi_start::top() const
+{
+ return m_pos.y;
+}
+
+int litehtml::lbi_start::bottom() const
+{
+ return m_pos.y + m_pos.height;
+}
+
+int litehtml::lbi_start::right() const
+{
+ return m_pos.x;
+}
+
+int litehtml::lbi_start::left() const
+{
+ return m_pos.x - m_element->content_offset_left();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+litehtml::lbi_end::lbi_end(const std::shared_ptr<render_item>& element) : lbi_start(element)
+{
+ m_pos.height = m_element->src_el()->css().get_font_metrics().height;
+ m_pos.width = m_element->content_offset_right();
+}
+
+void litehtml::lbi_end::place_to(int x, int y)
+{
+ m_pos.x = x;
+ m_pos.y = y;
+}
+
+int litehtml::lbi_end::right() const
+{
+ return m_pos.x + m_pos.width;
+}
+
+int litehtml::lbi_end::left() const
+{
+ return m_pos.x;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+litehtml::lbi_continue::lbi_continue(const std::shared_ptr<render_item>& element) : lbi_start(element)
+{
+ m_pos.height = m_element->src_el()->css().get_font_metrics().height;
+ m_pos.width = 0;
+}
+
+void litehtml::lbi_continue::place_to(int x, int y)
+{
+ m_pos.x = x;
+ m_pos.y = y;
+}
+
+int litehtml::lbi_continue::right() const
+{
+ return m_pos.x;
+}
+
+int litehtml::lbi_continue::left() const
+{
+ return m_pos.x;
+}
+
+int litehtml::lbi_continue::width() const
+{
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void litehtml::line_box::add_item(std::unique_ptr<line_box_item> item)
+{
+ item->get_el()->skip(false);
+ bool add = true;
+ switch (item->get_type())
+ {
+ case line_box_item::type_text_part:
+ if(item->get_el()->src_el()->is_white_space())
+ {
+ add = !is_empty() && !have_last_space();
+ }
+ break;
+ case line_box_item::type_inline_start:
+ case line_box_item::type_inline_end:
+ case line_box_item::type_inline_continue:
+ add = true;
+ break;
+ }
+ if(add)
+ {
+ item->place_to(m_left + m_width, m_top);
+ m_width += item->width();
+ m_height = std::max(m_height, item->get_el()->height());
+ m_items.emplace_back(std::move(item));
+ } else
+ {
+ item->get_el()->skip(true);
+ }
+}
+
+int litehtml::line_box::calc_va_baseline(const va_context& current, vertical_align va, const font_metrics& new_font, int top, int bottom)
+{
+ switch(va)
+ {
+ case va_super:
+ return current.baseline - current.fm.height / 3;
+ case va_sub:
+ return current.baseline + current.fm.height / 3;
+ case va_middle:
+ return current.baseline - current.fm.x_height / 2;
+ case va_text_top:
+ return current.baseline - (current.fm.height - current.fm.base_line()) +
+ new_font.height - new_font.base_line();
+ case va_text_bottom:
+ return current.baseline + current.fm.base_line() - new_font.base_line();
+ case va_top:
+ return top + new_font.height - new_font.base_line();
+ case va_bottom:
+ return bottom - new_font.height + new_font.base_line();
+ default:
+ return current.baseline;
+ }
+}
+
+std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish(bool last_box, const containing_block_context &containing_block_size)
+{
+ std::list< std::unique_ptr<line_box_item> > ret_items;
+
+ if(!last_box)
+ {
+ while(!m_items.empty())
+ {
+ if (m_items.back()->get_type() == line_box_item::type_text_part)
+ {
+ // remove trailing spaces
+ if (m_items.back()->get_el()->src_el()->is_break() ||
+ m_items.back()->get_el()->src_el()->is_white_space())
+ {
+ m_width -= m_items.back()->width();
+ m_items.back()->get_el()->skip(true);
+ m_items.pop_back();
+ } else
+ {
+ break;
+ }
+ } else if (m_items.back()->get_type() == line_box_item::type_inline_start)
+ {
+ // remove trailing empty inline_start markers
+ // these markers will be added at the beginning of the next line box
+ m_width -= m_items.back()->width();
+ ret_items.emplace_back(std::move(m_items.back()));
+ m_items.pop_back();
+ } else
+ {
+ break;
+ }
+ }
+ } else
+ {
+ // remove trailing spaces
+ auto iter = m_items.rbegin();
+ while(iter != m_items.rend())
+ {
+ if ((*iter)->get_type() == line_box_item::type_text_part)
+ {
+ if((*iter)->get_el()->src_el()->is_white_space())
+ {
+ (*iter)->get_el()->skip(true);
+ m_width -= (*iter)->width();
+ // Space can be between text and inline_end marker
+ // We have to shift all items on the right side
+ if(iter != m_items.rbegin())
+ {
+ auto r_iter = iter;
+ r_iter--;
+ while (true)
+ {
+ (*r_iter)->pos().x -= (*iter)->width();
+ if (r_iter == m_items.rbegin())
+ {
+ break;
+ }
+ r_iter--;
+ }
+ }
+ // erase white space element
+ iter = decltype(iter) (m_items.erase( std::next(iter).base() ));
+ } else
+ {
+ break;
+ }
+ } else
+ {
+ iter++;
+ }
+ }
+ }
+
+ if( is_empty() || (!is_empty() && last_box && is_break_only()) )
+ {
+ m_height = m_default_line_height;
+ m_baseline = m_font_metrics.base_line();
+ return ret_items;
+ }
+
+ int spc_x = 0;
+
+ int add_x = 0;
+ switch(m_text_align)
+ {
+ case text_align_right:
+ if(m_width < (m_right - m_left))
+ {
+ add_x = (m_right - m_left) - m_width;
+ }
+ break;
+ case text_align_center:
+ if(m_width < (m_right - m_left))
+ {
+ add_x = ((m_right - m_left) - m_width) / 2;
+ }
+ break;
+ case text_align_justify:
+ if (m_width < (m_right - m_left))
+ {
+ add_x = 0;
+ spc_x = (m_right - m_left) - m_width;
+ if (spc_x > m_width/4)
+ spc_x = 0;
+ }
+ break;
+ default:
+ add_x = 0;
+ }
+
+ int counter = 0;
+ float offj = float(spc_x) / std::max(1.f, float(m_items.size())-1.f);
+ float cixx = 0.0f;
+
+ int line_top = 0;
+ int line_bottom = 0;
+
+ va_context current_context;
+ std::list<va_context> contexts;
+
+ current_context.baseline = 0;
+ current_context.fm = m_font_metrics;
+
+ m_min_width = 0;
+
+ for (const auto& lbi : m_items)
+ {
+ m_min_width += lbi->get_rendered_min_width();
+ { // start text_align_justify
+ if (spc_x && counter)
+ {
+ cixx += offj;
+ if ((counter + 1) == int(m_items.size()))
+ cixx += 0.99f;
+ lbi->pos().x += int(cixx);
+ }
+ counter++;
+ if ((m_text_align == text_align_right || spc_x) && counter == int(m_items.size()))
+ {
+ // Forcible justify the last element to the right side for text align right and justify;
+ lbi->pos().x = m_right - lbi->pos().width;
+ } else if (add_x)
+ {
+ lbi->pos().x += add_x;
+ }
+ } // end text_align_justify
+
+ if (lbi->get_type() == line_box_item::type_inline_start || lbi->get_type() == line_box_item::type_inline_continue)
+ {
+ contexts.push_back(current_context);
+ current_context.baseline = calc_va_baseline(current_context,
+ lbi->get_el()->css().get_vertical_align(),
+ lbi->get_el()->css().get_font_metrics(),
+ line_top, line_bottom);
+ current_context.fm = lbi->get_el()->css().get_font_metrics();
+ }
+
+ // Align elements vertically by baseline.
+ if(lbi->get_el()->src_el()->css().get_display() == display_inline_text || lbi->get_el()->src_el()->css().get_display() == display_inline)
+ {
+ // inline elements and text are aligned by baseline only
+ // at this point the baseline for text is properly aligned already
+ lbi->pos().y = current_context.baseline - lbi->get_el()->css().get_font_metrics().height + lbi->get_el()->css().get_font_metrics().base_line();
+ } else
+ {
+ switch(lbi->get_el()->css().get_vertical_align())
+ {
+ case va_sub:
+ case va_super:
+ {
+ int bl = calc_va_baseline(current_context, lbi->get_el()->css().get_vertical_align(), current_context.fm, line_top, line_bottom);
+ lbi->pos().y = bl - lbi->get_el()->height() + lbi->get_el()->get_base_line() +
+ lbi->get_el()->content_offset_top();
+ }
+ break;
+ case va_bottom:
+ lbi->pos().y = line_bottom - lbi->get_el()->height() + lbi->get_el()->content_offset_top();
+ break;
+ case va_top:
+ lbi->pos().y = line_top + lbi->get_el()->content_offset_top();
+ break;
+ case va_baseline:
+ lbi->pos().y = current_context.baseline - lbi->get_el()->height() + lbi->get_el()->get_base_line() +
+ lbi->get_el()->content_offset_top();
+ break;
+ case va_text_top:
+ lbi->pos().y = current_context.baseline - current_context.fm.height + current_context.fm.base_line() +
+ lbi->get_el()->content_offset_top();
+ break;
+ case va_text_bottom:
+ lbi->pos().y = current_context.baseline + current_context.fm.base_line() - lbi->get_el()->height() +
+ lbi->get_el()->content_offset_top();
+ break;
+ case va_middle:
+ lbi->pos().y = current_context.baseline - current_context.fm.x_height / 2 - lbi->get_el()->height() / 2 +
+ lbi->get_el()->content_offset_top();
+ break;
+ }
+ }
+
+ if (lbi->get_type() == line_box_item::type_inline_end)
+ {
+ if(!contexts.empty())
+ {
+ current_context = contexts.back();
+ contexts.pop_back();
+ }
+ }
+
+ // calculate line height
+ line_top = std::min(line_top, lbi->top());
+ line_bottom = std::max(line_bottom, lbi->bottom());
+
+ if(lbi->get_el()->src_el()->css().get_display() == display_inline_text)
+ {
+ m_line_height = std::max(m_line_height, lbi->get_el()->css().get_line_height());
+ }
+ }
+
+ m_height = line_bottom - line_top;
+ int top_shift = line_top;
+ if(m_height < m_line_height)
+ {
+ top_shift -= (m_line_height - m_height) / 2;
+ m_height = m_line_height;
+ }
+ m_baseline = line_bottom;
+
+ struct inline_item_box
+ {
+ std::shared_ptr<render_item> element;
+ position box;
+
+ inline_item_box() = default;
+ explicit inline_item_box(const std::shared_ptr<render_item>& el) : element(el) {}
+ };
+
+ std::list<inline_item_box> inlines;
+
+ contexts.clear();
+
+ current_context.baseline = 0;
+ current_context.fm = m_font_metrics;
+ bool va_top_bottom = false;
+
+ for (const auto& lbi : m_items)
+ {
+ // Calculate baseline. Now we calculate baseline for vertical alignment top and bottom
+ if (lbi->get_type() == line_box_item::type_inline_start || lbi->get_type() == line_box_item::type_inline_continue)
+ {
+ contexts.push_back(current_context);
+ va_top_bottom = lbi->get_el()->css().get_vertical_align() == va_bottom || lbi->get_el()->css().get_vertical_align() == va_top;
+ current_context.baseline = calc_va_baseline(current_context,
+ lbi->get_el()->css().get_vertical_align(),
+ lbi->get_el()->css().get_font_metrics(),
+ top_shift, top_shift + m_height);
+ current_context.fm = lbi->get_el()->css().get_font_metrics();
+ }
+
+ // Align inlines and text by baseline if current vertical alignment is top or bottom
+ if(va_top_bottom)
+ {
+ if (lbi->get_el()->src_el()->css().get_display() == display_inline_text ||
+ lbi->get_el()->src_el()->css().get_display() == display_inline)
+ {
+ // inline elements and text are aligned by baseline only
+ // at this point the baseline for text is properly aligned already
+ lbi->pos().y = current_context.baseline - lbi->get_el()->css().get_font_metrics().height +
+ lbi->get_el()->css().get_font_metrics().base_line();
+ }
+ }
+
+ // Pop the prev context
+ if (lbi->get_type() == line_box_item::type_inline_end)
+ {
+ if(!contexts.empty())
+ {
+ current_context = contexts.back();
+ contexts.pop_back();
+ }
+ }
+
+ // move element to the correct position
+ lbi->pos().y += m_top - top_shift;
+
+ // Perform vertical align top and bottom for inline boxes
+ if(lbi->get_el()->css().get_display() != display_inline_text && lbi->get_el()->css().get_display() != display_inline)
+ {
+ if(lbi->get_el()->css().get_vertical_align() == va_top)
+ {
+ lbi->pos().y = m_top + lbi->get_el()->content_offset_top();
+ } else if(lbi->get_el()->css().get_vertical_align() == va_bottom)
+ {
+ lbi->pos().y = m_top + m_height - lbi->get_el()->height() + lbi->get_el()->content_offset_top();
+ }
+ }
+ lbi->get_el()->apply_relative_shift(containing_block_size);
+
+ // Calculate and push inline box into the render item element
+ if(lbi->get_type() == line_box_item::type_inline_start || lbi->get_type() == line_box_item::type_inline_continue)
+ {
+ if(lbi->get_type() == line_box_item::type_inline_start)
+ {
+ lbi->get_el()->clear_inline_boxes();
+ }
+ inlines.emplace_back(lbi->get_el());
+ inlines.back().box.x = lbi->left();
+ inlines.back().box.y = lbi->top() - lbi->get_el()->content_offset_top();
+ inlines.back().box.height = lbi->bottom() - lbi->top() + lbi->get_el()->content_offset_height();
+ } else if(lbi->get_type() == line_box_item::type_inline_end)
+ {
+ if(!inlines.empty())
+ {
+ inlines.back().box.width = lbi->right() - inlines.back().box.x;
+ inlines.back().element->add_inline_box(inlines.back().box);
+ inlines.pop_back();
+ }
+ }
+ }
+
+ for(auto iter = inlines.rbegin(); iter != inlines.rend(); ++iter)
+ {
+ iter->box.width = m_items.back()->right() - iter->box.x;
+ iter->element->add_inline_box(iter->box);
+
+ ret_items.emplace_front(std::unique_ptr<line_box_item>(new lbi_continue(iter->element)));
+ }
+
+ return std::move(ret_items);
+}
+
+std::shared_ptr<litehtml::render_item> litehtml::line_box::get_first_text_part() const
+{
+ for(const auto & item : m_items)
+ {
+ if(item->get_type() == line_box_item::type_text_part)
+ {
+ return item->get_el();
+ }
+ }
+ return nullptr;
+}
+
+
+std::shared_ptr<litehtml::render_item> litehtml::line_box::get_last_text_part() const
+{
+ for(auto iter = m_items.rbegin(); iter != m_items.rend(); iter++)
+ {
+ if((*iter)->get_type() == line_box_item::type_text_part)
+ {
+ return (*iter)->get_el();
+ }
+ }
+ return nullptr;
+}
+
+
+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_type() == line_box_item::type_text_part)
+ {
+ auto last_el = get_last_text_part();
+
+ // force new line if the last placed element was line break
+ if (last_el && last_el->src_el()->is_break())
+ {
+ return false;
+ }
+
+ // line break should stay in current line box
+ if (item->get_el()->src_el()->is_break())
+ {
+ return true;
+ }
+
+ if (ws == white_space_nowrap || ws == white_space_pre ||
+ (ws == white_space_pre_wrap && item->get_el()->src_el()->is_space()))
+ {
+ return true;
+ }
+
+ if (m_left + m_width + item->width() > m_right)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool litehtml::line_box::have_last_space() const
+{
+ auto last_el = get_last_text_part();
+ if(last_el)
+ {
+ return last_el->src_el()->is_white_space() || last_el->src_el()->is_break();
+ }
+ return false;
+}
+
+bool litehtml::line_box::is_empty() const
+{
+ if(m_items.empty()) return true;
+ for (const auto& el : m_items)
+ {
+ if(el->get_type() == line_box_item::type_text_part)
+ {
+ if (!el->get_el()->skip() || el->get_el()->src_el()->is_break())
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+int litehtml::line_box::baseline() const
+{
+ return m_baseline;
+}
+
+int litehtml::line_box::top_margin() const
+{
+ return 0;
+}
+
+int litehtml::line_box::bottom_margin() const
+{
+ return 0;
+}
+
+void litehtml::line_box::y_shift( int shift )
+{
+ m_top += shift;
+ for (auto& el : m_items)
+ {
+ el->pos().y += shift;
+ }
+}
+
+bool litehtml::line_box::is_break_only() const
+{
+ if(m_items.empty()) return false;
+
+ bool break_found = false;
+
+ for (auto iter = m_items.rbegin(); iter != m_items.rend(); iter++)
+ {
+ if((*iter)->get_type() == line_box_item::type_text_part)
+ {
+ if((*iter)->get_el()->src_el()->is_break())
+ {
+ break_found = true;
+ } else if(!(*iter)->get_el()->skip())
+ {
+ return false;
+ }
+ }
+ }
+ return break_found;
+}
+
+std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::new_width( int left, int right)
+{
+ std::list< std::unique_ptr<line_box_item> > ret_items;
+ int add = left - m_left;
+ if(add)
+ {
+ m_left = left;
+ m_right = right;
+ m_width = 0;
+ auto remove_begin = m_items.end();
+ auto i = m_items.begin();
+ i++;
+ while (i != m_items.end())
+ {
+ if(!(*i)->get_el()->skip())
+ {
+ if(m_left + m_width + (*i)->width() > m_right)
+ {
+ remove_begin = i;
+ break;
+ } else
+ {
+ (*i)->pos().x += add;
+ m_width += (*i)->get_el()->width();
+ }
+ }
+ i++;
+ }
+ if(remove_begin != m_items.end())
+ {
+ while(remove_begin != m_items.end())
+ {
+ ret_items.emplace_back(std::move(*remove_begin));
+ }
+ m_items.erase(remove_begin, m_items.end());
+ }
+ }
+ return ret_items;
+}
+
diff --git a/src/plugins/litehtml_viewer/litehtml/line_box.h b/src/plugins/litehtml_viewer/litehtml/line_box.h
new file mode 100644
index 000000000..43f5d439e
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/line_box.h
@@ -0,0 +1,170 @@
+#ifndef LH_LINE_BOX_H
+#define LH_LINE_BOX_H
+
+#include <vector>
+#include <memory>
+#include "os_types.h"
+#include "types.h"
+
+namespace litehtml
+{
+ class render_item;
+
+ struct line_context
+ {
+ int calculatedTop;
+ int top;
+ int left;
+ int right;
+
+ int width() const
+ {
+ return right - left;
+ }
+ void fix_top()
+ {
+ calculatedTop = top;
+ }
+ };
+
+ class line_box_item
+ {
+ public:
+ enum element_type
+ {
+ type_text_part,
+ type_inline_start,
+ type_inline_continue,
+ type_inline_end
+ };
+ protected:
+ std::shared_ptr<render_item> m_element;
+ int m_rendered_min_width;
+ public:
+ explicit line_box_item(const std::shared_ptr<render_item>& element) : m_element(element), m_rendered_min_width(0) {}
+ line_box_item() = default;
+ line_box_item(const line_box_item& el) = default;
+ line_box_item(line_box_item&&) = default;
+
+ int height() const { return right() - left(); }
+ const std::shared_ptr<render_item>& get_el() const { return m_element; }
+ virtual position& pos();
+ virtual void place_to(int x, int y);
+ virtual int width() const;
+ virtual int top() const;
+ virtual int bottom() const;
+ virtual int right() const;
+ virtual int left() const;
+ virtual element_type get_type() const { return type_text_part; }
+ virtual int get_rendered_min_width() const { return m_rendered_min_width; }
+ virtual void set_rendered_min_width(int min_width) { m_rendered_min_width = min_width; }
+ };
+
+ class lbi_start : public line_box_item
+ {
+ protected:
+ position m_pos;
+ public:
+ explicit lbi_start(const std::shared_ptr<render_item>& element);
+
+ void place_to(int x, int y) override;
+ int width() const override;
+ position& pos() override { return m_pos; }
+ int top() const override;
+ int bottom() const override;
+ int right() const override;
+ int left() const override;
+ element_type get_type() const override { return type_inline_start; }
+ int get_rendered_min_width() const override { return width(); }
+ };
+
+ class lbi_end : public lbi_start
+ {
+ public:
+ explicit lbi_end(const std::shared_ptr<render_item>& element);
+
+ void place_to(int x, int y) override;
+ int right() const override;
+ int left() const override;
+ element_type get_type() const override { return type_inline_end; }
+ };
+
+ class lbi_continue : public lbi_start
+ {
+ public:
+ explicit lbi_continue(const std::shared_ptr<render_item>& element);
+
+ void place_to(int x, int y) override;
+ int right() const override;
+ int left() const override;
+ int width() const override;
+ element_type get_type() const override { return type_inline_continue; }
+ };
+
+ class line_box
+ {
+ struct va_context
+ {
+ int baseline;
+ font_metrics fm;
+
+ va_context() : baseline(0) {}
+ };
+
+ int m_top;
+ int m_left;
+ int m_right;
+ int m_height;
+ int m_width;
+ int m_line_height;
+ int m_default_line_height;
+ font_metrics m_font_metrics;
+ int m_baseline;
+ text_align m_text_align;
+ int m_min_width;
+ std::list< std::unique_ptr<line_box_item> > m_items;
+ public:
+ line_box(int top, int left, int right, int line_height, const font_metrics& fm, text_align align) :
+ m_top(top),
+ m_left(left),
+ m_right(right),
+ m_height(0),
+ m_width(0),
+ m_font_metrics(fm),
+ m_default_line_height(line_height),
+ m_baseline(0),
+ m_line_height(0),
+ m_text_align(align),
+ m_min_width(0)
+ {
+ }
+
+ int bottom() const { return m_top + height(); }
+ int top() const { return m_top; }
+ int right() const { return m_left + width(); }
+ int left() const { return m_left; }
+ int height() const { return m_height; }
+ int width() const { return m_width; }
+ int line_right() const { return m_right; }
+ int min_width() const { return m_min_width; }
+
+ void add_item(std::unique_ptr<line_box_item> item);
+ bool can_hold(const std::unique_ptr<line_box_item>& item, white_space ws) const;
+ bool is_empty() const;
+ int baseline() const;
+ int top_margin() const;
+ int bottom_margin() const;
+ void y_shift(int shift);
+ std::list< std::unique_ptr<line_box_item> > finish(bool last_box, const containing_block_context &containing_block_size);
+ std::list< std::unique_ptr<line_box_item> > new_width(int left, int right);
+ std::shared_ptr<render_item> get_last_text_part() const;
+ std::shared_ptr<render_item> get_first_text_part() const;
+ std::list< std::unique_ptr<line_box_item> >& items() { return m_items; }
+ private:
+ bool have_last_space() const;
+ bool is_break_only() const;
+ static int calc_va_baseline(const va_context& current, vertical_align va, const font_metrics& new_font, int top, int bottom);
+ };
+}
+
+#endif //LH_LINE_BOX_H
diff --git a/src/plugins/litehtml_viewer/litehtml/litehtml.h b/src/plugins/litehtml_viewer/litehtml/litehtml.h
index 98a24e0da..2537aee83 100644
--- a/src/plugins/litehtml_viewer/litehtml/litehtml.h
+++ b/src/plugins/litehtml_viewer/litehtml/litehtml.h
@@ -6,5 +6,6 @@
#include <litehtml/html_tag.h>
#include <litehtml/stylesheet.h>
#include <litehtml/element.h>
+#include <litehtml/utf8_strings.h>
#endif // LITEHTML_H
diff --git a/src/plugins/litehtml_viewer/litehtml/master_css.h b/src/plugins/litehtml_viewer/litehtml/master_css.h
new file mode 100644
index 000000000..b5c7f3f03
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/master_css.h
@@ -0,0 +1,351 @@
+#ifndef LH_MASTER_CSS_H
+#define LH_MASTER_CSS_H
+namespace litehtml{ const char* const master_css = R"##(
+
+
+html {
+ display: block;
+ position: relative;
+}
+
+head {
+ display: none
+}
+
+meta {
+ display: none
+}
+
+title {
+ display: none
+}
+
+link {
+ display: none
+}
+
+style {
+ display: none
+}
+
+script {
+ display: none
+}
+
+body {
+ display:block;
+ margin:8px;
+}
+
+p {
+ display:block;
+ margin-top:1em;
+ margin-bottom:1em;
+}
+
+b, strong {
+ display:inline;
+ font-weight:bold;
+}
+
+i, em, cite {
+ display:inline;
+ font-style:italic;
+}
+
+ins, u {
+ text-decoration:underline
+}
+
+del, s, strike {
+ text-decoration:line-through
+}
+
+center
+{
+ text-align:center;
+ display:block;
+}
+
+a:link
+{
+ text-decoration: underline;
+ color: #00f;
+ cursor: pointer;
+}
+
+h1, h2, h3, h4, h5, h6, div {
+ display:block;
+}
+
+h1 {
+ font-weight:bold;
+ margin-top:0.67em;
+ margin-bottom:0.67em;
+ font-size: 2em;
+}
+
+h2 {
+ font-weight:bold;
+ margin-top:0.83em;
+ margin-bottom:0.83em;
+ font-size: 1.5em;
+}
+
+h3 {
+ font-weight:bold;
+ margin-top:1em;
+ margin-bottom:1em;
+ font-size:1.17em;
+}
+
+h4 {
+ font-weight:bold;
+ margin-top:1.33em;
+ margin-bottom:1.33em
+}
+
+h5 {
+ font-weight:bold;
+ margin-top:1.67em;
+ margin-bottom:1.67em;
+ font-size:.83em;
+}
+
+h6 {
+ font-weight:bold;
+ margin-top:2.33em;
+ margin-bottom:2.33em;
+ font-size:.67em;
+}
+
+br {
+ display:inline-block;
+}
+
+br[clear="all"]
+{
+ clear:both;
+}
+
+br[clear="left"]
+{
+ clear:left;
+}
+
+br[clear="right"]
+{
+ clear:right;
+}
+
+span {
+ display:inline
+}
+
+img {
+ display: inline-block;
+}
+
+img[align="right"]
+{
+ float: right;
+}
+
+img[align="left"]
+{
+ float: left;
+}
+
+hr {
+ display: block;
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+ margin-left: auto;
+ margin-right: auto;
+ border-style: inset;
+ border-width: 1px
+}
+
+
+/***************** TABLES ********************/
+
+table {
+ display: table;
+ border-collapse: separate;
+ border-spacing: 2px;
+ border-top-color:gray;
+ border-left-color:gray;
+ border-bottom-color:black;
+ border-right-color:black;
+ font-size: medium;
+ font-weight: normal;
+ font-style: normal;
+}
+
+tbody, tfoot, thead {
+ display:table-row-group;
+ vertical-align:middle;
+}
+
+tr {
+ display: table-row;
+ vertical-align: inherit;
+ border-color: inherit;
+}
+
+td, th {
+ display: table-cell;
+ vertical-align: inherit;
+ border-width:1px;
+ padding:1px;
+}
+
+th {
+ font-weight: bold;
+}
+
+table[border] {
+ border-style:solid;
+}
+
+table[border|=0] {
+ border-style:none;
+}
+
+table[border] td, table[border] th {
+ border-style:solid;
+ border-top-color:black;
+ border-left-color:black;
+ border-bottom-color:gray;
+ border-right-color:gray;
+}
+
+table[border|=0] td, table[border|=0] th {
+ border-style:none;
+}
+
+caption {
+ display: table-caption;
+}
+
+td[nowrap], th[nowrap] {
+ white-space:nowrap;
+}
+
+tt, code, kbd, samp {
+ font-family: monospace
+}
+
+pre, xmp, plaintext, listing {
+ display: block;
+ font-family: monospace;
+ white-space: pre;
+ margin: 1em 0
+}
+
+/***************** LISTS ********************/
+
+ul, menu, dir {
+ display: block;
+ list-style-type: disc;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ margin-left: 0;
+ margin-right: 0;
+ padding-left: 40px
+}
+
+ol {
+ display: block;
+ list-style-type: decimal;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ margin-left: 0;
+ margin-right: 0;
+ padding-left: 40px
+}
+
+li {
+ display: list-item;
+}
+
+ul ul, ol ul {
+ list-style-type: circle;
+}
+
+ol ol ul, ol ul ul, ul ol ul, ul ul ul {
+ list-style-type: square;
+}
+
+dd {
+ display: block;
+ margin-left: 40px;
+}
+
+dl {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+dt {
+ display: block;
+}
+
+ol ul, ul ol, ul ul, ol ol {
+ margin-top: 0;
+ margin-bottom: 0
+}
+
+blockquote {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+ margin-left: 40px;
+ margin-right: 40px;
+}
+
+/*********** FORM ELEMENTS ************/
+
+form {
+ display: block;
+ margin-top: 0em;
+}
+
+option {
+ display: none;
+}
+
+input, textarea, keygen, select, button, isindex {
+ margin: 0em;
+ color: initial;
+ line-height: normal;
+ text-transform: none;
+ text-indent: 0;
+ text-shadow: none;
+ display: inline-block;
+}
+input[type="hidden"] {
+ display: none;
+}
+
+
+article, aside, footer, header, hgroup, nav, section
+{
+ display: block;
+}
+
+sub {
+ vertical-align: sub;
+ font-size: smaller;
+}
+
+sup {
+ vertical-align: super;
+ font-size: smaller;
+}
+
+)##"; }
+#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 c2b4275ed..763620367 100644
--- a/src/plugins/litehtml_viewer/litehtml/media_query.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/media_query.cpp
@@ -16,28 +16,28 @@ litehtml::media_query::media_query( const media_query& val )
m_media_type = val.m_media_type;
}
-litehtml::media_query::ptr litehtml::media_query::create_from_string(const tstring& str, const std::shared_ptr<document>& doc)
+litehtml::media_query::ptr litehtml::media_query::create_from_string(const string& str, const std::shared_ptr<document>& doc)
{
media_query::ptr query = std::make_shared<media_query>();
string_vector tokens;
- split_string(str, tokens, _t(" \t\r\n"), _t(""), _t("("));
+ split_string(str, tokens, " \t\r\n", "", "(");
- for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+ for(auto & token : tokens)
{
- if((*tok) == _t("not"))
+ if(token == "not")
{
query->m_not = true;
- } else if(tok->at(0) == _t('('))
+ } else if(token.at(0) == '(')
{
- tok->erase(0, 1);
- if(tok->at(tok->length() - 1) == _t(')'))
+ token.erase(0, 1);
+ if(token.at(token.length() - 1) == ')')
{
- tok->erase(tok->length() - 1, 1);
+ token.erase(token.length() - 1, 1);
}
media_query_expression expr;
string_vector expr_tokens;
- split_string((*tok), expr_tokens, _t(":"));
+ split_string(token, expr_tokens, ":");
if(!expr_tokens.empty())
{
trim(expr_tokens[0]);
@@ -56,23 +56,20 @@ litehtml::media_query::ptr litehtml::media_query::create_from_string(const tstri
expr.val = value_index(expr_tokens[1], media_orientation_strings, media_orientation_landscape);
} else
{
- tstring::size_type slash_pos = expr_tokens[1].find(_t('/'));
- if( slash_pos != tstring::npos )
+ string::size_type slash_pos = expr_tokens[1].find('/');
+ if( slash_pos != string::npos )
{
- tstring val1 = expr_tokens[1].substr(0, slash_pos);
- tstring val2 = expr_tokens[1].substr(slash_pos + 1);
+ string val1 = expr_tokens[1].substr(0, slash_pos);
+ string val2 = expr_tokens[1].substr(slash_pos + 1);
trim(val1);
trim(val2);
- expr.val = t_atoi(val1.c_str());
- expr.val2 = t_atoi(val2.c_str());
+ expr.val = atoi(val1.c_str());
+ expr.val2 = atoi(val2.c_str());
} else
{
css_length length;
length.fromString(expr_tokens[1]);
- if(length.units() == css_units_dpcm)
- {
- expr.val = (int) (length.val() * 2.54);
- } else if(length.units() == css_units_dpi)
+ if(length.units() == css_units_dpcm || length.units() == css_units_dpi)
{
expr.val = (int) (length.val() * 2.54);
} else
@@ -91,7 +88,7 @@ litehtml::media_query::ptr litehtml::media_query::create_from_string(const tstri
}
} else
{
- query->m_media_type = (media_type) value_index((*tok), media_type_strings, media_type_all);
+ query->m_media_type = (media_type) value_index(token, media_type_strings, media_type_all);
}
}
@@ -105,11 +102,12 @@ bool litehtml::media_query::check( const media_features& features ) const
if(m_media_type == media_type_all || m_media_type == features.type)
{
res = true;
- for(media_query_expression::vector::const_iterator expr = m_expressions.begin(); expr != m_expressions.end() && res; expr++)
+ for(auto expression : m_expressions)
{
- if(!expr->check(features))
+ if(!expression.check(features))
{
res = false;
+ break;
}
}
}
@@ -124,19 +122,19 @@ bool litehtml::media_query::check( const media_features& features ) const
//////////////////////////////////////////////////////////////////////////
-litehtml::media_query_list::ptr litehtml::media_query_list::create_from_string(const tstring& str, const std::shared_ptr<document>& doc)
+litehtml::media_query_list::ptr litehtml::media_query_list::create_from_string(const string& str, const std::shared_ptr<document>& doc)
{
media_query_list::ptr list = std::make_shared<media_query_list>();
string_vector tokens;
- split_string(str, tokens, _t(","));
+ split_string(str, tokens, ",");
- for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+ for(auto & token : tokens)
{
- trim(*tok);
- lcase(*tok);
+ trim(token);
+ lcase(token);
- litehtml::media_query::ptr query = media_query::create_from_string(*tok, doc);
+ litehtml::media_query::ptr query = media_query::create_from_string(token, doc);
if(query)
{
list->m_queries.push_back(query);
@@ -144,7 +142,7 @@ litehtml::media_query_list::ptr litehtml::media_query_list::create_from_string(c
}
if(list->m_queries.empty())
{
- list = 0;
+ list = nullptr;
}
return list;
@@ -154,11 +152,12 @@ bool litehtml::media_query_list::apply_media_features( const media_features& fea
{
bool apply = false;
- for(media_query::vector::iterator iter = m_queries.begin(); iter != m_queries.end() && !apply; iter++)
+ for(auto & query : m_queries)
{
- if((*iter)->check(features))
+ if(query->check(features))
{
apply = true;
+ break;
}
}
diff --git a/src/plugins/litehtml_viewer/litehtml/media_query.h b/src/plugins/litehtml_viewer/litehtml/media_query.h
index 6a81bcb32..4cb21fc2f 100644
--- a/src/plugins/litehtml_viewer/litehtml/media_query.h
+++ b/src/plugins/litehtml_viewer/litehtml/media_query.h
@@ -35,7 +35,7 @@ namespace litehtml
media_query();
media_query(const media_query& val);
- static media_query::ptr create_from_string(const tstring& str, const std::shared_ptr<document>& doc);
+ static media_query::ptr create_from_string(const string& str, const std::shared_ptr<document>& doc);
bool check(const media_features& features) const;
};
@@ -51,7 +51,7 @@ namespace litehtml
media_query_list();
media_query_list(const media_query_list& val);
- static media_query_list::ptr create_from_string(const tstring& str, const std::shared_ptr<document>& doc);
+ static media_query_list::ptr create_from_string(const string& str, const std::shared_ptr<document>& doc);
bool is_used() const;
bool apply_media_features(const media_features& features); // returns true if the m_is_used changed
};
diff --git a/src/plugins/litehtml_viewer/litehtml/num_cvt.cpp b/src/plugins/litehtml_viewer/litehtml/num_cvt.cpp
index 16e7af442..23d594b5c 100644
--- a/src/plugins/litehtml_viewer/litehtml/num_cvt.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/num_cvt.cpp
@@ -1,16 +1,15 @@
#include "num_cvt.h"
-#include "types.h"
#include "utf8_strings.h"
#include <vector>
-static std::vector<litehtml::tchar_t> latin_lower = { _t('a'), _t('b'), _t('c'), _t('d'), _t('e'), _t('f'), _t('g'), _t('h'), _t('i'), _t('j'), _t('k'), _t('l'), _t('m'), _t('n'), _t('o'), _t('p'), _t('q'), _t('r'), _t('s'), _t('t'), _t('u'), _t('v'), _t('w'), _t('x'), _t('y'), _t('z') };
-static std::vector<litehtml::tchar_t> latin_upper = { _t('A'), _t('B'), _t('C'), _t('D'), _t('E'), _t('F'), _t('G'), _t('H'), _t('I'), _t('J'), _t('K'), _t('L'), _t('M'), _t('N'), _t('O'), _t('P'), _t('Q'), _t('R'), _t('S'), _t('T'), _t('U'), _t('V'), _t('W'), _t('X'), _t('Y'), _t('Z') };
+static std::vector<char> latin_lower = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
+static std::vector<char> latin_upper = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
static std::vector<std::wstring> greek_lower = { L"α", L"β", L"γ", L"δ", L"ε", L"ζ", L"η", L"θ", L"ι", L"κ", L"λ", L"μ", L"ν", L"ξ", L"ο", L"π", L"ρ", L"σ", L"τ", L"υ", L"φ", L"χ", L"ψ", L"ω" };
-static litehtml::tstring to_mapped_alpha(int num, const std::vector<litehtml::tchar_t>& map)
+static litehtml::string to_mapped_alpha(int num, const std::vector<char>& map)
{
int dividend = num;
- litehtml::tstring out;
+ litehtml::string out;
int modulo;
while (dividend > 0)
@@ -23,10 +22,10 @@ static litehtml::tstring to_mapped_alpha(int num, const std::vector<litehtml::tc
return out;
}
-static litehtml::tstring to_mapped_alpha(int num, const std::vector<std::wstring>& map)
+static litehtml::string to_mapped_alpha(int num, const std::vector<std::wstring>& map)
{
int dividend = num;
- litehtml::tstring out;
+ litehtml::string out;
int modulo;
while (dividend > 0)
@@ -39,37 +38,37 @@ static litehtml::tstring to_mapped_alpha(int num, const std::vector<std::wstring
return out;
}
-litehtml::tstring litehtml::num_cvt::to_latin_lower(int val)
+litehtml::string litehtml::num_cvt::to_latin_lower(int val)
{
return to_mapped_alpha(val, latin_lower);
}
-litehtml::tstring litehtml::num_cvt::to_latin_upper(int val)
+litehtml::string litehtml::num_cvt::to_latin_upper(int val)
{
return to_mapped_alpha(val, latin_upper);
}
-litehtml::tstring litehtml::num_cvt::to_greek_lower(int val)
+litehtml::string litehtml::num_cvt::to_greek_lower(int val)
{
return to_mapped_alpha(val, greek_lower);
}
-litehtml::tstring litehtml::num_cvt::to_roman_lower(int value)
+litehtml::string litehtml::num_cvt::to_roman_lower(int value)
{
- struct romandata_t { int value; const litehtml::tchar_t* numeral; };
+ struct romandata_t { int value; const char* numeral; };
const struct romandata_t romandata[] =
{
- { 1000, _t("m") }, { 900, _t("cm" )},
- { 500, _t("d") }, { 400, _t("cd") },
- { 100, _t("c") }, { 90, _t("xc") },
- { 50, _t("l") }, { 40, _t("xl") },
- { 10, _t("x") }, { 9, _t("ix") },
- { 5, _t("v") }, { 4, _t("iv") },
- { 1, _t("i") },
- { 0, NULL } // end marker
+ { 1000, "m" }, { 900, "cm" },
+ { 500, "d" }, { 400, "cd" },
+ { 100, "c" }, { 90, "xc" },
+ { 50, "l" }, { 40, "xl" },
+ { 10, "x" }, { 9, "ix" },
+ { 5, "v" }, { 4, "iv" },
+ { 1, "i" },
+ { 0, nullptr } // end marker
};
- litehtml::tstring result;
+ litehtml::string result;
for (const romandata_t* current = romandata; current->value > 0; ++current)
{
while (value >= current->value)
@@ -81,22 +80,22 @@ litehtml::tstring litehtml::num_cvt::to_roman_lower(int value)
return result;
}
-litehtml::tstring litehtml::num_cvt::to_roman_upper(int value)
+litehtml::string litehtml::num_cvt::to_roman_upper(int value)
{
- struct romandata_t { int value; const litehtml::tchar_t* numeral; };
+ struct romandata_t { int value; const char* numeral; };
const struct romandata_t romandata[] =
{
- { 1000, _t("M") }, { 900, _t("CM") },
- { 500, _t("D") }, { 400, _t("CD") },
- { 100, _t("C") }, { 90, _t("XC") },
- { 50, _t("L") }, { 40, _t("XL") },
- { 10, _t("X") }, { 9, _t("IX") },
- { 5, _t("V") }, { 4, _t("IV") },
- { 1, _t("I") },
- { 0, NULL } // end marker
+ { 1000, "M" }, { 900, "CM" },
+ { 500, "D" }, { 400, "CD" },
+ { 100, "C" }, { 90, "XC" },
+ { 50, "L" }, { 40, "XL" },
+ { 10, "X" }, { 9, "IX" },
+ { 5, "V" }, { 4, "IV" },
+ { 1, "I" },
+ { 0, nullptr } // end marker
};
- litehtml::tstring result;
+ litehtml::string result;
for (const romandata_t* current = romandata; current->value > 0; ++current)
{
while (value >= current->value)
diff --git a/src/plugins/litehtml_viewer/litehtml/num_cvt.h b/src/plugins/litehtml_viewer/litehtml/num_cvt.h
index 367dcc36a..0eaaa6886 100644
--- a/src/plugins/litehtml_viewer/litehtml/num_cvt.h
+++ b/src/plugins/litehtml_viewer/litehtml/num_cvt.h
@@ -2,18 +2,17 @@
#define NUM_CVT_H
#include <string>
-#include <cstdint>
#include "os_types.h"
namespace litehtml
{
namespace num_cvt
{
- litehtml::tstring to_latin_lower(int val);
- litehtml::tstring to_latin_upper(int val);
- litehtml::tstring to_greek_lower(int val);
- litehtml::tstring to_roman_lower(int value);
- litehtml::tstring to_roman_upper(int value);
+ string to_latin_lower(int val);
+ string to_latin_upper(int val);
+ string to_greek_lower(int val);
+ string to_roman_lower(int value);
+ string to_roman_upper(int value);
}
}
diff --git a/src/plugins/litehtml_viewer/litehtml/os_types.h b/src/plugins/litehtml_viewer/litehtml/os_types.h
index 53fd76643..bbc2c3cf6 100644
--- a/src/plugins/litehtml_viewer/litehtml/os_types.h
+++ b/src/plugins/litehtml_viewer/litehtml/os_types.h
@@ -1,90 +1,28 @@
#ifndef LH_OS_TYPES_H
#define LH_OS_TYPES_H
+#include <string>
+#include <cstdint>
+
namespace litehtml
{
-#if defined( WIN32 ) || defined( _WIN32 ) || defined( WINCE )
-
-#ifndef LITEHTML_UTF8
-
- typedef std::wstring tstring;
- typedef wchar_t tchar_t;
- typedef std::wstringstream tstringstream;
-
- #define _t(quote) L##quote
-
- #define t_strlen wcslen
- #define t_strcmp wcscmp
- #define t_strncmp wcsncmp
- #define t_strcasecmp _wcsicmp
- #define t_strncasecmp _wcsnicmp
- #define t_strtol wcstol
- #define t_atoi _wtoi
- #define t_strtod wcstod
- #define t_itoa(value, buffer, size, radix) _itow_s(value, buffer, size, radix)
- #define t_strstr wcsstr
- #define t_tolower towlower
- #define t_isdigit iswdigit
- #define t_to_string(val) std::to_wstring(val)
-
-#else
-
- typedef std::string tstring;
- typedef char tchar_t;
- typedef std::stringstream tstringstream;
+ using std::string;
+ typedef std::uintptr_t uint_ptr;
- #define _t(quote) quote
-
- #define t_strlen strlen
- #define t_strcmp strcmp
- #define t_strncmp strncmp
- #define t_strcasecmp _stricmp
- #define t_strncasecmp _strnicmp
- #define t_strtol strtol
- #define t_atoi atoi
- #define t_strtod strtod
- #define t_itoa(value, buffer, size, radix) _itoa_s(value, buffer, size, radix)
- #define t_strstr strstr
- #define t_tolower tolower
- #define t_isdigit isdigit
- #define t_to_string(val) std::to_string(val)
+#if defined( WIN32 ) || defined( _WIN32 ) || defined( WINCE )
+// noexcept appeared since Visual Studio 2015
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#define noexcept
#endif
-/*
- #ifdef _WIN64
- typedef unsigned __int64 uint_ptr;
- #else
- typedef unsigned int uint_ptr;
- #endif
-*/
- typedef std::uintptr_t uint_ptr;
+ #define t_itoa(value, buffer, size, radix) _itoa_s(value, buffer, size, radix)
+ #define t_snprintf(s, n, format, ...) _snprintf_s(s, _TRUNCATE, n, format, __VA_ARGS__)
#else
- #define LITEHTML_UTF8
- typedef std::string tstring;
- typedef char tchar_t;
- typedef std::uintptr_t uint_ptr;
- typedef std::stringstream tstringstream;
-
- #define _t(quote) quote
-
- #define t_strlen strlen
- #define t_strcmp strcmp
- #define t_strncmp strncmp
-
- #define t_strcasecmp strcasecmp
- #define t_strncasecmp strncasecmp
#define t_itoa(value, buffer, size, radix) snprintf(buffer, size, "%d", value)
-
- #define t_strtol strtol
- #define t_atoi atoi
- #define t_strtod strtod
- #define t_strstr strstr
- #define t_tolower tolower
- #define t_isdigit isdigit
- #define t_to_string(val) std::to_string(val)
+ #define t_snprintf(s, n, format, ...) snprintf(s, n, format, __VA_ARGS__)
#endif
}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_block.cpp b/src/plugins/litehtml_viewer/litehtml/render_block.cpp
new file mode 100644
index 000000000..8e1d107b4
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_block.cpp
@@ -0,0 +1,856 @@
+#include "html.h"
+#include "render_item.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 line_top = 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);
+
+ int ret_width = 0;
+
+ 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();
+ }
+ add_float(el, 0, 0, self_size.context_idx);
+ fix_line_width(float_left, self_size);
+ ret_width = el->right();
+ } 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();
+ 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);
+ }
+ 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()
+{
+ {
+ css_selector sel;
+ sel.parse(".inline_rating");
+ if(src_el()->select(sel))
+ {
+ int i = 0;
+ i++;
+ }
+ }
+ std::shared_ptr<render_item> ret;
+
+ // Initialize indexes for list items
+ if(src_el()->css().get_display() == display_list_item && src_el()->css().get_list_style_type() >= list_style_type_armenian)
+ {
+ 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++)
+ {
+ auto child = p->get_child(i);
+ if (child == src_el())
+ {
+ src_el()->set_attr("list_index", std::to_string(val).c_str());
+ break;
+ }
+ else if (child->css().get_display() == display_list_item)
+ val++;
+ }
+ }
+ }
+ // Split inline blocks with box blocks inside
+ auto iter = m_children.begin();
+ while (iter != m_children.end())
+ {
+ const auto& el = *iter;
+ if(el->src_el()->css().get_display() == display_inline && !el->children().empty())
+ {
+ auto split_el = el->split_inlines();
+ if(std::get<0>(split_el))
+ {
+ iter = m_children.erase(iter);
+ iter = m_children.insert(iter, std::get<2>(split_el));
+ iter = m_children.insert(iter, std::get<1>(split_el));
+ iter = m_children.insert(iter, std::get<0>(split_el));
+
+ std::get<0>(split_el)->parent(shared_from_this());
+ std::get<1>(split_el)->parent(shared_from_this());
+ std::get<2>(split_el)->parent(shared_from_this());
+ continue;
+ }
+ }
+ ++iter;
+ }
+
+ bool has_block_level = false;
+ bool has_inlines = false;
+ bool has_floats = false;
+ for (const auto& el : m_children)
+ {
+ if(!el->src_el()->is_float())
+ {
+ if (el->src_el()->is_block_box())
+ {
+ has_block_level = true;
+ } else if (el->src_el()->is_inline_box())
+ {
+ has_inlines = true;
+ }
+ }
+ if(has_block_level && has_inlines)
+ break;
+ }
+ if(has_block_level)
+ {
+ ret = std::make_shared<render_item_block_context>(src_el());
+ ret->parent(parent());
+
+ auto doc = src_el()->get_document();
+ decltype(m_children) new_children;
+ decltype(m_children) inlines;
+ bool not_ws_added = false;
+ for (const auto& el : m_children)
+ {
+ if(el->src_el()->is_inline_box())
+ {
+ inlines.push_back(el);
+ if(!el->src_el()->is_white_space())
+ not_ws_added = true;
+ } else
+ {
+ if(not_ws_added)
+ {
+ auto anon_el = std::make_shared<html_tag>(src_el());
+ auto anon_ri = std::make_shared<render_item_block>(anon_el);
+ for(const auto& inl : inlines)
+ {
+ anon_ri->add_child(inl);
+ }
+
+ not_ws_added = false;
+ new_children.push_back(anon_ri);
+ anon_ri->parent(ret);
+ }
+ new_children.push_back(el);
+ el->parent(ret);
+ inlines.clear();
+ }
+ }
+ if(!inlines.empty() && not_ws_added)
+ {
+ auto anon_el = std::make_shared<html_tag>(src_el());
+ auto anon_ri = std::make_shared<render_item_block>(anon_el);
+ for(const auto& inl : inlines)
+ {
+ anon_ri->add_child(inl);
+ }
+
+ new_children.push_back(anon_ri);
+ anon_ri->parent(ret);
+ }
+ ret->children() = new_children;
+ }
+
+ if(!ret)
+ {
+ ret = std::make_shared<render_item_inline_context>(src_el());
+ ret->parent(parent());
+ ret->children() = children();
+ for (const auto &el: ret->children())
+ {
+ el->parent(ret);
+ }
+ }
+
+ ret->src_el()->add_render(ret);
+
+ for(auto& el : ret->children())
+ {
+ el = el->init();
+ }
+
+ return ret;
+}
+
+int litehtml::render_item_block::render(int x, int y, const containing_block_context &containing_block_size, 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);
+ //*****************************************
+
+ bool requires_rerender = false; // when true, the second pass for content rendering is required
+
+ // Set block width
+ if(self_size.width.type == containing_block_context::cbc_value_type_absolute)
+ {
+ ret_width = m_pos.width = self_size.render_width;
+ } else if(self_size.width.type == containing_block_context::cbc_value_type_percentage)
+ {
+ 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;
+ }
+ }
+
+ // Fix width with min-width attribute
+ if(self_size.min_width.type != containing_block_context::cbc_value_type_none)
+ {
+ if(m_pos.width < self_size.min_width)
+ {
+ m_pos.width = self_size.min_width;
+ requires_rerender = true;
+ }
+ }
+
+ // Fix width with max-width attribute
+ if(self_size.max_width.type != containing_block_context::cbc_value_type_none)
+ {
+ if(m_pos.width > self_size.max_width)
+ {
+ m_pos.width = self_size.max_width;
+ requires_rerender = true;
+ }
+ }
+
+ // re-render content with new width if required
+ if (requires_rerender && !second_pass && !is_root())
+ {
+ if(src_el()->is_floats_holder())
+ {
+ m_floats_left.clear();
+ m_floats_right.clear();
+ } else
+ {
+ 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));
+ }
+
+ // Set block height
+ if (self_size.height.type != containing_block_context::cbc_value_type_auto)
+ {
+ 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())
+ {
+ // add the floats' height to the block height
+ int floats_height = get_floats_height();
+ if (floats_height > m_pos.height)
+ {
+ m_pos.height = floats_height;
+ }
+ }
+
+ // Fix height with min-height attribute
+ if(self_size.min_height.type != containing_block_context::cbc_value_type_none)
+ {
+ if(m_pos.height < self_size.min_height)
+ {
+ m_pos.height = self_size.min_height;
+ }
+ }
+
+ // Fix width with max-width attribute
+ if(self_size.max_height.type != containing_block_context::cbc_value_type_none)
+ {
+ if(m_pos.height > self_size.max_height)
+ {
+ m_pos.height = self_size.max_height;
+ }
+ }
+
+ // calculate the final position
+ m_pos.move_to(x, y);
+ m_pos.x += content_offset_left();
+ m_pos.y += content_offset_top();
+
+ if (src_el()->css().get_display() == display_list_item)
+ {
+ string list_image = src_el()->css().get_list_style_image();
+ if (!list_image.empty())
+ {
+ size sz;
+ string list_image_baseurl = src_el()->css().get_list_style_image_baseurl();
+ src_el()->get_document()->container()->get_image_size(list_image.c_str(), list_image_baseurl.c_str(), sz);
+ if (m_pos.height < sz.height)
+ {
+ m_pos.height = sz.height;
+ }
+ }
+
+ }
+
+ 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_context.cpp b/src/plugins/litehtml_viewer/litehtml/render_block_context.cpp
new file mode 100644
index 000000000..b0aa444d7
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_block_context.cpp
@@ -0,0 +1,125 @@
+#include "html.h"
+#include "render_item.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)
+{
+ element_position el_position;
+
+ int child_top = 0;
+ int last_margin = 0;
+ std::shared_ptr<render_item> last_margin_el;
+ bool is_first = true;
+ for (const auto& el : m_children)
+ {
+ // we don't need to process absolute and fixed positioned element on the second pass
+ if (second_pass)
+ {
+ el_position = el->src_el()->css().get_position();
+ if ((el_position == element_position_absolute || el_position == element_position_fixed)) continue;
+ }
+
+ if(el->src_el()->css().get_float() != float_none)
+ {
+ int rw = place_float(el, child_top, self_size);
+ if (rw > ret_width)
+ {
+ ret_width = rw;
+ }
+ } else if(el->src_el()->css().get_display() != display_none)
+ {
+ 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);
+ } else
+ {
+ child_top = get_cleared_top(el, child_top);
+ int child_x = 0;
+ int child_width = self_size.render_width;
+
+ el->calc_outlines(self_size.width);
+
+ // Collapse top margin
+ if(is_first && collapse_top_margin())
+ {
+ child_top -= el->get_margins().top;
+ if(el->get_margins().top > get_margins().top)
+ {
+ m_margins.top = el->get_margins().top;
+ }
+ } else
+ {
+ if(last_margin > el->get_margins().top)
+ {
+ child_top -= el->get_margins().top;
+ } else
+ {
+ child_top -= last_margin;
+ }
+ }
+
+ if(el->src_el()->is_replaced() || el->src_el()->is_floats_holder() || 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);
+ child_x = ln_left;
+ child_width = ln_right - ln_left;
+
+ auto el_parent = el->parent();
+ el->pos().width = el->src_el()->css().get_width().calc_percent(child_width);
+ 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));
+ // 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));
+ }
+ int auto_margin = el->calc_auto_margins(child_width);
+ if(auto_margin)
+ {
+ el->pos().x += auto_margin;
+ }
+ if (rw > ret_width)
+ {
+ ret_width = rw;
+ }
+ child_top += el->height();
+ last_margin = el->get_margins().bottom;
+ last_margin_el = el;
+ is_first = false;
+
+ if (el->src_el()->css().get_position() == element_position_relative)
+ {
+ el->apply_relative_shift(self_size);
+ }
+ }
+ }
+ }
+
+ int block_height = 0;
+ if (get_predefined_height(block_height, self_size.height))
+ {
+ m_pos.height = block_height;
+ } else
+ {
+ m_pos.height = child_top;
+ if(collapse_bottom_margin())
+ {
+ m_pos.height -= last_margin;
+ if(m_margins.bottom < last_margin)
+ {
+ m_margins.bottom = last_margin;
+ }
+ if(last_margin_el)
+ {
+ last_margin_el->get_margins().bottom = 0;
+ }
+ }
+ }
+
+ return ret_width;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_flex.cpp b/src/plugins/litehtml_viewer/litehtml/render_flex.cpp
new file mode 100644
index 000000000..c9cf8e538
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_flex.cpp
@@ -0,0 +1,91 @@
+#include "html.h"
+#include "render_item.h"
+#include "types.h"
+
+int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass, int ret_width,
+ const containing_block_context &self_size)
+{
+ return 0;
+}
+
+void litehtml::render_item_flex::draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex)
+{
+
+}
+
+std::shared_ptr<litehtml::render_item> litehtml::render_item_flex::init()
+{
+ auto doc = src_el()->get_document();
+ decltype(m_children) new_children;
+ decltype(m_children) inlines;
+
+ auto convert_inlines = [&]()
+ {
+ if(!inlines.empty())
+ {
+ // Find last not space
+ auto not_space = std::find_if(inlines.rbegin(), inlines.rend(), [&](const std::shared_ptr<render_item>& el)
+ {
+ return !el->src_el()->is_space();
+ });
+ if(not_space != inlines.rend())
+ {
+ // Erase all spaces at the end
+ inlines.erase((not_space.base()), inlines.end());
+ }
+
+ auto anon_el = std::make_shared<html_tag>(src_el());
+ auto anon_ri = std::make_shared<render_item_block>(anon_el);
+ for(const auto& inl : inlines)
+ {
+ anon_ri->add_child(inl);
+ }
+ anon_ri->parent(shared_from_this());
+
+ new_children.push_back(anon_ri->init());
+ inlines.clear();
+ }
+ };
+
+ for (const auto& el : m_children)
+ {
+ if(el->src_el()->css().get_display() == display_inline_text)
+ {
+ if(!inlines.empty())
+ {
+ inlines.push_back(el);
+ } else
+ {
+ if (!el->src_el()->is_white_space())
+ {
+ inlines.push_back(el);
+ }
+ }
+ } else
+ {
+ convert_inlines();
+ if(el->src_el()->is_block_box())
+ {
+ // Add block boxes as is
+ el->parent(shared_from_this());
+ new_children.push_back(el->init());
+ } else
+ {
+ // Wrap inlines with anonymous block box
+ auto anon_el = std::make_shared<html_tag>(el->src_el());
+ auto anon_ri = std::make_shared<render_item_block>(anon_el);
+ anon_ri->add_child(el->init());
+ anon_ri->parent(shared_from_this());
+ new_children.push_back(anon_ri->init());
+ }
+ }
+ }
+ convert_inlines();
+ children() = new_children;
+ for(const auto& el : children())
+ {
+ m_flex_items.emplace_back(new flex_item(el));
+ }
+
+ return shared_from_this();
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_image.cpp b/src/plugins/litehtml_viewer/litehtml/render_image.cpp
new file mode 100644
index 000000000..38f576bc1
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_image.cpp
@@ -0,0 +1,148 @@
+#include "html.h"
+#include "render_item.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 parent_width = containing_block_size.width;
+
+ calc_outlines(parent_width);
+
+ m_pos.move_to(x, y);
+
+ document::ptr doc = src_el()->get_document();
+
+ litehtml::size sz;
+ src_el()->get_content_size(sz, containing_block_size.width);
+
+ m_pos.width = sz.width;
+ m_pos.height = sz.height;
+
+ src_el()->css_w().set_line_height(height());
+
+ if(src_el()->css().get_height().is_predefined() && src_el()->css().get_width().is_predefined())
+ {
+ m_pos.height = sz.height;
+ m_pos.width = sz.width;
+
+ // check for max-width
+ if(!src_el()->css().get_max_width().is_predefined())
+ {
+ int max_width = doc->to_pixels(src_el()->css().get_max_width(), src_el()->css().get_font_size(), parent_width);
+ if(m_pos.width > max_width)
+ {
+ m_pos.width = max_width;
+ }
+ if(sz.width)
+ {
+ m_pos.height = (int) ((float) m_pos.width * (float) sz.height / (float)sz.width);
+ } else
+ {
+ m_pos.height = sz.height;
+ }
+ }
+
+ // check for max-height
+ if(!src_el()->css().get_max_height().is_predefined())
+ {
+ int max_height = calc_max_height(sz.height, containing_block_size.height);
+ if(m_pos.height > max_height)
+ {
+ m_pos.height = max_height;
+ }
+ if(sz.height)
+ {
+ m_pos.width = (int) ((float )m_pos.height * (float)sz.width / (float)sz.height);
+ } else
+ {
+ m_pos.width = sz.width;
+ }
+ }
+ } else if(!src_el()->css().get_height().is_predefined() && src_el()->css().get_width().is_predefined())
+ {
+ if (!get_predefined_height(m_pos.height, containing_block_size.height))
+ {
+ m_pos.height = (int)src_el()->css().get_height().val();
+ }
+
+ // check for max-height
+ if(!src_el()->css().get_max_height().is_predefined())
+ {
+ int max_height = calc_max_height(sz.height, containing_block_size.height);
+ if(m_pos.height > max_height)
+ {
+ m_pos.height = max_height;
+ }
+ }
+
+ if(sz.height)
+ {
+ m_pos.width = (int) ((float )m_pos.height * (float)sz.width / (float)sz.height);
+ } else
+ {
+ m_pos.width = sz.width;
+ }
+ } else if(src_el()->css().get_height().is_predefined() && !src_el()->css().get_width().is_predefined())
+ {
+ m_pos.width = (int) src_el()->css().get_width().calc_percent(parent_width);
+
+ // check for max-width
+ if(!src_el()->css().get_max_width().is_predefined())
+ {
+ int max_width = doc->to_pixels(src_el()->css().get_max_width(), src_el()->css().get_font_size(), parent_width);
+ if(m_pos.width > max_width)
+ {
+ m_pos.width = max_width;
+ }
+ }
+
+ if(sz.width)
+ {
+ m_pos.height = (int) ((float) m_pos.width * (float) sz.height / (float)sz.width);
+ } else
+ {
+ m_pos.height = sz.height;
+ }
+ } else
+ {
+ m_pos.width = (int) src_el()->css().get_width().calc_percent(parent_width);
+ m_pos.height = 0;
+ if (!get_predefined_height(m_pos.height, containing_block_size.height))
+ {
+ m_pos.height = (int)src_el()->css().get_height().val();
+ }
+
+ // check for max-height
+ if(!src_el()->css().get_max_height().is_predefined())
+ {
+ int max_height = calc_max_height(sz.height, containing_block_size.height);
+ if(m_pos.height > max_height)
+ {
+ m_pos.height = max_height;
+ }
+ }
+
+ // check for max-height
+ if(!src_el()->css().get_max_width().is_predefined())
+ {
+ int max_width = doc->to_pixels(src_el()->css().get_max_width(), src_el()->css().get_font_size(), parent_width);
+ if(m_pos.width > max_width)
+ {
+ m_pos.width = max_width;
+ }
+ }
+ }
+
+ m_pos.x += content_offset_left();
+ m_pos.y += content_offset_top();
+
+ return m_pos.width + content_offset_left() + content_offset_right();
+}
+
+int litehtml::render_item_image::calc_max_height(int image_height, int containing_block_height)
+{
+ document::ptr doc = src_el()->get_document();
+ return doc->to_pixels(src_el()->css().get_max_height(), src_el()->css().get_font_size(),
+ containing_block_height == 0 ? image_height : containing_block_height);
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_inline.cpp b/src/plugins/litehtml_viewer/litehtml/render_inline.cpp
new file mode 100644
index 000000000..0ea24b17d
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_inline.cpp
@@ -0,0 +1,3 @@
+#include "html.h"
+#include "render_item.h"
+
diff --git a/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp b/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp
new file mode 100644
index 000000000..b348a8cf7
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp
@@ -0,0 +1,403 @@
+#include "html.h"
+#include "render_item.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)
+{
+ m_line_boxes.clear();
+ m_max_line_width = 0;
+
+ white_space ws = src_el()->css().get_white_space();
+ bool skip_spaces = false;
+ if (ws == white_space_normal ||
+ ws == white_space_nowrap ||
+ ws == white_space_pre_line)
+ {
+ skip_spaces = true;
+ }
+
+ bool was_space = false;
+
+ go_inside_inline go_inside_inlines_selector;
+ inline_selector select_inlines;
+ elements_iterator inlines_iter(true, &go_inside_inlines_selector, &select_inlines);
+
+ inlines_iter.process(shared_from_this(), [&](const std::shared_ptr<render_item>& el, iterator_item_type item_type)
+ {
+ switch (item_type)
+ {
+ case iterator_item_type_child:
+ {
+ // skip spaces to make rendering a bit faster
+ if (skip_spaces)
+ {
+ if (el->src_el()->is_white_space())
+ {
+ if (was_space)
+ {
+ el->skip(true);
+ return;
+ } else
+ {
+ was_space = true;
+ }
+ } else
+ {
+ // skip all spaces after line break
+ was_space = el->src_el()->is_break();
+ }
+ }
+ // place element into rendering flow
+ place_inline(std::unique_ptr<line_box_item>(new line_box_item(el)), self_size);
+ }
+ break;
+
+ case iterator_item_type_start_parent:
+ {
+ el->clear_inline_boxes();
+ place_inline(std::unique_ptr<lbi_start>(new lbi_start(el)), self_size);
+ }
+ break;
+
+ case iterator_item_type_end_parent:
+ {
+ place_inline(std::unique_ptr<lbi_end>(new lbi_end(el)), self_size);
+ }
+ break;
+ }
+ });
+
+ finish_last_box(true, self_size);
+
+ if (!m_line_boxes.empty())
+ {
+ if (collapse_top_margin())
+ {
+ int old_top = m_margins.top;
+ 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());
+ }
+ }
+ if (collapse_bottom_margin())
+ {
+ m_margins.bottom = std::max(m_line_boxes.back()->bottom_margin(), m_margins.bottom);
+ m_pos.height = m_line_boxes.back()->bottom() - m_line_boxes.back()->bottom_margin();
+ }
+ else
+ {
+ m_pos.height = m_line_boxes.back()->bottom();
+ }
+ }
+
+ return std::max(ret_width, m_max_line_width);
+}
+
+void litehtml::render_item_inline_context::fix_line_width(element_float flt,
+ const containing_block_context &self_size)
+{
+ int ret_width = 0;
+ if(!m_line_boxes.empty())
+ {
+ auto el_front = m_line_boxes.back()->get_first_text_part();
+
+ std::vector<std::shared_ptr<render_item>> els;
+ bool was_cleared = false;
+ if(el_front && el_front->src_el()->css().get_clear() != clear_none)
+ {
+ if(el_front->src_el()->css().get_clear() == clear_both)
+ {
+ was_cleared = true;
+ } else
+ {
+ if( (flt == float_left && el_front->src_el()->css().get_clear() == clear_left) ||
+ (flt == float_right && el_front->src_el()->css().get_clear() == clear_right) )
+ {
+ was_cleared = true;
+ }
+ }
+ }
+
+ if(!was_cleared)
+ {
+ std::list<std::unique_ptr<line_box_item> > items = std::move(m_line_boxes.back()->items());
+ m_line_boxes.pop_back();
+
+ for(auto& item : items)
+ {
+ place_inline(std::move(item), self_size);
+ }
+ } else
+ {
+ int line_top = 0;
+ line_top = m_line_boxes.back()->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);
+
+ if(m_line_boxes.size() == 1)
+ {
+ if (src_el()->css().get_list_style_type() != list_style_type_none && src_el()->css().get_list_style_position() == list_style_position_inside)
+ {
+ int sz_font = src_el()->css().get_font_size();
+ line_left += sz_font;
+ }
+
+ if (src_el()->css().get_text_indent().val() != 0)
+ {
+ line_left += src_el()->css().get_text_indent().calc_percent(self_size.width);
+ }
+
+ }
+
+ auto items = m_line_boxes.back()->new_width(line_left, line_right);
+ for(auto& item : items)
+ {
+ place_inline(std::move(item), self_size);
+ }
+ }
+ }
+}
+
+std::list<std::unique_ptr<litehtml::line_box_item> > litehtml::render_item_inline_context::finish_last_box(bool end_of_render, const containing_block_context &self_size)
+{
+ std::list<std::unique_ptr<line_box_item> > ret;
+
+ if(!m_line_boxes.empty())
+ {
+ ret = m_line_boxes.back()->finish(end_of_render, self_size);
+
+ if(m_line_boxes.back()->is_empty() && end_of_render)
+ {
+ // remove the last empty line
+ m_line_boxes.pop_back();
+ } else
+ {
+ m_max_line_width = std::max(m_max_line_width, m_line_boxes.back()->min_width());
+ }
+ }
+ 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)
+{
+ auto items = finish_last_box(false, self_size);
+ int line_top = 0;
+ if(!m_line_boxes.empty())
+ {
+ line_top = m_line_boxes.back()->bottom();
+ }
+ line_ctx.top = 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);
+
+ if(el->get_el()->src_el()->is_inline_box() || el->get_el()->src_el()->is_floats_holder())
+ {
+ 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.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);
+ }
+ }
+
+ int first_line_margin = 0;
+ int text_indent = 0;
+ if(m_line_boxes.empty())
+ {
+ if(src_el()->css().get_list_style_type() != list_style_type_none && src_el()->css().get_list_style_position() == list_style_position_inside)
+ {
+ int sz_font = src_el()->css().get_font_size();
+ first_line_margin = sz_font;
+ }
+ if(src_el()->css().get_text_indent().val() != 0)
+ {
+ text_indent = src_el()->css().get_text_indent().calc_percent(self_size.width);
+ }
+ }
+
+ m_line_boxes.emplace_back(std::unique_ptr<line_box>(new line_box(
+ line_ctx.top,
+ line_ctx.left + first_line_margin + text_indent, line_ctx.right,
+ css().get_line_height(),
+ css().get_font_metrics(),
+ css().get_text_align())));
+
+ // Add items returned by finish_last_box function into the new line
+ for(auto& it : items)
+ {
+ m_line_boxes.back()->add_item(std::move(it));
+ }
+
+ 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)
+{
+ if(item->get_el()->src_el()->css().get_display() == display_none) return;
+
+ if(item->get_el()->src_el()->is_float())
+ {
+ int line_top = 0;
+ if(!m_line_boxes.empty())
+ {
+ line_top = m_line_boxes.back()->top();
+ }
+ int ret = place_float(item->get_el(), line_top, self_size);
+ if(ret > m_max_line_width)
+ {
+ m_max_line_width = ret;
+ }
+ return;
+ }
+
+ line_context line_ctx = {0};
+ line_ctx.top = 0;
+ if (!m_line_boxes.empty())
+ {
+ line_ctx.top = m_line_boxes.back().get()->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);
+
+ if(item->get_type() == line_box_item::type_text_part)
+ {
+ switch (item->get_el()->src_el()->css().get_display())
+ {
+ 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:
+ {
+ 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);
+ }
+ break;
+ }
+ }
+
+ bool add_box = true;
+ if(!m_line_boxes.empty())
+ {
+ if(m_line_boxes.back()->can_hold(item, src_el()->css().get_white_space()))
+ {
+ add_box = false;
+ }
+ }
+ if(add_box)
+ {
+ new_box(item, line_ctx, self_size);
+ } else if(!m_line_boxes.empty())
+ {
+ line_ctx.top = m_line_boxes.back()->top();
+ }
+
+ if (line_ctx.top != line_ctx.calculatedTop)
+ {
+ 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);
+ }
+
+ if(!item->get_el()->src_el()->is_inline_box())
+ {
+ if(m_line_boxes.size() == 1)
+ {
+ if(collapse_top_margin())
+ {
+ int shift = item->get_el()->margin_top();
+ if(shift >= 0)
+ {
+ line_ctx.top -= shift;
+ m_line_boxes.back()->y_shift(-shift);
+ }
+ }
+ } else
+ {
+ int shift = 0;
+ int prev_margin = m_line_boxes[m_line_boxes.size() - 2]->bottom_margin();
+
+ if(prev_margin > item->get_el()->margin_top())
+ {
+ shift = item->get_el()->margin_top();
+ } else
+ {
+ shift = prev_margin;
+ }
+ if(shift >= 0)
+ {
+ line_ctx.top -= shift;
+ m_line_boxes.back()->y_shift(-shift);
+ }
+ }
+ }
+
+ m_line_boxes.back()->add_item(std::move(item));
+}
+
+void litehtml::render_item_inline_context::apply_vertical_align()
+{
+ if(!m_line_boxes.empty())
+ {
+ int add = 0;
+ int content_height = m_line_boxes.back()->bottom();
+
+ if(m_pos.height > content_height)
+ {
+ switch(src_el()->css().get_vertical_align())
+ {
+ case va_middle:
+ add = (m_pos.height - content_height) / 2;
+ break;
+ case va_bottom:
+ add = m_pos.height - content_height;
+ break;
+ default:
+ add = 0;
+ break;
+ }
+ }
+
+ if(add)
+ {
+ for(auto & box : m_line_boxes)
+ {
+ box->y_shift(add);
+ }
+ }
+ }
+}
+
+int litehtml::render_item_inline_context::get_base_line()
+{
+ auto el_parent = parent();
+ if(el_parent && src_el()->css().get_display() == display_inline_flex)
+ {
+ return el_parent->get_base_line();
+ }
+ if(src_el()->is_replaced())
+ {
+ return 0;
+ }
+ int bl = 0;
+ if(!m_line_boxes.empty())
+ {
+ bl = m_line_boxes.back()->baseline() + content_offset_bottom();
+ }
+ return bl;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_item.cpp b/src/plugins/litehtml_viewer/litehtml/render_item.cpp
new file mode 100644
index 000000000..2fc8e99c7
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_item.cpp
@@ -0,0 +1,1076 @@
+#include "html.h"
+#include "render_item.h"
+#include "document.h"
+#include <typeinfo>
+#include <utf8_strings.h>
+
+litehtml::render_item::render_item(std::shared_ptr<element> _src_el) :
+ m_element(std::move(_src_el)),
+ m_skip(false)
+{
+ document::ptr doc = src_el()->get_document();
+ auto fnt_size = src_el()->css().get_font_size();
+
+ m_margins.left = doc->to_pixels(src_el()->css().get_margins().left, fnt_size);
+ m_margins.right = doc->to_pixels(src_el()->css().get_margins().right, fnt_size);
+ m_margins.top = doc->to_pixels(src_el()->css().get_margins().top, fnt_size);
+ m_margins.bottom = doc->to_pixels(src_el()->css().get_margins().bottom, fnt_size);
+
+ m_padding.left = doc->to_pixels(src_el()->css().get_padding().left, fnt_size);
+ m_padding.right = doc->to_pixels(src_el()->css().get_padding().right, fnt_size);
+ m_padding.top = doc->to_pixels(src_el()->css().get_padding().top, fnt_size);
+ m_padding.bottom = doc->to_pixels(src_el()->css().get_padding().bottom, fnt_size);
+
+ m_borders.left = doc->to_pixels(src_el()->css().get_borders().left.width, fnt_size);
+ m_borders.right = doc->to_pixels(src_el()->css().get_borders().right.width, fnt_size);
+ m_borders.top = doc->to_pixels(src_el()->css().get_borders().top.width, fnt_size);
+ m_borders.bottom = doc->to_pixels(src_el()->css().get_borders().bottom.width, fnt_size);
+}
+
+
+void litehtml::render_item::calc_outlines( int parent_width )
+{
+ m_padding.left = m_element->css().get_padding().left.calc_percent(parent_width);
+ m_padding.right = m_element->css().get_padding().right.calc_percent(parent_width);
+
+ m_borders.left = m_element->css().get_borders().left.width.calc_percent(parent_width);
+ m_borders.right = m_element->css().get_borders().right.width.calc_percent(parent_width);
+
+ m_margins.left = m_element->css().get_margins().left.calc_percent(parent_width);
+ m_margins.right = m_element->css().get_margins().right.calc_percent(parent_width);
+
+ m_margins.top = m_element->css().get_margins().top.calc_percent(parent_width);
+ m_margins.bottom = m_element->css().get_margins().bottom.calc_percent(parent_width);
+
+ m_padding.top = m_element->css().get_padding().top.calc_percent(parent_width);
+ m_padding.bottom = m_element->css().get_padding().bottom.calc_percent(parent_width);
+}
+
+int litehtml::render_item::calc_auto_margins(int parent_width)
+{
+ if ((src_el()->css().get_display() == display_block || src_el()->css().get_display() == display_table) &&
+ src_el()->css().get_position() != element_position_absolute &&
+ src_el()->css().get_float() == float_none)
+ {
+ if (src_el()->css().get_margins().left.is_predefined() && src_el()->css().get_margins().right.is_predefined())
+ {
+ int el_width = m_pos.width + m_borders.left + m_borders.right + m_padding.left + m_padding.right;
+ if (el_width <= parent_width)
+ {
+ m_margins.left = (parent_width - el_width) / 2;
+ m_margins.right = (parent_width - el_width) - m_margins.left;
+ }
+ else
+ {
+ m_margins.left = 0;
+ m_margins.right = 0;
+ }
+ return m_margins.left;
+ }
+ else if (src_el()->css().get_margins().left.is_predefined() && !src_el()->css().get_margins().right.is_predefined())
+ {
+ int el_width = m_pos.width + m_borders.left + m_borders.right + m_padding.left + m_padding.right + m_margins.right;
+ m_margins.left = parent_width - el_width;
+ if (m_margins.left < 0) m_margins.left = 0;
+ return m_margins.left;
+ }
+ else if (!src_el()->css().get_margins().left.is_predefined() && src_el()->css().get_margins().right.is_predefined())
+ {
+ int el_width = m_pos.width + m_borders.left + m_borders.right + m_padding.left + m_padding.right + m_margins.left;
+ m_margins.right = parent_width - el_width;
+ if (m_margins.right < 0) m_margins.right = 0;
+ }
+ }
+ return 0;
+}
+
+void litehtml::render_item::apply_relative_shift(const containing_block_context &containing_block_size)
+{
+ if (src_el()->css().get_position() == element_position_relative)
+ {
+ css_offsets offsets = src_el()->css().get_offsets();
+ if (!offsets.left.is_predefined())
+ {
+ m_pos.x += offsets.left.calc_percent(containing_block_size.width);
+ }
+ else if (!offsets.right.is_predefined())
+ {
+ m_pos.x -= offsets.right.calc_percent(containing_block_size.width);
+ }
+ if (!offsets.top.is_predefined())
+ {
+ m_pos.y += offsets.top.calc_percent(containing_block_size.height);
+ }
+ else if (!offsets.bottom.is_predefined())
+ {
+ m_pos.y -= offsets.bottom.calc_percent(containing_block_size.height);
+ }
+ }
+}
+
+bool litehtml::render_item::get_predefined_height(int& p_height, int containing_block_height) const
+{
+ css_length h = src_el()->css().get_height();
+ if(h.is_predefined())
+ {
+ p_height = m_pos.height;
+ return false;
+ }
+ if(h.units() == css_units_percentage)
+ {
+ p_height = h.calc_percent(containing_block_height);
+ return containing_block_height != 0;
+ }
+ p_height = src_el()->get_document()->to_pixels(h, src_el()->css().get_font_size());
+ return true;
+}
+
+int litehtml::render_item::calc_width(int defVal, int containing_block_width) const
+{
+ css_length w = src_el()->css().get_width();
+ if(w.is_predefined() || src_el()->css().get_display() == display_table_cell)
+ {
+ return defVal;
+ }
+ if(w.units() == css_units_percentage)
+ {
+ return w.calc_percent(containing_block_width);
+ }
+ return src_el()->get_document()->to_pixels(w, src_el()->css().get_font_size());
+}
+
+std::tuple<
+ std::shared_ptr<litehtml::render_item>,
+ std::shared_ptr<litehtml::render_item>,
+ std::shared_ptr<litehtml::render_item>
+ > litehtml::render_item::split_inlines()
+{
+ std::tuple<
+ std::shared_ptr<litehtml::render_item>,
+ std::shared_ptr<litehtml::render_item>,
+ std::shared_ptr<litehtml::render_item>
+ > ret;
+ for(const auto& child: m_children)
+ {
+ if(child->src_el()->is_block_box() && child->src_el()->css().get_float() == float_none)
+ {
+ std::get<0>(ret) = clone();
+ std::get<1>(ret) = child;
+ std::get<2>(ret) = clone();
+
+ std::get<1>(ret)->parent(std::get<0>(ret));
+ std::get<2>(ret)->parent(std::get<0>(ret));
+
+ bool found = false;
+ for(const auto& ch: m_children)
+ {
+ if(ch == child)
+ {
+ found = true;
+ continue;
+ }
+ if(!found)
+ {
+ std::get<0>(ret)->add_child(ch);
+ } else
+ {
+ std::get<2>(ret)->add_child(ch);
+ }
+ }
+ break;
+ }
+ if(!child->children().empty())
+ {
+ auto child_split = child->split_inlines();
+ if(std::get<0>(child_split))
+ {
+ std::get<0>(ret) = clone();
+ std::get<1>(ret) = std::get<1>(child_split);
+ std::get<2>(ret) = clone();
+
+ std::get<2>(ret)->parent(std::get<0>(ret));
+
+ bool found = false;
+ for(const auto& ch: m_children)
+ {
+ if(ch == child)
+ {
+ found = true;
+ continue;
+ }
+ if(!found)
+ {
+ std::get<0>(ret)->add_child(ch);
+ } else
+ {
+ std::get<2>(ret)->add_child(ch);
+ }
+ }
+ std::get<0>(ret)->add_child(std::get<0>(child_split));
+ std::get<2>(ret)->add_child(std::get<2>(child_split));
+ break;
+ }
+ }
+ }
+ return ret;
+}
+
+bool litehtml::render_item::fetch_positioned()
+{
+ bool ret = false;
+
+ m_positioned.clear();
+
+ litehtml::element_position el_pos;
+
+ for(auto& el : m_children)
+ {
+ el_pos = el->src_el()->css().get_position();
+ if (el_pos != element_position_static)
+ {
+ add_positioned(el);
+ }
+ if (!ret && (el_pos == element_position_absolute || el_pos == element_position_fixed))
+ {
+ ret = true;
+ }
+ if(el->fetch_positioned())
+ {
+ ret = true;
+ }
+ }
+ return ret;
+}
+
+void litehtml::render_item::render_positioned(render_type rt)
+{
+ position wnd_position;
+ src_el()->get_document()->container()->get_client_rect(wnd_position);
+
+ element_position el_position;
+ bool process;
+ for (auto& el : m_positioned)
+ {
+ el_position = el->src_el()->css().get_position();
+
+ process = false;
+ if(el->src_el()->css().get_display() != display_none)
+ {
+ if(el_position == element_position_absolute)
+ {
+ if(rt != render_fixed_only)
+ {
+ process = true;
+ }
+ } else if(el_position == element_position_fixed)
+ {
+ if(rt != render_no_fixed)
+ {
+ process = true;
+ }
+ }
+ }
+
+ if(process)
+ {
+ containing_block_context containing_block_size;
+ int client_x = 0;
+ int client_y = 0;
+ if(el_position == element_position_fixed)
+ {
+ containing_block_size.height = wnd_position.height;
+ containing_block_size.width = wnd_position.width;
+ client_x = wnd_position.left();
+ client_y = wnd_position.top();
+ } else
+ {
+ containing_block_size.height = m_pos.height;
+ containing_block_size.width = m_pos.width;
+ }
+
+ css_length css_left = el->src_el()->css().get_offsets().left;
+ css_length css_right = el->src_el()->css().get_offsets().right;
+ css_length css_top = el->src_el()->css().get_offsets().top;
+ css_length css_bottom = el->src_el()->css().get_offsets().bottom;
+
+ bool need_render = false;
+
+ css_length el_w = el->src_el()->css().get_width();
+ css_length el_h = el->src_el()->css().get_height();
+
+ int new_width = -1;
+ int new_height = -1;
+ if(el_w.units() == css_units_percentage && containing_block_size.width)
+ {
+ new_width = el_w.calc_percent(containing_block_size.width);
+ if(el->m_pos.width != new_width)
+ {
+ need_render = true;
+ el->m_pos.width = new_width;
+ }
+ }
+
+ if(el_h.units() == css_units_percentage && containing_block_size.height)
+ {
+ new_height = el_h.calc_percent(containing_block_size.height);
+ if(el->m_pos.height != new_height)
+ {
+ need_render = true;
+ el->m_pos.height = new_height;
+ }
+ }
+
+ bool cvt_x = false;
+ bool cvt_y = false;
+
+ if(el_position == element_position_fixed)
+ {
+ if(!css_left.is_predefined() || !css_right.is_predefined())
+ {
+ if(!css_left.is_predefined() && css_right.is_predefined())
+ {
+ el->m_pos.x = css_left.calc_percent(containing_block_size.width) + el->content_offset_left();
+ } else if(css_left.is_predefined() && !css_right.is_predefined())
+ {
+ el->m_pos.x = containing_block_size.width - css_right.calc_percent(containing_block_size.width) - el->m_pos.width -
+ el->content_offset_right();
+ } else
+ {
+ el->m_pos.x = css_left.calc_percent(containing_block_size.width) + el->content_offset_left();
+ el->m_pos.width = containing_block_size.width -
+ css_left.calc_percent(containing_block_size.width) -
+ css_right.calc_percent(containing_block_size.width) -
+ (el->content_offset_left() + el->content_offset_right());
+ need_render = true;
+ }
+ }
+
+ if(!css_top.is_predefined() || !css_bottom.is_predefined())
+ {
+ if(!css_top.is_predefined() && css_bottom.is_predefined())
+ {
+ el->m_pos.y = css_top.calc_percent(containing_block_size.height) + el->content_offset_top();
+ } else if(css_top.is_predefined() && !css_bottom.is_predefined())
+ {
+ el->m_pos.y = containing_block_size.height - css_bottom.calc_percent(containing_block_size.height) - el->m_pos.height -
+ el->content_offset_bottom();
+ } else
+ {
+ el->m_pos.y = css_top.calc_percent(containing_block_size.height) + el->content_offset_top();
+ el->m_pos.height = containing_block_size.height -
+ css_top.calc_percent(containing_block_size.height) -
+ css_bottom.calc_percent(containing_block_size.height) -
+ (el->content_offset_top() + el->content_offset_bottom());
+ need_render = true;
+ }
+ }
+ } else
+ {
+ if(!css_left.is_predefined() || !css_right.is_predefined())
+ {
+ if(!css_left.is_predefined() && css_right.is_predefined())
+ {
+ el->m_pos.x = css_left.calc_percent(containing_block_size.height) + el->content_offset_left() - m_padding.left;
+ } else if(css_left.is_predefined() && !css_right.is_predefined())
+ {
+ el->m_pos.x = m_pos.width + m_padding.right - css_right.calc_percent(containing_block_size.height) - el->m_pos.width -
+ el->content_offset_right();
+ } else
+ {
+ el->m_pos.x = css_left.calc_percent(containing_block_size.height) + el->content_offset_left() - m_padding.left;
+ el->m_pos.width = m_pos.width + m_padding.left + m_padding.right -
+ css_left.calc_percent(containing_block_size.height) -
+ css_right.calc_percent(containing_block_size.height) -
+ (el->content_offset_left() + el->content_offset_right());
+ if (new_width != -1)
+ {
+ el->m_pos.x += (el->m_pos.width - new_width) / 2;
+ el->m_pos.width = new_width;
+ }
+ need_render = true;
+ }
+ cvt_x = true;
+ }
+
+ if(!css_top.is_predefined() || !css_bottom.is_predefined())
+ {
+ if(!css_top.is_predefined() && css_bottom.is_predefined())
+ {
+ el->m_pos.y = css_top.calc_percent(containing_block_size.height) + el->content_offset_top() - m_padding.top;
+ } else if(css_top.is_predefined() && !css_bottom.is_predefined())
+ {
+ el->m_pos.y = m_pos.height + m_padding.bottom - css_bottom.calc_percent(containing_block_size.height) - el->m_pos.height -
+ el->content_offset_bottom();
+ } else
+ {
+ el->m_pos.y = css_top.calc_percent(containing_block_size.height) + el->content_offset_top() - m_padding.top;
+ el->m_pos.height = m_pos.height + m_padding.top + m_padding.bottom -
+ css_top.calc_percent(containing_block_size.height) -
+ css_bottom.calc_percent(containing_block_size.height) -
+ (el->content_offset_top() + el->content_offset_bottom());
+ if (new_height != -1)
+ {
+ el->m_pos.y += (el->m_pos.height - new_height) / 2;
+ el->m_pos.height = new_height;
+ }
+ need_render = true;
+ }
+ cvt_y = true;
+ }
+ }
+
+ if(cvt_x || cvt_y)
+ {
+ int offset_x = 0;
+ int offset_y = 0;
+ auto cur_el = el->parent();
+ auto this_el = shared_from_this();
+ while(cur_el && cur_el != this_el)
+ {
+ offset_x += cur_el->m_pos.x;
+ offset_y += cur_el->m_pos.y;
+ cur_el = cur_el->parent();
+ }
+ if(cvt_x) el->m_pos.x -= offset_x;
+ if(cvt_y) el->m_pos.y -= offset_y;
+ }
+
+ if(need_render)
+ {
+ position pos = el->m_pos;
+ el->render(el->left(), el->top(), containing_block_size.new_width(el->width()), true);
+ el->m_pos = pos;
+ }
+
+ if(el_position == element_position_fixed)
+ {
+ position fixed_pos;
+ el->get_redraw_box(fixed_pos);
+ src_el()->get_document()->add_fixed_box(fixed_pos);
+ }
+ }
+
+ el->render_positioned();
+ }
+
+ if(!m_positioned.empty())
+ {
+ std::stable_sort(m_positioned.begin(), m_positioned.end(), [](const std::shared_ptr<render_item>& Left, const std::shared_ptr<render_item>& Right)
+ {
+ return (Left->src_el()->css().get_z_index() < Right->src_el()->css().get_z_index());
+ });
+ }
+}
+
+void litehtml::render_item::add_positioned(const std::shared_ptr<litehtml::render_item> &el)
+{
+ if (src_el()->css().get_position() != element_position_static || is_root())
+ {
+ m_positioned.push_back(el);
+ } else
+ {
+ auto el_parent = parent();
+ if (el_parent)
+ {
+ el_parent->add_positioned(el);
+ }
+ }
+}
+
+void litehtml::render_item::get_redraw_box(litehtml::position& pos, int x /*= 0*/, int y /*= 0*/)
+{
+ if(is_visible())
+ {
+ int p_left = std::min(pos.left(), x + m_pos.left() - m_padding.left - m_borders.left);
+ int p_right = std::max(pos.right(), x + m_pos.right() + m_padding.left + m_borders.left);
+ int p_top = std::min(pos.top(), y + m_pos.top() - m_padding.top - m_borders.top);
+ int p_bottom = std::max(pos.bottom(), y + m_pos.bottom() + m_padding.bottom + m_borders.bottom);
+
+ pos.x = p_left;
+ pos.y = p_top;
+ pos.width = p_right - p_left;
+ pos.height = p_bottom - p_top;
+
+ if(src_el()->css().get_overflow() == overflow_visible)
+ {
+ for(auto& el : m_children)
+ {
+ if(el->src_el()->css().get_position() != element_position_fixed)
+ {
+ el->get_redraw_box(pos, x + m_pos.x, y + m_pos.y);
+ }
+ }
+ }
+ }
+}
+
+void litehtml::render_item::calc_document_size( litehtml::size& sz, litehtml::size& content_size, int x /*= 0*/, int y /*= 0*/ )
+{
+ if(is_visible() && src_el()->css().get_position() != element_position_fixed)
+ {
+ sz.width = std::max(sz.width, x + right());
+ sz.height = std::max(sz.height, y + bottom());
+
+ if(!src_el()->is_root() && !src_el()->is_body())
+ {
+ content_size.width = std::max(content_size.width, x + right());
+ content_size.height = std::max(content_size.height, y + bottom());
+ }
+
+ // All children of tables and blocks with style other than "overflow: visible" are inside element.
+ // We can skip calculating size of children
+ if(src_el()->css().get_overflow() == overflow_visible && src_el()->css().get_display() != display_table)
+ {
+ for(auto& el : m_children)
+ {
+ el->calc_document_size(sz, content_size, x + m_pos.x, y + m_pos.y);
+ }
+ }
+
+ if(src_el()->is_root() || src_el()->is_body())
+ {
+ content_size.width += content_offset_right();
+ content_size.height += content_offset_bottom();
+ }
+ }
+}
+
+void litehtml::render_item::draw_stacking_context( uint_ptr hdc, int x, int y, const position* clip, bool with_positioned )
+{
+ if(!is_visible()) return;
+
+ std::map<int, bool> z_indexes;
+ if(with_positioned)
+ {
+ for(const auto& idx : m_positioned)
+ {
+ z_indexes[idx->src_el()->css().get_z_index()];
+ }
+
+ for(const auto& idx : z_indexes)
+ {
+ if(idx.first < 0)
+ {
+ draw_children(hdc, x, y, clip, draw_positioned, idx.first);
+ }
+ }
+ }
+ draw_children(hdc, x, y, clip, draw_block, 0);
+ draw_children(hdc, x, y, clip, draw_floats, 0);
+ draw_children(hdc, x, y, clip, draw_inlines, 0);
+ if(with_positioned)
+ {
+ for(auto& z_index : z_indexes)
+ {
+ if(z_index.first == 0)
+ {
+ draw_children(hdc, x, y, clip, draw_positioned, z_index.first);
+ }
+ }
+
+ for(auto& z_index : z_indexes)
+ {
+ if(z_index.first > 0)
+ {
+ draw_children(hdc, x, y, clip, draw_positioned, z_index.first);
+ }
+ }
+ }
+}
+
+void litehtml::render_item::draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex)
+{
+ position pos = m_pos;
+ pos.x += x;
+ pos.y += y;
+
+ document::ptr doc = src_el()->get_document();
+
+ if (src_el()->css().get_overflow() > overflow_visible)
+ {
+ // TODO: Process overflow for inline elements
+ if(src_el()->css().get_display() != display_inline)
+ {
+ position border_box = pos;
+ border_box += m_padding;
+ border_box += m_borders;
+
+ border_radiuses bdr_radius = src_el()->css().get_borders().radius.calc_percents(border_box.width,
+ border_box.height);
+
+ bdr_radius -= m_borders;
+ bdr_radius -= m_padding;
+
+ doc->container()->set_clip(pos, bdr_radius);
+ }
+ }
+
+ for (const auto& el : m_children)
+ {
+ if (el->is_visible())
+ {
+ bool process = true;
+ switch (flag)
+ {
+ case draw_positioned:
+ if (el->src_el()->is_positioned() && el->src_el()->css().get_z_index() == zindex)
+ {
+ if (el->src_el()->css().get_position() == element_position_fixed)
+ {
+ position browser_wnd;
+ doc->container()->get_client_rect(browser_wnd);
+
+ el->src_el()->draw(hdc, browser_wnd.x, browser_wnd.y, clip, el);
+ el->draw_stacking_context(hdc, browser_wnd.x, browser_wnd.y, clip, true);
+ }
+ else
+ {
+ el->src_el()->draw(hdc, pos.x, pos.y, clip, el);
+ el->draw_stacking_context(hdc, pos.x, pos.y, clip, true);
+ }
+ process = false;
+ }
+ break;
+ case draw_block:
+ if (!el->src_el()->is_inline_box() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned())
+ {
+ el->src_el()->draw(hdc, pos.x, pos.y, clip, el);
+ }
+ break;
+ case draw_floats:
+ if (el->src_el()->css().get_float() != float_none && !el->src_el()->is_positioned())
+ {
+ el->src_el()->draw(hdc, pos.x, pos.y, clip, el);
+ el->draw_stacking_context(hdc, pos.x, pos.y, clip, false);
+ process = false;
+ }
+ break;
+ case draw_inlines:
+ if (el->src_el()->is_inline_box() && 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)
+ {
+ el->draw_stacking_context(hdc, pos.x, pos.y, clip, false);
+ process = false;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (process)
+ {
+ if (flag == draw_positioned)
+ {
+ if (!el->src_el()->is_positioned())
+ {
+ el->draw_children(hdc, pos.x, pos.y, clip, flag, zindex);
+ }
+ }
+ else
+ {
+ if (el->src_el()->css().get_float() == float_none &&
+ el->src_el()->css().get_display() != display_inline_block &&
+ !el->src_el()->is_positioned())
+ {
+ el->draw_children(hdc, pos.x, pos.y, clip, flag, zindex);
+ }
+ }
+ }
+ }
+ }
+
+ if (src_el()->css().get_overflow() > overflow_visible)
+ {
+ doc->container()->del_clip();
+ }
+}
+
+std::shared_ptr<litehtml::element> litehtml::render_item::get_child_by_point(int x, int y, int client_x, int client_y, draw_flag flag, int zindex)
+{
+ element::ptr ret = nullptr;
+
+ if(src_el()->css().get_overflow() > overflow_visible)
+ {
+ if(!m_pos.is_point_inside(x, y))
+ {
+ return ret;
+ }
+ }
+
+ position el_pos = m_pos;
+ el_pos.x = x - el_pos.x;
+ el_pos.y = y - el_pos.y;
+
+ for(auto i = m_children.rbegin(); i != m_children.rend() && !ret; std::advance(i, 1))
+ {
+ auto el = (*i);
+
+ if(el->is_visible() && el->src_el()->css().get_display() != display_inline_text)
+ {
+ switch(flag)
+ {
+ case draw_positioned:
+ if(el->src_el()->is_positioned() && el->src_el()->css().get_z_index() == zindex)
+ {
+ if(el->src_el()->css().get_position() == element_position_fixed)
+ {
+ ret = el->get_element_by_point(client_x, client_y, client_x, client_y);
+ if(!ret && (*i)->is_point_inside(client_x, client_y))
+ {
+ ret = (*i)->src_el();
+ }
+ } else
+ {
+ ret = el->get_element_by_point(el_pos.x, el_pos.y, client_x, client_y);
+ if(!ret && (*i)->is_point_inside(el_pos.x, el_pos.y))
+ {
+ ret = (*i)->src_el();
+ }
+ }
+ el = nullptr;
+ }
+ 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->is_point_inside(el_pos.x, el_pos.y))
+ {
+ ret = el->src_el();
+ }
+ }
+ break;
+ case draw_floats:
+ if(el->src_el()->css().get_float() != float_none && !el->src_el()->is_positioned())
+ {
+ ret = el->get_element_by_point(el_pos.x, el_pos.y, client_x, client_y);
+
+ if(!ret && (*i)->is_point_inside(el_pos.x, el_pos.y))
+ {
+ ret = (*i)->src_el();
+ }
+ el = nullptr;
+ }
+ 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()->css().get_display() == display_inline_block ||
+ el->src_el()->css().get_display() == display_inline_table ||
+ el->src_el()->css().get_display() == display_inline_flex)
+ {
+ ret = el->get_element_by_point(el_pos.x, el_pos.y, client_x, client_y);
+ el = nullptr;
+ }
+ if(!ret && (*i)->is_point_inside(el_pos.x, el_pos.y))
+ {
+ ret = (*i)->src_el();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if(el && !el->src_el()->is_positioned())
+ {
+ if(flag == draw_positioned)
+ {
+ element::ptr child = el->get_child_by_point(el_pos.x, el_pos.y, client_x, client_y, flag, zindex);
+ if(child)
+ {
+ ret = child;
+ }
+ } else
+ {
+ if( el->src_el()->css().get_float() == float_none &&
+ el->src_el()->css().get_display() != display_inline_block)
+ {
+ element::ptr child = el->get_child_by_point(el_pos.x, el_pos.y, client_x, client_y, flag, zindex);
+ if(child)
+ {
+ ret = child;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+std::shared_ptr<litehtml::element> litehtml::render_item::get_element_by_point(int x, int y, int client_x, int client_y)
+{
+ if(!is_visible()) return nullptr;
+
+ element::ptr ret;
+
+ std::map<int, bool> z_indexes;
+
+ for(const auto& i : m_positioned)
+ {
+ z_indexes[i->src_el()->css().get_z_index()];
+ }
+
+ for(const auto& zindex : z_indexes)
+ {
+ if(zindex.first > 0)
+ {
+ ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, zindex.first);
+ break;
+ }
+ }
+ if(ret) return ret;
+
+ for(const auto& z_index : z_indexes)
+ {
+ if(z_index.first == 0)
+ {
+ ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, z_index.first);
+ break;
+ }
+ }
+ if(ret) return ret;
+
+ ret = get_child_by_point(x, y, client_x, client_y, draw_inlines, 0);
+ if(ret) return ret;
+
+ ret = get_child_by_point(x, y, client_x, client_y, draw_floats, 0);
+ if(ret) return ret;
+
+ ret = get_child_by_point(x, y, client_x, client_y, draw_block, 0);
+ if(ret) return ret;
+
+
+ for(const auto& z_index : z_indexes)
+ {
+ if(z_index.first < 0)
+ {
+ ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, z_index.first);
+ break;
+ }
+ }
+ if(ret) return ret;
+
+ if(src_el()->css().get_position() == element_position_fixed)
+ {
+ if(is_point_inside(client_x, client_y))
+ {
+ ret = src_el();
+ }
+ } else
+ {
+ if(is_point_inside(x, y))
+ {
+ ret = src_el();
+ }
+ }
+
+ return ret;
+}
+
+bool litehtml::render_item::is_point_inside( int x, int y )
+{
+ if(src_el()->css().get_display() != display_inline && src_el()->css().get_display() != display_table_row)
+ {
+ position pos = m_pos;
+ pos += m_padding;
+ pos += m_borders;
+ if(pos.is_point_inside(x, y))
+ {
+ return true;
+ } else
+ {
+ return false;
+ }
+ } else
+ {
+ position::vector boxes;
+ get_inline_boxes(boxes);
+ for(auto & box : boxes)
+ {
+ if(box.is_point_inside(x, y))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void litehtml::render_item::get_rendering_boxes( position::vector& redraw_boxes)
+{
+ if(src_el()->css().get_display() == display_inline || src_el()->css().get_display() == display_table_row)
+ {
+ get_inline_boxes(redraw_boxes);
+ } else
+ {
+ position pos = m_pos;
+ pos += m_padding;
+ pos += m_borders;
+ redraw_boxes.push_back(pos);
+ }
+
+ if(src_el()->css().get_position() != element_position_fixed)
+ {
+ auto cur_el = parent();
+ while(cur_el)
+ {
+ for(auto& box : redraw_boxes)
+ {
+ box.x += cur_el->m_pos.x;
+ box.y += cur_el->m_pos.y;
+ }
+ cur_el = cur_el->parent();
+ }
+ }
+}
+
+void litehtml::render_item::dump(litehtml::dumper& cout)
+{
+ cout.begin_node(src_el()->dump_get_name() + "{" + string(typeid(*this).name()) + "}");
+
+ auto attrs = src_el()->dump_get_attrs();
+ if(!attrs.empty())
+ {
+ cout.begin_attrs_group("attributes");
+ for (const auto &attr: attrs)
+ {
+ cout.add_attr(std::get<0>(attr), std::get<1>(attr));
+ }
+ cout.end_attrs_group();
+ }
+
+ if(!m_children.empty())
+ {
+ cout.begin_attrs_group("children");
+ for (const auto &el: m_children)
+ {
+ el->dump(cout);
+ }
+ cout.end_attrs_group();
+ }
+
+ cout.end_node();
+}
+
+litehtml::position litehtml::render_item::get_placement() const
+{
+ litehtml::position pos = m_pos;
+ auto cur_el = parent();
+ while(cur_el)
+ {
+ pos.x += cur_el->m_pos.x;
+ pos.y += cur_el->m_pos.y;
+ cur_el = cur_el->parent();
+ }
+ return pos;
+}
+
+std::shared_ptr<litehtml::render_item> litehtml::render_item::init()
+{
+ src_el()->add_render(shared_from_this());
+
+ for(auto& el : children())
+ {
+ el = el->init();
+ }
+
+ return shared_from_this();
+}
+
+void litehtml::render_item::calc_cb_length(const css_length& len, int percent_base, containing_block_context::typed_int& out_value) const
+{
+ if (!len.is_predefined())
+ {
+ if(len.units() == litehtml::css_units_percentage)
+ {
+ out_value.value = len.calc_percent(percent_base);
+ out_value.type = litehtml::containing_block_context::cbc_value_type_percentage;
+ } else
+ {
+ out_value.value = src_el()->get_document()->to_pixels(len, src_el()->css().get_font_size());
+ out_value.type = containing_block_context::cbc_value_type_absolute;
+ }
+ }
+}
+
+litehtml::containing_block_context litehtml::render_item::calculate_containing_block_context(const containing_block_context& cb_context)
+{
+ containing_block_context ret;
+ ret.context_idx = cb_context.context_idx + 1;
+ ret.width.value = ret.max_width.value = cb_context.width.value - content_offset_width();
+ if(src_el()->css().get_position() != element_position_absolute && src_el()->css().get_position() != element_position_fixed)
+ {
+ ret.height.value = cb_context.height.value - content_offset_height();
+ }
+
+ // Calculate width if css property is not auto
+ // We have to use aut value for display_table_cell also.
+ if (src_el()->css().get_display() != display_table_cell)
+ {
+ calc_cb_length(src_el()->css().get_width(), cb_context.width, ret.width);
+ calc_cb_length(src_el()->css().get_height(), cb_context.height, ret.height);
+ if (ret.width.type != containing_block_context::cbc_value_type_auto && (src_el()->css().get_display() == display_table || src_el()->is_root()))
+ {
+ ret.width.value -= content_offset_width();
+ }
+ if (ret.height.type != containing_block_context::cbc_value_type_auto && (src_el()->css().get_display() == display_table || src_el()->is_root()))
+ {
+ ret.height.value -= content_offset_height();
+ }
+ }
+ ret.render_width = ret.width;
+
+ calc_cb_length(src_el()->css().get_min_width(), cb_context.width, ret.min_width);
+ calc_cb_length(src_el()->css().get_max_width(), cb_context.width, ret.max_width);
+
+ calc_cb_length(src_el()->css().get_min_height(), cb_context.height, ret.min_height);
+ calc_cb_length(src_el()->css().get_max_height(), cb_context.height, ret.max_height);
+
+ if (src_el()->css().get_box_sizing() == box_sizing_border_box)
+ {
+ if(ret.width.type != containing_block_context::cbc_value_type_auto)
+ {
+ ret.render_width = ret.width - box_sizing_width();
+ }
+ if(ret.min_width.type != containing_block_context::cbc_value_type_none)
+ {
+ ret.min_width.value -= box_sizing_width();
+ }
+ if(ret.max_width.type != containing_block_context::cbc_value_type_none)
+ {
+ ret.max_width.value -= box_sizing_width();
+ }
+ if(ret.min_height.type != containing_block_context::cbc_value_type_none)
+ {
+ ret.min_height.value -= box_sizing_height();
+ }
+ if(ret.max_height.type != containing_block_context::cbc_value_type_none)
+ {
+ ret.max_height.value -= box_sizing_height();
+ }
+ }
+ 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
new file mode 100644
index 000000000..f3575778f
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_item.h
@@ -0,0 +1,599 @@
+#ifndef LH_RENDER_ITEM_H
+#define LH_RENDER_ITEM_H
+
+#include <memory>
+#include <utility>
+#include <list>
+#include <tuple>
+#include "types.h"
+#include "line_box.h"
+#include "table.h"
+
+namespace litehtml
+{
+ class element;
+
+ class render_item : public std::enable_shared_from_this<render_item>
+ {
+ protected:
+ std::shared_ptr<element> m_element;
+ std::weak_ptr<render_item> m_parent;
+ std::list<std::shared_ptr<render_item>> m_children;
+ margins m_margins;
+ margins m_padding;
+ margins m_borders;
+ position m_pos;
+ bool m_skip;
+ std::vector<std::shared_ptr<render_item>> m_positioned;
+
+ 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;
+
+ public:
+ explicit render_item(std::shared_ptr<element> src_el);
+
+ virtual ~render_item() = default;
+
+ std::list<std::shared_ptr<render_item>>& children()
+ {
+ return m_children;
+ }
+
+ position& pos()
+ {
+ return m_pos;
+ }
+
+ bool skip() const
+ {
+ return m_skip;
+ }
+
+ void skip(bool val)
+ {
+ m_skip = val;
+ }
+
+ int right() const
+ {
+ return left() + width();
+ }
+
+ int left() const
+ {
+ return m_pos.left() - m_margins.left - m_padding.left - m_borders.left;
+ }
+
+ int top() const
+ {
+ return m_pos.top() - m_margins.top - m_padding.top - m_borders.top;
+ }
+
+ int bottom() const
+ {
+ return top() + height();
+ }
+
+ int height() const
+ {
+ return m_pos.height + m_margins.height() + m_padding.height() + m_borders.height();
+ }
+
+ int width() const
+ {
+ return m_pos.width + m_margins.left + m_margins.right + m_padding.width() + m_borders.width();
+ }
+
+ int padding_top() const
+ {
+ return m_padding.top;
+ }
+
+ int padding_bottom() const
+ {
+ return m_padding.bottom;
+ }
+
+ int padding_left() const
+ {
+ return m_padding.left;
+ }
+
+ int padding_right() const
+ {
+ return m_padding.right;
+ }
+
+ int border_top() const
+ {
+ return m_borders.top;
+ }
+
+ int border_bottom() const
+ {
+ return m_borders.bottom;
+ }
+
+ int border_left() const
+ {
+ return m_borders.left;
+ }
+
+ int border_right() const
+ {
+ return m_borders.right;
+ }
+
+ int margin_top() const
+ {
+ return m_margins.top;
+ }
+
+ int margin_bottom() const
+ {
+ return m_margins.bottom;
+ }
+
+ int margin_left() const
+ {
+ return m_margins.left;
+ }
+
+ int margin_right() const
+ {
+ return m_margins.right;
+ }
+
+ std::shared_ptr<render_item> parent() const
+ {
+ return m_parent.lock();
+ }
+
+ margins& get_margins()
+ {
+ return m_margins;
+ }
+
+ margins& get_paddings()
+ {
+ return m_padding;
+ }
+
+ void set_paddings(const margins& val)
+ {
+ m_padding = val;
+ }
+
+ margins& get_borders()
+ {
+ return m_borders;
+ }
+
+ /**
+ * Top offset to the element content. Includes paddings, margins and borders.
+ */
+ int content_offset_top() const
+ {
+ return m_margins.top + m_padding.top + m_borders.top;
+ }
+
+ /**
+ * Bottom offset to the element content. Includes paddings, margins and borders.
+ */
+ inline int content_offset_bottom() const
+ {
+ return m_margins.bottom + m_padding.bottom + m_borders.bottom;
+ }
+
+ /**
+ * Left offset to the element content. Includes paddings, margins and borders.
+ */
+ int content_offset_left() const
+ {
+ return m_margins.left + m_padding.left + m_borders.left;
+ }
+
+ /**
+ * Right offset to the element content. Includes paddings, margins and borders.
+ */
+ int content_offset_right() const
+ {
+ return m_margins.right + m_padding.right + m_borders.right;
+ }
+
+ /**
+ * Sum of left and right offsets to the element content. Includes paddings, margins and borders.
+ */
+ int content_offset_width() const
+ {
+ return content_offset_left() + content_offset_right();
+ }
+
+ /**
+ * Sum of top and bottom offsets to the element content. Includes paddings, margins and borders.
+ */
+ int content_offset_height() const
+ {
+ return content_offset_top() + content_offset_bottom();
+ }
+
+ int box_sizing_left() const
+ {
+ return m_padding.left + m_borders.left;
+ }
+
+ int box_sizing_right() const
+ {
+ return m_padding.right + m_borders.right;
+ }
+
+ int box_sizing_width() const
+ {
+ return box_sizing_left() + box_sizing_left();
+ }
+
+ int box_sizing_top() const
+ {
+ return m_padding.top + m_borders.top;
+ }
+
+ int box_sizing_bottom() const
+ {
+ return m_padding.bottom + m_borders.bottom;
+ }
+
+ int box_sizing_height() const
+ {
+ return box_sizing_top() + box_sizing_bottom();
+ }
+
+ void parent(const std::shared_ptr<render_item>& par)
+ {
+ m_parent = par;
+ }
+
+ const std::shared_ptr<element>& src_el() const
+ {
+ return m_element;
+ }
+
+ const css_properties& css() const
+ {
+ return m_element->css();
+ }
+
+ void add_child(const std::shared_ptr<render_item>& ri)
+ {
+ m_children.push_back(ri);
+ 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();
+ }
+
+ bool collapse_top_margin() const
+ {
+ return !m_borders.top &&
+ !m_padding.top &&
+ m_element->in_normal_flow() &&
+ m_element->css().get_float() == float_none &&
+ m_margins.top >= 0 &&
+ !is_root();
+ }
+
+ bool collapse_bottom_margin() const
+ {
+ return !m_borders.bottom &&
+ !m_padding.bottom &&
+ m_element->in_normal_flow() &&
+ m_element->css().get_float() == float_none &&
+ m_margins.bottom >= 0 &&
+ !is_root();
+ }
+
+ bool is_visible() const
+ {
+ return !(m_skip || src_el()->css().get_display() == display_none || src_el()->css().get_visibility() != visibility_visible);
+ }
+
+ 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);
+ void calc_outlines( int parent_width );
+ int calc_auto_margins(int parent_width); // returns left margin
+
+ virtual std::shared_ptr<render_item> init();
+ virtual void apply_vertical_align() {}
+ virtual int get_base_line() { return 0; }
+ virtual std::shared_ptr<render_item> clone()
+ {
+ return std::make_shared<render_item>(src_el());
+ }
+ std::tuple<
+ std::shared_ptr<litehtml::render_item>,
+ std::shared_ptr<litehtml::render_item>,
+ std::shared_ptr<litehtml::render_item>
+ > split_inlines();
+ bool fetch_positioned();
+ void render_positioned(render_type rt = render_all);
+ void add_positioned(const std::shared_ptr<litehtml::render_item> &el);
+ void get_redraw_box(litehtml::position& pos, int x = 0, int y = 0);
+ void calc_document_size( litehtml::size& sz, litehtml::size& content_size, int x = 0, int y = 0 );
+ virtual void get_inline_boxes( position::vector& boxes ) const {};
+ virtual void set_inline_boxes( position::vector& boxes ) {};
+ virtual void add_inline_box( const position& box ) {};
+ virtual void clear_inline_boxes() {};
+ void draw_stacking_context( uint_ptr hdc, int x, int y, const position* clip, bool with_positioned );
+ virtual void draw_children( uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex );
+ virtual int get_draw_vertical_offset() { return 0; }
+ virtual std::shared_ptr<element> get_child_by_point(int x, int y, int client_x, int client_y, draw_flag flag, int zindex);
+ std::shared_ptr<element> get_element_by_point(int x, int y, int client_x, int client_y);
+ bool is_point_inside( int x, int y );
+ void dump(litehtml::dumper& cout);
+ position get_placement() const;
+ /**
+ * Returns the boxes of rendering element. All coordinates are absolute
+ *
+ * @param redraw_boxes [out] resulting rendering boxes
+ * @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
new file mode 100644
index 000000000..2ec048a98
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/render_table.cpp
@@ -0,0 +1,482 @@
+#include "html.h"
+#include "render_item.h"
+#include "document.h"
+#include "iterators.h"
+
+
+litehtml::render_item_table::render_item_table(std::shared_ptr<element> _src_el) :
+ render_item(std::move(_src_el)),
+ m_border_spacing_x(0),
+ m_border_spacing_y(0)
+{
+}
+
+int litehtml::render_item_table::render(int x, int y, const containing_block_context &containing_block_size, 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)
+ {
+ table_width_spacing = m_border_spacing_x * (m_grid->cols_count() + 1);
+ }
+ else
+ {
+ table_width_spacing = 0;
+
+ if (m_grid->cols_count())
+ {
+ table_width_spacing -= std::min(border_left(), m_grid->column(0).border_left);
+ table_width_spacing -= std::min(border_right(), m_grid->column(m_grid->cols_count() - 1).border_right);
+ }
+
+ for (int col = 1; col < m_grid->cols_count(); col++)
+ {
+ table_width_spacing -= std::min(m_grid->column(col).border_left, m_grid->column(col - 1).border_right);
+ }
+ }
+
+
+ // Calculate the minimum content width (MCW) of each cell: the formatted content may span any number of lines but may not overflow the cell box.
+ // If the specified 'width' (W) of the cell is greater than MCW, W is the minimum cell width. A value of 'auto' means that MCW is the minimum
+ // cell width.
+ //
+ // Also, calculate the "maximum" cell width of each cell: formatting the content without breaking lines other than where explicit line breaks occur.
+
+ if (m_grid->cols_count() == 1 && self_size.width.type != containing_block_context::cbc_value_type_auto)
+ {
+ for (int row = 0; row < m_grid->rows_count(); row++)
+ {
+ 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->el->pos().width = cell->min_width - cell->el->content_offset_left() -
+ cell->el->content_offset_right();
+ }
+ }
+ }
+ else
+ {
+ for (int row = 0; row < m_grid->rows_count(); row++)
+ {
+ for (int col = 0; col < m_grid->cols_count(); col++)
+ {
+ table_cell* cell = m_grid->cell(col, row);
+ if (cell && cell->el)
+ {
+ 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));
+ 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();
+ }
+ else
+ {
+ // calculate minimum content width
+ cell->min_width = cell->el->render(0, 0, self_size.new_width(cell->el->content_offset_width()));
+ // calculate maximum content width
+ cell->max_width = cell->el->render(0, 0, self_size.new_width(self_size.render_width - table_width_spacing));
+ }
+ }
+ }
+ }
+ }
+
+ // For each column, determine a maximum and minimum column width from the cells that span only that column.
+ // The minimum is that required by the cell with the largest minimum cell width (or the column 'width', whichever is larger).
+ // The maximum is that required by the cell with the largest maximum cell width (or the column 'width', whichever is larger).
+
+ for (int col = 0; col < m_grid->cols_count(); col++)
+ {
+ m_grid->column(col).max_width = 0;
+ m_grid->column(col).min_width = 0;
+ for (int row = 0; row < m_grid->rows_count(); row++)
+ {
+ if (m_grid->cell(col, row)->colspan <= 1)
+ {
+ m_grid->column(col).max_width = std::max(m_grid->column(col).max_width, m_grid->cell(col, row)->max_width);
+ m_grid->column(col).min_width = std::max(m_grid->column(col).min_width, m_grid->cell(col, row)->min_width);
+ }
+ }
+ }
+
+ // For each cell that spans more than one column, increase the minimum widths of the columns it spans so that together,
+ // they are at least as wide as the cell. Do the same for the maximum widths.
+ // If possible, widen all spanned columns by approximately the same amount.
+
+ for (int col = 0; col < m_grid->cols_count(); col++)
+ {
+ for (int row = 0; row < m_grid->rows_count(); row++)
+ {
+ if (m_grid->cell(col, row)->colspan > 1)
+ {
+ int max_total_width = m_grid->column(col).max_width;
+ int min_total_width = m_grid->column(col).min_width;
+ for (int col2 = col + 1; col2 < col + m_grid->cell(col, row)->colspan; col2++)
+ {
+ max_total_width += m_grid->column(col2).max_width;
+ min_total_width += m_grid->column(col2).min_width;
+ }
+ if (min_total_width < m_grid->cell(col, row)->min_width)
+ {
+ m_grid->distribute_min_width(m_grid->cell(col, row)->min_width - min_total_width, col, col + m_grid->cell(col, row)->colspan - 1);
+ }
+ if (max_total_width < m_grid->cell(col, row)->max_width)
+ {
+ m_grid->distribute_max_width(m_grid->cell(col, row)->max_width - max_total_width, col, col + m_grid->cell(col, row)->colspan - 1);
+ }
+ }
+ }
+ }
+
+ // If the 'table' or 'inline-table' element's 'width' property has a computed value (W) other than 'auto', the used width is the
+ // greater of W, CAPMIN, and the minimum width required by all the columns plus cell spacing or borders (MIN).
+ // If the used width is greater than MIN, the extra width should be distributed over the columns.
+ //
+ // If the 'table' or 'inline-table' element has 'width: auto', the used width is the greater of the table's containing block width,
+ // CAPMIN, and MIN. However, if either CAPMIN or the maximum width required by the columns plus cell spacing or borders (MAX) is
+ // less than that of the containing block, use max(MAX, CAPMIN).
+
+
+ int table_width = 0;
+ int min_table_width = 0;
+ int max_table_width = 0;
+
+ if (self_size.width.type == containing_block_context::cbc_value_type_absolute)
+ {
+ table_width = m_grid->calc_table_width(self_size.render_width - table_width_spacing, false, min_table_width, max_table_width);
+ }
+ else
+ {
+ table_width = m_grid->calc_table_width(self_size.render_width - table_width_spacing, self_size.width.type == containing_block_context::cbc_value_type_auto, min_table_width, max_table_width);
+ }
+
+ min_table_width += table_width_spacing;
+ max_table_width += table_width_spacing;
+ table_width += table_width_spacing;
+ m_grid->calc_horizontal_positions(m_borders, src_el()->css().get_border_collapse(), m_border_spacing_x);
+
+ bool row_span_found = false;
+
+ // render cells with computed width
+ for (int row = 0; row < m_grid->rows_count(); row++)
+ {
+ m_grid->row(row).height = 0;
+ for (int col = 0; col < m_grid->cols_count(); col++)
+ {
+ table_cell* cell = m_grid->cell(col, row);
+ if (cell->el)
+ {
+ int span_col = col + cell->colspan - 1;
+ if (span_col >= m_grid->cols_count())
+ {
+ span_col = m_grid->cols_count() - 1;
+ }
+ int cell_width = m_grid->column(span_col).right - m_grid->column(col).left;
+
+ //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->pos().width = cell_width - cell->el->content_offset_left() -
+ cell->el->content_offset_right();
+ }
+ /*else
+ {
+ cell->el->pos().x = m_grid->column(col).left + cell->el->content_offset_left();
+ }*/
+
+ if (cell->rowspan <= 1)
+ {
+ m_grid->row(row).height = std::max(m_grid->row(row).height, cell->el->height());
+ }
+ else
+ {
+ row_span_found = true;
+ }
+
+ }
+ }
+ }
+
+ if (row_span_found)
+ {
+ for (int col = 0; col < m_grid->cols_count(); col++)
+ {
+ for (int row = 0; row < m_grid->rows_count(); row++)
+ {
+ table_cell* cell = m_grid->cell(col, row);
+ if (cell->el)
+ {
+ int span_row = row + cell->rowspan - 1;
+ if (span_row >= m_grid->rows_count())
+ {
+ span_row = m_grid->rows_count() - 1;
+ }
+ if (span_row != row)
+ {
+ int h = 0;
+ for (int i = row; i <= span_row; i++)
+ {
+ h += m_grid->row(i).height;
+ }
+ if (h < cell->el->height())
+ {
+ m_grid->row(span_row).height += cell->el->height() - h;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Calculate vertical table spacing
+ int table_height_spacing = 0;
+ if (src_el()->css().get_border_collapse() == border_collapse_separate)
+ {
+ table_height_spacing = m_border_spacing_y * (m_grid->rows_count() + 1);
+ }
+ else
+ {
+ table_height_spacing = 0;
+
+ if (m_grid->rows_count())
+ {
+ table_height_spacing -= std::min(border_top(), m_grid->row(0).border_top);
+ table_height_spacing -= std::min(border_bottom(), m_grid->row(m_grid->rows_count() - 1).border_bottom);
+ }
+
+ for (int row = 1; row < m_grid->rows_count(); row++)
+ {
+ table_height_spacing -= std::min(m_grid->row(row).border_top, m_grid->row(row - 1).border_bottom);
+ }
+ }
+
+
+ // calculate block height
+ int block_height = 0;
+ if (get_predefined_height(block_height, containing_block_size.height))
+ {
+ block_height -= m_padding.height() + m_borders.height();
+ }
+
+ // calculate minimum height from m_css.get_min_height()
+ int min_height = 0;
+ if (!src_el()->css().get_min_height().is_predefined() && src_el()->css().get_min_height().units() == css_units_percentage)
+ {
+ min_height = src_el()->css().get_min_height().calc_percent(containing_block_size.height);
+ }
+ else
+ {
+ min_height = (int)src_el()->css().get_min_height().val();
+ }
+
+ int minimum_table_height = std::max(block_height, min_height);
+
+ m_grid->calc_rows_height(minimum_table_height - table_height_spacing, m_border_spacing_y);
+ m_grid->calc_vertical_positions(m_borders, src_el()->css().get_border_collapse(), m_border_spacing_y);
+
+ int table_height = 0;
+
+ // place cells vertically
+ for (int col = 0; col < m_grid->cols_count(); col++)
+ {
+ for (int row = 0; row < m_grid->rows_count(); row++)
+ {
+ table_cell* cell = m_grid->cell(col, row);
+ if (cell->el)
+ {
+ int span_row = row + cell->rowspan - 1;
+ if (span_row >= m_grid->rows_count())
+ {
+ span_row = m_grid->rows_count() - 1;
+ }
+ cell->el->pos().y = m_grid->row(row).top + cell->el->content_offset_top();
+ cell->el->pos().height = m_grid->row(span_row).bottom - m_grid->row(row).top -
+ cell->el->content_offset_top() -
+ cell->el->content_offset_bottom();
+ table_height = std::max(table_height, m_grid->row(span_row).bottom);
+ cell->el->apply_vertical_align();
+ }
+ }
+ }
+
+ if (src_el()->css().get_border_collapse() == border_collapse_collapse)
+ {
+ if (m_grid->rows_count())
+ {
+ table_height -= std::min(border_bottom(), m_grid->row(m_grid->rows_count() - 1).border_bottom);
+ }
+ }
+ else
+ {
+ table_height += m_border_spacing_y;
+ }
+
+ // 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();
+
+ 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 (captions_height)
+ {
+ // Add border height to get the top of cells
+ captions_height += border_top();
+
+ // Save caption height for draw_background
+ m_grid->captions_height(captions_height);
+
+ // 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;
+ 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;
+ }
+ }
+ }
+ }
+
+ m_pos.move_to(x + content_offset_left(), y + content_offset_top());
+ m_pos.width = table_width;
+ m_pos.height = table_height + captions_height;
+
+ if(self_size.width.type != containing_block_context::cbc_value_type_absolute)
+ {
+ return std::min(table_width, max_table_width) + content_offset_width();
+ }
+ return table_width + content_offset_width();
+}
+
+std::shared_ptr<litehtml::render_item> litehtml::render_item_table::init()
+{
+ // Initialize Grid
+ m_grid = std::unique_ptr<table_grid>(new table_grid());
+
+ go_inside_table table_selector;
+ table_rows_selector row_selector;
+ table_cells_selector cell_selector;
+
+ elements_iterator row_iter(false, &table_selector, &row_selector);
+
+ row_iter.process(shared_from_this(), [&](std::shared_ptr<render_item>& el, iterator_item_type item_type)
+ {
+ m_grid->begin_row(el);
+
+
+ elements_iterator cell_iter(true, &table_selector, &cell_selector);
+ cell_iter.process(el, [&](std::shared_ptr<render_item>& el, iterator_item_type item_type)
+ {
+ if(item_type != iterator_item_type_end_parent)
+ {
+ el = el->init();
+ m_grid->add_cell(el);
+ }
+ });
+ });
+
+ for (auto& el : m_children)
+ {
+ if (el->src_el()->css().get_display() == display_table_caption)
+ {
+ el = el->init();
+ m_grid->captions().push_back(el);
+ }
+ }
+
+ m_grid->finish();
+
+ if(src_el()->css().get_border_collapse() == border_collapse_separate)
+ {
+ int font_size = src_el()->css().get_font_size();
+ document::ptr doc = src_el()->get_document();
+ m_border_spacing_x = doc->to_pixels(src_el()->css().get_border_spacing_x(), font_size);
+ m_border_spacing_y = doc->to_pixels(src_el()->css().get_border_spacing_y(), font_size);
+ } else
+ {
+ m_border_spacing_x = 0;
+ m_border_spacing_y = 0;
+ }
+
+ src_el()->add_render(shared_from_this());
+
+ return shared_from_this();
+}
+
+void litehtml::render_item_table::draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex)
+{
+ if (!m_grid) return;
+
+ position pos = m_pos;
+ pos.x += x;
+ pos.y += y;
+ for (auto& caption : m_grid->captions())
+ {
+ if (flag == draw_block)
+ {
+ caption->src_el()->draw(hdc, pos.x, pos.y, clip, caption);
+ }
+ caption->draw_children(hdc, pos.x, pos.y, clip, flag, zindex);
+ }
+ for (int row = 0; row < m_grid->rows_count(); row++)
+ {
+ if (flag == draw_block)
+ {
+ m_grid->row(row).el_row->src_el()->draw_background(hdc, pos.x, pos.y, clip, m_grid->row(row).el_row);
+ }
+ for (int col = 0; col < m_grid->cols_count(); col++)
+ {
+ table_cell* cell = m_grid->cell(col, row);
+ if (cell->el)
+ {
+ if (flag == draw_block)
+ {
+ cell->el->src_el()->draw(hdc, pos.x, pos.y, clip, cell->el);
+ }
+ cell->el->draw_children(hdc, pos.x, pos.y, clip, flag, zindex);
+ }
+ }
+ }
+}
+
+int litehtml::render_item_table::get_draw_vertical_offset()
+{
+ if(m_grid)
+ {
+ return m_grid->captions_height();
+ }
+ return 0;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/string_id.cpp b/src/plugins/litehtml_viewer/litehtml/string_id.cpp
new file mode 100644
index 000000000..9f8390303
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/string_id.cpp
@@ -0,0 +1,54 @@
+#include "html.h"
+#include "string_id.h"
+#include <assert.h>
+
+#ifndef LITEHTML_NO_THREADS
+ #include <mutex>
+ static std::mutex mutex;
+ #define lock_guard std::lock_guard<std::mutex> lock(mutex)
+#else
+ #define lock_guard
+#endif
+
+namespace litehtml
+{
+
+static std::map<string, string_id> map;
+static std::vector<string> array;
+
+static int init()
+{
+ string_vector names;
+ split_string(initial_string_ids, names, ",");
+ for (auto& name : names)
+ {
+ trim(name);
+ assert(name[0] == '_' && name.back() == '_');
+ name = name.substr(1, name.size() - 2); // _border_color_ -> border_color
+ std::replace(name.begin(), name.end(), '_', '-'); // border_color -> border-color
+ _id(name); // this will create association _border_color_ <-> "border-color"
+ }
+ return 0;
+}
+static int dummy = init();
+
+const string_id empty_id = _id("");
+const string_id star_id = _id("*");
+
+string_id _id(const string& str)
+{
+ lock_guard;
+ auto it = map.find(str);
+ if (it != map.end()) return it->second;
+ // else: str not found, add it to the array and the map
+ array.push_back(str);
+ return map[str] = (string_id)(array.size() - 1);
+}
+
+const string& _s(string_id id)
+{
+ lock_guard;
+ return array[id];
+}
+
+} // namespace litehtml
\ No newline at end of file
diff --git a/src/plugins/litehtml_viewer/litehtml/string_id.h b/src/plugins/litehtml_viewer/litehtml/string_id.h
new file mode 100644
index 000000000..340ac7fbc
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/string_id.h
@@ -0,0 +1,300 @@
+#ifndef LH_STRING_ID_H
+#define LH_STRING_ID_H
+
+namespace litehtml
+{
+
+#define STRING_ID(...)\
+ enum string_id { __VA_ARGS__ };\
+ const auto initial_string_ids = #__VA_ARGS__;
+
+STRING_ID(
+
+ // HTML tags
+ _a_,
+ _abbr_,
+ _acronym_,
+ _address_,
+ _applet_,
+ _area_,
+ _article_,
+ _aside_,
+ _audio_,
+ _b_,
+ _base_,
+ _basefont_,
+ _bdi_,
+ _bdo_,
+ _big_,
+ _blockquote_,
+ _body_,
+ _br_,
+ _button_,
+ _canvas_,
+ _caption_,
+ _center_,
+ _cite_,
+ _code_,
+ _col_,
+ _colgroup_,
+ _data_,
+ _datalist_,
+ _dd_,
+ _del_,
+ _details_,
+ _dfn_,
+ _dialog_,
+ _dir_,
+ _div_,
+ _dl_,
+ _dt_,
+ _em_,
+ _embed_,
+ _fieldset_,
+ _figcaption_,
+ _figure_,
+ _footer_,
+ _form_,
+ _frame_,
+ _frameset_,
+ _h1_,
+ _h2_,
+ _h3_,
+ _h4_,
+ _h5_,
+ _h6_,
+ _head_,
+ _header_,
+ _hr_,
+ _html_,
+ _i_,
+ _iframe_,
+ _img_,
+ _input_,
+ _ins_,
+ _kbd_,
+ _label_,
+ _legend_,
+ _li_,
+ _link_,
+ _main_,
+ _map_,
+ _mark_,
+ _meta_,
+ _meter_,
+ _nav_,
+ _noframes_,
+ _noscript_,
+ _object_,
+ _ol_,
+ _optgroup_,
+ _option_,
+ _output_,
+ _p_,
+ _param_,
+ _picture_,
+ _pre_,
+ _progress_,
+ _q_,
+ _rp_,
+ _rt_,
+ _ruby_,
+ _s_,
+ _samp_,
+ _script_,
+ _section_,
+ _select_,
+ _small_,
+ _source_,
+ _span_,
+ _strike_,
+ _strong_,
+ _style_,
+ _sub_,
+ _summary_,
+ _sup_,
+ _svg_,
+ _table_,
+ _tbody_,
+ _td_,
+ _template_,
+ _textarea_,
+ _tfoot_,
+ _th_,
+ _thead_,
+ _time_,
+ _title_,
+ _tr_,
+ _track_,
+ _tt_,
+ _u_,
+ _ul_,
+ _var_,
+ _video_,
+ _wbr_,
+
+ // litehtml internal tags
+ __tag_before_, // note: real tag cannot start with '-'
+ __tag_after_,
+
+ // CSS pseudo-elements
+ _before_,
+ _after_,
+
+ // CSS pseudo-classes
+ _root_,
+ _only_child_,
+ _only_of_type_,
+ _first_child_,
+ _first_of_type_,
+ _last_child_,
+ _last_of_type_,
+ _nth_child_,
+ _nth_of_type_,
+ _nth_last_child_,
+ _nth_last_of_type_,
+ _not_,
+ _lang_,
+
+ _active_,
+ _hover_,
+
+ // CSS property names
+ _background_,
+ _background_color_,
+ _background_image_,
+ _background_image_baseurl_,
+ _background_repeat_,
+ _background_origin_,
+ _background_clip_,
+ _background_attachment_,
+ _background_size_,
+ _background_position_,
+ _background_position_x_,
+ _background_position_y_,
+
+ _border_,
+ _border_width_,
+ _border_style_,
+ _border_color_,
+
+ _border_spacing_,
+ __litehtml_border_spacing_x_,
+ __litehtml_border_spacing_y_,
+
+ _border_left_,
+ _border_right_,
+ _border_top_,
+ _border_bottom_,
+
+ _border_left_style_,
+ _border_right_style_,
+ _border_top_style_,
+ _border_bottom_style_,
+
+ _border_left_width_,
+ _border_right_width_,
+ _border_top_width_,
+ _border_bottom_width_,
+
+ _border_left_color_,
+ _border_right_color_,
+ _border_top_color_,
+ _border_bottom_color_,
+
+ _border_radius_,
+ _border_radius_x_,
+ _border_radius_y_,
+
+ _border_bottom_left_radius_,
+ _border_bottom_left_radius_x_,
+ _border_bottom_left_radius_y_,
+
+ _border_bottom_right_radius_,
+ _border_bottom_right_radius_x_,
+ _border_bottom_right_radius_y_,
+
+ _border_top_left_radius_,
+ _border_top_left_radius_x_,
+ _border_top_left_radius_y_,
+
+ _border_top_right_radius_,
+ _border_top_right_radius_x_,
+ _border_top_right_radius_y_,
+
+ _list_style_,
+ _list_style_type_,
+ _list_style_position_,
+ _list_style_image_,
+ _list_style_image_baseurl_,
+
+ _margin_,
+ _margin_left_,
+ _margin_right_,
+ _margin_top_,
+ _margin_bottom_,
+ _padding_,
+ _padding_left_,
+ _padding_right_,
+ _padding_top_,
+ _padding_bottom_,
+
+ _font_,
+ _font_family_,
+ _font_style_,
+ _font_variant_,
+ _font_weight_,
+ _font_size_,
+ _line_height_,
+ _text_decoration_,
+
+ _white_space_,
+ _text_align_,
+ _vertical_align_,
+ _color_,
+ _width_,
+ _height_,
+ _min_width_,
+ _min_height_,
+ _max_width_,
+ _max_height_,
+ _position_,
+ _overflow_,
+ _display_,
+ _visibility_,
+ _box_sizing_,
+ _z_index_,
+ _float_,
+ _clear_,
+ _text_indent_,
+ _left_,
+ _right_,
+ _top_,
+ _bottom_,
+ _cursor_,
+ _content_,
+ _border_collapse_,
+ _text_transform_,
+
+ _flex_,
+ _flex_flow_,
+ _flex_direction_,
+ _flex_wrap_,
+ _justify_content_,
+ _align_items_,
+ _align_content_,
+ _align_self_,
+ _flex_grow_,
+ _flex_shrink_,
+ _flex_basis_,
+);
+#undef STRING_ID
+extern const string_id empty_id; // _id("")
+extern const string_id star_id; // _id("*")
+
+string_id _id(const string& str);
+const string& _s(string_id id);
+
+} // namespace litehtml
+
+#endif // LH_STRING_ID_H
diff --git a/src/plugins/litehtml_viewer/litehtml/strtod.cpp b/src/plugins/litehtml_viewer/litehtml/strtod.cpp
new file mode 100644
index 000000000..22392c494
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/strtod.cpp
@@ -0,0 +1,275 @@
+/*
+ * strtod.c --
+ *
+ * Source code for the "strtod" library procedure.
+ *
+ * Copyright (c) 1988-1993 The Regents of the University of California.
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies. The University of California
+ * makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#include "html.h"
+#include <cstdlib>
+#include <cctype>
+#include <cerrno>
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+
+static int maxExponent = 511; /* Largest possible base 10 exponent. Any
+ * exponent larger than this will already
+ * produce underflow or overflow, so there's
+ * no need to worry about additional digits.
+ */
+static double powersOf10[] = { /* Table giving binary powers of 10. Entry */
+ 10., /* is 10^2^i. Used to convert decimal */
+ 100., /* exponents into floating-point numbers. */
+ 1.0e4,
+ 1.0e8,
+ 1.0e16,
+ 1.0e32,
+ 1.0e64,
+ 1.0e128,
+ 1.0e256
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * strtod --
+ *
+ * This procedure converts a floating-point number from an ASCII
+ * decimal representation to internal double-precision format.
+ *
+ * Results:
+ * The return value is the double-precision floating-point
+ * representation of the characters in string. If endPtr isn't
+ * NULL, then *endPtr is filled in with the address of the
+ * next character after the last one that was part of the
+ * floating-point number.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+double litehtml::t_strtod(const char* string, char** endPtr)
+{
+ int sign, expSign = FALSE;
+ double fraction, dblExp, *d;
+ const char *p;
+ int c;
+ int exp = 0; /* Exponent read from "EX" field. */
+ int fracExp = 0; /* Exponent that derives from the fractional
+ * part. Under normal circumstatnces, it is
+ * the negative of the number of digits in F.
+ * However, if I is very long, the last digits
+ * of I get dropped (otherwise a long I with a
+ * large negative exponent could cause an
+ * unnecessary overflow on I alone). In this
+ * case, fracExp is incremented one for each
+ * dropped digit. */
+ int mantSize; /* Number of digits in mantissa. */
+ int decPt; /* Number of mantissa digits BEFORE decimal
+ * point. */
+ const char *pExp; /* Temporarily holds location of exponent
+ * in string. */
+
+ /*
+ * Strip off leading blanks and check for a sign.
+ */
+
+ p = string;
+ while (isspace(*p))
+ {
+ p += 1;
+ }
+ if (*p == '-')
+ {
+ sign = TRUE;
+ p += 1;
+ } else
+ {
+ if (*p == '+')
+ {
+ p += 1;
+ }
+ sign = FALSE;
+ }
+
+ /*
+ * Count the number of digits in the mantissa (including the decimal
+ * point), and also locate the decimal point.
+ */
+
+ decPt = -1;
+ for (mantSize = 0; ; mantSize += 1)
+ {
+ c = *p;
+ if (!t_isdigit(c))
+ {
+ if ((c != '.') || (decPt >= 0))
+ {
+ break;
+ }
+ decPt = mantSize;
+ }
+ p += 1;
+ }
+
+ /*
+ * Now suck up the digits in the mantissa. Use two integers to
+ * collect 9 digits each (this is faster than using floating-point).
+ * If the mantissa has more than 18 digits, ignore the extras, since
+ * they can't affect the value anyway.
+ */
+
+ pExp = p;
+ p -= mantSize;
+ if (decPt < 0)
+ {
+ decPt = mantSize;
+ } else
+ {
+ mantSize -= 1; /* One of the digits was the point. */
+ }
+ if (mantSize > 18)
+ {
+ fracExp = decPt - 18;
+ mantSize = 18;
+ } else
+ {
+ fracExp = decPt - mantSize;
+ }
+ if (mantSize == 0)
+ {
+ fraction = 0.0;
+ p = string;
+ goto done;
+ } else
+ {
+ int frac1, frac2;
+ frac1 = 0;
+ for ( ; mantSize > 9; mantSize -= 1)
+ {
+ c = *p;
+ p += 1;
+ if (c == '.')
+ {
+ c = *p;
+ p += 1;
+ }
+ frac1 = 10*frac1 + (c - '0');
+ }
+ frac2 = 0;
+ for (; mantSize > 0; mantSize -= 1)
+ {
+ c = *p;
+ p += 1;
+ if (c == '.')
+ {
+ c = *p;
+ p += 1;
+ }
+ frac2 = 10*frac2 + (c - '0');
+ }
+ fraction = (1.0e9 * frac1) + frac2;
+ }
+
+ /*
+ * Skim off the exponent.
+ */
+
+ p = pExp;
+ if ((*p == 'E') || (*p == 'e'))
+ {
+ p += 1;
+ if (*p == '-')
+ {
+ expSign = TRUE;
+ p += 1;
+ } else
+ {
+ if (*p == '+')
+ {
+ p += 1;
+ }
+ expSign = FALSE;
+ }
+ while (isdigit(*p))
+ {
+ exp = exp * 10 + (*p - '0');
+ p += 1;
+ }
+ }
+ if (expSign)
+ {
+ exp = fracExp - exp;
+ } else
+ {
+ exp = fracExp + exp;
+ }
+
+ /*
+ * Generate a floating-point number that represents the exponent.
+ * Do this by processing the exponent one bit at a time to combine
+ * many powers of 2 of 10. Then combine the exponent with the
+ * fraction.
+ */
+
+ if (exp < 0)
+ {
+ expSign = TRUE;
+ exp = -exp;
+ } else
+ {
+ expSign = FALSE;
+ }
+ if (exp > maxExponent)
+ {
+ exp = maxExponent;
+ errno = ERANGE;
+ }
+ dblExp = 1.0;
+ for (d = powersOf10; exp != 0; exp >>= 1, d += 1)
+ {
+ if (exp & 01)
+ {
+ dblExp *= *d;
+ }
+ }
+ if (expSign)
+ {
+ fraction /= dblExp;
+ } else
+ {
+ fraction *= dblExp;
+ }
+
+done:
+ if (endPtr != nullptr)
+ {
+ *endPtr = (char *) p;
+ }
+
+ if (sign)
+ {
+ return -fraction;
+ }
+ return fraction;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/style.cpp b/src/plugins/litehtml_viewer/litehtml/style.cpp
index 2a7c8b9de..ca6b18f06 100644
--- a/src/plugins/litehtml_viewer/litehtml/style.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/style.cpp
@@ -1,48 +1,69 @@
#include "html.h"
#include "style.h"
-#include <functional>
-#include <algorithm>
-#ifndef WINCE
-#include <locale>
-#endif
-litehtml::string_map litehtml::style::m_valid_values =
+namespace litehtml
{
- { _t("white-space"), white_space_strings }
-};
-litehtml::style::style()
+std::map<string_id, string> style::m_valid_values =
{
-}
+ { _display_, style_display_strings },
+ { _visibility_, visibility_strings },
+ { _position_, element_position_strings },
+ { _float_, element_float_strings },
+ { _clear_, element_clear_strings },
+ { _overflow_, overflow_strings },
+ { _box_sizing_, box_sizing_strings },
-litehtml::style::style( const style& val )
-{
- m_properties = val.m_properties;
-}
+ { _text_align_, text_align_strings },
+ { _vertical_align_, vertical_align_strings },
+ { _text_transform_, text_transform_strings },
+ { _white_space_, white_space_strings },
-litehtml::style::~style()
-{
+ { _font_style_, font_style_strings },
+ { _font_variant_, font_variant_strings },
+ { _font_weight_, font_weight_strings },
-}
+ { _list_style_type_, list_style_type_strings },
+ { _list_style_position_, list_style_position_strings },
-void litehtml::style::parse( const tchar_t* txt, const tchar_t* baseurl )
+ { _border_left_style_, border_style_strings },
+ { _border_right_style_, border_style_strings },
+ { _border_top_style_, border_style_strings },
+ { _border_bottom_style_, border_style_strings },
+ { _border_collapse_, border_collapse_strings },
+
+ // these 4 properties are comma-separated lists of keywords, see parse_keyword_comma_list
+ { _background_attachment_, background_attachment_strings },
+ { _background_repeat_, background_repeat_strings },
+ { _background_clip_, background_box_strings },
+ { _background_origin_, background_box_strings },
+
+ { _flex_direction_, flex_direction_strings },
+ { _flex_wrap_, flex_wrap_strings },
+ { _justify_content_, flex_justify_content_strings },
+ { _align_items_, flex_align_items_strings },
+ { _align_content_, flex_align_content_strings },
+ { _align_self_, flex_align_self_strings },
+};
+
+void style::parse(const string& txt, const string& baseurl, document_container* container)
{
- std::vector<tstring> properties;
- split_string(txt, properties, _t(";"), _t(""), _t("\"'"));
+ std::vector<string> properties;
+ split_string(txt, properties, ";", "", "\"'");
- for(std::vector<tstring>::const_iterator i = properties.begin(); i != properties.end(); i++)
+ for(const auto & property : properties)
{
- parse_property(*i, baseurl);
+ parse_property(property, baseurl, container);
}
}
-void litehtml::style::parse_property( const tstring& txt, const tchar_t* baseurl )
+void style::parse_property(const string& txt, const string& baseurl, document_container* container)
{
- tstring::size_type pos = txt.find_first_of(_t(":"));
- if(pos != tstring::npos)
+ string::size_type pos = txt.find_first_of(':');
+ if(pos != string::npos)
{
- tstring name = txt.substr(0, pos);
- tstring val = txt.substr(pos + 1);
+ string name = txt.substr(0, pos);
+ string val = txt.substr(pos + 1);
trim(name); lcase(name);
trim(val);
@@ -50,594 +71,1028 @@ void litehtml::style::parse_property( const tstring& txt, const tchar_t* baseurl
if(!name.empty() && !val.empty())
{
string_vector vals;
- split_string(val, vals, _t("!"));
+ split_string(val, vals, "!");
if(vals.size() == 1)
{
- add_property(name.c_str(), val.c_str(), baseurl, false);
+ add_property(_id(name), val, baseurl, false, container);
} else if(vals.size() > 1)
{
trim(vals[0]);
lcase(vals[1]);
- add_property(name.c_str(), vals[0].c_str(), baseurl, vals[1] == _t("important"));
+ add_property(_id(name), vals[0], baseurl, vals[1] == "important", container);
}
}
}
}
-void litehtml::style::combine( const litehtml::style& src )
+void style::add_property(string_id name, const string& val, const string& baseurl, bool important, document_container* container)
{
- for(props_map::const_iterator i = src.m_properties.begin(); i != src.m_properties.end(); i++)
- {
- add_parsed_property(i->first.c_str(), i->second.m_value.c_str(), i->second.m_important);
- }
-}
+ if (val.find("var(") != -1) return add_parsed_property(name, property_value(val, important, prop_type_var));
+ if (val == "inherit" && name != _font_) return add_parsed_property(name, property_value(important, prop_type_inherit));
-void litehtml::style::add_property( const tchar_t* name, const tchar_t* val, const tchar_t* baseurl, bool important )
-{
- if(!name || !val)
- {
- return;
- }
+ int idx;
+ string url;
+ css_length len[4], length;
- // Add baseurl for background image
- if( !t_strcmp(name, _t("background-image")))
+ switch (name)
{
- add_parsed_property(name, val, important);
- if(baseurl)
+ // keyword-only properties
+ case _display_:
+ case _visibility_:
+ case _position_:
+ case _float_:
+ case _clear_:
+ case _box_sizing_:
+ case _overflow_:
+
+ case _text_align_:
+ case _vertical_align_:
+ case _text_transform_:
+ case _white_space_:
+
+ case _font_style_:
+ case _font_variant_:
+ case _font_weight_:
+
+ case _list_style_type_:
+ case _list_style_position_:
+
+ case _border_top_style_:
+ case _border_bottom_style_:
+ case _border_left_style_:
+ case _border_right_style_:
+ case _border_collapse_:
+
+ case _flex_direction_:
+ case _flex_wrap_:
+ case _justify_content_:
+ case _align_items_:
+ case _align_content_:
+ case _align_self_:
+
+ idx = value_index(val, m_valid_values[name]);
+ if (idx >= 0)
{
- add_parsed_property(_t("background-image-baseurl"), baseurl, important);
+ add_parsed_property(name, property_value(idx, important));
}
- } else
+ break;
+
+ // <length>
+ case _text_indent_:
+ case _padding_left_:
+ case _padding_right_:
+ case _padding_top_:
+ case _padding_bottom_:
+ length.fromString(val);
+ add_parsed_property(name, property_value(length, important));
+ break;
+
+ // <length> | auto
+ case _left_:
+ case _right_:
+ case _top_:
+ case _bottom_:
+ case _z_index_: // <integer> | auto
+ case _width_:
+ case _height_:
+ case _min_width_:
+ case _min_height_:
+ case _margin_left_:
+ case _margin_right_:
+ case _margin_top_:
+ case _margin_bottom_:
+ length.fromString(val, "auto", -1);
+ add_parsed_property(name, property_value(length, important));
+ break;
+
+ // <length> | none
+ case _max_width_:
+ case _max_height_:
+ length.fromString(val, "none", -1);
+ add_parsed_property(name, property_value(length, important));
+ break;
+
+ case _line_height_:
+ length.fromString(val, "normal", -1);
+ add_parsed_property(name, property_value(length, important));
+ break;
+
+ case _font_size_:
+ length.fromString(val, font_size_strings, -1);
+ add_parsed_property(name, property_value(length, important));
+ break;
+
+ // Parse background shorthand properties
+ case _background_:
+ parse_background(val, baseurl, important, container);
+ break;
+
+ case _background_image_:
+ parse_background_image(val, baseurl, important);
+ break;
+
+ case _background_attachment_:
+ case _background_repeat_:
+ case _background_clip_:
+ case _background_origin_:
+ parse_keyword_comma_list(name, val, important);
+ break;
+
+ case _background_position_:
+ parse_background_position(val, important);
+ break;
+
+ case _background_size_:
+ parse_background_size(val, important);
+ break;
// Parse border spacing properties
- if( !t_strcmp(name, _t("border-spacing")))
- {
- string_vector tokens;
- split_string(val, tokens, _t(" "));
- if(tokens.size() == 1)
- {
- add_parsed_property(_t("-litehtml-border-spacing-x"), tokens[0].c_str(), important);
- add_parsed_property(_t("-litehtml-border-spacing-y"), tokens[0].c_str(), important);
- } else if(tokens.size() == 2)
- {
- add_parsed_property(_t("-litehtml-border-spacing-x"), tokens[0].c_str(), important);
- add_parsed_property(_t("-litehtml-border-spacing-y"), tokens[1].c_str(), important);
- }
- } else
+ case _border_spacing_:
+ parse_two_lengths(val, len);
+ add_parsed_property(__litehtml_border_spacing_x_, property_value(len[0], important));
+ add_parsed_property(__litehtml_border_spacing_y_, property_value(len[1], important));
+ break;
// Parse borders shorthand properties
-
- if( !t_strcmp(name, _t("border")))
+ case _border_:
{
string_vector tokens;
- split_string(val, tokens, _t(" "), _t(""), _t("("));
- int idx;
- tstring str;
- for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+ split_string(val, tokens, " ", "", "(");
+ for (const auto& token : tokens)
{
- idx = value_index(tok->c_str(), border_style_strings, -1);
- if(idx >= 0)
+ int idx = value_index(token, border_style_strings);
+ if (idx >= 0)
{
- add_property(_t("border-left-style"), tok->c_str(), baseurl, important);
- add_property(_t("border-right-style"), tok->c_str(), baseurl, important);
- add_property(_t("border-top-style"), tok->c_str(), baseurl, important);
- add_property(_t("border-bottom-style"), tok->c_str(), baseurl, important);
- } else
+ property_value style(idx, important);
+ add_parsed_property(_border_left_style_, style);
+ add_parsed_property(_border_right_style_, style);
+ add_parsed_property(_border_top_style_, style);
+ add_parsed_property(_border_bottom_style_, style);
+ }
+ else if (t_isdigit(token[0]) || token[0] == '.' ||
+ value_in_list(token, border_width_strings))
{
- if (t_isdigit((*tok)[0]) || (*tok)[0] == _t('.') ||
- value_in_list((*tok), _t("thin;medium;thick")))
- {
- add_property(_t("border-left-width"), tok->c_str(), baseurl, important);
- add_property(_t("border-right-width"), tok->c_str(), baseurl, important);
- add_property(_t("border-top-width"), tok->c_str(), baseurl, important);
- add_property(_t("border-bottom-width"), tok->c_str(), baseurl, important);
- }
- else
- {
- add_property(_t("border-left-color"), tok->c_str(), baseurl, important);
- add_property(_t("border-right-color"), tok->c_str(), baseurl, important);
- add_property(_t("border-top-color"), tok->c_str(), baseurl, important);
- add_property(_t("border-bottom-color"), tok->c_str(), baseurl, important);
- }
+ property_value width(parse_border_width(token), important);
+ add_parsed_property(_border_left_width_, width);
+ add_parsed_property(_border_right_width_, width);
+ add_parsed_property(_border_top_width_, width);
+ add_parsed_property(_border_bottom_width_, width);
+ }
+ else
+ {
+ web_color _color = web_color::from_string(token, container);
+ property_value color(_color, important);
+ add_parsed_property(_border_left_color_, color);
+ add_parsed_property(_border_right_color_, color);
+ add_parsed_property(_border_top_color_, color);
+ add_parsed_property(_border_bottom_color_, color);
}
}
- } else if( !t_strcmp(name, _t("border-left")) ||
- !t_strcmp(name, _t("border-right")) ||
- !t_strcmp(name, _t("border-top")) ||
- !t_strcmp(name, _t("border-bottom")) )
+ break;
+ }
+
+ case _border_left_:
+ case _border_right_:
+ case _border_top_:
+ case _border_bottom_:
{
string_vector tokens;
- split_string(val, tokens, _t(" "), _t(""), _t("("));
- int idx;
- tstring str;
- for(string_vector::const_iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+ split_string(val, tokens, " ", "", "(");
+ for (const auto& token : tokens)
{
- idx = value_index(tok->c_str(), border_style_strings, -1);
- if(idx >= 0)
+ int idx = value_index(token, border_style_strings);
+ if (idx >= 0)
{
- str = name;
- str += _t("-style");
- add_property(str.c_str(), tok->c_str(), baseurl, important);
- } else
+ add_parsed_property(_id(_s(name) + "-style"), property_value(idx, important));
+ }
+ else if (t_isdigit(token[0]) || token[0] == '.' ||
+ value_in_list(token, border_width_strings))
{
- if(web_color::is_color(tok->c_str()))
- {
- str = name;
- str += _t("-color");
- add_property(str.c_str(), tok->c_str(), baseurl, important);
- } else
- {
- str = name;
- str += _t("-width");
- add_property(str.c_str(), tok->c_str(), baseurl, important);
- }
+ property_value width(parse_border_width(token), important);
+ add_parsed_property(_id(_s(name) + "-width"), width);
+ }
+ else
+ {
+ web_color color = web_color::from_string(token, container);
+ add_parsed_property(_id(_s(name) + "-color"), property_value(color, important));
}
}
- } else
+ break;
+ }
- // Parse border radius shorthand properties
- if(!t_strcmp(name, _t("border-bottom-left-radius")))
+ // Parse border-width/style/color shorthand properties
+ case _border_width_:
+ case _border_style_:
+ case _border_color_:
{
- string_vector tokens;
- split_string(val, tokens, _t(" "));
- if(tokens.size() >= 2)
- {
- add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
- } else if(tokens.size() == 1)
- {
- add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);
- }
+ string prop = name == _border_width_ ? "-width" : name == _border_style_ ? "-style" : "-color";
- } else if(!t_strcmp(name, _t("border-bottom-right-radius")))
- {
string_vector tokens;
- split_string(val, tokens, _t(" "));
- if(tokens.size() >= 2)
+ split_string(val, tokens, " ");
+ if (tokens.size() == 4)
{
- add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-bottom-right-radius-y"), tokens[1].c_str(), baseurl, important);
- } else if(tokens.size() == 1)
+ add_property(_id("border-top" + prop), tokens[0], baseurl, important, container);
+ add_property(_id("border-right" + prop), tokens[1], baseurl, important, container);
+ add_property(_id("border-bottom" + prop), tokens[2], baseurl, important, container);
+ add_property(_id("border-left" + prop), tokens[3], baseurl, important, container);
+ }
+ else if (tokens.size() == 3)
{
- add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);
+ add_property(_id("border-top" + prop), tokens[0], baseurl, important, container);
+ add_property(_id("border-right" + prop), tokens[1], baseurl, important, container);
+ add_property(_id("border-left" + prop), tokens[1], baseurl, important, container);
+ add_property(_id("border-bottom" + prop), tokens[2], baseurl, important, container);
}
-
- } else if(!t_strcmp(name, _t("border-top-right-radius")))
- {
- string_vector tokens;
- split_string(val, tokens, _t(" "));
- if(tokens.size() >= 2)
+ else if (tokens.size() == 2)
{
- add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
- } else if(tokens.size() == 1)
+ add_property(_id("border-top" + prop), tokens[0], baseurl, important, container);
+ add_property(_id("border-bottom" + prop), tokens[0], baseurl, important, container);
+ add_property(_id("border-right" + prop), tokens[1], baseurl, important, container);
+ add_property(_id("border-left" + prop), tokens[1], baseurl, important, container);
+ }
+ else if (tokens.size() == 1)
{
- add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-right-radius-y"), tokens[0].c_str(), baseurl, important);
+ add_property(_id("border-top" + prop), tokens[0], baseurl, important, container);
+ add_property(_id("border-bottom" + prop), tokens[0], baseurl, important, container);
+ add_property(_id("border-right" + prop), tokens[0], baseurl, important, container);
+ add_property(_id("border-left" + prop), tokens[0], baseurl, important, container);
}
+ break;
+ }
+
+ case _border_top_width_:
+ case _border_bottom_width_:
+ case _border_left_width_:
+ case _border_right_width_:
+ length = parse_border_width(val);
+ add_parsed_property(name, property_value(length, important));
+ break;
- } else if(!t_strcmp(name, _t("border-top-left-radius")))
+ case _color_:
+ case _background_color_:
+ case _border_top_color_:
+ case _border_bottom_color_:
+ case _border_left_color_:
+ case _border_right_color_:
{
- string_vector tokens;
- split_string(val, tokens, _t(" "));
- if(tokens.size() >= 2)
- {
- add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-left-radius-y"), tokens[1].c_str(), baseurl, important);
- } else if(tokens.size() == 1)
- {
- add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
- }
+ web_color color = web_color::from_string(val, container);
+ add_parsed_property(name, property_value(color, important));
+ break;
+ }
- } else
+ // Parse border radius shorthand properties
+ case _border_bottom_left_radius_:
+ case _border_bottom_right_radius_:
+ case _border_top_right_radius_:
+ case _border_top_left_radius_:
+ parse_two_lengths(val, len);
+ add_parsed_property(_id(_s(name) + "-x"), property_value(len[0], important));
+ add_parsed_property(_id(_s(name) + "-y"), property_value(len[1], important));
+ break;
// Parse border-radius shorthand properties
- if(!t_strcmp(name, _t("border-radius")))
+ case _border_radius_:
{
string_vector tokens;
- split_string(val, tokens, _t("/"));
- if(tokens.size() == 1)
+ split_string(val, tokens, "/");
+ if (tokens.size() == 1)
{
- add_property(_t("border-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-radius-y"), tokens[0].c_str(), baseurl, important);
- } else if(tokens.size() >= 2)
+ add_property(_border_radius_x_, tokens[0], baseurl, important, container);
+ add_property(_border_radius_y_, tokens[0], baseurl, important, container);
+ }
+ else if (tokens.size() >= 2)
{
- add_property(_t("border-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-radius-y"), tokens[1].c_str(), baseurl, important);
+ add_property(_border_radius_x_, tokens[0], baseurl, important, container);
+ add_property(_border_radius_y_, tokens[1], baseurl, important, container);
}
- } else if(!t_strcmp(name, _t("border-radius-x")))
- {
- string_vector tokens;
- split_string(val, tokens, _t(" "));
- if(tokens.size() == 1)
- {
- add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-right-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-bottom-left-radius-x"), tokens[0].c_str(), baseurl, important);
- } else if(tokens.size() == 2)
- {
- add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-right-radius-x"), tokens[1].c_str(), baseurl, important);
- add_property(_t("border-bottom-right-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);
- } else if(tokens.size() == 3)
- {
- add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-right-radius-x"), tokens[1].c_str(), baseurl, important);
- add_property(_t("border-bottom-right-radius-x"), tokens[2].c_str(), baseurl, important);
- add_property(_t("border-bottom-left-radius-x"), tokens[1].c_str(), baseurl, important);
- } else if(tokens.size() == 4)
- {
- add_property(_t("border-top-left-radius-x"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-right-radius-x"), tokens[1].c_str(), baseurl, important);
- add_property(_t("border-bottom-right-radius-x"), tokens[2].c_str(), baseurl, important);
- add_property(_t("border-bottom-left-radius-x"), tokens[3].c_str(), baseurl, important);
- }
- } else if(!t_strcmp(name, _t("border-radius-y")))
+ break;
+ }
+ case _border_radius_x_:
+ case _border_radius_y_:
{
- string_vector tokens;
- split_string(val, tokens, _t(" "));
- if(tokens.size() == 1)
- {
- add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-right-radius-y"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-bottom-left-radius-y"), tokens[0].c_str(), baseurl, important);
- } else if(tokens.size() == 2)
+ string_id top_left, top_right, bottom_right, bottom_left;
+ if (name == _border_radius_x_)
{
- add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
- add_property(_t("border-bottom-right-radius-y"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
- } else if(tokens.size() == 3)
+ top_left = _border_top_left_radius_x_;
+ top_right = _border_top_right_radius_x_;
+ bottom_right = _border_bottom_right_radius_x_;
+ bottom_left = _border_bottom_left_radius_x_;
+ }
+ else
{
- add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
- add_property(_t("border-bottom-right-radius-y"), tokens[2].c_str(), baseurl, important);
- add_property(_t("border-bottom-left-radius-y"), tokens[1].c_str(), baseurl, important);
- } else if(tokens.size() == 4)
+ top_left = _border_top_left_radius_y_;
+ top_right = _border_top_right_radius_y_;
+ bottom_right = _border_bottom_right_radius_y_;
+ bottom_left = _border_bottom_left_radius_y_;
+ }
+
+ switch (parse_four_lengths(val, len))
{
- add_property(_t("border-top-left-radius-y"), tokens[0].c_str(), baseurl, important);
- add_property(_t("border-top-right-radius-y"), tokens[1].c_str(), baseurl, important);
- add_property(_t("border-bottom-right-radius-y"), tokens[2].c_str(), baseurl, important);
- add_property(_t("border-bottom-left-radius-y"), tokens[3].c_str(), baseurl, important);
+ case 1:
+ add_parsed_property(top_left, property_value(len[0], important));
+ add_parsed_property(top_right, property_value(len[0], important));
+ add_parsed_property(bottom_right, property_value(len[0], important));
+ add_parsed_property(bottom_left, property_value(len[0], important));
+ break;
+ case 2:
+ add_parsed_property(top_left, property_value(len[0], important));
+ add_parsed_property(top_right, property_value(len[1], important));
+ add_parsed_property(bottom_right, property_value(len[0], important));
+ add_parsed_property(bottom_left, property_value(len[1], important));
+ break;
+ case 3:
+ add_parsed_property(top_left, property_value(len[0], important));
+ add_parsed_property(top_right, property_value(len[1], important));
+ add_parsed_property(bottom_right, property_value(len[2], important));
+ add_parsed_property(bottom_left, property_value(len[1], important));
+ break;
+ case 4:
+ add_parsed_property(top_left, property_value(len[0], important));
+ add_parsed_property(top_right, property_value(len[1], important));
+ add_parsed_property(bottom_right, property_value(len[2], important));
+ add_parsed_property(bottom_left, property_value(len[3], important));
+ break;
}
+ break;
}
- else
// Parse list-style shorthand properties
- if(!t_strcmp(name, _t("list-style")))
+ case _list_style_:
{
- add_parsed_property(_t("list-style-type"), _t("disc"), important);
- add_parsed_property(_t("list-style-position"), _t("outside"), important);
- add_parsed_property(_t("list-style-image"), _t(""), important);
- add_parsed_property(_t("list-style-image-baseurl"), _t(""), important);
+ add_parsed_property(_list_style_type_, property_value(list_style_type_disc, important));
+ add_parsed_property(_list_style_position_, property_value(list_style_position_outside, important));
+ add_parsed_property(_list_style_image_, property_value("", important));
+ add_parsed_property(_list_style_image_baseurl_, property_value("", important));
string_vector tokens;
- split_string(val, tokens, _t(" "), _t(""), _t("("));
- for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+ split_string(val, tokens, " ", "", "(");
+ for (const auto& token : tokens)
{
- int idx = value_index(tok->c_str(), list_style_type_strings, -1);
- if(idx >= 0)
+ int idx = value_index(token, list_style_type_strings);
+ if (idx >= 0)
{
- add_parsed_property(_t("list-style-type"), *tok, important);
- } else
+ add_parsed_property(_list_style_type_, property_value(idx, important));
+ }
+ else
{
- idx = value_index(tok->c_str(), list_style_position_strings, -1);
- if(idx >= 0)
+ idx = value_index(token, list_style_position_strings);
+ if (idx >= 0)
{
- add_parsed_property(_t("list-style-position"), *tok, important);
- } else if(!t_strncmp(val, _t("url"), 3))
+ add_parsed_property(_list_style_position_, property_value(idx, important));
+ }
+ else if (!strncmp(token.c_str(), "url", 3))
{
- add_parsed_property(_t("list-style-image"), *tok, important);
- if(baseurl)
- {
- add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);
- }
+ css::parse_css_url(token, url);
+ add_parsed_property(_list_style_image_, property_value(url, important));
+ add_parsed_property(_list_style_image_baseurl_, property_value(baseurl, important));
}
}
}
- } else
+ break;
+ }
- // Add baseurl for background image
- if( !t_strcmp(name, _t("list-style-image")))
+ case _list_style_image_:
+ css::parse_css_url(val, url);
+ add_parsed_property(_list_style_image_, property_value(url, important));
+ add_parsed_property(_list_style_image_baseurl_, property_value(baseurl, important));
+ break;
+
+ // Parse margin and padding shorthand properties
+ case _margin_:
+ case _padding_:
{
- add_parsed_property(name, val, important);
- if(baseurl)
+ switch (parse_four_lengths(val, len))
{
- add_parsed_property(_t("list-style-image-baseurl"), baseurl, important);
+ case 4:
+ add_parsed_property(_id(_s(name) + "-top"), property_value(len[0], important));
+ add_parsed_property(_id(_s(name) + "-right"), property_value(len[1], important));
+ add_parsed_property(_id(_s(name) + "-bottom"), property_value(len[2], important));
+ add_parsed_property(_id(_s(name) + "-left"), property_value(len[3], important));
+ break;
+ case 3:
+ add_parsed_property(_id(_s(name) + "-top"), property_value(len[0], important));
+ add_parsed_property(_id(_s(name) + "-right"), property_value(len[1], important));
+ add_parsed_property(_id(_s(name) + "-left"), property_value(len[1], important));
+ add_parsed_property(_id(_s(name) + "-bottom"), property_value(len[2], important));
+ break;
+ case 2:
+ add_parsed_property(_id(_s(name) + "-top"), property_value(len[0], important));
+ add_parsed_property(_id(_s(name) + "-bottom"), property_value(len[0], important));
+ add_parsed_property(_id(_s(name) + "-right"), property_value(len[1], important));
+ add_parsed_property(_id(_s(name) + "-left"), property_value(len[1], important));
+ break;
+ case 1:
+ add_parsed_property(_id(_s(name) + "-top"), property_value(len[0], important));
+ add_parsed_property(_id(_s(name) + "-bottom"), property_value(len[0], important));
+ add_parsed_property(_id(_s(name) + "-right"), property_value(len[0], important));
+ add_parsed_property(_id(_s(name) + "-left"), property_value(len[0], important));
+ break;
}
- } else
-
- // Parse background shorthand properties
- if(!t_strcmp(name, _t("background")))
- {
- parse_short_background(val, baseurl, important);
+ break;
+ }
- } else
-
- // Parse margin and padding shorthand properties
- if(!t_strcmp(name, _t("margin")) || !t_strcmp(name, _t("padding")))
+ // Parse font shorthand properties
+ case _font_:
+ parse_font(val, important);
+ break;
+
+ // Parse flex-flow shorthand properties
+ case _flex_flow_:
{
string_vector tokens;
- split_string(val, tokens, _t(" "));
- if(tokens.size() >= 4)
- {
- add_parsed_property(tstring(name) + _t("-top"), tokens[0], important);
- add_parsed_property(tstring(name) + _t("-right"), tokens[1], important);
- add_parsed_property(tstring(name) + _t("-bottom"), tokens[2], important);
- add_parsed_property(tstring(name) + _t("-left"), tokens[3], important);
- } else if(tokens.size() == 3)
- {
- add_parsed_property(tstring(name) + _t("-top"), tokens[0], important);
- add_parsed_property(tstring(name) + _t("-right"), tokens[1], important);
- add_parsed_property(tstring(name) + _t("-left"), tokens[1], important);
- add_parsed_property(tstring(name) + _t("-bottom"), tokens[2], important);
- } else if(tokens.size() == 2)
- {
- add_parsed_property(tstring(name) + _t("-top"), tokens[0], important);
- add_parsed_property(tstring(name) + _t("-bottom"), tokens[0], important);
- add_parsed_property(tstring(name) + _t("-right"), tokens[1], important);
- add_parsed_property(tstring(name) + _t("-left"), tokens[1], important);
- } else if(tokens.size() == 1)
- {
- add_parsed_property(tstring(name) + _t("-top"), tokens[0], important);
- add_parsed_property(tstring(name) + _t("-bottom"), tokens[0], important);
- add_parsed_property(tstring(name) + _t("-right"), tokens[0], important);
- add_parsed_property(tstring(name) + _t("-left"), tokens[0], important);
- }
- } else
-
-
- // Parse border-* shorthand properties
- if( !t_strcmp(name, _t("border-left")) ||
- !t_strcmp(name, _t("border-right")) ||
- !t_strcmp(name, _t("border-top")) ||
- !t_strcmp(name, _t("border-bottom")))
- {
- parse_short_border(name, val, important);
- } else
-
- // Parse border-width/style/color shorthand properties
- if( !t_strcmp(name, _t("border-width")) ||
- !t_strcmp(name, _t("border-style")) ||
- !t_strcmp(name, _t("border-color")) )
+ split_string(val, tokens, " ");
+ for (const auto& tok : tokens)
+ {
+ int idx;
+ if ((idx = value_index(tok, flex_direction_strings)) >= 0)
+ {
+ add_parsed_property(_flex_direction_, property_value(idx, important));
+ }
+ else if ((idx = value_index(tok, flex_wrap_strings)) >= 0)
+ {
+ add_parsed_property(_flex_wrap_, property_value(idx, important));
+ }
+ }
+ break;
+ }
+
+ // Parse flex shorthand properties
+ case _flex_:
+ parse_flex(val, important);
+ break;
+
+ case _flex_grow_:
+ case _flex_shrink_:
+ add_parsed_property(name, property_value(t_strtof(val), important));
+ break;
+
+ case _flex_basis_:
+ length.fromString(val, flex_basis_strings, -1);
+ add_parsed_property(_flex_basis_, property_value(length, important));
+ break;
+
+ default:
+ add_parsed_property(name, property_value(val, important));
+ }
+}
+
+css_length style::parse_border_width(const string& str)
+{
+ css_length len;
+ if (t_isdigit(str[0]) || str[0] == '.')
{
- string_vector nametokens;
- split_string(name, nametokens, _t("-"));
+ len.fromString(str);
+ }
+ else
+ {
+ int idx = value_index(str, border_width_strings);
+ if (idx >= 0)
+ {
+ len.set_value(border_width_values[idx], css_units_px);
+ }
+ }
+ return len;
+}
- string_vector tokens;
- split_string(val, tokens, _t(" "));
- if(tokens.size() >= 4)
- {
- add_parsed_property(nametokens[0] + _t("-top-") + nametokens[1], tokens[0], important);
- add_parsed_property(nametokens[0] + _t("-right-") + nametokens[1], tokens[1], important);
- add_parsed_property(nametokens[0] + _t("-bottom-") + nametokens[1], tokens[2], important);
- add_parsed_property(nametokens[0] + _t("-left-") + nametokens[1], tokens[3], important);
- } else if(tokens.size() == 3)
- {
- add_parsed_property(nametokens[0] + _t("-top-") + nametokens[1], tokens[0], important);
- add_parsed_property(nametokens[0] + _t("-right-") + nametokens[1], tokens[1], important);
- add_parsed_property(nametokens[0] + _t("-left-") + nametokens[1], tokens[1], important);
- add_parsed_property(nametokens[0] + _t("-bottom-") + nametokens[1], tokens[2], important);
- } else if(tokens.size() == 2)
- {
- add_parsed_property(nametokens[0] + _t("-top-") + nametokens[1], tokens[0], important);
- add_parsed_property(nametokens[0] + _t("-bottom-") + nametokens[1], tokens[0], important);
- add_parsed_property(nametokens[0] + _t("-right-") + nametokens[1], tokens[1], important);
- add_parsed_property(nametokens[0] + _t("-left-") + nametokens[1], tokens[1], important);
- } else if(tokens.size() == 1)
- {
- add_parsed_property(nametokens[0] + _t("-top-") + nametokens[1], tokens[0], important);
- add_parsed_property(nametokens[0] + _t("-bottom-") + nametokens[1], tokens[0], important);
- add_parsed_property(nametokens[0] + _t("-right-") + nametokens[1], tokens[0], important);
- add_parsed_property(nametokens[0] + _t("-left-") + nametokens[1], tokens[0], important);
- }
- } else
-
- // Parse font shorthand properties
- if(!t_strcmp(name, _t("font")))
+void style::parse_two_lengths(const string& str, css_length len[2])
+{
+ string_vector tokens;
+ split_string(str, tokens, " ");
+ if (tokens.size() == 1)
{
- parse_short_font(val, important);
- } else
+ css_length length;
+ length.fromString(tokens[0]);
+ len[0] = len[1] = length;
+ }
+ else if (tokens.size() == 2)
{
- add_parsed_property(name, val, important);
+ len[0].fromString(tokens[0]);
+ len[1].fromString(tokens[1]);
}
}
-void litehtml::style::parse_short_border( const tstring& prefix, const tstring& val, bool important )
+int style::parse_four_lengths(const string& str, css_length len[4])
{
string_vector tokens;
- split_string(val, tokens, _t(" "), _t(""), _t("("));
- if(tokens.size() >= 3)
+ split_string(str, tokens, " ");
+ if (tokens.size() == 0 || tokens.size() > 4)
{
- add_parsed_property(prefix + _t("-width"), tokens[0], important);
- add_parsed_property(prefix + _t("-style"), tokens[1], important);
- add_parsed_property(prefix + _t("-color"), tokens[2], important);
- } else if(tokens.size() == 2)
+ return 0;
+ }
+ for (size_t i = 0; i < tokens.size(); i++)
{
- if(iswdigit(tokens[0][0]) || value_index(val.c_str(), border_width_strings) >= 0)
- {
- add_parsed_property(prefix + _t("-width"), tokens[0], important);
- add_parsed_property(prefix + _t("-style"), tokens[1], important);
- } else
- {
- add_parsed_property(prefix + _t("-style"), tokens[0], important);
- add_parsed_property(prefix + _t("-color"), tokens[1], important);
- }
+ len[i].fromString(tokens[i]);
}
+ return (int)tokens.size();
}
-void litehtml::style::parse_short_background( const tstring& val, const tchar_t* baseurl, bool important )
+void style::parse_background(const string& val, const string& baseurl, bool important, document_container* container)
{
- add_parsed_property(_t("background-color"), _t("transparent"), important);
- add_parsed_property(_t("background-image"), _t(""), important);
- add_parsed_property(_t("background-image-baseurl"), _t(""), important);
- add_parsed_property(_t("background-repeat"), _t("repeat"), important);
- add_parsed_property(_t("background-origin"), _t("padding-box"), important);
- add_parsed_property(_t("background-clip"), _t("border-box"), important);
- add_parsed_property(_t("background-attachment"), _t("scroll"), important);
+ string_vector tokens;
+ split_string(val, tokens, ",", "", "(");
+ if (tokens.empty()) return;
+
+ web_color color;
+ string_vector images;
+ int_vector repeats, origins, clips, attachments;
+ length_vector x_positions, y_positions;
+ size_vector sizes;
- if(val == _t("none"))
+ for (const auto& token : tokens)
{
- return;
+ background bg;
+ if (!parse_one_background(token, container, bg))
+ return;
+
+ color = bg.m_color;
+ images.push_back(bg.m_image[0]);
+ repeats.push_back(bg.m_repeat[0]);
+ origins.push_back(bg.m_origin[0]);
+ clips.push_back(bg.m_clip[0]);
+ attachments.push_back(bg.m_attachment[0]);
+ x_positions.push_back(bg.m_position_x[0]);
+ y_positions.push_back(bg.m_position_y[0]);
+ sizes.push_back(bg.m_size[0]);
+ }
+
+ add_parsed_property(_background_color_, property_value(color, important));
+ add_parsed_property(_background_image_, property_value(images, important));
+ add_parsed_property(_background_image_baseurl_, property_value(baseurl, important));
+ add_parsed_property(_background_repeat_, property_value(repeats, important));
+ add_parsed_property(_background_origin_, property_value(origins, important));
+ add_parsed_property(_background_clip_, property_value(clips, important));
+ add_parsed_property(_background_attachment_, property_value(attachments, important));
+ add_parsed_property(_background_position_x_, property_value(x_positions, important));
+ add_parsed_property(_background_position_y_, property_value(y_positions, important));
+ add_parsed_property(_background_size_, property_value(sizes, important));
+}
+
+bool style::parse_one_background(const string& val, document_container* container, background& bg)
+{
+ bg.m_color = web_color::transparent;
+ bg.m_image = {""};
+ bg.m_repeat = { background_repeat_repeat };
+ bg.m_origin = { background_box_padding };
+ bg.m_clip = { background_box_border };
+ bg.m_attachment = { background_attachment_scroll };
+ bg.m_position_x = { css_length(0, css_units_percentage) };
+ bg.m_position_y = { css_length(0, css_units_percentage) };
+ bg.m_size = { css_size(css_length::predef_value(background_size_auto), css_length::predef_value(background_size_auto)) };
+
+ if(val == "none")
+ {
+ return true;
}
string_vector tokens;
- split_string(val, tokens, _t(" "), _t(""), _t("("));
+ split_string(val, tokens, " \t\n\r", "", "(");
+
+ bool color_found = false;
+ bool image_found = false;
bool origin_found = false;
- for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+ bool clip_found = false;
+ bool repeat_found = false;
+ bool attachment_found = false;
+
+ string position;
+ for(const auto& token : tokens)
{
- if(tok->substr(0, 3) == _t("url"))
+ int idx;
+ if(token.substr(0, 3) == "url")
{
- add_parsed_property(_t("background-image"), *tok, important);
- if(baseurl)
- {
- add_parsed_property(_t("background-image-baseurl"), baseurl, important);
- }
-
- } else if( value_in_list(tok->c_str(), background_repeat_strings) )
+ if (image_found) return false;
+ string url;
+ css::parse_css_url(token, url);
+ bg.m_image = { url };
+ image_found = true;
+ } else if( (idx = value_index(token, background_repeat_strings)) >= 0 )
{
- add_parsed_property(_t("background-repeat"), *tok, important);
- } else if( value_in_list(tok->c_str(), background_attachment_strings) )
+ if (repeat_found) return false;
+ bg.m_repeat = { idx };
+ repeat_found = true;
+ } else if( (idx = value_index(token, background_attachment_strings)) >= 0 )
{
- add_parsed_property(_t("background-attachment"), *tok, important);
- } else if( value_in_list(tok->c_str(), background_box_strings) )
+ if (attachment_found) return false;
+ bg.m_attachment = { idx };
+ attachment_found = true;
+ } else if( (idx = value_index(token, background_box_strings)) >= 0 )
{
if(!origin_found)
{
- add_parsed_property(_t("background-origin"), *tok, important);
+ bg.m_origin = { idx };
origin_found = true;
} else
{
- add_parsed_property(_t("background-clip"),*tok, important);
+ if (clip_found) return false;
+ bg.m_clip = { idx };
+ clip_found = true;
}
- } else if( value_in_list(tok->c_str(), _t("left;right;top;bottom;center")) ||
- iswdigit((*tok)[0]) ||
- (*tok)[0] == _t('-') ||
- (*tok)[0] == _t('.') ||
- (*tok)[0] == _t('+'))
+ } else if( value_in_list(token, background_position_strings) ||
+ token.find('/') != -1 ||
+ t_isdigit(token[0]) ||
+ token[0] == '+' ||
+ token[0] == '-' ||
+ token[0] == '.' )
{
- if(m_properties.find(_t("background-position")) != m_properties.end())
- {
- m_properties[_t("background-position")].m_value = m_properties[_t("background-position")].m_value + _t(" ") + *tok;
- } else
- {
- add_parsed_property(_t("background-position"), *tok, important);
- }
- } else if (web_color::is_color(tok->c_str()))
+ position += " " + token;
+ } else if (web_color::is_color(token, container))
+ {
+ if (color_found) return false;
+ bg.m_color = web_color::from_string(token, container);
+ color_found = true;
+ }
+ else
{
- add_parsed_property(_t("background-color"), *tok, important);
+ return false;
}
}
+
+ if (position != "")
+ {
+ string_vector tokens;
+ split_string(position, tokens, "/");
+
+ if (tokens.size() > 2) return false;
+
+ if (tokens.size() == 2 && !parse_one_background_size(tokens[1], bg.m_size[0]))
+ return false;
+
+ if (tokens.size() > 0 && !parse_one_background_position(tokens[0], bg.m_position_x[0], bg.m_position_y[0]))
+ return false;
+ }
+
+ return true;
+}
+
+void style::parse_background_image(const string& val, const string& baseurl, bool important)
+{
+ string_vector tokens;
+ split_string(val, tokens, ",", "", "(");
+ if (tokens.empty()) return;
+
+ string_vector images;
+
+ for (const auto& token : tokens)
+ {
+ string url;
+ css::parse_css_url(token, url);
+ images.push_back(url);
+ }
+
+ add_parsed_property(_background_image_, property_value(images, important));
+ add_parsed_property(_background_image_baseurl_, property_value(baseurl, important));
+}
+
+void style::parse_keyword_comma_list(string_id name, const string& val, bool important)
+{
+ string_vector tokens;
+ split_string(val, tokens, ",");
+ if (tokens.empty()) return;
+
+ int_vector vec;
+
+ for (auto& token : tokens)
+ {
+ trim(token);
+ int idx = value_index(token, m_valid_values[name]);
+ if (idx == -1) return;
+ vec.push_back(idx);
+ }
+
+ add_parsed_property(name, property_value(vec, important));
+}
+
+void style::parse_background_position(const string& val, bool important)
+{
+ string_vector tokens;
+ split_string(val, tokens, ",");
+ if (tokens.empty()) return;
+
+ length_vector x_positions, y_positions;
+
+ for (const auto& token : tokens)
+ {
+ css_length x, y;
+ if(!parse_one_background_position(token, x, y)) return;
+ x_positions.push_back(x);
+ y_positions.push_back(y);
+ }
+
+ add_parsed_property(_background_position_x_, property_value(x_positions, important));
+ add_parsed_property(_background_position_y_, property_value(y_positions, important));
+}
+
+bool style::parse_one_background_position(const string& val, css_length& x, css_length& y)
+{
+ string_vector pos;
+ split_string(val, pos, " \t");
+
+ if (pos.empty() || pos.size() > 2)
+ {
+ return false;
+ }
+
+ if (pos.size() == 1)
+ {
+ if (value_in_list(pos[0], "left;right;center"))
+ {
+ x.fromString(pos[0], "left;right;center");
+ y.set_value(50, css_units_percentage);
+ }
+ else if (value_in_list(pos[0], "top;bottom;center"))
+ {
+ y.fromString(pos[0], "top;bottom;center");
+ x.set_value(50, css_units_percentage);
+ }
+ else
+ {
+ x.fromString(pos[0], "left;right;center");
+ y.set_value(50, css_units_percentage);
+ }
+ }
+ else if (pos.size() == 2)
+ {
+ if (value_in_list(pos[0], "left;right"))
+ {
+ x.fromString(pos[0], "left;right;center");
+ y.fromString(pos[1], "top;bottom;center");
+ }
+ else if (value_in_list(pos[0], "top;bottom"))
+ {
+ x.fromString(pos[1], "left;right;center");
+ y.fromString(pos[0], "top;bottom;center");
+ }
+ else if (value_in_list(pos[1], "left;right"))
+ {
+ x.fromString(pos[1], "left;right;center");
+ y.fromString(pos[0], "top;bottom;center");
+ }
+ else if (value_in_list(pos[1], "top;bottom"))
+ {
+ x.fromString(pos[0], "left;right;center");
+ y.fromString(pos[1], "top;bottom;center");
+ }
+ else
+ {
+ x.fromString(pos[0], "left;right;center");
+ y.fromString(pos[1], "top;bottom;center");
+ }
+ }
+
+ if (x.is_predefined())
+ {
+ switch (x.predef())
+ {
+ case 0:
+ x.set_value(0, css_units_percentage);
+ break;
+ case 1:
+ x.set_value(100, css_units_percentage);
+ break;
+ case 2:
+ x.set_value(50, css_units_percentage);
+ break;
+ }
+ }
+ if (y.is_predefined())
+ {
+ switch (y.predef())
+ {
+ case 0:
+ y.set_value(0, css_units_percentage);
+ break;
+ case 1:
+ y.set_value(100, css_units_percentage);
+ break;
+ case 2:
+ y.set_value(50, css_units_percentage);
+ break;
+ }
+ }
+ return true;
+}
+
+void style::parse_background_size(const string& val, bool important)
+{
+ string_vector tokens;
+ split_string(val, tokens, ",");
+ if (tokens.empty()) return;
+
+ size_vector sizes;
+
+ for (const auto& token : tokens)
+ {
+ css_size size;
+ if (!parse_one_background_size(token, size)) return;
+ sizes.push_back(size);
+ }
+
+ add_parsed_property(_background_size_, property_value(sizes, important));
+}
+
+bool style::parse_one_background_size(const string& val, css_size& size)
+{
+ string_vector res;
+ split_string(val, res, " \t");
+ if (res.empty())
+ {
+ return false;
+ }
+
+ size.width.fromString(res[0], background_size_strings);
+ if (res.size() > 1)
+ {
+ size.height.fromString(res[1], background_size_strings);
+ }
+ else
+ {
+ size.height.predef(background_size_auto);
+ }
+ return true;
}
-void litehtml::style::parse_short_font( const tstring& val, bool important )
+void style::parse_font(const string& val, bool important)
{
- add_parsed_property(_t("font-style"), _t("normal"), important);
- add_parsed_property(_t("font-variant"), _t("normal"), important);
- add_parsed_property(_t("font-weight"), _t("normal"), important);
- add_parsed_property(_t("font-size"), _t("medium"), important);
- add_parsed_property(_t("line-height"), _t("normal"), important);
+ if (val == "inherit")
+ {
+ add_parsed_property(_font_style_, property_value(important, prop_type_inherit));
+ add_parsed_property(_font_variant_, property_value(important, prop_type_inherit));
+ add_parsed_property(_font_weight_, property_value(important, prop_type_inherit));
+ add_parsed_property(_font_size_, property_value(important, prop_type_inherit));
+ add_parsed_property(_line_height_, property_value(important, prop_type_inherit));
+ return;
+ } else
+ {
+ add_parsed_property(_font_style_, property_value(font_style_normal, important));
+ add_parsed_property(_font_variant_, property_value(font_variant_normal, important));
+ add_parsed_property(_font_weight_, property_value(font_weight_normal, important));
+ add_parsed_property(_font_size_, property_value(font_size_medium, important));
+ add_parsed_property(_line_height_, property_value(line_height_normal, important));
+ }
string_vector tokens;
- split_string(val, tokens, _t(" "), _t(""), _t("\""));
+ split_string(val, tokens, " ", "", "\"");
- int idx = 0;
- bool was_normal = false;
+ int idx;
bool is_family = false;
- tstring font_family;
- for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+ string font_family;
+ for(const auto& token : tokens)
{
- idx = value_index(tok->c_str(), font_style_strings);
- if(!is_family)
+ if(is_family)
{
- if(idx >= 0)
+ font_family += token;
+ continue;
+ }
+
+ if((idx = value_index(token, font_style_strings)) >= 0)
+ {
+ if(idx == 0)
{
- if(idx == 0 && !was_normal)
- {
- add_parsed_property(_t("font-weight"), *tok, important);
- add_parsed_property(_t("font-variant"), *tok, important);
- add_parsed_property(_t("font-style"), *tok, important);
- } else
- {
- add_parsed_property(_t("font-style"), *tok, important);
- }
+ add_parsed_property(_font_style_, property_value(font_style_normal, important));
+ add_parsed_property(_font_variant_, property_value(font_variant_normal, important));
+ add_parsed_property(_font_weight_, property_value(font_weight_normal, important));
} else
{
- if(value_in_list(tok->c_str(), font_weight_strings))
- {
- add_parsed_property(_t("font-weight"), *tok, important);
- } else
- {
- if(value_in_list(tok->c_str(), font_variant_strings))
- {
- add_parsed_property(_t("font-variant"), *tok, important);
- } else if( iswdigit((*tok)[0]) )
- {
- string_vector szlh;
- split_string(*tok, szlh, _t("/"));
-
- if(szlh.size() == 1)
- {
- add_parsed_property(_t("font-size"), szlh[0], important);
- } else if(szlh.size() >= 2)
- {
- add_parsed_property(_t("font-size"), szlh[0], important);
- add_parsed_property(_t("line-height"), szlh[1], important);
- }
- } else
- {
- is_family = true;
- font_family += *tok;
- }
- }
+ add_parsed_property(_font_style_, property_value(idx, important));
+ }
+ } else if((idx = value_index(token, font_weight_strings)) >= 0)
+ {
+ add_parsed_property(_font_weight_, property_value(idx, important));
+ } else if((idx = value_index(token, font_variant_strings)) >= 0)
+ {
+ add_parsed_property(_font_variant_, property_value(idx, important));
+ }
+ else if(t_isdigit(token[0]) || token[0] == '.' ||
+ value_in_list(token, font_size_strings) || token.find('/') != -1)
+ {
+ string_vector szlh;
+ split_string(token, szlh, "/");
+
+ auto size = css_length::from_string(szlh[0], font_size_strings, -1);
+ add_parsed_property(_font_size_, property_value(size, important));
+
+ if(szlh.size() == 2)
+ {
+ auto height = css_length::from_string(szlh[1], "normal", -1);
+ add_parsed_property(_line_height_, property_value(height, important));
}
} else
{
- font_family += *tok;
+ is_family = true;
+ font_family += token;
}
}
- add_parsed_property(_t("font-family"), font_family, important);
+ add_parsed_property(_font_family_, property_value(font_family, important));
}
-void litehtml::style::add_parsed_property( const tstring& name, const tstring& val, bool important )
+void style::parse_flex(const string& val, bool important)
{
- bool is_valid = true;
- string_map::iterator vals = m_valid_values.find(name);
- if (vals != m_valid_values.end())
+ auto is_number = [](const string& val)
{
- if (!value_in_list(val, vals->second))
+ for (auto ch : val)
{
- is_valid = false;
+ if ((ch < '0' || ch > '9') && ch != '.')
+ {
+ return false;
+ }
}
- }
+ return true;
+ };
- if (is_valid)
+ css_length _auto = css_length::predef_value(flex_basis_auto);
+
+ if (val == "initial")
{
- props_map::iterator prop = m_properties.find(name);
- if (prop != m_properties.end())
+ // 0 1 auto
+ add_parsed_property(_flex_grow_, property_value(0.f, important));
+ add_parsed_property(_flex_shrink_, property_value(1.f, important));
+ add_parsed_property(_flex_basis_, property_value(_auto, important));
+ }
+ else if (val == "auto")
+ {
+ // 1 1 auto
+ add_parsed_property(_flex_grow_, property_value(1.f, important));
+ add_parsed_property(_flex_shrink_, property_value(1.f, important));
+ add_parsed_property(_flex_basis_, property_value(_auto, important));
+ }
+ else if (val == "none")
+ {
+ // 0 0 auto
+ add_parsed_property(_flex_grow_, property_value(0.f, important));
+ add_parsed_property(_flex_shrink_, property_value(0.f, important));
+ add_parsed_property(_flex_basis_, property_value(_auto, important));
+ }
+ else
+ {
+ string_vector tokens;
+ split_string(val, tokens, " ");
+ if (tokens.size() == 3)
{
- if (!prop->second.m_important || (important && prop->second.m_important))
+ float grow = t_strtof(tokens[0]);
+ float shrink = t_strtof(tokens[1]);
+ auto basis = css_length::from_string(tokens[2], flex_basis_strings, -1);
+
+ add_parsed_property(_flex_grow_, property_value(grow, important));
+ add_parsed_property(_flex_shrink_, property_value(shrink, important));
+ add_parsed_property(_flex_basis_, property_value(basis, important));
+ }
+ else if (tokens.size() == 2)
+ {
+ float grow = t_strtof(tokens[0]);
+ add_parsed_property(_flex_grow_, property_value(grow, important));
+
+ if (is_number(tokens[1]))
{
- prop->second.m_value = val;
- prop->second.m_important = important;
+ float shrink = t_strtof(tokens[1]);
+ add_parsed_property(_flex_shrink_, property_value(shrink, important));
+ }
+ else
+ {
+ auto basis = css_length::from_string(tokens[1], flex_basis_strings, -1);
+ add_parsed_property(_flex_basis_, property_value(basis, important));
}
}
- else
+ else if (tokens.size() == 1)
{
- m_properties[name] = property_value(val.c_str(), important);
+ if (is_number(tokens[0]))
+ {
+ float grow = t_strtof(tokens[0]);
+ add_parsed_property(_flex_grow_, property_value(grow, important));
+
+ if (grow >= 1)
+ {
+ add_parsed_property(_flex_shrink_, property_value(1.f, important));
+ add_parsed_property(_flex_basis_, property_value(css_length(0), important));
+ }
+ }
+ else
+ {
+ auto basis = css_length::from_string(tokens[0], flex_basis_strings, -1);
+ add_parsed_property(_flex_basis_, property_value(basis, important));
+ }
}
}
}
-void litehtml::style::remove_property( const tstring& name, bool important )
+void style::add_parsed_property( string_id name, const property_value& propval )
{
- props_map::iterator prop = m_properties.find(name);
+ auto prop = m_properties.find(name);
+ if (prop != m_properties.end())
+ {
+ if (!prop->second.m_important || (propval.m_important && prop->second.m_important))
+ {
+ prop->second = propval;
+ }
+ }
+ else
+ {
+ m_properties[name] = propval;
+ }
+}
+
+void style::remove_property( string_id name, bool important )
+{
+ auto prop = m_properties.find(name);
if(prop != m_properties.end())
{
if( !prop->second.m_important || (important && prop->second.m_important) )
@@ -646,3 +1101,55 @@ void litehtml::style::remove_property( const tstring& name, bool important )
}
}
}
+
+void style::combine(const style& src)
+{
+ for (const auto& property : src.m_properties)
+ {
+ add_parsed_property(property.first, property.second);
+ }
+}
+
+const property_value& style::get_property(string_id name) const
+{
+ auto it = m_properties.find(name);
+ if (it != m_properties.end())
+ {
+ return it->second;
+ }
+ static property_value dummy;
+ return dummy;
+}
+
+void style::subst_vars_(string& str, const element* el)
+{
+ while (1)
+ {
+ auto start = str.find("var(");
+ if (start == -1) break;
+ if (start > 0 && isalnum(str[start - 1])) break;
+ auto end = str.find(")", start + 4);
+ if (end == -1) break;
+ auto name = str.substr(start + 4, end - start - 4);
+ trim(name);
+ string val = el->get_custom_property(_id(name), "");
+ str.replace(start, end - start + 1, val);
+ }
+}
+
+void style::subst_vars(const element* el)
+{
+ for (auto& prop : m_properties)
+ {
+ if (prop.second.m_type == prop_type_var)
+ {
+ subst_vars_(prop.second.m_string, el);
+ // re-adding the same property
+ // if it is a custom property it will be readded as a string (currently it is prop_type_var)
+ // if it is a standard css property it will be parsed and properly added as typed property
+ add_property(prop.first, prop.second.m_string, "", prop.second.m_important, el->get_document()->container());
+ }
+ }
+}
+
+} // namespace litehtml
\ No newline at end of file
diff --git a/src/plugins/litehtml_viewer/litehtml/style.h b/src/plugins/litehtml_viewer/litehtml/style.h
index d84ee20e0..c83876ad6 100644
--- a/src/plugins/litehtml_viewer/litehtml/style.h
+++ b/src/plugins/litehtml_viewer/litehtml/style.h
@@ -1,41 +1,163 @@
#ifndef LH_STYLE_H
#define LH_STYLE_H
-#include "attributes.h"
-#include <string>
-
namespace litehtml
{
+ enum property_type
+ {
+ prop_type_invalid, // indicates "not found" condition in style::get_property
+ prop_type_inherit, // "inherit" was specified as the value of this property
+
+ prop_type_enum_item,
+ prop_type_enum_item_vector,
+ prop_type_length,
+ prop_type_length_vector,
+ prop_type_number,
+ prop_type_color,
+ prop_type_string,
+ prop_type_string_vector,
+ prop_type_size_vector,
+
+ prop_type_var, // also string, but needs further parsing because of var()
+ };
+
class property_value
{
public:
- tstring m_value;
+ property_type m_type;
bool m_important;
+ union {
+ int m_enum_item;
+ int_vector m_enum_item_vector;
+ css_length m_length;
+ length_vector m_length_vector;
+ float m_number;
+ web_color m_color;
+ string m_string;
+ string_vector m_string_vector;
+ size_vector m_size_vector;
+ };
+
property_value()
+ : m_type(prop_type_invalid)
{
- m_important = false;
}
- property_value(const tchar_t* val, bool imp)
+ property_value(bool important, property_type type)
+ : m_type(type), m_important(important)
{
- m_important = imp;
- m_value = val;
}
- property_value(const property_value& val)
+ property_value(const string& str, bool important, property_type type = prop_type_string)
+ : m_string(str), m_type(type), m_important(important)
{
- m_value = val.m_value;
- m_important = val.m_important;
}
-
+ property_value(const string_vector& vec, bool important)
+ : m_string_vector(vec), m_type(prop_type_string_vector), m_important(important)
+ {
+ }
+ property_value(const css_length& length, bool important)
+ : m_length(length), m_type(prop_type_length), m_important(important)
+ {
+ }
+ property_value(const length_vector& vec, bool important)
+ : m_length_vector(vec), m_type(prop_type_length_vector), m_important(important)
+ {
+ }
+ property_value(float number, bool important)
+ : m_number(number), m_type(prop_type_number), m_important(important)
+ {
+ }
+ property_value(int enum_item, bool important)
+ : m_enum_item(enum_item), m_type(prop_type_enum_item), m_important(important)
+ {
+ }
+ property_value(const int_vector& vec, bool important)
+ : m_enum_item_vector(vec), m_type(prop_type_enum_item_vector), m_important(important)
+ {
+ }
+ property_value(web_color color, bool important)
+ : m_color(color), m_type(prop_type_color), m_important(important)
+ {
+ }
+ property_value(const size_vector& vec, bool important)
+ : m_size_vector(vec), m_type(prop_type_size_vector), m_important(important)
+ {
+ }
+ ~property_value()
+ {
+ switch (m_type)
+ {
+ case prop_type_string:
+ case prop_type_var:
+ m_string.~string();
+ break;
+ case prop_type_string_vector:
+ m_string_vector.~string_vector();
+ break;
+ case prop_type_length:
+ m_length.~css_length();
+ break;
+ case prop_type_length_vector:
+ m_length_vector.~length_vector();
+ break;
+ case prop_type_enum_item_vector:
+ m_enum_item_vector.~int_vector();
+ break;
+ case prop_type_color:
+ m_color.~web_color();
+ break;
+ case prop_type_size_vector:
+ m_size_vector.~size_vector();
+ break;
+ }
+ }
property_value& operator=(const property_value& val)
{
- m_value = val.m_value;
- m_important = val.m_important;
+ this->~property_value();
+
+ switch (val.m_type)
+ {
+ case prop_type_invalid:
+ new(this) property_value();
+ break;
+ case prop_type_inherit:
+ new(this) property_value(val.m_important, val.m_type);
+ break;
+ case prop_type_string:
+ case prop_type_var:
+ new(this) property_value(val.m_string, val.m_important, val.m_type);
+ break;
+ case prop_type_string_vector:
+ new(this) property_value(val.m_string_vector, val.m_important);
+ break;
+ case prop_type_enum_item:
+ new(this) property_value(val.m_enum_item, val.m_important);
+ break;
+ case prop_type_enum_item_vector:
+ new(this) property_value(val.m_enum_item_vector, val.m_important);
+ break;
+ case prop_type_length:
+ new(this) property_value(val.m_length, val.m_important);
+ break;
+ case prop_type_length_vector:
+ new(this) property_value(val.m_length_vector, val.m_important);
+ break;
+ case prop_type_number:
+ new(this) property_value(val.m_number, val.m_important);
+ break;
+ case prop_type_color:
+ new(this) property_value(val.m_color, val.m_important);
+ break;
+ case prop_type_size_vector:
+ new(this) property_value(val.m_size_vector, val.m_important);
+ break;
+ }
+
return *this;
}
};
- typedef std::map<tstring, property_value> props_map;
+ typedef std::map<string_id, property_value> props_map;
class style
{
@@ -43,52 +165,47 @@ namespace litehtml
typedef std::shared_ptr<style> ptr;
typedef std::vector<style::ptr> vector;
private:
- props_map m_properties;
- static string_map m_valid_values;
+ props_map m_properties;
+ static std::map<string_id, string> m_valid_values;
public:
- style();
- style(const style& val);
- virtual ~style();
-
- void operator=(const style& val)
+ void add(const string& txt, const string& baseurl = "", document_container* container = nullptr)
{
- m_properties = val.m_properties;
+ parse(txt, baseurl, container);
}
- void add(const tchar_t* txt, const tchar_t* baseurl)
- {
- parse(txt, baseurl);
- }
+ void add_property(string_id name, const string& val, const string& baseurl = "", bool important = false, document_container* container = nullptr);
- void add_property(const tchar_t* name, const tchar_t* val, const tchar_t* baseurl, bool important);
-
- const tchar_t* get_property(const tchar_t* name) const
- {
- if(name)
- {
- props_map::const_iterator f = m_properties.find(name);
- if(f != m_properties.end())
- {
- return f->second.m_value.c_str();
- }
- }
- return 0;
- }
+ const property_value& get_property(string_id name) const;
- void combine(const litehtml::style& src);
+ void combine(const style& src);
void clear()
{
m_properties.clear();
}
+ void subst_vars(const element* el);
+
private:
- void parse_property(const tstring& txt, const tchar_t* baseurl);
- void parse(const tchar_t* txt, const tchar_t* baseurl);
- void parse_short_border(const tstring& prefix, const tstring& val, bool important);
- void parse_short_background(const tstring& val, const tchar_t* baseurl, bool important);
- void parse_short_font(const tstring& val, bool important);
- void add_parsed_property(const tstring& name, const tstring& val, bool important);
- void remove_property(const tstring& name, bool important);
+ void parse_property(const string& txt, const string& baseurl, document_container* container);
+ void parse(const string& txt, const string& baseurl, document_container* container);
+ void parse_background(const string& val, const string& baseurl, bool important, document_container* container);
+ bool parse_one_background(const string& val, document_container* container, background& bg);
+ void parse_background_image(const string& val, const string& baseurl, bool important);
+ // parse comma-separated list of keywords
+ void parse_keyword_comma_list(string_id name, const string& val, bool important);
+ void parse_background_position(const string& val, bool important);
+ bool parse_one_background_position(const string& val, css_length& x, css_length& y);
+ void parse_background_size(const string& val, bool important);
+ bool parse_one_background_size(const string& val, css_size& size);
+ void parse_font(const string& val, bool important);
+ void parse_flex(const string& val, bool important);
+ static css_length parse_border_width(const string& str);
+ static void parse_two_lengths(const string& str, css_length len[2]);
+ static int parse_four_lengths(const string& str, css_length len[4]);
+ static void subst_vars_(string& str, const element* el);
+
+ void add_parsed_property(string_id name, const property_value& propval);
+ void remove_property(string_id name, bool important);
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/stylesheet.cpp b/src/plugins/litehtml_viewer/litehtml/stylesheet.cpp
index 08ace6205..12bfd721d 100644
--- a/src/plugins/litehtml_viewer/litehtml/stylesheet.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/stylesheet.cpp
@@ -4,31 +4,31 @@
#include "document.h"
-void litehtml::css::parse_stylesheet(const tchar_t* str, const tchar_t* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media)
+void litehtml::css::parse_stylesheet(const char* str, const char* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media)
{
- tstring text = str;
+ string text = str;
// remove comments
- tstring::size_type c_start = text.find(_t("/*"));
- while(c_start != tstring::npos)
+ string::size_type c_start = text.find("/*");
+ while(c_start != string::npos)
{
- tstring::size_type c_end = text.find(_t("*/"), c_start + 2);
+ string::size_type c_end = text.find("*/", c_start + 2);
text.erase(c_start, c_end - c_start + 2);
- c_start = text.find(_t("/*"));
+ c_start = text.find("/*");
}
- tstring::size_type pos = text.find_first_not_of(_t(" \n\r\t"));
- while(pos != tstring::npos)
+ string::size_type pos = text.find_first_not_of(" \n\r\t");
+ while(pos != string::npos)
{
- while(pos != tstring::npos && text[pos] == _t('@'))
+ while(pos != string::npos && text[pos] == '@')
{
- tstring::size_type sPos = pos;
- pos = text.find_first_of(_t("{;"), pos);
- if(pos != tstring::npos && text[pos] == _t('{'))
+ string::size_type sPos = pos;
+ pos = text.find_first_of("{;", pos);
+ if(pos != string::npos && text[pos] == '{')
{
- pos = find_close_bracket(text, pos, _t('{'), _t('}'));
+ pos = find_close_bracket(text, pos, '{', '}');
}
- if(pos != tstring::npos)
+ if(pos != string::npos)
{
parse_atrule(text.substr(sPos, pos - sPos + 1), baseurl, doc, media);
} else
@@ -36,25 +36,26 @@ void litehtml::css::parse_stylesheet(const tchar_t* str, const tchar_t* baseurl,
parse_atrule(text.substr(sPos), baseurl, doc, media);
}
- if(pos != tstring::npos)
+ if(pos != string::npos)
{
- pos = text.find_first_not_of(_t(" \n\r\t"), pos + 1);
+ pos = text.find_first_not_of(" \n\r\t", pos + 1);
}
}
- if(pos == tstring::npos)
+ if(pos == string::npos)
{
break;
}
- tstring::size_type style_start = text.find(_t("{"), pos);
- tstring::size_type style_end = text.find(_t("}"), pos);
- if(style_start != tstring::npos && style_end != tstring::npos)
+ string::size_type style_start = text.find('{', pos);
+ string::size_type style_end = text.find('}', pos);
+ if(style_start != string::npos && style_end != string::npos)
{
- style::ptr st = std::make_shared<style>();
- st->add(text.substr(style_start + 1, style_end - style_start - 1).c_str(), baseurl);
+ auto str_style = text.substr(style_start + 1, style_end - style_start - 1);
+ style::ptr style = std::make_shared<litehtml::style>();
+ style->add(str_style, baseurl ? baseurl : "", doc->container());
- parse_selectors(text.substr(pos, style_start - pos), st, media);
+ parse_selectors(text.substr(pos, style_start - pos), style, media);
if(media && doc)
{
@@ -64,34 +65,34 @@ void litehtml::css::parse_stylesheet(const tchar_t* str, const tchar_t* baseurl,
pos = style_end + 1;
} else
{
- pos = tstring::npos;
+ pos = string::npos;
}
- if(pos != tstring::npos)
+ if(pos != string::npos)
{
- pos = text.find_first_not_of(_t(" \n\r\t"), pos);
+ pos = text.find_first_not_of(" \n\r\t", pos);
}
}
}
-void litehtml::css::parse_css_url( const tstring& str, tstring& url )
+void litehtml::css::parse_css_url( const string& str, string& url )
{
- url = _t("");
- size_t pos1 = str.find(_t('('));
- size_t pos2 = str.find(_t(')'));
- if(pos1 != tstring::npos && pos2 != tstring::npos)
+ url = "";
+ size_t pos1 = str.find('(');
+ size_t pos2 = str.find(')');
+ if(pos1 != string::npos && pos2 != string::npos)
{
url = str.substr(pos1 + 1, pos2 - pos1 - 1);
if(url.length())
{
- if(url[0] == _t('\'') || url[0] == _t('"'))
+ if(url[0] == '\'' || url[0] == '"')
{
url.erase(0, 1);
}
}
if(url.length())
{
- if(url[url.length() - 1] == _t('\'') || url[url.length() - 1] == _t('"'))
+ if(url[url.length() - 1] == '\'' || url[url.length() - 1] == '"')
{
url.erase(url.length() - 1, 1);
}
@@ -99,24 +100,24 @@ void litehtml::css::parse_css_url( const tstring& str, tstring& url )
}
}
-bool litehtml::css::parse_selectors( const tstring& txt, const litehtml::style::ptr& styles, const media_query_list::ptr& media )
+bool litehtml::css::parse_selectors( const string& txt, const style::ptr& styles, const media_query_list::ptr& media )
{
- tstring selector = txt;
+ string selector = txt;
trim(selector);
string_vector tokens;
- split_string(selector, tokens, _t(","));
+ split_string(selector, tokens, ",");
bool added_something = false;
- for(string_vector::iterator tok = tokens.begin(); tok != tokens.end(); tok++)
+ for(auto & token : tokens)
{
- css_selector::ptr selector = std::make_shared<css_selector>(media);
- selector->m_style = styles;
- trim(*tok);
- if(selector->parse(*tok))
+ css_selector::ptr new_selector = std::make_shared<css_selector>(media);
+ new_selector->m_style = styles;
+ trim(token);
+ if(new_selector->parse(token))
{
- selector->calc_specificity();
- add_selector(selector);
+ new_selector->calc_specificity();
+ add_selector(new_selector);
added_something = true;
}
}
@@ -134,23 +135,23 @@ void litehtml::css::sort_selectors()
);
}
-void litehtml::css::parse_atrule(const tstring& text, const tchar_t* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media)
+void litehtml::css::parse_atrule(const string& text, const char* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media)
{
- if(text.substr(0, 7) == _t("@import"))
+ if(text.substr(0, 7) == "@import")
{
int sPos = 7;
- tstring iStr;
+ string iStr;
iStr = text.substr(sPos);
- if(iStr[iStr.length() - 1] == _t(';'))
+ if(iStr[iStr.length() - 1] == ';')
{
iStr.erase(iStr.length() - 1);
}
trim(iStr);
string_vector tokens;
- split_string(iStr, tokens, _t(" "), _t(""), _t("(\""));
+ split_string(iStr, tokens, " ", "", "(\"");
if(!tokens.empty())
{
- tstring url;
+ string url;
parse_css_url(tokens.front(), url);
if(url.empty())
{
@@ -162,8 +163,8 @@ void litehtml::css::parse_atrule(const tstring& text, const tchar_t* baseurl, co
document_container* doc_cont = doc->container();
if(doc_cont)
{
- tstring css_text;
- tstring css_baseurl;
+ string css_text;
+ string css_baseurl;
if(baseurl)
{
css_baseurl = baseurl;
@@ -174,12 +175,12 @@ void litehtml::css::parse_atrule(const tstring& text, const tchar_t* baseurl, co
media_query_list::ptr new_media = media;
if(!tokens.empty())
{
- tstring media_str;
- for(string_vector::iterator iter = tokens.begin(); iter != tokens.end(); iter++)
+ string media_str;
+ for(auto iter = tokens.begin(); iter != tokens.end(); iter++)
{
if(iter != tokens.begin())
{
- media_str += _t(" ");
+ media_str += " ";
}
media_str += (*iter);
}
@@ -194,18 +195,18 @@ void litehtml::css::parse_atrule(const tstring& text, const tchar_t* baseurl, co
}
}
}
- } else if(text.substr(0, 6) == _t("@media"))
+ } else if(text.substr(0, 6) == "@media")
{
- tstring::size_type b1 = text.find_first_of(_t('{'));
- tstring::size_type b2 = text.find_last_of(_t('}'));
- if(b1 != tstring::npos)
+ string::size_type b1 = text.find_first_of('{');
+ string::size_type b2 = text.find_last_of('}');
+ if(b1 != string::npos)
{
- tstring media_type = text.substr(6, b1 - 6);
+ string media_type = text.substr(6, b1 - 6);
trim(media_type);
media_query_list::ptr new_media = media_query_list::create_from_string(media_type, doc);
- tstring media_style;
- if(b2 != tstring::npos)
+ string media_style;
+ if(b2 != string::npos)
{
media_style = text.substr(b1 + 1, b2 - b1 - 1);
} else
diff --git a/src/plugins/litehtml_viewer/litehtml/stylesheet.h b/src/plugins/litehtml_viewer/litehtml/stylesheet.h
index 84c5f1fbf..923853d76 100644
--- a/src/plugins/litehtml_viewer/litehtml/stylesheet.h
+++ b/src/plugins/litehtml_viewer/litehtml/stylesheet.h
@@ -12,15 +12,8 @@ namespace litehtml
{
css_selector::vector m_selectors;
public:
- css()
- {
-
- }
-
- ~css()
- {
-
- }
+ css() = default;
+ ~css() = default;
const css_selector::vector& selectors() const
{
@@ -32,18 +25,18 @@ namespace litehtml
m_selectors.clear();
}
- void parse_stylesheet(const tchar_t* str, const tchar_t* baseurl, const std::shared_ptr <document>& doc, const media_query_list::ptr& media);
+ void parse_stylesheet(const char* str, const char* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media);
void sort_selectors();
- static void parse_css_url(const tstring& str, tstring& url);
+ static void parse_css_url(const string& str, string& url);
private:
- void parse_atrule(const tstring& text, const tchar_t* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media);
- void add_selector(css_selector::ptr selector);
- bool parse_selectors(const tstring& txt, const litehtml::style::ptr& styles, const media_query_list::ptr& media);
+ void parse_atrule(const string& text, const char* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media);
+ void add_selector(const css_selector::ptr& selector);
+ bool parse_selectors(const string& txt, const style::ptr& styles, const media_query_list::ptr& media);
};
- inline void litehtml::css::add_selector( css_selector::ptr selector )
+ inline void litehtml::css::add_selector( const css_selector::ptr& selector )
{
selector->m_order = (int) m_selectors.size();
m_selectors.push_back(selector);
diff --git a/src/plugins/litehtml_viewer/litehtml/table.cpp b/src/plugins/litehtml_viewer/litehtml/table.cpp
index c53509c76..da272c070 100644
--- a/src/plugins/litehtml_viewer/litehtml/table.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/table.cpp
@@ -1,13 +1,14 @@
#include "html.h"
#include "table.h"
-#include "html_tag.h"
+#include "element.h"
+#include "render_item.h"
-void litehtml::table_grid::add_cell(element::ptr& el)
+void litehtml::table_grid::add_cell(const std::shared_ptr<render_item>& el)
{
table_cell cell;
cell.el = el;
- cell.colspan = t_atoi(el->get_attr(_t("colspan"), _t("1")));
- cell.rowspan = t_atoi(el->get_attr(_t("rowspan"), _t("1")));
+ cell.colspan = atoi(el->src_el()->get_attr("colspan", "1"));
+ cell.rowspan = atoi(el->src_el()->get_attr("rowspan", "1"));
cell.borders = el->get_borders();
while( is_rowspanned( (int) m_cells.size() - 1, (int) m_cells.back().size() ) )
@@ -24,13 +25,12 @@ void litehtml::table_grid::add_cell(element::ptr& el)
}
-void litehtml::table_grid::begin_row(element::ptr& row)
+void litehtml::table_grid::begin_row(const std::shared_ptr<render_item>& row)
{
std::vector<table_cell> r;
m_cells.push_back(r);
m_rows.push_back(table_row(0, row));
-
}
@@ -56,16 +56,16 @@ void litehtml::table_grid::finish()
{
m_rows_count = (int) m_cells.size();
m_cols_count = 0;
- for(int i = 0; i < (int) m_cells.size(); i++)
+ for(auto& cell : m_cells)
{
- m_cols_count = std::max(m_cols_count, (int) m_cells[i].size());
+ m_cols_count = std::max(m_cols_count, (int) cell.size());
}
- for(int i = 0; i < (int) m_cells.size(); i++)
+ for(auto& cell : m_cells)
{
- for(int j = (int) m_cells[i].size(); j < m_cols_count; j++)
+ for(int j = (int) cell.size(); j < m_cols_count; j++)
{
table_cell empty_cell;
- m_cells[i].push_back(empty_cell);
+ cell.push_back(empty_cell);
}
}
@@ -117,9 +117,9 @@ void litehtml::table_grid::finish()
if(cell(col, row)->el && cell(col, row)->colspan <= 1)
{
- if (!cell(col, row)->el->get_css_width().is_predefined() && m_columns[col].css_width.is_predefined())
+ if (!cell(col, row)->el->src_el()->css().get_width().is_predefined() && m_columns[col].css_width.is_predefined())
{
- m_columns[col].css_width = cell(col, row)->el->get_css_width();
+ m_columns[col].css_width = cell(col, row)->el->src_el()->css().get_width();
}
}
}
@@ -129,9 +129,9 @@ void litehtml::table_grid::finish()
{
for(int row = 0; row < m_rows_count; row++)
{
- if(cell(col, row)->el)
+ if(cell(col, row)->el && cell(col, row)->colspan == 1)
{
- cell(col, row)->el->set_css_width(m_columns[col].css_width);
+ cell(col, row)->el->src_el()->css_w().set_width(m_columns[col].css_width);
}
}
}
@@ -143,7 +143,7 @@ litehtml::table_cell* litehtml::table_grid::cell( int t_col, int t_row )
{
return &m_cells[t_row][t_col];
}
- return 0;
+ return nullptr;
}
void litehtml::table_grid::distribute_max_width( int width, int start, int end )
@@ -243,25 +243,25 @@ void litehtml::table_grid::distribute_width( int width, int start, int end )
if(!distribute_columns.empty() || step == 2)
{
int cols_width = 0;
- for(std::vector<table_column*>::iterator col = distribute_columns.begin(); col != distribute_columns.end(); col++)
+ for(const auto& column : distribute_columns)
{
- cols_width += (*col)->max_width - (*col)->min_width;
+ cols_width += column->max_width - column->min_width;
}
if(cols_width)
{
int add = width / (int) distribute_columns.size();
- for(std::vector<table_column*>::iterator col = distribute_columns.begin(); col != distribute_columns.end(); col++)
+ for(const auto& column : distribute_columns)
{
- add = round_f( (float) width * ((float) ((*col)->max_width - (*col)->min_width) / (float) cols_width) );
- if((*col)->width + add >= (*col)->min_width)
+ add = round_f( (float) width * ((float) (column->max_width - column->min_width) / (float) cols_width) );
+ if(column->width + add >= column->min_width)
{
- (*col)->width += add;
+ column->width += add;
added_width += add;
} else
{
- added_width += ((*col)->width - (*col)->min_width) * (add / abs(add));
- (*col)->width = (*col)->min_width;
+ added_width += (column->width - column->min_width) * (add / abs(add));
+ column->width = column->min_width;
}
}
if(added_width < width && step)
@@ -359,7 +359,7 @@ int litehtml::table_grid::calc_table_width(int block_width, bool is_auto, int& m
fixed_width += m_columns[col].width;
}
}
- float scale = (float) (100.0 / percent);
+ auto scale = (float) (100.0 / percent);
cur_width = 0;
for(int col = 0; col < m_cols_count; col++)
{
@@ -375,6 +375,34 @@ int litehtml::table_grid::calc_table_width(int block_width, bool is_auto, int& m
}
cur_width += m_columns[col].width;
}
+ // If the table is still too wide shrink columns with % widths
+ if(cur_width > block_width)
+ {
+ while(true)
+ {
+ bool shrunk = false;
+ for(int col = 0; col < m_cols_count; col++)
+ {
+ if(!m_columns[col].css_width.is_predefined() && m_columns[col].css_width.units() == css_units_percentage)
+ {
+ if(m_columns[col].width > m_columns[col].min_width)
+ {
+ m_columns[col].width--;
+ cur_width--;
+ shrunk = true;
+ if(cur_width == block_width)
+ {
+ break;
+ }
+ }
+ }
+ }
+ if(cur_width == block_width || !shrunk)
+ {
+ break;
+ }
+ }
+ }
}
return cur_width;
}
@@ -388,7 +416,7 @@ void litehtml::table_grid::clear()
m_rows.clear();
}
-void litehtml::table_grid::calc_horizontal_positions( margins& table_borders, border_collapse bc, int bdr_space_x)
+void litehtml::table_grid::calc_horizontal_positions( const margins& table_borders, border_collapse bc, int bdr_space_x)
{
if(bc == border_collapse_separate)
{
@@ -420,7 +448,7 @@ void litehtml::table_grid::calc_horizontal_positions( margins& table_borders, bo
}
}
-void litehtml::table_grid::calc_vertical_positions( margins& table_borders, border_collapse bc, int bdr_space_y )
+void litehtml::table_grid::calc_vertical_positions( const margins& table_borders, border_collapse bc, int bdr_space_y )
{
if(bc == border_collapse_separate)
{
@@ -564,3 +592,18 @@ int& litehtml::table_column_accessor_width::get( table_column& col )
{
return col.width;
}
+
+litehtml::table_row::table_row(int h, const std::shared_ptr<render_item>& row)
+{
+ min_height = 0;
+ height = h;
+ el_row = row;
+ border_bottom = 0;
+ border_top = 0;
+ top = 0;
+ bottom = 0;
+ if (row)
+ {
+ css_height = row->src_el()->css().get_height();
+ }
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/table.h b/src/plugins/litehtml_viewer/litehtml/table.h
index ca95febf5..edd5f055e 100644
--- a/src/plugins/litehtml_viewer/litehtml/table.h
+++ b/src/plugins/litehtml_viewer/litehtml/table.h
@@ -1,8 +1,14 @@
#ifndef LH_TABLE_H
#define LH_TABLE_H
+#include <vector>
+#include <memory>
+#include "css_length.h"
+
namespace litehtml
{
+ class render_item;
+
struct table_row
{
typedef std::vector<table_row> vector;
@@ -10,7 +16,7 @@ namespace litehtml
int height;
int border_top;
int border_bottom;
- element::ptr el_row;
+ std::shared_ptr<render_item> el_row;
int top;
int bottom;
css_length css_height;
@@ -28,20 +34,7 @@ namespace litehtml
css_height.predef(0);
}
- table_row(int h, element::ptr& row)
- {
- min_height = 0;
- height = h;
- el_row = row;
- border_bottom = 0;
- border_top = 0;
- top = 0;
- bottom = 0;
- if (row)
- {
- css_height = row->get_css_height();
- }
- }
+ table_row(int h, const std::shared_ptr<render_item>& row);
table_row(const table_row& val)
{
@@ -55,7 +48,7 @@ namespace litehtml
el_row = val.el_row;
}
- table_row(table_row&& val)
+ table_row(table_row&& val) noexcept
{
min_height = val.min_height;
top = val.top;
@@ -122,29 +115,32 @@ namespace litehtml
{
public:
virtual int& get(table_column& col) = 0;
+
+ protected:
+ ~table_column_accessor() = default;
};
- class table_column_accessor_max_width : public table_column_accessor
+ class table_column_accessor_max_width final : public table_column_accessor
{
public:
- virtual int& get(table_column& col);
+ int& get(table_column& col) override;
};
- class table_column_accessor_min_width : public table_column_accessor
+ class table_column_accessor_min_width final : public table_column_accessor
{
public:
- virtual int& get(table_column& col);
+ int& get(table_column& col) override;
};
- class table_column_accessor_width : public table_column_accessor
+ class table_column_accessor_width final : public table_column_accessor
{
public:
- virtual int& get(table_column& col);
+ int& get(table_column& col) override;
};
struct table_cell
{
- element::ptr el;
+ std::shared_ptr<render_item> el;
int colspan;
int rowspan;
int min_width;
@@ -182,8 +178,8 @@ namespace litehtml
borders = val.borders;
}
- table_cell(const table_cell&& val)
- {
+ table_cell(table_cell&& val) noexcept
+ {
el = std::move(val.el);
colspan = val.colspan;
rowspan = val.rowspan;
@@ -207,33 +203,40 @@ namespace litehtml
rows m_cells;
table_column::vector m_columns;
table_row::vector m_rows;
+ std::vector<std::shared_ptr<render_item>> m_captions;
+ int m_captions_height;
public:
table_grid()
{
m_rows_count = 0;
m_cols_count = 0;
+ m_captions_height = 0;
}
void clear();
- void begin_row(element::ptr& row);
- void add_cell(element::ptr& el);
+ void begin_row(const std::shared_ptr<render_item>& row);
+ void add_cell(const std::shared_ptr<render_item>& el);
bool is_rowspanned(int r, int c);
void finish();
table_cell* cell(int t_col, int t_row);
table_column& column(int c) { return m_columns[c]; }
table_row& row(int r) { return m_rows[r]; }
+ std::vector<std::shared_ptr<render_item>>& captions() { return m_captions; }
+
+ int rows_count() const { return m_rows_count; }
+ int cols_count() const { return m_cols_count; }
- int rows_count() { return m_rows_count; }
- int cols_count() { return m_cols_count; }
+ void captions_height(int height) { m_captions_height = height; }
+ int captions_height() const { return m_captions_height; }
void distribute_max_width(int width, int start, int end);
void distribute_min_width(int width, int start, int end);
void distribute_width(int width, int start, int end);
void distribute_width(int width, int start, int end, table_column_accessor* acc);
int calc_table_width(int block_width, bool is_auto, int& min_table_width, int& max_table_width);
- void calc_horizontal_positions(margins& table_borders, border_collapse bc, int bdr_space_x);
- void calc_vertical_positions(margins& table_borders, border_collapse bc, int bdr_space_y);
+ void calc_horizontal_positions(const margins& table_borders, border_collapse bc, int bdr_space_x);
+ void calc_vertical_positions(const margins& table_borders, border_collapse bc, int bdr_space_y);
void calc_rows_height(int blockHeight, int borderSpacingY);
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/tstring_view.cpp b/src/plugins/litehtml_viewer/litehtml/tstring_view.cpp
new file mode 100644
index 000000000..f9afa4bbc
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/tstring_view.cpp
@@ -0,0 +1,46 @@
+// Copyright (C) 2020-2021 Primate Labs Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the names of the copyright holders nor the names of their
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "tstring_view.h"
+
+namespace litehtml {
+
+
+std::basic_ostream<tstring_view::value_type>& operator<<(
+ std::basic_ostream<tstring_view::value_type>& os,
+ tstring_view str)
+{
+ if (os.good()) {
+ os.write(str.data(), str.size());
+ }
+
+ return os;
+}
+
+} // namespace litehtml
\ No newline at end of file
diff --git a/src/plugins/litehtml_viewer/litehtml/tstring_view.h b/src/plugins/litehtml_viewer/litehtml/tstring_view.h
new file mode 100644
index 000000000..384c8d7df
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/tstring_view.h
@@ -0,0 +1,136 @@
+// Copyright (C) 2020-2021 Primate Labs Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the names of the copyright holders nor the names of their
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef LITEHTML_TSTRING_VIEW_H__
+#define LITEHTML_TSTRING_VIEW_H__
+
+#include <cstddef>
+#include <ostream>
+
+#include "os_types.h"
+
+namespace litehtml {
+
+// tstring_view is a string reference type that provides a view into a string
+// that is owned elsewhere (e.g., by a std::string object).
+
+// tstring_view implements the same interface as std::base_string_view in the
+// standard library. When litehtml moves to C++17 consider replacing the
+// tstring_view implementation with the standard library implementations
+// (e.g., via a using statement).
+
+class tstring_view {
+public:
+ using value_type = char;
+
+ using pointer = char*;
+
+ using const_pointer = const char*;
+
+ using reference = char&;
+
+ using const_reference = const char&;
+
+ using iterator = const_pointer;
+
+ using const_iterator = const_pointer;
+
+ using size_type = size_t;
+
+ using difference_type = std::ptrdiff_t;
+
+public:
+ tstring_view() = default;
+
+ tstring_view(const tstring_view& other) = default;
+
+ tstring_view(const_pointer s, size_type size)
+ : data_(s)
+ , size_(size)
+ {
+ }
+
+ constexpr const_iterator begin() const
+ {
+ return data_;
+ }
+
+ constexpr const_iterator cbegin() const
+ {
+ return data_;
+ }
+
+ constexpr const_iterator end() const
+ {
+ return data_ + size_;
+ }
+
+ constexpr const_iterator cend() const
+ {
+ return data_ + size_;
+ }
+
+ constexpr const_reference operator[](size_type offset) const
+ {
+ return *(data_ + offset);
+ }
+
+ constexpr const_pointer data() const
+ {
+ return data_;
+ }
+
+ size_type size() const
+ {
+ return size_;
+ }
+
+ size_type length() const
+ {
+ return size_;
+ }
+
+ bool empty() const
+ {
+ return (size_ == 0);
+ }
+
+private:
+ const_pointer data_ = nullptr;
+
+ size_type size_ = 0;
+};
+
+std::basic_ostream<tstring_view::value_type>& operator<<(
+ std::basic_ostream<tstring_view::value_type>&,
+ tstring_view str);
+
+} // namespace litehtml
+
+#endif // LITEHTML_TSTRING_VIEW_H__
diff --git a/src/plugins/litehtml_viewer/litehtml/types.h b/src/plugins/litehtml_viewer/litehtml/types.h
index 682fd7354..7946a3f08 100644
--- a/src/plugins/litehtml_viewer/litehtml/types.h
+++ b/src/plugins/litehtml_viewer/litehtml/types.h
@@ -1,7 +1,7 @@
#ifndef LH_TYPES_H
#define LH_TYPES_H
-#include <stdlib.h>
+#include <cstdlib>
#include <memory>
#include <map>
#include <vector>
@@ -11,10 +11,10 @@ namespace litehtml
class document;
class element;
- typedef std::map<litehtml::tstring, litehtml::tstring> string_map;
- typedef std::vector< std::shared_ptr<litehtml::element> > elements_vector;
- typedef std::vector<int> int_vector;
- typedef std::vector<litehtml::tstring> string_vector;
+ typedef std::map<string, string> string_map;
+ typedef std::vector< std::shared_ptr<element> > elements_vector;
+ typedef std::vector<int> int_vector;
+ typedef std::vector<string> string_vector;
const unsigned int font_decoration_none = 0x00;
const unsigned int font_decoration_underline = 0x01;
@@ -45,10 +45,12 @@ namespace litehtml
int width;
int height;
- size()
+ size(int w, int h) : width(w), height(h)
+ {
+ }
+
+ size() : width(0), height(0)
{
- width = 0;
- height = 0;
}
};
@@ -162,7 +164,7 @@ namespace litehtml
x_height = 0;
draw_spaces = true;
}
- int base_line() { return descent; }
+ int base_line() const { return descent; }
};
struct font_item
@@ -171,7 +173,7 @@ namespace litehtml
font_metrics metrics;
};
- typedef std::map<tstring, font_item> fonts_map;
+ typedef std::map<string, font_item> fonts_map;
enum draw_flag
{
@@ -182,7 +184,81 @@ namespace litehtml
draw_positioned,
};
-#define style_display_strings _t("none;block;inline;inline-block;inline-table;list-item;table;table-caption;table-cell;table-column;table-column-group;table-footer-group;table-header-group;table-row;table-row-group;inline-text")
+ struct containing_block_context
+ {
+ enum cbc_value_type
+ {
+ cbc_value_type_absolute, // width/height of containing block is defined as absolute value
+ cbc_value_type_percentage, // width/height of containing block is defined as percentage
+ cbc_value_type_auto, // width/height of containing block is defined as auto
+ cbc_value_type_none, // min/max width/height of containing block is defined as none
+ };
+
+ struct typed_int
+ {
+ int value;
+ cbc_value_type type;
+
+ typed_int(int val, cbc_value_type tp)
+ {
+ value = val;
+ type = tp;
+ }
+
+ operator int() const
+ {
+ return value;
+ }
+
+ typed_int& operator=(int val)
+ {
+ value = val;
+ return *this;
+ }
+
+ typed_int& operator=(const typed_int& v)
+ {
+ value = v.value;
+ type = v.type;
+ return *this;
+ }
+ };
+
+ typed_int width; // width of the containing block
+ typed_int render_width;
+ typed_int min_width;
+ typed_int max_width;
+
+ typed_int height; // height of the containing block
+ typed_int min_height;
+ typed_int max_height;
+
+ int context_idx;
+
+ containing_block_context() :
+ width(0, cbc_value_type_auto),
+ render_width(0, cbc_value_type_auto),
+ min_width(0, cbc_value_type_none),
+ max_width(0, cbc_value_type_none),
+ height(0, cbc_value_type_auto),
+ min_height(0, cbc_value_type_none),
+ max_height(0, cbc_value_type_none),
+ context_idx(0)
+ {}
+
+ containing_block_context new_width(int w) const
+ {
+ containing_block_context ret = *this;
+ //if(ret.width.type != cbc_value_type_absolute)
+ {
+ ret.render_width = w - (ret.width - ret.render_width);
+ ret.width = w;
+ }
+ return ret;
+ }
+ };
+
+#define style_display_strings "none;block;inline;inline-block;inline-table;list-item;table;table-caption;table-cell;table-column;table-column-group;table-footer-group;table-header-group;table-row;table-row-group;inline-text;flex;inline-flex"
enum style_display
{
@@ -202,68 +278,68 @@ namespace litehtml
display_table_row,
display_table_row_group,
display_inline_text,
+ display_flex,
+ display_inline_flex,
};
- enum style_border
+#define font_size_strings "xx-small;x-small;small;medium;large;x-large;xx-large;smaller;larger"
+
+ enum font_size
{
- borderNope,
- borderNone,
- borderHidden,
- borderDotted,
- borderDashed,
- borderSolid,
- borderDouble
+ font_size_xx_small,
+ font_size_x_small,
+ font_size_small,
+ font_size_medium,
+ font_size_large,
+ font_size_x_large,
+ font_size_xx_large,
+ font_size_smaller,
+ font_size_larger,
};
-#define font_size_strings _t("xx-small;x-small;small;medium;large;x-large;xx-large;smaller;larger")
+#define line_height_strings "normal"
- enum font_size
+ enum line_height
{
- fontSize_xx_small,
- fontSize_x_small,
- fontSize_small,
- fontSize_medium,
- fontSize_large,
- fontSize_x_large,
- fontSize_xx_large,
- fontSize_smaller,
- fontSize_larger,
+ line_height_normal
};
-#define font_style_strings _t("normal;italic")
+#define font_style_strings "normal;italic"
enum font_style
{
- fontStyleNormal,
- fontStyleItalic
+ font_style_normal,
+ font_style_italic
};
-#define font_variant_strings _t("normal;small-caps")
+#define font_variant_strings "normal;small-caps"
enum font_variant
{
font_variant_normal,
- font_variant_italic
+ font_variant_small_caps
};
-#define font_weight_strings _t("normal;bold;bolder;lighter;100;200;300;400;500;600;700")
+#define font_weight_strings "normal;bold;bolder;lighter;100;200;300;400;500;600;700;800;900"
enum font_weight
{
- fontWeightNormal,
- fontWeightBold,
- fontWeightBolder,
- fontWeightLighter,
- fontWeight100,
- fontWeight200,
- fontWeight300,
- fontWeight400,
- fontWeight500,
- fontWeight600,
- fontWeight700
+ font_weight_normal,
+ font_weight_bold,
+ font_weight_bolder,
+ font_weight_lighter,
+ font_weight_100,
+ font_weight_200,
+ font_weight_300,
+ font_weight_400,
+ font_weight_500,
+ font_weight_600,
+ font_weight_700,
+ font_weight_800,
+ font_weight_900
};
-#define list_style_type_strings _t("none;circle;disc;square;armenian;cjk-ideographic;decimal;decimal-leading-zero;georgian;hebrew;hiragana;hiragana-iroha;katakana;katakana-iroha;lower-alpha;lower-greek;lower-latin;lower-roman;upper-alpha;upper-latin;upper-roman")
+#define list_style_type_strings "none;circle;disc;square;armenian;cjk-ideographic;decimal;decimal-leading-zero;georgian;hebrew;hiragana;hiragana-iroha;katakana;katakana-iroha;lower-alpha;lower-greek;lower-latin;lower-roman;upper-alpha;upper-latin;upper-roman"
enum list_style_type
{
@@ -290,7 +366,7 @@ namespace litehtml
list_style_type_upper_roman,
};
-#define list_style_position_strings _t("inside;outside")
+#define list_style_position_strings "inside;outside"
enum list_style_position
{
@@ -298,7 +374,7 @@ namespace litehtml
list_style_position_outside
};
-#define vertical_align_strings _t("baseline;sub;super;top;text-top;middle;bottom;text-bottom")
+#define vertical_align_strings "baseline;sub;super;top;text-top;middle;bottom;text-bottom"
enum vertical_align
{
@@ -312,7 +388,7 @@ namespace litehtml
va_text_bottom
};
-#define border_width_strings _t("thin;medium;thick")
+#define border_width_strings "thin;medium;thick"
enum border_width
{
@@ -321,7 +397,12 @@ namespace litehtml
border_width_thick
};
-#define border_style_strings _t("none;hidden;dotted;dashed;solid;double;groove;ridge;inset;outset")
+ const float border_width_thin_value = 1;
+ const float border_width_medium_value = 3;
+ const float border_width_thick_value = 5;
+ const float border_width_values[] = { border_width_thin_value, border_width_medium_value, border_width_thick_value };
+
+#define border_style_strings "none;hidden;dotted;dashed;solid;double;groove;ridge;inset;outset"
enum border_style
{
@@ -337,7 +418,7 @@ namespace litehtml
border_style_outset
};
-#define element_float_strings _t("none;left;right")
+#define element_float_strings "none;left;right"
enum element_float
{
@@ -346,7 +427,7 @@ namespace litehtml
float_right
};
-#define element_clear_strings _t("none;left;right;both")
+#define element_clear_strings "none;left;right;both"
enum element_clear
{
@@ -356,9 +437,9 @@ namespace litehtml
clear_both
};
-#define css_units_strings _t("none;%;in;cm;mm;em;ex;pt;pc;px;dpi;dpcm;vw;vh;vmin;vmax;rem")
+#define css_units_strings "none;%;in;cm;mm;em;ex;pt;pc;px;dpi;dpcm;vw;vh;vmin;vmax;rem"
- enum css_units
+ enum css_units : byte
{
css_units_none,
css_units_percentage,
@@ -379,7 +460,7 @@ namespace litehtml
css_units_rem,
};
-#define background_attachment_strings _t("scroll;fixed")
+#define background_attachment_strings "scroll;fixed"
enum background_attachment
{
@@ -387,7 +468,7 @@ namespace litehtml
background_attachment_fixed
};
-#define background_repeat_strings _t("repeat;repeat-x;repeat-y;no-repeat")
+#define background_repeat_strings "repeat;repeat-x;repeat-y;no-repeat"
enum background_repeat
{
@@ -397,7 +478,7 @@ namespace litehtml
background_repeat_no_repeat
};
-#define background_box_strings _t("border-box;padding-box;content-box")
+#define background_box_strings "border-box;padding-box;content-box"
enum background_box
{
@@ -406,7 +487,18 @@ namespace litehtml
background_box_content
};
-#define element_position_strings _t("static;relative;absolute;fixed")
+#define background_position_strings "top;bottom;left;right;center"
+
+ enum background_position
+ {
+ background_position_top,
+ background_position_bottom,
+ background_position_left,
+ background_position_right,
+ background_position_center,
+ };
+
+#define element_position_strings "static;relative;absolute;fixed"
enum element_position
{
@@ -416,7 +508,7 @@ namespace litehtml
element_position_fixed,
};
-#define text_align_strings _t("left;right;center;justify")
+#define text_align_strings "left;right;center;justify"
enum text_align
{
@@ -426,7 +518,7 @@ namespace litehtml
text_align_justify
};
-#define text_transform_strings _t("none;capitalize;uppercase;lowercase")
+#define text_transform_strings "none;capitalize;uppercase;lowercase"
enum text_transform
{
@@ -436,7 +528,7 @@ namespace litehtml
text_transform_lowercase
};
-#define white_space_strings _t("normal;nowrap;pre;pre-line;pre-wrap")
+#define white_space_strings "normal;nowrap;pre;pre-line;pre-wrap"
enum white_space
{
@@ -447,7 +539,7 @@ namespace litehtml
white_space_pre_wrap
};
-#define overflow_strings _t("visible;hidden;scroll;auto;no-display;no-content")
+#define overflow_strings "visible;hidden;scroll;auto;no-display;no-content"
enum overflow
{
@@ -459,7 +551,7 @@ namespace litehtml
overflow_no_content
};
-#define background_size_strings _t("auto;cover;contain")
+#define background_size_strings "auto;cover;contain"
enum background_size
{
@@ -468,7 +560,7 @@ namespace litehtml
background_size_contain,
};
-#define visibility_strings _t("visible;hidden;collapse")
+#define visibility_strings "visible;hidden;collapse"
enum visibility
{
@@ -477,7 +569,7 @@ namespace litehtml
visibility_collapse,
};
-#define border_collapse_strings _t("collapse;separate")
+#define border_collapse_strings "collapse;separate"
enum border_collapse
{
@@ -485,26 +577,7 @@ namespace litehtml
border_collapse_separate,
};
-
-#define pseudo_class_strings _t("only-child;only-of-type;first-child;first-of-type;last-child;last-of-type;nth-child;nth-of-type;nth-last-child;nth-last-of-type;not;lang")
-
- enum pseudo_class
- {
- pseudo_class_only_child,
- pseudo_class_only_of_type,
- pseudo_class_first_child,
- pseudo_class_first_of_type,
- pseudo_class_last_child,
- pseudo_class_last_of_type,
- pseudo_class_nth_child,
- pseudo_class_nth_of_type,
- pseudo_class_nth_last_child,
- pseudo_class_nth_last_of_type,
- pseudo_class_not,
- pseudo_class_lang,
- };
-
-#define content_property_string _t("none;normal;open-quote;close-quote;no-open-quote;no-close-quote")
+#define content_property_string "none;normal;open-quote;close-quote;no-open-quote;no-close-quote"
enum content_property
{
@@ -516,15 +589,15 @@ namespace litehtml
content_property_no_close_quote,
};
+ class render_item;
struct floated_box
{
- typedef std::vector<floated_box> vector;
-
- position pos;
- element_float float_side;
- element_clear clear_floats;
- std::shared_ptr<element> el;
+ position pos;
+ element_float float_side;
+ element_clear clear_floats;
+ std::shared_ptr<render_item> el;
+ int context;
floated_box() = default;
floated_box(const floated_box& val)
@@ -533,6 +606,7 @@ namespace litehtml
float_side = val.float_side;
clear_floats = val.clear_floats;
el = val.el;
+ context = val.context;
}
floated_box& operator=(const floated_box& val)
{
@@ -540,6 +614,7 @@ namespace litehtml
float_side = val.float_side;
clear_floats = val.clear_floats;
el = val.el;
+ context = val.context;
return *this;
}
floated_box(floated_box&& val)
@@ -548,6 +623,7 @@ namespace litehtml
float_side = val.float_side;
clear_floats = val.clear_floats;
el = std::move(val.el);
+ context = val.context;
}
void operator=(floated_box&& val)
{
@@ -555,6 +631,7 @@ namespace litehtml
float_side = val.float_side;
clear_floats = val.clear_floats;
el = std::move(val.el);
+ context = val.context;
}
};
@@ -627,7 +704,7 @@ namespace litehtml
};
-#define media_orientation_strings _t("portrait;landscape")
+#define media_orientation_strings "portrait;landscape"
enum media_orientation
{
@@ -635,7 +712,7 @@ namespace litehtml
media_orientation_landscape,
};
-#define media_feature_strings _t("none;width;min-width;max-width;height;min-height;max-height;device-width;min-device-width;max-device-width;device-height;min-device-height;max-device-height;orientation;aspect-ratio;min-aspect-ratio;max-aspect-ratio;device-aspect-ratio;min-device-aspect-ratio;max-device-aspect-ratio;color;min-color;max-color;color-index;min-color-index;max-color-index;monochrome;min-monochrome;max-monochrome;resolution;min-resolution;max-resolution")
+#define media_feature_strings "none;width;min-width;max-width;height;min-height;max-height;device-width;min-device-width;max-device-width;device-height;min-device-height;max-device-height;orientation;aspect-ratio;min-aspect-ratio;max-aspect-ratio;device-aspect-ratio;min-device-aspect-ratio;max-device-aspect-ratio;color;min-color;max-color;color-index;min-color-index;max-color-index;monochrome;min-monochrome;max-monochrome;resolution;min-resolution;max-resolution"
enum media_feature
{
@@ -684,7 +761,7 @@ namespace litehtml
media_feature_max_resolution,
};
-#define box_sizing_strings _t("content-box;border-box")
+#define box_sizing_strings "content-box;border-box"
enum box_sizing
{
@@ -693,7 +770,7 @@ namespace litehtml
};
-#define media_type_strings _t("none;all;screen;print;braille;embossed;handheld;projection;speech;tty;tv")
+#define media_type_strings "none;all;screen;print;braille;embossed;handheld;projection;speech;tty;tv"
enum media_type
{
@@ -721,6 +798,19 @@ namespace litehtml
int color_index; // The number of entries in the color lookup table of the output device. If the device does not use a color lookup table, the value is zero.
int monochrome; // The number of bits per pixel in a monochrome frame buffer. If the device is not a monochrome device, the output device value will be 0.
int resolution; // The resolution of the output device (in DPI)
+
+ media_features()
+ {
+ type = media_type::media_type_none,
+ width =0;
+ height = 0;
+ device_width = 0;
+ device_height = 0;
+ color = 0;
+ color_index = 0;
+ monochrome = 0;
+ resolution = 0;
+ }
};
enum render_type
@@ -731,7 +821,84 @@ namespace litehtml
};
// List of the Void Elements (can't have any contents)
- const litehtml::tchar_t* const void_elements = _t("area;base;br;col;command;embed;hr;img;input;keygen;link;meta;param;source;track;wbr");
+ const char* const void_elements = "area;base;br;col;command;embed;hr;img;input;keygen;link;meta;param;source;track;wbr";
+
+#define flex_direction_strings "row;row-reverse;column;column-reverse"
+
+ enum flex_direction
+ {
+ flex_direction_row,
+ flex_direction_row_reverse,
+ flex_direction_column,
+ flex_direction_column_reverse
+ };
+
+#define flex_wrap_strings "nowrap;wrap;wrap-reverse"
+
+ enum flex_wrap
+ {
+ flex_wrap_nowrap,
+ flex_wrap_wrap,
+ flex_wrap_wrap_reverse
+ };
+
+#define flex_justify_content_strings "flex-start;flex-end;center;space-between;space-around"
+
+ enum flex_justify_content
+ {
+ flex_justify_content_flex_start,
+ flex_justify_content_flex_end,
+ flex_justify_content_center,
+ flex_justify_content_space_between,
+ flex_justify_content_space_around
+ };
+
+#define flex_align_items_strings "flex-start;flex-end;center;baseline;stretch"
+
+ enum flex_align_items
+ {
+ flex_align_items_flex_start,
+ flex_align_items_flex_end,
+ flex_align_items_center,
+ flex_align_items_baseline,
+ flex_align_items_stretch
+ };
+
+#define flex_align_self_strings "auto;flex-start;flex-end;center;baseline;stretch"
+
+ enum flex_align_self
+ {
+ flex_align_self_auto,
+ flex_align_self_flex_start,
+ flex_align_self_flex_end,
+ flex_align_self_center,
+ flex_align_self_baseline,
+ flex_align_self_stretch
+ };
+
+#define flex_align_content_strings "flex-start;flex-end;center;space-between;space-around;stretch"
+
+ enum flex_align_content
+ {
+ flex_align_content_flex_start,
+ flex_align_content_flex_end,
+ flex_align_content_center,
+ flex_align_content_space_between,
+ flex_align_content_space_around,
+ flex_align_content_stretch
+ };
+
+#define flex_basis_strings "auto;content;fit-content;min-content;max-content"
+
+ enum flex_basis
+ {
+ flex_basis_auto,
+ flex_basis_content,
+ flex_basis_fit_content,
+ flex_basis_min_content,
+ flex_basis_max_content,
+ };
+
}
#endif // LH_TYPES_H
diff --git a/src/plugins/litehtml_viewer/litehtml/url.cpp b/src/plugins/litehtml_viewer/litehtml/url.cpp
new file mode 100644
index 000000000..13076e338
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/url.cpp
@@ -0,0 +1,163 @@
+// Copyright (C) 2020-2021 Primate Labs Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the names of the copyright holders nor the names of their
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "url.h"
+
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+
+#include "codepoint.h"
+#include "url_path.h"
+
+namespace litehtml {
+
+url::url(const string& str)
+: str_(str)
+{
+ // TODO: Rewrite using tstring_view to avoid unnecessary allocations.
+ string tmp = str_;
+
+ // Does the URL include a scheme?
+ size_t offset = tmp.find(':');
+ if (offset != string::npos) {
+ bool valid_scheme = true;
+ for (size_t i = 0; i < offset; i++) {
+ if (!is_url_scheme_codepoint(tmp[i])) {
+ valid_scheme = false;
+ break;
+ }
+ }
+ if (valid_scheme) {
+ scheme_ = tmp.substr(0, offset);
+ tmp = tmp.substr(offset + 1);
+ }
+ }
+
+ // Does the URL include an authority? An authority component is preceded
+ // by a double slash ("//") and is terminated by the next slash ("/"),
+ // question mark ("?"), number sign ("#"), or the end of the URL.
+
+ if (tmp.size() >= 2 && tmp[0] == '/' && tmp[1] == '/') {
+ tmp = tmp.substr(2);
+ offset = tmp.size();
+ offset = std::min(offset, tmp.find('/'));
+ offset = std::min(offset, tmp.find('?'));
+ offset = std::min(offset, tmp.find('#'));
+ authority_ = tmp.substr(0, offset);
+ tmp = tmp.substr(offset);
+
+ // TODO: Parse the network location into host and port?
+ }
+
+ // Does the URL include a fragment?
+ offset = tmp.find('#');
+ if (offset != string::npos) {
+ fragment_ = tmp.substr(offset + 1);
+ tmp = tmp.substr(0, offset);
+ }
+
+ // Does the URL include a query?
+ offset = tmp.find('?');
+ if (offset != string::npos) {
+ query_ = tmp.substr(offset + 1);
+ tmp = tmp.substr(0, offset);
+ }
+
+ // Whatever remains of the URL after removing the scheme, the network
+ // location, the query, and the fragment is the path.
+ path_ = tmp;
+}
+
+url::url(const string& scheme,
+ const string& authority,
+ const string& path,
+ const string& query,
+ const string& fragment)
+: scheme_(scheme)
+, authority_(authority)
+, path_(path)
+, query_(query)
+, fragment_(fragment)
+{
+ std::stringstream tss;
+
+ if (!scheme_.empty()) {
+ tss << scheme_ << ":";
+ }
+ if (!authority_.empty()) {
+ tss << "//" << authority_;
+ }
+ if (!path_.empty()) {
+ tss << path_;
+ }
+ if (!query_.empty()) {
+ tss << "?" << query_;
+ }
+ if (!fragment_.empty()) {
+ tss << "#" << fragment_;
+ }
+ str_ = tss.str();
+}
+
+url resolve(const url& b, const url& r)
+{
+ // The resolution algorithm roughly follows the resolution algorithm
+ // outlined in Section 5.2 (in particular Section 5.2.2) of RFC 3986. The
+ // major difference between the resolution algorithm and resolve() is that
+ // resolve() does not attempt to normalize the path components.
+
+ if (r.has_scheme()) {
+ return r;
+ } else if (r.has_authority()) {
+ return url(b.scheme(), r.authority(), r.path(), r.query(), r.fragment());
+ } else if (r.has_path()) {
+
+ // The relative URL path is either an absolute path or a relative
+ // path. If it is an absolute path, build the URL using only the
+ // relative path. If it is a relative path, resolve the relative path
+ // against the base path and build the URL using the resolved path.
+
+ if (is_url_path_absolute(r.path())) {
+ return url(b.scheme(), b.authority(), r.path(), r.query(), r.fragment());
+ } else {
+ string path = url_path_resolve(b.path(), r.path());
+ return url(b.scheme(), b.authority(), path, r.query(), r.fragment());
+ }
+
+ } else if (r.has_query()) {
+ return url(b.scheme(), b.authority(), b.path(), r.query(), r.fragment());
+ } else {
+ // The resolved URL never includes the base URL fragment (i.e., it
+ // always includes the reference URL fragment).
+ return url(b.scheme(), b.authority(), b.path(), b.query(), r.fragment());
+ }
+}
+
+} // namespace litehtml
diff --git a/src/plugins/litehtml_viewer/litehtml/url.h b/src/plugins/litehtml_viewer/litehtml/url.h
new file mode 100644
index 000000000..bd0cdc63c
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/url.h
@@ -0,0 +1,139 @@
+// Copyright (C) 2020-2021 Primate Labs Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the names of the copyright holders nor the names of their
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef LITEHTML_URL_H__
+#define LITEHTML_URL_H__
+
+#include <ostream>
+
+#include "os_types.h"
+
+// https://datatracker.ietf.org/doc/html/rfc3986
+
+namespace litehtml {
+
+class url {
+public:
+ url() = default;
+
+ explicit url(const string& str);
+
+ url(const string& scheme,
+ const string& authority,
+ const string& path,
+ const string& query,
+ const string& fragment);
+
+ const string& str() const
+ {
+ return str_;
+ }
+
+ const string& scheme() const
+ {
+ return scheme_;
+ }
+
+ bool has_scheme() const
+ {
+ return !scheme_.empty();
+ }
+
+ const string& authority() const
+ {
+ return authority_;
+ }
+
+ bool has_authority() const
+ {
+ return !authority_.empty();
+ }
+
+ const string& path() const
+ {
+ return path_;
+ }
+
+ bool has_path() const
+ {
+ return !path_.empty();
+ }
+
+ const string& query() const
+ {
+ return query_;
+ }
+
+ bool has_query() const
+ {
+ return !query_.empty();
+ }
+
+ const string& fragment() const
+ {
+ return fragment_;
+ }
+
+ bool has_fragment() const
+ {
+ return !fragment_.empty();
+ }
+
+protected:
+ string str_;
+
+ // Assume URLs are relative by default. See RFC 3986 Section 4.3 for
+ // information on which URLs are considered relative and which URLs are
+ // considered absolute:
+ //
+ // https://datatracker.ietf.org/doc/html/rfc3986#section-4.3
+
+ bool absolute_ = false;
+
+ string scheme_;
+
+ string authority_;
+
+ string path_;
+
+ string query_;
+
+ string fragment_;
+};
+
+// Returns a URL that is resolved from the reference URL that might be
+// relative to the base URL. For example, given <https://www.twitter.com/> as
+// the base URL and </foo> as the relative URL, resolve() will return the URL
+// <https://www.twitter.com/foo>.
+
+url resolve(const url& base, const url& reference);
+
+} // namespace litehtml
+
+#endif // LITEHTML_URL_H__
diff --git a/src/plugins/litehtml_viewer/litehtml/url_path.cpp b/src/plugins/litehtml_viewer/litehtml/url_path.cpp
new file mode 100644
index 000000000..da8620251
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/url_path.cpp
@@ -0,0 +1,86 @@
+// Copyright (C) 2020-2021 Primate Labs Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the names of the copyright holders nor the names of their
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "url_path.h"
+
+namespace litehtml {
+
+bool is_url_path_absolute(const string& path)
+{
+ return path.length() > 0 && path[0] == '/';
+}
+
+string url_path_directory_name(const string& path)
+{
+ size_t offset = path.find_last_of('/');
+ if (offset == string::npos) {
+ return ".";
+ } else {
+ return path.substr(0, offset + 1);
+ }
+}
+
+string url_path_base_name(const string& path)
+{
+ size_t offset = path.find_last_of('/');
+ if (offset == string::npos) {
+ return path;
+ } else {
+ return path.substr(offset + 1);
+ }
+}
+
+string url_path_append(const string& base, const string& path)
+{
+ string result(base);
+
+ // Only append a separator if both base and path are not empty and if the
+ // last character of base is not already a separator.
+ if (!result.empty() && !path.empty() && result.back() != '/') {
+ result.append(1, '/');
+ }
+
+ result.append(path);
+
+ return result;
+}
+
+string url_path_resolve(const string& base, const string& path)
+{
+
+ // If the possibly relative path is an absolute path then it is not
+ // relative and the base path is irrelevant.
+ if (is_url_path_absolute(path)) {
+ return path;
+ }
+
+ return url_path_append(url_path_directory_name(base), path);
+}
+
+} // namespace litehtml
diff --git a/src/plugins/litehtml_viewer/litehtml/url_path.h b/src/plugins/litehtml_viewer/litehtml/url_path.h
new file mode 100644
index 000000000..6b102139d
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/url_path.h
@@ -0,0 +1,51 @@
+// Copyright (C) 2020-2021 Primate Labs Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the names of the copyright holders nor the names of their
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef LITEHTML_URL_PATH_H__
+#define LITEHTML_URL_PATH_H__
+
+#include <ostream>
+
+#include "os_types.h"
+
+namespace litehtml {
+
+bool is_url_path_absolute(const string& path);
+
+string url_path_directory_name(const string& path);
+
+string url_path_base_name(const string& path);
+
+string url_path_append(const string& base, const string& path);
+
+string url_path_resolve(const string& base, const string& path);
+
+} // namespace litehtml
+
+#endif // LITEHTML_URL_PATH_H__
diff --git a/src/plugins/litehtml_viewer/litehtml/utf8_strings.cpp b/src/plugins/litehtml_viewer/litehtml/utf8_strings.cpp
index 3cebc73dc..787af86f4 100644
--- a/src/plugins/litehtml_viewer/litehtml/utf8_strings.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/utf8_strings.cpp
@@ -5,6 +5,8 @@
litehtml::utf8_to_wchar::utf8_to_wchar(const char* val)
{
m_utf8 = (const byte*) val;
+ if (!m_utf8) return;
+
while (true)
{
ucode_t wch = get_char();
diff --git a/src/plugins/litehtml_viewer/litehtml/utf8_strings.h b/src/plugins/litehtml_viewer/litehtml/utf8_strings.h
index c5b24217b..72969fd3d 100644
--- a/src/plugins/litehtml_viewer/litehtml/utf8_strings.h
+++ b/src/plugins/litehtml_viewer/litehtml/utf8_strings.h
@@ -1,6 +1,9 @@
#ifndef LH_UTF8_STRINGS_H
#define LH_UTF8_STRINGS_H
+#include "os_types.h"
+#include "types.h"
+
namespace litehtml
{
class utf8_to_wchar
@@ -42,15 +45,8 @@ namespace litehtml
}
};
-#ifdef LITEHTML_UTF8
-#define litehtml_from_utf8(str) str
-#define litehtml_to_utf8(str) str
#define litehtml_from_wchar(str) litehtml::wchar_to_utf8(str)
-#else
-#define litehtml_from_utf8(str) litehtml::utf8_to_wchar(str)
-#define litehtml_from_wchar(str) str
-#define litehtml_to_utf8(str) litehtml::wchar_to_utf8(str)
-#endif
+#define litehtml_to_wchar(str) litehtml::utf8_to_wchar(str)
}
#endif // LH_UTF8_STRINGS_H
diff --git a/src/plugins/litehtml_viewer/litehtml/web_color.cpp b/src/plugins/litehtml_viewer/litehtml/web_color.cpp
index 39ce2d7f0..78b201fac 100644
--- a/src/plugins/litehtml_viewer/litehtml/web_color.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/web_color.cpp
@@ -1,171 +1,176 @@
#include "html.h"
#include "web_color.h"
-#include <string.h>
+#include <cstring>
+
+const litehtml::web_color litehtml::web_color::transparent = web_color(0, 0, 0, 0);
+const litehtml::web_color litehtml::web_color::black = web_color(0, 0, 0, 255);
+const litehtml::web_color litehtml::web_color::white = web_color(255, 255, 255, 255);
litehtml::def_color litehtml::g_def_colors[] =
{
- {_t("transparent"),_t("rgba(0, 0, 0, 0)")},
- {_t("AliceBlue"),_t("#F0F8FF")},
- {_t("AntiqueWhite"),_t("#FAEBD7")},
- {_t("Aqua"),_t("#00FFFF")},
- {_t("Aquamarine"),_t("#7FFFD4")},
- {_t("Azure"),_t("#F0FFFF")},
- {_t("Beige"),_t("#F5F5DC")},
- {_t("Bisque"),_t("#FFE4C4")},
- {_t("Black"),_t("#000000")},
- {_t("BlanchedAlmond"),_t("#FFEBCD")},
- {_t("Blue"),_t("#0000FF")},
- {_t("BlueViolet"),_t("#8A2BE2")},
- {_t("Brown"),_t("#A52A2A")},
- {_t("BurlyWood"),_t("#DEB887")},
- {_t("CadetBlue"),_t("#5F9EA0")},
- {_t("Chartreuse"),_t("#7FFF00")},
- {_t("Chocolate"),_t("#D2691E")},
- {_t("Coral"),_t("#FF7F50")},
- {_t("CornflowerBlue"),_t("#6495ED")},
- {_t("Cornsilk"),_t("#FFF8DC")},
- {_t("Crimson"),_t("#DC143C")},
- {_t("Cyan"),_t("#00FFFF")},
- {_t("DarkBlue"),_t("#00008B")},
- {_t("DarkCyan"),_t("#008B8B")},
- {_t("DarkGoldenRod"),_t("#B8860B")},
- {_t("DarkGray"),_t("#A9A9A9")},
- {_t("DarkGrey"),_t("#A9A9A9")},
- {_t("DarkGreen"),_t("#006400")},
- {_t("DarkKhaki"),_t("#BDB76B")},
- {_t("DarkMagenta"),_t("#8B008B")},
- {_t("DarkOliveGreen"),_t("#556B2F")},
- {_t("Darkorange"),_t("#FF8C00")},
- {_t("DarkOrchid"),_t("#9932CC")},
- {_t("DarkRed"),_t("#8B0000")},
- {_t("DarkSalmon"),_t("#E9967A")},
- {_t("DarkSeaGreen"),_t("#8FBC8F")},
- {_t("DarkSlateBlue"),_t("#483D8B")},
- {_t("DarkSlateGray"),_t("#2F4F4F")},
- {_t("DarkSlateGrey"),_t("#2F4F4F")},
- {_t("DarkTurquoise"),_t("#00CED1")},
- {_t("DarkViolet"),_t("#9400D3")},
- {_t("DeepPink"),_t("#FF1493")},
- {_t("DeepSkyBlue"),_t("#00BFFF")},
- {_t("DimGray"),_t("#696969")},
- {_t("DimGrey"),_t("#696969")},
- {_t("DodgerBlue"),_t("#1E90FF")},
- {_t("FireBrick"),_t("#B22222")},
- {_t("FloralWhite"),_t("#FFFAF0")},
- {_t("ForestGreen"),_t("#228B22")},
- {_t("Fuchsia"),_t("#FF00FF")},
- {_t("Gainsboro"),_t("#DCDCDC")},
- {_t("GhostWhite"),_t("#F8F8FF")},
- {_t("Gold"),_t("#FFD700")},
- {_t("GoldenRod"),_t("#DAA520")},
- {_t("Gray"),_t("#808080")},
- {_t("Grey"),_t("#808080")},
- {_t("Green"),_t("#008000")},
- {_t("GreenYellow"),_t("#ADFF2F")},
- {_t("HoneyDew"),_t("#F0FFF0")},
- {_t("HotPink"),_t("#FF69B4")},
- {_t("Ivory"),_t("#FFFFF0")},
- {_t("Khaki"),_t("#F0E68C")},
- {_t("Lavender"),_t("#E6E6FA")},
- {_t("LavenderBlush"),_t("#FFF0F5")},
- {_t("LawnGreen"),_t("#7CFC00")},
- {_t("LemonChiffon"),_t("#FFFACD")},
- {_t("LightBlue"),_t("#ADD8E6")},
- {_t("LightCoral"),_t("#F08080")},
- {_t("LightCyan"),_t("#E0FFFF")},
- {_t("LightGoldenRodYellow"),_t("#FAFAD2")},
- {_t("LightGray"),_t("#D3D3D3")},
- {_t("LightGrey"),_t("#D3D3D3")},
- {_t("LightGreen"),_t("#90EE90")},
- {_t("LightPink"),_t("#FFB6C1")},
- {_t("LightSalmon"),_t("#FFA07A")},
- {_t("LightSeaGreen"),_t("#20B2AA")},
- {_t("LightSkyBlue"),_t("#87CEFA")},
- {_t("LightSlateGray"),_t("#778899")},
- {_t("LightSlateGrey"),_t("#778899")},
- {_t("LightSteelBlue"),_t("#B0C4DE")},
- {_t("LightYellow"),_t("#FFFFE0")},
- {_t("Lime"),_t("#00FF00")},
- {_t("LimeGreen"),_t("#32CD32")},
- {_t("Linen"),_t("#FAF0E6")},
- {_t("Magenta"),_t("#FF00FF")},
- {_t("Maroon"),_t("#800000")},
- {_t("MediumAquaMarine"),_t("#66CDAA")},
- {_t("MediumBlue"),_t("#0000CD")},
- {_t("MediumOrchid"),_t("#BA55D3")},
- {_t("MediumPurple"),_t("#9370D8")},
- {_t("MediumSeaGreen"),_t("#3CB371")},
- {_t("MediumSlateBlue"),_t("#7B68EE")},
- {_t("MediumSpringGreen"),_t("#00FA9A")},
- {_t("MediumTurquoise"),_t("#48D1CC")},
- {_t("MediumVioletRed"),_t("#C71585")},
- {_t("MidnightBlue"),_t("#191970")},
- {_t("MintCream"),_t("#F5FFFA")},
- {_t("MistyRose"),_t("#FFE4E1")},
- {_t("Moccasin"),_t("#FFE4B5")},
- {_t("NavajoWhite"),_t("#FFDEAD")},
- {_t("Navy"),_t("#000080")},
- {_t("OldLace"),_t("#FDF5E6")},
- {_t("Olive"),_t("#808000")},
- {_t("OliveDrab"),_t("#6B8E23")},
- {_t("Orange"),_t("#FFA500")},
- {_t("OrangeRed"),_t("#FF4500")},
- {_t("Orchid"),_t("#DA70D6")},
- {_t("PaleGoldenRod"),_t("#EEE8AA")},
- {_t("PaleGreen"),_t("#98FB98")},
- {_t("PaleTurquoise"),_t("#AFEEEE")},
- {_t("PaleVioletRed"),_t("#D87093")},
- {_t("PapayaWhip"),_t("#FFEFD5")},
- {_t("PeachPuff"),_t("#FFDAB9")},
- {_t("Peru"),_t("#CD853F")},
- {_t("Pink"),_t("#FFC0CB")},
- {_t("Plum"),_t("#DDA0DD")},
- {_t("PowderBlue"),_t("#B0E0E6")},
- {_t("Purple"),_t("#800080")},
- {_t("Red"),_t("#FF0000")},
- {_t("RosyBrown"),_t("#BC8F8F")},
- {_t("RoyalBlue"),_t("#4169E1")},
- {_t("SaddleBrown"),_t("#8B4513")},
- {_t("Salmon"),_t("#FA8072")},
- {_t("SandyBrown"),_t("#F4A460")},
- {_t("SeaGreen"),_t("#2E8B57")},
- {_t("SeaShell"),_t("#FFF5EE")},
- {_t("Sienna"),_t("#A0522D")},
- {_t("Silver"),_t("#C0C0C0")},
- {_t("SkyBlue"),_t("#87CEEB")},
- {_t("SlateBlue"),_t("#6A5ACD")},
- {_t("SlateGray"),_t("#708090")},
- {_t("SlateGrey"),_t("#708090")},
- {_t("Snow"),_t("#FFFAFA")},
- {_t("SpringGreen"),_t("#00FF7F")},
- {_t("SteelBlue"),_t("#4682B4")},
- {_t("Tan"),_t("#D2B48C")},
- {_t("Teal"),_t("#008080")},
- {_t("Thistle"),_t("#D8BFD8")},
- {_t("Tomato"),_t("#FF6347")},
- {_t("Turquoise"),_t("#40E0D0")},
- {_t("Violet"),_t("#EE82EE")},
- {_t("Wheat"),_t("#F5DEB3")},
- {_t("White"),_t("#FFFFFF")},
- {_t("WhiteSmoke"),_t("#F5F5F5")},
- {_t("Yellow"),_t("#FFFF00")},
- {_t("YellowGreen"),_t("#9ACD32")},
- {0,0}
+ {"transparent","rgba(0, 0, 0, 0)"},
+ {"AliceBlue","#F0F8FF"},
+ {"AntiqueWhite","#FAEBD7"},
+ {"Aqua","#00FFFF"},
+ {"Aquamarine","#7FFFD4"},
+ {"Azure","#F0FFFF"},
+ {"Beige","#F5F5DC"},
+ {"Bisque","#FFE4C4"},
+ {"Black","#000000"},
+ {"BlanchedAlmond","#FFEBCD"},
+ {"Blue","#0000FF"},
+ {"BlueViolet","#8A2BE2"},
+ {"Brown","#A52A2A"},
+ {"BurlyWood","#DEB887"},
+ {"CadetBlue","#5F9EA0"},
+ {"Chartreuse","#7FFF00"},
+ {"Chocolate","#D2691E"},
+ {"Coral","#FF7F50"},
+ {"CornflowerBlue","#6495ED"},
+ {"Cornsilk","#FFF8DC"},
+ {"Crimson","#DC143C"},
+ {"Cyan","#00FFFF"},
+ {"DarkBlue","#00008B"},
+ {"DarkCyan","#008B8B"},
+ {"DarkGoldenRod","#B8860B"},
+ {"DarkGray","#A9A9A9"},
+ {"DarkGrey","#A9A9A9"},
+ {"DarkGreen","#006400"},
+ {"DarkKhaki","#BDB76B"},
+ {"DarkMagenta","#8B008B"},
+ {"DarkOliveGreen","#556B2F"},
+ {"Darkorange","#FF8C00"},
+ {"DarkOrchid","#9932CC"},
+ {"DarkRed","#8B0000"},
+ {"DarkSalmon","#E9967A"},
+ {"DarkSeaGreen","#8FBC8F"},
+ {"DarkSlateBlue","#483D8B"},
+ {"DarkSlateGray","#2F4F4F"},
+ {"DarkSlateGrey","#2F4F4F"},
+ {"DarkTurquoise","#00CED1"},
+ {"DarkViolet","#9400D3"},
+ {"DeepPink","#FF1493"},
+ {"DeepSkyBlue","#00BFFF"},
+ {"DimGray","#696969"},
+ {"DimGrey","#696969"},
+ {"DodgerBlue","#1E90FF"},
+ {"FireBrick","#B22222"},
+ {"FloralWhite","#FFFAF0"},
+ {"ForestGreen","#228B22"},
+ {"Fuchsia","#FF00FF"},
+ {"Gainsboro","#DCDCDC"},
+ {"GhostWhite","#F8F8FF"},
+ {"Gold","#FFD700"},
+ {"GoldenRod","#DAA520"},
+ {"Gray","#808080"},
+ {"Grey","#808080"},
+ {"Green","#008000"},
+ {"GreenYellow","#ADFF2F"},
+ {"HoneyDew","#F0FFF0"},
+ {"HotPink","#FF69B4"},
+ {"Ivory","#FFFFF0"},
+ {"Khaki","#F0E68C"},
+ {"Lavender","#E6E6FA"},
+ {"LavenderBlush","#FFF0F5"},
+ {"LawnGreen","#7CFC00"},
+ {"LemonChiffon","#FFFACD"},
+ {"LightBlue","#ADD8E6"},
+ {"LightCoral","#F08080"},
+ {"LightCyan","#E0FFFF"},
+ {"LightGoldenRodYellow","#FAFAD2"},
+ {"LightGray","#D3D3D3"},
+ {"LightGrey","#D3D3D3"},
+ {"LightGreen","#90EE90"},
+ {"LightPink","#FFB6C1"},
+ {"LightSalmon","#FFA07A"},
+ {"LightSeaGreen","#20B2AA"},
+ {"LightSkyBlue","#87CEFA"},
+ {"LightSlateGray","#778899"},
+ {"LightSlateGrey","#778899"},
+ {"LightSteelBlue","#B0C4DE"},
+ {"LightYellow","#FFFFE0"},
+ {"Lime","#00FF00"},
+ {"LimeGreen","#32CD32"},
+ {"Linen","#FAF0E6"},
+ {"Magenta","#FF00FF"},
+ {"Maroon","#800000"},
+ {"MediumAquaMarine","#66CDAA"},
+ {"MediumBlue","#0000CD"},
+ {"MediumOrchid","#BA55D3"},
+ {"MediumPurple","#9370D8"},
+ {"MediumSeaGreen","#3CB371"},
+ {"MediumSlateBlue","#7B68EE"},
+ {"MediumSpringGreen","#00FA9A"},
+ {"MediumTurquoise","#48D1CC"},
+ {"MediumVioletRed","#C71585"},
+ {"MidnightBlue","#191970"},
+ {"MintCream","#F5FFFA"},
+ {"MistyRose","#FFE4E1"},
+ {"Moccasin","#FFE4B5"},
+ {"NavajoWhite","#FFDEAD"},
+ {"Navy","#000080"},
+ {"OldLace","#FDF5E6"},
+ {"Olive","#808000"},
+ {"OliveDrab","#6B8E23"},
+ {"Orange","#FFA500"},
+ {"OrangeRed","#FF4500"},
+ {"Orchid","#DA70D6"},
+ {"PaleGoldenRod","#EEE8AA"},
+ {"PaleGreen","#98FB98"},
+ {"PaleTurquoise","#AFEEEE"},
+ {"PaleVioletRed","#D87093"},
+ {"PapayaWhip","#FFEFD5"},
+ {"PeachPuff","#FFDAB9"},
+ {"Peru","#CD853F"},
+ {"Pink","#FFC0CB"},
+ {"Plum","#DDA0DD"},
+ {"PowderBlue","#B0E0E6"},
+ {"Purple","#800080"},
+ {"Red","#FF0000"},
+ {"RosyBrown","#BC8F8F"},
+ {"RoyalBlue","#4169E1"},
+ {"SaddleBrown","#8B4513"},
+ {"Salmon","#FA8072"},
+ {"SandyBrown","#F4A460"},
+ {"SeaGreen","#2E8B57"},
+ {"SeaShell","#FFF5EE"},
+ {"Sienna","#A0522D"},
+ {"Silver","#C0C0C0"},
+ {"SkyBlue","#87CEEB"},
+ {"SlateBlue","#6A5ACD"},
+ {"SlateGray","#708090"},
+ {"SlateGrey","#708090"},
+ {"Snow","#FFFAFA"},
+ {"SpringGreen","#00FF7F"},
+ {"SteelBlue","#4682B4"},
+ {"Tan","#D2B48C"},
+ {"Teal","#008080"},
+ {"Thistle","#D8BFD8"},
+ {"Tomato","#FF6347"},
+ {"Turquoise","#40E0D0"},
+ {"Violet","#EE82EE"},
+ {"Wheat","#F5DEB3"},
+ {"White","#FFFFFF"},
+ {"WhiteSmoke","#F5F5F5"},
+ {"Yellow","#FFFF00"},
+ {"YellowGreen","#9ACD32"},
+ {nullptr,nullptr}
};
-litehtml::web_color litehtml::web_color::from_string(const tchar_t* str, litehtml::document_container* callback)
+litehtml::web_color litehtml::web_color::from_string(const string& _str, document_container* callback)
{
- if(!str || !str[0])
+ auto str = _str.c_str();
+ if(!str[0])
{
return web_color(0, 0, 0);
}
- if(str[0] == _t('#'))
+ if(str[0] == '#')
{
- tstring red = _t("");
- tstring green = _t("");
- tstring blue = _t("");
- if(t_strlen(str + 1) == 3)
+ string red;
+ string green;
+ string blue;
+ if(strlen(str + 1) == 3)
{
red += str[1];
red += str[1];
@@ -173,7 +178,7 @@ litehtml::web_color litehtml::web_color::from_string(const tchar_t* str, litehtm
green += str[2];
blue += str[3];
blue += str[3];
- } else if(t_strlen(str + 1) == 6)
+ } else if(strlen(str + 1) == 6)
{
red += str[1];
red += str[2];
@@ -182,41 +187,41 @@ litehtml::web_color litehtml::web_color::from_string(const tchar_t* str, litehtm
blue += str[5];
blue += str[6];
}
- tchar_t* sss = 0;
+ char* sss = nullptr;
web_color clr;
- clr.red = (byte) t_strtol(red.c_str(), &sss, 16);
- clr.green = (byte) t_strtol(green.c_str(), &sss, 16);
- clr.blue = (byte) t_strtol(blue.c_str(), &sss, 16);
+ clr.red = (byte) strtol(red.c_str(), &sss, 16);
+ clr.green = (byte) strtol(green.c_str(), &sss, 16);
+ clr.blue = (byte) strtol(blue.c_str(), &sss, 16);
return clr;
- } else if(!t_strncmp(str, _t("rgb"), 3))
+ } else if(!strncmp(str, "rgb", 3))
{
- tstring s = str;
+ string s = str;
- tstring::size_type pos = s.find_first_of(_t("("));
- if(pos != tstring::npos)
+ string::size_type pos = s.find_first_of('(');
+ if(pos != string::npos)
{
s.erase(s.begin(), s.begin() + pos + 1);
}
- pos = s.find_last_of(_t(")"));
- if(pos != tstring::npos)
+ pos = s.find_last_of(')');
+ if(pos != string::npos)
{
s.erase(s.begin() + pos, s.end());
}
- std::vector<tstring> tokens;
- split_string(s, tokens, _t(", \t"));
+ std::vector<string> tokens;
+ split_string(s, tokens, ", \t");
web_color clr;
- if(tokens.size() >= 1) clr.red = (byte) t_atoi(tokens[0].c_str());
- if(tokens.size() >= 2) clr.green = (byte) t_atoi(tokens[1].c_str());
- if(tokens.size() >= 3) clr.blue = (byte) t_atoi(tokens[2].c_str());
- if(tokens.size() >= 4) clr.alpha = (byte) (t_strtod(tokens[3].c_str(), 0) * 255.0);
+ if(tokens.size() >= 1) clr.red = (byte) atoi(tokens[0].c_str());
+ if(tokens.size() >= 2) clr.green = (byte) atoi(tokens[1].c_str());
+ if(tokens.size() >= 3) clr.blue = (byte) atoi(tokens[2].c_str());
+ if(tokens.size() >= 4) clr.alpha = (byte) (t_strtod(tokens[3].c_str(), nullptr) * 255.0);
return clr;
} else
{
- tstring rgb = resolve_name(str, callback);
+ string rgb = resolve_name(str, callback);
if(!rgb.empty())
{
return from_string(rgb.c_str(), callback);
@@ -225,32 +230,45 @@ litehtml::web_color litehtml::web_color::from_string(const tchar_t* str, litehtm
return web_color(0, 0, 0);
}
-litehtml::tstring litehtml::web_color::resolve_name(const tchar_t* name, litehtml::document_container* callback)
+litehtml::string litehtml::web_color::resolve_name(const string& name, document_container* callback)
{
for(int i=0; g_def_colors[i].name; i++)
{
- if(!t_strcasecmp(name, g_def_colors[i].name))
+ if(!t_strcasecmp(name.c_str(), g_def_colors[i].name))
{
- return std::move(litehtml::tstring(g_def_colors[i].rgb));
+ return g_def_colors[i].rgb;
}
}
if (callback)
{
- litehtml::tstring clr = callback->resolve_color(name);
- return std::move(clr);
+ string clr = callback->resolve_color(name);
+ return clr;
}
- return std::move(litehtml::tstring());
+ return "";
}
-bool litehtml::web_color::is_color(const tchar_t* str)
+bool litehtml::web_color::is_color(const string& str, document_container* callback)
{
- if(!t_strncasecmp(str, _t("rgb"), 3) || str[0] == _t('#'))
+ if (!t_strncasecmp(str.c_str(), "rgb", 3) || str[0] == '#')
{
return true;
}
- if (!t_isdigit(str[0]) && str[0] != _t('.'))
+ if (t_isalpha(str[0]) && resolve_name(str, callback) != "")
{
return true;
}
return false;
}
+
+litehtml::string litehtml::web_color::to_string() const
+{
+ char str[9];
+ if(alpha)
+ {
+ t_snprintf(str, 9, "%02X%02X%02X%02X", red, green, blue, alpha);
+ } else
+ {
+ t_snprintf(str, 9, "%02X%02X%02X", red, green, blue);
+ }
+ return str;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/web_color.h b/src/plugins/litehtml_viewer/litehtml/web_color.h
index fa3b370b8..a42b416ca 100644
--- a/src/plugins/litehtml_viewer/litehtml/web_color.h
+++ b/src/plugins/litehtml_viewer/litehtml/web_color.h
@@ -5,56 +5,48 @@ namespace litehtml
{
struct def_color
{
- const tchar_t* name;
- const tchar_t* rgb;
+ const char* name;
+ const char* rgb;
};
extern def_color g_def_colors[];
- class document_container;
+ class document_container;
struct web_color
{
- byte blue;
- byte green;
- byte red;
- byte alpha;
+ byte red;
+ byte green;
+ byte blue;
+ byte alpha;
+
+ static const web_color transparent;
+ static const web_color black;
+ static const web_color white;
web_color(byte r, byte g, byte b, byte a = 255)
{
- blue = b;
- green = g;
red = r;
+ green = g;
+ blue = b;
alpha = a;
}
web_color()
{
- blue = 0;
- green = 0;
red = 0;
+ green = 0;
+ blue = 0;
alpha = 0xFF;
}
- web_color(const web_color& val)
- {
- blue = val.blue;
- green = val.green;
- red = val.red;
- alpha = val.alpha;
- }
+ bool operator==(web_color color) const { return red == color.red && green == color.green && blue == color.blue && alpha == color.alpha; }
+ bool operator!=(web_color color) const { return !(*this == color); }
- web_color& operator=(const web_color& val)
- {
- blue = val.blue;
- green = val.green;
- red = val.red;
- alpha = val.alpha;
- return *this;
- }
- static web_color from_string(const tchar_t* str, litehtml::document_container* callback);
- static litehtml::tstring resolve_name(const tchar_t* name, litehtml::document_container* callback);
- static bool is_color(const tchar_t* str);
+ string to_string() const;
+ static web_color from_string(const string& str, document_container* callback);
+ static string resolve_name(const string& name, document_container* callback);
+ static bool is_color(const string& str, document_container* callback);
};
}
-----------------------------------------------------------------------
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list