From 705c4d24c9c61edffc82864bf9c24384dc29a8d7 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Mon, 18 Mar 2024 12:13:54 +0300 Subject: litehtml - lightweight html renderer --- libs/litehtml/include/litehtml.h | 11 + libs/litehtml/include/litehtml/background.h | 69 ++ libs/litehtml/include/litehtml/borders.h | 345 +++++++ libs/litehtml/include/litehtml/codepoint.h | 51 + libs/litehtml/include/litehtml/css_length.h | 119 +++ libs/litehtml/include/litehtml/css_margins.h | 44 + libs/litehtml/include/litehtml/css_offsets.h | 44 + libs/litehtml/include/litehtml/css_position.h | 28 + libs/litehtml/include/litehtml/css_properties.h | 673 +++++++++++++ libs/litehtml/include/litehtml/css_selector.h | 300 ++++++ libs/litehtml/include/litehtml/document.h | 134 +++ .../litehtml/include/litehtml/document_container.h | 71 ++ libs/litehtml/include/litehtml/el_anchor.h | 18 + libs/litehtml/include/litehtml/el_base.h | 17 + libs/litehtml/include/litehtml/el_before_after.h | 39 + libs/litehtml/include/litehtml/el_body.h | 17 + libs/litehtml/include/litehtml/el_break.h | 17 + libs/litehtml/include/litehtml/el_cdata.h | 19 + libs/litehtml/include/litehtml/el_comment.h | 25 + libs/litehtml/include/litehtml/el_div.h | 17 + libs/litehtml/include/litehtml/el_font.h | 17 + libs/litehtml/include/litehtml/el_image.h | 29 + libs/litehtml/include/litehtml/el_link.h | 18 + libs/litehtml/include/litehtml/el_para.h | 18 + libs/litehtml/include/litehtml/el_script.h | 21 + libs/litehtml/include/litehtml/el_space.h | 21 + libs/litehtml/include/litehtml/el_style.h | 21 + libs/litehtml/include/litehtml/el_table.h | 25 + libs/litehtml/include/litehtml/el_td.h | 17 + libs/litehtml/include/litehtml/el_text.h | 31 + libs/litehtml/include/litehtml/el_title.h | 18 + libs/litehtml/include/litehtml/el_tr.h | 17 + libs/litehtml/include/litehtml/element.h | 234 +++++ libs/litehtml/include/litehtml/flex_item.h | 137 +++ libs/litehtml/include/litehtml/flex_line.h | 56 ++ .../litehtml/include/litehtml/formatting_context.h | 54 ++ libs/litehtml/include/litehtml/html.h | 88 ++ libs/litehtml/include/litehtml/html_tag.h | 139 +++ libs/litehtml/include/litehtml/iterators.h | 84 ++ libs/litehtml/include/litehtml/line_box.h | 171 ++++ libs/litehtml/include/litehtml/master_css.h | 376 ++++++++ libs/litehtml/include/litehtml/media_query.h | 77 ++ libs/litehtml/include/litehtml/num_cvt.h | 19 + libs/litehtml/include/litehtml/os_types.h | 30 + libs/litehtml/include/litehtml/render_block.h | 40 + .../include/litehtml/render_block_context.h | 31 + libs/litehtml/include/litehtml/render_flex.h | 33 + libs/litehtml/include/litehtml/render_image.h | 25 + libs/litehtml/include/litehtml/render_inline.h | 38 + .../include/litehtml/render_inline_context.h | 56 ++ libs/litehtml/include/litehtml/render_item.h | 387 ++++++++ libs/litehtml/include/litehtml/render_table.h | 56 ++ libs/litehtml/include/litehtml/string_id.h | 306 ++++++ libs/litehtml/include/litehtml/style.h | 215 +++++ libs/litehtml/include/litehtml/stylesheet.h | 47 + libs/litehtml/include/litehtml/table.h | 248 +++++ libs/litehtml/include/litehtml/tstring_view.h | 136 +++ libs/litehtml/include/litehtml/types.h | 1000 ++++++++++++++++++++ libs/litehtml/include/litehtml/url.h | 139 +++ libs/litehtml/include/litehtml/url_path.h | 51 + libs/litehtml/include/litehtml/utf8_strings.h | 52 + libs/litehtml/include/litehtml/web_color.h | 63 ++ 62 files changed, 6699 insertions(+) create mode 100644 libs/litehtml/include/litehtml.h create mode 100644 libs/litehtml/include/litehtml/background.h create mode 100644 libs/litehtml/include/litehtml/borders.h create mode 100644 libs/litehtml/include/litehtml/codepoint.h create mode 100644 libs/litehtml/include/litehtml/css_length.h create mode 100644 libs/litehtml/include/litehtml/css_margins.h create mode 100644 libs/litehtml/include/litehtml/css_offsets.h create mode 100644 libs/litehtml/include/litehtml/css_position.h create mode 100644 libs/litehtml/include/litehtml/css_properties.h create mode 100644 libs/litehtml/include/litehtml/css_selector.h create mode 100644 libs/litehtml/include/litehtml/document.h create mode 100644 libs/litehtml/include/litehtml/document_container.h create mode 100644 libs/litehtml/include/litehtml/el_anchor.h create mode 100644 libs/litehtml/include/litehtml/el_base.h create mode 100644 libs/litehtml/include/litehtml/el_before_after.h create mode 100644 libs/litehtml/include/litehtml/el_body.h create mode 100644 libs/litehtml/include/litehtml/el_break.h create mode 100644 libs/litehtml/include/litehtml/el_cdata.h create mode 100644 libs/litehtml/include/litehtml/el_comment.h create mode 100644 libs/litehtml/include/litehtml/el_div.h create mode 100644 libs/litehtml/include/litehtml/el_font.h create mode 100644 libs/litehtml/include/litehtml/el_image.h create mode 100644 libs/litehtml/include/litehtml/el_link.h create mode 100644 libs/litehtml/include/litehtml/el_para.h create mode 100644 libs/litehtml/include/litehtml/el_script.h create mode 100644 libs/litehtml/include/litehtml/el_space.h create mode 100644 libs/litehtml/include/litehtml/el_style.h create mode 100644 libs/litehtml/include/litehtml/el_table.h create mode 100644 libs/litehtml/include/litehtml/el_td.h create mode 100644 libs/litehtml/include/litehtml/el_text.h create mode 100644 libs/litehtml/include/litehtml/el_title.h create mode 100644 libs/litehtml/include/litehtml/el_tr.h create mode 100644 libs/litehtml/include/litehtml/element.h create mode 100644 libs/litehtml/include/litehtml/flex_item.h create mode 100644 libs/litehtml/include/litehtml/flex_line.h create mode 100644 libs/litehtml/include/litehtml/formatting_context.h create mode 100644 libs/litehtml/include/litehtml/html.h create mode 100644 libs/litehtml/include/litehtml/html_tag.h create mode 100644 libs/litehtml/include/litehtml/iterators.h create mode 100644 libs/litehtml/include/litehtml/line_box.h create mode 100644 libs/litehtml/include/litehtml/master_css.h create mode 100644 libs/litehtml/include/litehtml/media_query.h create mode 100644 libs/litehtml/include/litehtml/num_cvt.h create mode 100644 libs/litehtml/include/litehtml/os_types.h create mode 100644 libs/litehtml/include/litehtml/render_block.h create mode 100644 libs/litehtml/include/litehtml/render_block_context.h create mode 100644 libs/litehtml/include/litehtml/render_flex.h create mode 100644 libs/litehtml/include/litehtml/render_image.h create mode 100644 libs/litehtml/include/litehtml/render_inline.h create mode 100644 libs/litehtml/include/litehtml/render_inline_context.h create mode 100644 libs/litehtml/include/litehtml/render_item.h create mode 100644 libs/litehtml/include/litehtml/render_table.h create mode 100644 libs/litehtml/include/litehtml/string_id.h create mode 100644 libs/litehtml/include/litehtml/style.h create mode 100644 libs/litehtml/include/litehtml/stylesheet.h create mode 100644 libs/litehtml/include/litehtml/table.h create mode 100644 libs/litehtml/include/litehtml/tstring_view.h create mode 100644 libs/litehtml/include/litehtml/types.h create mode 100644 libs/litehtml/include/litehtml/url.h create mode 100644 libs/litehtml/include/litehtml/url_path.h create mode 100644 libs/litehtml/include/litehtml/utf8_strings.h create mode 100644 libs/litehtml/include/litehtml/web_color.h (limited to 'libs/litehtml/include') diff --git a/libs/litehtml/include/litehtml.h b/libs/litehtml/include/litehtml.h new file mode 100644 index 0000000000..2537aee839 --- /dev/null +++ b/libs/litehtml/include/litehtml.h @@ -0,0 +1,11 @@ +#ifndef LITEHTML_H +#define LITEHTML_H + +#include +#include +#include +#include +#include +#include + +#endif // LITEHTML_H diff --git a/libs/litehtml/include/litehtml/background.h b/libs/litehtml/include/litehtml/background.h new file mode 100644 index 0000000000..c56443d548 --- /dev/null +++ b/libs/litehtml/include/litehtml/background.h @@ -0,0 +1,69 @@ +#ifndef LH_BACKGROUND_H +#define LH_BACKGROUND_H + +#include "types.h" +#include "css_length.h" +#include "css_position.h" +#include "web_color.h" +#include "borders.h" + +namespace litehtml +{ + class background + { + public: + string_vector m_image; + string m_baseurl; + web_color m_color; + 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; + + 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: + string image; + string baseurl; + background_attachment attachment; + background_repeat repeat; + web_color color; + position clip_box; + position origin_box; + position border_box; + border_radiuses border_radius; + size image_size; + int position_x; + int position_y; + bool is_root; + + public: + background_paint() + { + attachment = background_attachment_scroll; + repeat = background_repeat_repeat; + color = web_color::transparent; + position_x = 0; + position_y = 0; + is_root = false; + } + }; + +} + +#endif // LH_BACKGROUND_H diff --git a/libs/litehtml/include/litehtml/borders.h b/libs/litehtml/include/litehtml/borders.h new file mode 100644 index 0000000000..9c47abca07 --- /dev/null +++ b/libs/litehtml/include/litehtml/borders.h @@ -0,0 +1,345 @@ +#ifndef LH_BORDERS_H +#define LH_BORDERS_H + +#include "css_length.h" +#include "types.h" +#include "web_color.h" + +namespace litehtml +{ + struct css_border + { + css_length width; + border_style style; + web_color color; + + css_border() + { + style = border_style_none; + } + + css_border(const css_border& val) + { + width = val.width; + style = val.style; + color = val.color; + } + + css_border& operator=(const css_border& val) + { + width = val.width; + style = val.style; + color = val.color; + return *this; + } + + string to_string() const; + }; + + struct border + { + int width; + border_style style; + web_color color; + + border() + { + width = 0; + } + border(const border& val) + { + width = val.width; + style = val.style; + color = val.color; + } + border(const css_border& val) + { + width = (int) val.width.val(); + style = val.style; + color = val.color; + } + border& operator=(const border& val) + { + width = val.width; + style = val.style; + color = val.color; + return *this; + } + border& operator=(const css_border& val) + { + width = (int) val.width.val(); + style = val.style; + color = val.color; + return *this; + } + }; + + struct border_radiuses + { + int top_left_x; + int top_left_y; + + int top_right_x; + int top_right_y; + + int bottom_right_x; + int bottom_right_y; + + int bottom_left_x; + int bottom_left_y; + + border_radiuses() + { + top_left_x = 0; + top_left_y = 0; + top_right_x = 0; + top_right_y = 0; + bottom_right_x = 0; + bottom_right_y = 0; + bottom_left_x = 0; + bottom_left_y = 0; + } + border_radiuses(const border_radiuses& val) + { + top_left_x = val.top_left_x; + top_left_y = val.top_left_y; + top_right_x = val.top_right_x; + top_right_y = val.top_right_y; + bottom_right_x = val.bottom_right_x; + bottom_right_y = val.bottom_right_y; + bottom_left_x = val.bottom_left_x; + bottom_left_y = val.bottom_left_y; + } + border_radiuses& operator = (const border_radiuses& val) + { + top_left_x = val.top_left_x; + top_left_y = val.top_left_y; + top_right_x = val.top_right_x; + top_right_y = val.top_right_y; + bottom_right_x = val.bottom_right_x; + bottom_right_y = val.bottom_right_y; + bottom_left_x = val.bottom_left_x; + bottom_left_y = val.bottom_left_y; + return *this; + } + void operator += (const margins& mg) + { + top_left_x += mg.left; + top_left_y += mg.top; + top_right_x += mg.right; + top_right_y += mg.top; + bottom_right_x += mg.right; + bottom_right_y += mg.bottom; + bottom_left_x += mg.left; + bottom_left_y += mg.bottom; + fix_values(); + } + void operator -= (const margins& mg) + { + top_left_x -= mg.left; + top_left_y -= mg.top; + top_right_x -= mg.right; + top_right_y -= mg.top; + bottom_right_x -= mg.right; + bottom_right_y -= mg.bottom; + bottom_left_x -= mg.left; + bottom_left_y -= mg.bottom; + fix_values(); + } + void fix_values() + { + if (top_left_x < 0) top_left_x = 0; + if (top_left_y < 0) top_left_y = 0; + if (top_right_x < 0) top_right_x = 0; + if (top_right_y < 0) top_right_y = 0; + if (bottom_right_x < 0) bottom_right_x = 0; + if (bottom_right_y < 0) bottom_right_y = 0; + if (bottom_left_x < 0) bottom_left_x = 0; + if (bottom_left_y < 0) bottom_left_y = 0; + } + void fix_values(int width, int height) + { + fix_values(); + int half_width = width / 2; + int half_height = height / 2; + auto fix_one = [&](int& radii_x, int& radii_y) + { + double factor = std::min((double) half_width / (double) radii_x, (double) half_height / (double) radii_y); + radii_x = (int) ((double) radii_x * factor); + radii_y = (int) ((double) radii_y * factor); + }; + + if(top_left_x > half_width || top_left_y > half_height) + { + fix_one(top_left_x, top_left_y); + } + if(top_right_x > half_width || top_right_y > half_height) + { + fix_one(top_right_x, top_right_y); + } + if(bottom_right_x > half_width || bottom_right_y > half_height) + { + fix_one(bottom_right_x, bottom_right_y); + } + if(bottom_left_x > half_width || bottom_left_y > half_height) + { + fix_one(bottom_left_x, bottom_left_y); + } + } + }; + + struct css_border_radius + { + css_length top_left_x; + css_length top_left_y; + + css_length top_right_x; + css_length top_right_y; + + css_length bottom_right_x; + css_length bottom_right_y; + + css_length bottom_left_x; + css_length bottom_left_y; + + css_border_radius() + { + + } + + css_border_radius(const css_border_radius& val) + { + top_left_x = val.top_left_x; + top_left_y = val.top_left_y; + top_right_x = val.top_right_x; + top_right_y = val.top_right_y; + bottom_left_x = val.bottom_left_x; + bottom_left_y = val.bottom_left_y; + bottom_right_x = val.bottom_right_x; + bottom_right_y = val.bottom_right_y; + } + + css_border_radius& operator=(const css_border_radius& val) + { + top_left_x = val.top_left_x; + top_left_y = val.top_left_y; + top_right_x = val.top_right_x; + top_right_y = val.top_right_y; + bottom_left_x = val.bottom_left_x; + bottom_left_y = val.bottom_left_y; + bottom_right_x = val.bottom_right_x; + bottom_right_y = val.bottom_right_y; + return *this; + } + border_radiuses calc_percents(int width, int height) const + { + border_radiuses ret; + ret.bottom_left_x = bottom_left_x.calc_percent(width); + ret.bottom_left_y = bottom_left_y.calc_percent(height); + ret.top_left_x = top_left_x.calc_percent(width); + ret.top_left_y = top_left_y.calc_percent(height); + ret.top_right_x = top_right_x.calc_percent(width); + ret.top_right_y = top_right_y.calc_percent(height); + ret.bottom_right_x = bottom_right_x.calc_percent(width); + ret.bottom_right_y = bottom_right_y.calc_percent(height); + ret.fix_values(width, height); + return ret; + } + }; + + struct css_borders + { + css_border left; + css_border top; + css_border right; + css_border bottom; + css_border_radius radius; + + 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) + { + left = val.left; + right = val.right; + top = val.top; + bottom = val.bottom; + radius = val.radius; + } + + css_borders& operator=(const css_borders& val) + { + left = val.left; + right = val.right; + top = val.top; + bottom = val.bottom; + 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 + { + border left; + border top; + border right; + border bottom; + border_radiuses radius; + + borders() = default; + + borders(const borders& val) + { + left = val.left; + right = val.right; + top = val.top; + bottom = val.bottom; + radius = val.radius; + } + + borders(const css_borders& val) + { + left = val.left; + right = val.right; + top = val.top; + 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; + right = val.right; + top = val.top; + bottom = val.bottom; + radius = val.radius; + return *this; + } + + borders& operator=(const css_borders& val) + { + left = val.left; + right = val.right; + top = val.top; + bottom = val.bottom; + return *this; + } + }; +} + +#endif // LH_BORDERS_H diff --git a/libs/litehtml/include/litehtml/codepoint.h b/libs/litehtml/include/litehtml/codepoint.h new file mode 100644 index 0000000000..52dd495559 --- /dev/null +++ b/libs/litehtml/include/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 + +#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/libs/litehtml/include/litehtml/css_length.h b/libs/litehtml/include/litehtml/css_length.h new file mode 100644 index 0000000000..ae787105af --- /dev/null +++ b/libs/litehtml/include/litehtml/css_length.h @@ -0,0 +1,119 @@ +#ifndef LH_CSS_LENGTH_H +#define LH_CSS_LENGTH_H + +#include "types.h" + +namespace litehtml +{ + class css_length + { + union + { + float m_value; + int m_predef; + }; + css_units m_units; + bool m_is_predefined; + public: + css_length(); + 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 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 inlines + + inline css_length::css_length() + { + m_value = 0; + m_predef = 0; + m_units = css_units_none; + m_is_predefined = false; + } + + inline css_length::css_length(float val, css_units units) + { + m_value = val; + m_units = units; + m_is_predefined = false; + } + + inline css_length& css_length::operator=(float val) + { + m_value = val; + m_units = css_units_px; + m_is_predefined = false; + return *this; + } + + inline bool css_length::is_predefined() const + { + return m_is_predefined; + } + + inline void css_length::predef(int val) + { + m_predef = val; + m_is_predefined = true; + } + + inline int css_length::predef() const + { + if(m_is_predefined) + { + return m_predef; + } + return 0; + } + + inline void css_length::set_value(float val, css_units units) + { + m_value = val; + m_is_predefined = false; + m_units = units; + } + + inline float css_length::val() const + { + if(!m_is_predefined) + { + return m_value; + } + return 0; + } + + inline css_units css_length::units() const + { + return m_units; + } + + inline int css_length::calc_percent(int width) const + { + if(!is_predefined()) + { + if(units() == css_units_percentage) + { + return (int) ((double) width * (double) m_value / 100.0); + } else + { + return (int) val(); + } + } + return 0; + } +} + +#endif // LH_CSS_LENGTH_H diff --git a/libs/litehtml/include/litehtml/css_margins.h b/libs/litehtml/include/litehtml/css_margins.h new file mode 100644 index 0000000000..17dc7698da --- /dev/null +++ b/libs/litehtml/include/litehtml/css_margins.h @@ -0,0 +1,44 @@ +#ifndef LH_CSS_MARGINS_H +#define LH_CSS_MARGINS_H + +#include "css_length.h" + +namespace litehtml +{ + struct css_margins + { + css_length left; + css_length right; + css_length top; + css_length bottom; + + css_margins() = default; + + css_margins(const css_margins& val) + { + left = val.left; + right = val.right; + top = val.top; + bottom = val.bottom; + } + + css_margins& operator=(const css_margins& val) + { + left = val.left; + right = val.right; + top = val.top; + 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(); + } + }; +} + +#endif // LH_CSS_MARGINS_H diff --git a/libs/litehtml/include/litehtml/css_offsets.h b/libs/litehtml/include/litehtml/css_offsets.h new file mode 100644 index 0000000000..5ab175ce26 --- /dev/null +++ b/libs/litehtml/include/litehtml/css_offsets.h @@ -0,0 +1,44 @@ +#ifndef LH_CSS_OFFSETS_H +#define LH_CSS_OFFSETS_H + +#include "css_length.h" + +namespace litehtml +{ + struct css_offsets + { + css_length left; + css_length top; + css_length right; + css_length bottom; + + css_offsets() = default; + + css_offsets(const css_offsets& val) + { + left = val.left; + top = val.top; + right = val.right; + bottom = val.bottom; + } + + css_offsets& operator=(const css_offsets& val) + { + left = val.left; + top = val.top; + right = val.right; + 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(); + } + }; +} + +#endif // LH_CSS_OFFSETS_H diff --git a/libs/litehtml/include/litehtml/css_position.h b/libs/litehtml/include/litehtml/css_position.h new file mode 100644 index 0000000000..978a81ab5d --- /dev/null +++ b/libs/litehtml/include/litehtml/css_position.h @@ -0,0 +1,28 @@ +#ifndef LH_CSS_POSITION_H +#define LH_CSS_POSITION_H + +#include "css_length.h" + +namespace litehtml +{ + struct css_position + { + css_length x; + css_length y; + css_length width; + css_length height; + }; + + struct css_size + { + css_length width; + css_length height; + + css_size() = default; + css_size(css_length width, css_length height) : width(width), height(height) {} + }; + + using size_vector = std::vector; +} + +#endif // LH_CSS_POSITION_H diff --git a/libs/litehtml/include/litehtml/css_properties.h b/libs/litehtml/include/litehtml/css_properties.h new file mode 100644 index 0000000000..a915616861 --- /dev/null +++ b/libs/litehtml/include/litehtml/css_properties.h @@ -0,0 +1,673 @@ +#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_items m_flex_align_self; + flex_align_content m_flex_align_content; + + caption_side m_caption_side; + + int m_order; + + private: + void compute_font(const element* el, const std::shared_ptr& doc); + void compute_background(const element* el, const std::shared_ptr& doc); + void compute_flex(const element* el, const std::shared_ptr& 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(0), + m_font_size(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_items_auto), + m_flex_align_content(flex_align_content_stretch), + m_order(0) + {} + + void compute(const element* el, const std::shared_ptr& doc); + std::vector> 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); + + caption_side get_caption_side() const; + void set_caption_side(caption_side side); + + float get_flex_grow() const; + float get_flex_shrink() const; + const css_length& get_flex_basis() const; + 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_items get_flex_align_self() const; + flex_align_content get_flex_align_content() const; + + int get_order() const; + void set_order(int order); + }; + + 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_items 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; + } + + inline caption_side css_properties::get_caption_side() const + { + return m_caption_side; + } + inline void css_properties::set_caption_side(caption_side side) + { + m_caption_side = side; + } + + inline int css_properties::get_order() const + { + return m_order; + } + + inline void css_properties::set_order(int order) + { + m_order = order; + } +} + +#endif //LITEHTML_CSS_PROPERTIES_H diff --git a/libs/litehtml/include/litehtml/css_selector.h b/libs/litehtml/include/litehtml/css_selector.h new file mode 100644 index 0000000000..4fe7db9e50 --- /dev/null +++ b/libs/litehtml/include/litehtml/css_selector.h @@ -0,0 +1,300 @@ +#ifndef LH_CSS_SELECTOR_H +#define LH_CSS_SELECTOR_H + +#include "style.h" +#include "media_query.h" + +namespace litehtml +{ + ////////////////////////////////////////////////////////////////////////// + + struct selector_specificity + { + int a; + int b; + int c; + int d; + + explicit selector_specificity(int va = 0, int vb = 0, int vc = 0, int vd = 0) + { + a = va; + b = vb; + c = vc; + d = vd; + } + + void operator += (const selector_specificity& val) + { + a += val.a; + b += val.b; + c += val.c; + d += val.d; + } + + bool operator==(const selector_specificity& val) const + { + if(a == val.a && b == val.b && c == val.c && d == val.d) + { + return true; + } + return false; + } + + bool operator!=(const selector_specificity& val) const + { + if(a != val.a || b != val.b || c != val.c || d != val.d) + { + return true; + } + return false; + } + + bool operator > (const selector_specificity& val) const + { + if(a > val.a) + { + return true; + } else if(a < val.a) + { + return false; + } else + { + if(b > val.b) + { + return true; + } else if(b < val.b) + { + return false; + } else + { + if(c > val.c) + { + return true; + } else if(c < val.c) + { + return false; + } else + { + if(d > val.d) + { + return true; + } else if(d < val.d) + { + return false; + } + } + } + } + return false; + } + + bool operator >= (const selector_specificity& val) const + { + if((*this) == val) return true; + if((*this) > val) return true; + return false; + } + + bool operator <= (const selector_specificity& val) const + { + if((*this) > val) + { + return false; + } + return true; + } + + bool operator < (const selector_specificity& val) const + { + if((*this) <= val && (*this) != val) + { + return true; + } + return false; + } + + }; + + ////////////////////////////////////////////////////////////////////////// + + 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 vector; + + attr_select_type type; + string_id name; // .name, #name, [name], :name + string val; // [name=val], :lang(val) + + std::shared_ptr sel; // :not(sel) + int a, b; // :nth-child(an+b) + + css_attribute_selector() + { + type = select_class; + name = empty_id; + a = b = 0; + } + }; + + ////////////////////////////////////////////////////////////////////////// + + class css_element_selector + { + public: + string_id m_tag; + css_attribute_selector::vector m_attrs; + public: + + void parse(const string& txt); + static void parse_nth_child_params(const string& param, int& num, int& off); + }; + + ////////////////////////////////////////////////////////////////////////// + + enum css_combinator + { + combinator_descendant, + combinator_child, + combinator_adjacent_sibling, + combinator_general_sibling + }; + + ////////////////////////////////////////////////////////////////////////// + + class css_selector + { + public: + typedef std::shared_ptr ptr; + typedef std::vector vector; + public: + selector_specificity m_specificity; + css_element_selector m_right; + css_selector::ptr m_left; + css_combinator m_combinator; + style::ptr m_style; + int m_order; + media_query_list::ptr m_media_query; + public: + explicit css_selector(const media_query_list::ptr& media = nullptr) + { + m_media_query = media; + m_combinator = combinator_descendant; + m_order = 0; + } + + ~css_selector() = default; + + css_selector(const css_selector& val) + { + m_right = val.m_right; + if(val.m_left) + { + m_left = std::make_shared(*val.m_left); + } else + { + m_left = nullptr; + } + m_combinator = val.m_combinator; + m_specificity = val.m_specificity; + m_order = val.m_order; + m_media_query = val.m_media_query; + } + + bool parse(const string& text); + void calc_specificity(); + bool is_media_valid() const; + void add_media_to_doc(document* doc) const; + }; + + inline bool css_selector::is_media_valid() const + { + if(!m_media_query) + { + return true; + } + return m_media_query->is_used(); + } + + + ////////////////////////////////////////////////////////////////////////// + + inline bool operator > (const css_selector& v1, const css_selector& v2) + { + if(v1.m_specificity == v2.m_specificity) + { + return (v1.m_order > v2.m_order); + } + return (v1.m_specificity > v2.m_specificity); + } + + inline bool operator < (const css_selector& v1, const css_selector& v2) + { + if(v1.m_specificity == v2.m_specificity) + { + return (v1.m_order < v2.m_order); + } + return (v1.m_specificity < v2.m_specificity); + } + + inline bool operator > (const css_selector::ptr& v1, const css_selector::ptr& v2) + { + return (*v1 > *v2); + } + + inline bool operator < (const css_selector::ptr& v1, const css_selector::ptr& v2) + { + return (*v1 < *v2); + } + + ////////////////////////////////////////////////////////////////////////// + + class used_selector + { + public: + typedef std::unique_ptr ptr; + typedef std::vector vector; + + css_selector::ptr m_selector; + bool m_used; + + used_selector(const css_selector::ptr& selector, bool used) + { + 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; + } + }; +} + +#endif // LH_CSS_SELECTOR_H diff --git a/libs/litehtml/include/litehtml/document.h b/libs/litehtml/include/litehtml/document.h new file mode 100644 index 0000000000..e2623b2221 --- /dev/null +++ b/libs/litehtml/include/litehtml/document.h @@ -0,0 +1,134 @@ +#ifndef LH_DOCUMENT_H +#define LH_DOCUMENT_H + +#include "style.h" +#include "types.h" +#include "master_css.h" + +namespace litehtml +{ + struct css_text + { + typedef std::vector vector; + + string text; + string baseurl; + string media; + + css_text() = default; + + css_text(const char* txt, const char* url, const char* media_str) + { + text = txt ? txt : ""; + baseurl = url ? url : ""; + media = media_str ? media_str : ""; + } + + css_text(const css_text& val) + { + text = val.text; + baseurl = val.baseurl; + media = val.media; + } + }; + + 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 + { + public: + typedef std::shared_ptr ptr; + typedef std::weak_ptr weak_ptr; + private: + std::shared_ptr m_root; + std::shared_ptr 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::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; + std::list> m_tabular_elements; + media_features m_media; + string m_lang; + string m_culture; + public: + document(document_container* objContainer); + virtual ~document(); + + 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 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; + 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); + element::ptr create_element(const char* tag_name, const string_map& attributes); + element::ptr root(); + void get_fixed_boxes(position::vector& fixed_boxes); + void add_fixed_box(const position& pos); + void add_media_list(const media_query_list::ptr& list); + bool media_changed(); + bool lang_changed(); + bool match_lang(const string& lang); + void add_tabular(const std::shared_ptr& el); + element::const_ptr get_over_element() const { return m_over_element; } + + void append_children_from_string(element& parent, const char* str); + void dump(dumper& cout); + + static litehtml::document::ptr createFromString(const char* str, litehtml::document_container* objPainter, const char* master_styles = litehtml::master_css, const char* user_styles = ""); + + private: + uint_ptr add_font(const char* name, int size, const char* weight, const char* style, const char* decoration, font_metrics* fm); + + void create_node(void* gnode, elements_list& elements, bool parseTextNode); + bool update_media_lists(const media_features& features); + void fix_tables_layout(); + void fix_table_children(const std::shared_ptr& el_ptr, style_display disp, const char* disp_str); + void fix_table_parent(const std::shared_ptr & el_ptr, style_display disp, const char* disp_str); + }; + + inline element::ptr document::root() + { + return m_root; + } + inline void document::add_tabular(const std::shared_ptr& el) + { + m_tabular_elements.push_back(el); + } + inline bool document::match_lang(const string& lang) + { + return lang == m_lang || lang == m_culture; + } +} + +#endif // LH_DOCUMENT_H diff --git a/libs/litehtml/include/litehtml/document_container.h b/libs/litehtml/include/litehtml/document_container.h new file mode 100644 index 0000000000..391873c1ab --- /dev/null +++ b/libs/litehtml/include/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 +#include + +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 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& 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& 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& 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& on_word, const std::function& on_space); + + protected: + ~document_container() = default; + }; +} + +#endif // LH_DOCUMENT_CONTAINER_H diff --git a/libs/litehtml/include/litehtml/el_anchor.h b/libs/litehtml/include/litehtml/el_anchor.h new file mode 100644 index 0000000000..b33794c52f --- /dev/null +++ b/libs/litehtml/include/litehtml/el_anchor.h @@ -0,0 +1,18 @@ +#ifndef LH_EL_ANCHOR_H +#define LH_EL_ANCHOR_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_anchor : public html_tag + { + public: + explicit el_anchor(const std::shared_ptr& doc); + + void on_click() override; + void apply_stylesheet(const litehtml::css& stylesheet) override; + }; +} + +#endif // LH_EL_ANCHOR_H diff --git a/libs/litehtml/include/litehtml/el_base.h b/libs/litehtml/include/litehtml/el_base.h new file mode 100644 index 0000000000..d7efb80649 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_base.h @@ -0,0 +1,17 @@ +#ifndef LH_EL_BASE_H +#define LH_EL_BASE_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_base : public html_tag + { + public: + explicit el_base(const std::shared_ptr& doc); + + void parse_attributes() override; + }; +} + +#endif // LH_EL_BASE_H diff --git a/libs/litehtml/include/litehtml/el_before_after.h b/libs/litehtml/include/litehtml/el_before_after.h new file mode 100644 index 0000000000..eed5f3dad7 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_before_after.h @@ -0,0 +1,39 @@ +#ifndef LH_EL_BEFORE_AFTER_H +#define LH_EL_BEFORE_AFTER_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_before_after_base : public html_tag + { + public: + el_before_after_base(const std::shared_ptr& doc, bool before); + + void add_style(const style& style) override; + private: + 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: + explicit el_before(const std::shared_ptr& doc) : el_before_after_base(doc, true) + { + + } + }; + + class el_after : public el_before_after_base + { + public: + explicit el_after(const std::shared_ptr& doc) : el_before_after_base(doc, false) + { + + } + }; +} + +#endif // LH_EL_BEFORE_AFTER_H diff --git a/libs/litehtml/include/litehtml/el_body.h b/libs/litehtml/include/litehtml/el_body.h new file mode 100644 index 0000000000..fb30e0c513 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_body.h @@ -0,0 +1,17 @@ +#ifndef LH_EL_BODY_H +#define LH_EL_BODY_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_body : public html_tag + { + public: + explicit el_body(const std::shared_ptr& doc); + + bool is_body() const override; + }; +} + +#endif // LH_EL_BODY_H diff --git a/libs/litehtml/include/litehtml/el_break.h b/libs/litehtml/include/litehtml/el_break.h new file mode 100644 index 0000000000..2a4d8fe45b --- /dev/null +++ b/libs/litehtml/include/litehtml/el_break.h @@ -0,0 +1,17 @@ +#ifndef LH_EL_BREAK_H +#define LH_EL_BREAK_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_break : public html_tag + { + public: + explicit el_break(const std::shared_ptr& doc); + + bool is_break() const override; + }; +} + +#endif // LH_EL_BREAK_H diff --git a/libs/litehtml/include/litehtml/el_cdata.h b/libs/litehtml/include/litehtml/el_cdata.h new file mode 100644 index 0000000000..838cd92b1e --- /dev/null +++ b/libs/litehtml/include/litehtml/el_cdata.h @@ -0,0 +1,19 @@ +#ifndef LH_EL_CDATA_H +#define LH_EL_CDATA_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_cdata : public element + { + string m_text; + public: + explicit el_cdata(const std::shared_ptr& doc); + + void get_text(string& text) override; + void set_data(const char* data) override; + }; +} + +#endif // LH_EL_CDATA_H diff --git a/libs/litehtml/include/litehtml/el_comment.h b/libs/litehtml/include/litehtml/el_comment.h new file mode 100644 index 0000000000..746238e9aa --- /dev/null +++ b/libs/litehtml/include/litehtml/el_comment.h @@ -0,0 +1,25 @@ +#ifndef LH_EL_COMMENT_H +#define LH_EL_COMMENT_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_comment : public element + { + string m_text; + public: + explicit el_comment(const std::shared_ptr& doc); + + bool is_comment() const override; + void get_text(string& text) override; + void set_data(const char* data) override; + std::shared_ptr create_render_item(const std::shared_ptr& /*parent_ri*/) override + { + // Comments are not rendered + return nullptr; + } + }; +} + +#endif // LH_EL_COMMENT_H diff --git a/libs/litehtml/include/litehtml/el_div.h b/libs/litehtml/include/litehtml/el_div.h new file mode 100644 index 0000000000..a2d031a32f --- /dev/null +++ b/libs/litehtml/include/litehtml/el_div.h @@ -0,0 +1,17 @@ +#ifndef LH_EL_DIV_H +#define LH_EL_DIV_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_div : public html_tag + { + public: + explicit el_div(const std::shared_ptr& doc); + + void parse_attributes() override; + }; +} + +#endif // LH_EL_DIV_H diff --git a/libs/litehtml/include/litehtml/el_font.h b/libs/litehtml/include/litehtml/el_font.h new file mode 100644 index 0000000000..ccb8945124 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_font.h @@ -0,0 +1,17 @@ +#ifndef LH_EL_FONT_H +#define LH_EL_FONT_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_font : public html_tag + { + public: + explicit el_font(const std::shared_ptr& doc); + + void parse_attributes() override; + }; +} + +#endif // LH_EL_FONT_H diff --git a/libs/litehtml/include/litehtml/el_image.h b/libs/litehtml/include/litehtml/el_image.h new file mode 100644 index 0000000000..2b73940815 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_image.h @@ -0,0 +1,29 @@ +#ifndef LH_EL_IMAGE_H +#define LH_EL_IMAGE_H + +#include "html_tag.h" + +namespace litehtml +{ + + class el_image : public html_tag + { + string m_src; + public: + 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 &ri) override; + void get_content_size(size& sz, int max_width) override; + string dump_get_name() override; + + std::shared_ptr create_render_item(const std::shared_ptr& parent_ri) override; + + private: +// int calc_max_height(int image_height); + }; +} + +#endif // LH_EL_IMAGE_H diff --git a/libs/litehtml/include/litehtml/el_link.h b/libs/litehtml/include/litehtml/el_link.h new file mode 100644 index 0000000000..0da3513dcd --- /dev/null +++ b/libs/litehtml/include/litehtml/el_link.h @@ -0,0 +1,18 @@ +#ifndef LH_EL_LINK_H +#define LH_EL_LINK_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_link : public html_tag + { + public: + explicit el_link(const std::shared_ptr& doc); + + protected: + void parse_attributes() override; + }; +} + +#endif // LH_EL_LINK_H diff --git a/libs/litehtml/include/litehtml/el_para.h b/libs/litehtml/include/litehtml/el_para.h new file mode 100644 index 0000000000..32ad537581 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_para.h @@ -0,0 +1,18 @@ +#ifndef LH_EL_PARA_H +#define LH_EL_PARA_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_para : public html_tag + { + public: + explicit el_para(const std::shared_ptr& doc); + + void parse_attributes() override; + + }; +} + +#endif // LH_EL_PARA_H diff --git a/libs/litehtml/include/litehtml/el_script.h b/libs/litehtml/include/litehtml/el_script.h new file mode 100644 index 0000000000..e0a0374057 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_script.h @@ -0,0 +1,21 @@ +#ifndef LH_EL_SCRIPT_H +#define LH_EL_SCRIPT_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_script : public element + { + string m_text; + public: + explicit el_script(const std::shared_ptr& doc); + + void parse_attributes() override; + bool appendChild(const ptr &el) override; + string_id tag() const override; + const char* get_tagName() const override; + }; +} + +#endif // LH_EL_SCRIPT_H diff --git a/libs/litehtml/include/litehtml/el_space.h b/libs/litehtml/include/litehtml/el_space.h new file mode 100644 index 0000000000..46a292ebcb --- /dev/null +++ b/libs/litehtml/include/litehtml/el_space.h @@ -0,0 +1,21 @@ +#ifndef LH_EL_SPACE_H +#define LH_EL_SPACE_H + +#include "html_tag.h" +#include "el_text.h" + +namespace litehtml +{ + class el_space : public el_text + { + public: + el_space(const char* text, const std::shared_ptr& doc); + + bool is_white_space() const override; + bool is_break() const override; + bool is_space() const override; + string dump_get_name() override; + }; +} + +#endif // LH_EL_SPACE_H diff --git a/libs/litehtml/include/litehtml/el_style.h b/libs/litehtml/include/litehtml/el_style.h new file mode 100644 index 0000000000..62f1546259 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_style.h @@ -0,0 +1,21 @@ +#ifndef LH_EL_STYLE_H +#define LH_EL_STYLE_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_style : public element + { + elements_list m_children; + public: + explicit el_style(const std::shared_ptr& doc); + + void parse_attributes() override; + bool appendChild(const ptr &el) override; + string_id tag() const override; + const char* get_tagName() const override; + }; +} + +#endif // LH_EL_STYLE_H diff --git a/libs/litehtml/include/litehtml/el_table.h b/libs/litehtml/include/litehtml/el_table.h new file mode 100644 index 0000000000..38352503bf --- /dev/null +++ b/libs/litehtml/include/litehtml/el_table.h @@ -0,0 +1,25 @@ +#ifndef LH_EL_TABLE_H +#define LH_EL_TABLE_H + +#include "html_tag.h" + +namespace litehtml +{ + struct col_info + { + int width; + bool is_auto; + }; + + + class el_table : public html_tag + { + public: + explicit el_table(const std::shared_ptr& doc); + + bool appendChild(const litehtml::element::ptr& el) override; + void parse_attributes() override; + }; +} + +#endif // LH_EL_TABLE_H diff --git a/libs/litehtml/include/litehtml/el_td.h b/libs/litehtml/include/litehtml/el_td.h new file mode 100644 index 0000000000..03d21c1c77 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_td.h @@ -0,0 +1,17 @@ +#ifndef LH_EL_TD_H +#define LH_EL_TD_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_td : public html_tag + { + public: + explicit el_td(const std::shared_ptr& doc); + + void parse_attributes() override; + }; +} + +#endif // LH_EL_TD_H diff --git a/libs/litehtml/include/litehtml/el_text.h b/libs/litehtml/include/litehtml/el_text.h new file mode 100644 index 0000000000..4b8a442f38 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_text.h @@ -0,0 +1,31 @@ +#ifndef LH_EL_TEXT_H +#define LH_EL_TEXT_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_text : public element + { + protected: + string m_text; + string m_transformed_text; + size m_size; + bool m_use_transformed; + bool m_draw_spaces; + public: + el_text(const char* text, const document::ptr& doc); + + 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 &ri) override; + string dump_get_name() override; + std::vector> dump_get_attrs() override; + protected: + void get_content_size(size& sz, int max_width) override; + }; +} + +#endif // LH_EL_TEXT_H diff --git a/libs/litehtml/include/litehtml/el_title.h b/libs/litehtml/include/litehtml/el_title.h new file mode 100644 index 0000000000..201186a4a0 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_title.h @@ -0,0 +1,18 @@ +#ifndef LH_EL_TITLE_H +#define LH_EL_TITLE_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_title : public html_tag + { + public: + explicit el_title(const std::shared_ptr& doc); + + protected: + void parse_attributes() override; + }; +} + +#endif // LH_EL_TITLE_H diff --git a/libs/litehtml/include/litehtml/el_tr.h b/libs/litehtml/include/litehtml/el_tr.h new file mode 100644 index 0000000000..49c0b9a9b2 --- /dev/null +++ b/libs/litehtml/include/litehtml/el_tr.h @@ -0,0 +1,17 @@ +#ifndef LH_EL_TR_H +#define LH_EL_TR_H + +#include "html_tag.h" + +namespace litehtml +{ + class el_tr : public html_tag + { + public: + explicit el_tr(const std::shared_ptr& doc); + + void parse_attributes() override; + }; +} + +#endif // LH_EL_TR_H diff --git a/libs/litehtml/include/litehtml/element.h b/libs/litehtml/include/litehtml/element.h new file mode 100644 index 0000000000..4d244736ba --- /dev/null +++ b/libs/litehtml/include/litehtml/element.h @@ -0,0 +1,234 @@ +#ifndef LH_ELEMENT_H +#define LH_ELEMENT_H + +#include +#include +#include +#include "stylesheet.h" +#include "css_offsets.h" +#include "css_margins.h" +#include "css_properties.h" + +namespace litehtml +{ + class line_box; + class dumper; + class render_item; + + class element : public std::enable_shared_from_this + { + friend class line_box; + friend class html_tag; + friend class el_table; + friend class document; + public: + typedef std::shared_ptr ptr; + typedef std::shared_ptr const_ptr; + typedef std::weak_ptr weak_ptr; + protected: + std::weak_ptr m_parent; + std::weak_ptr m_doc; + elements_list m_children; + css_properties m_css; + std::list> m_renders; + used_selector::vector m_used_styles; + + virtual void select_all(const css_selector& selector, elements_list& res); + element::ptr _add_before_after(int type, const style& style); + + private: + std::map m_counter_values; + + public: + explicit element(const std::shared_ptr& doc); + virtual ~element() = default; + + const css_properties& css() const; + css_properties& css_w(); + + bool in_normal_flow() const; + bool is_inline() const; // returns true if element is inline + bool is_inline_box() const; // returns true if element is inline box (inline-table, inline-box, inline-flex) + bool is_block_box() const; + position get_placement() const; + bool is_positioned() const; + bool is_float() const; + bool is_block_formatting_context() const; + + bool is_root() const; + element::ptr parent() const; + 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 get_document() const; + const std::list>& children() const; + + virtual elements_list select_all(const string& selector); + virtual elements_list select_all(const css_selector& selector); + + virtual element::ptr select_one(const string& selector); + virtual element::ptr select_one(const css_selector& selector); + + virtual bool appendChild(const ptr &el); + virtual bool removeChild(const ptr &el); + virtual void clearRecursive(); + + 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 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 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 set_pseudo_class(string_id cls, bool add); + virtual bool set_class(const char* pclass, bool add); + virtual bool is_replaced() const; + virtual void compute_styles(bool recursive = true); + virtual void draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr& ri); + virtual void draw_background(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr &ri); + virtual int get_enum_property (string_id name, bool inherited, int default_value, uint_ptr css_properties_member_offset) const; + virtual int get_int_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 = 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 = nullptr); + virtual element::ptr find_sibling(const element::ptr& el, const css_selector& selector, bool apply_pseudo = true, bool* is_pseudo = nullptr); + virtual void get_content_size(size& sz, int max_width); + virtual bool is_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 void add_style(const style& style); + virtual const background* get_background(bool own_only = false); + + virtual string dump_get_name(); + virtual std::vector> dump_get_attrs(); + void dump(litehtml::dumper& cout); + + std::tuple split_inlines(); + virtual std::shared_ptr create_render_item(const std::shared_ptr& parent_ri); + bool requires_styles_update(); + void add_render(const std::shared_ptr& 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); + } + + string get_counter_value(const string& counter_name); + string get_counters_value(const string_vector& parameters); + void increment_counter(const string_id& counter_name_id, const int increment = 1); + void reset_counter(const string_id& counter_name_id, const int value = 0); + + private: + std::vector get_siblings_before() const; + bool find_counter(const string_id& counter_name_id, std::map::iterator& map_iterator); + void parse_counter_tokens(const string_vector& tokens, const int default_value, std::function handler) const; + }; + + ////////////////////////////////////////////////////////////////////////// + // INLINE FUNCTIONS // + ////////////////////////////////////////////////////////////////////////// + + inline bool litehtml::element::in_normal_flow() const + { + if(css().get_position() != element_position_absolute && css().get_display() != display_none) + { + return true; + } + return false; + } + + inline bool litehtml::element::is_root() const + { + return m_parent.expired(); + } + + inline element::ptr litehtml::element::parent() const + { + return m_parent.lock(); + } + + inline void litehtml::element::parent(const element::ptr& par) + { + m_parent = par; + } + + inline bool litehtml::element::is_positioned() const + { + return (css().get_position() > element_position_static); + } + + inline bool litehtml::element::is_float() const + { + return (css().get_float() != float_none); + } + + inline std::shared_ptr element::get_document() const + { + return m_doc.lock(); + } + + inline const css_properties& element::css() const + { + return m_css; + } + + inline css_properties& element::css_w() + { + return m_css; + } + + inline bool element::is_block_box() const + { + 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; + } + + inline const std::list>& element::children() const + { + return m_children; + } +} + +#endif // LH_ELEMENT_H diff --git a/libs/litehtml/include/litehtml/flex_item.h b/libs/litehtml/include/litehtml/flex_item.h new file mode 100644 index 0000000000..0c4244ae2d --- /dev/null +++ b/libs/litehtml/include/litehtml/flex_item.h @@ -0,0 +1,137 @@ +#ifndef LITEHTML_FLEX_ITEM_H +#define LITEHTML_FLEX_ITEM_H + +#include +#include "formatting_context.h" + +namespace litehtml +{ + class flex_line; + + /** + * Base class for flex item + */ + class flex_item + { + public: + std::shared_ptr el; + int base_size; + int min_size; + def_value max_size; + int main_size; + int grow; + int shrink; + int scaled_flex_shrink_factor; + bool frozen; + int order; + int src_order; + def_value auto_margin_main_start; + def_value auto_margin_main_end; + bool auto_margin_cross_start; + bool auto_margin_cross_end; + flex_align_items align; + + explicit flex_item(std::shared_ptr &_el) : + el(_el), + base_size(0), + min_size(0), + max_size(0), + main_size(0), + grow(0), + shrink(0), + scaled_flex_shrink_factor(0), + frozen(false), + order(0), + src_order(0), + auto_margin_main_start(0), + auto_margin_main_end(0), + auto_margin_cross_start(false), + auto_margin_cross_end(false), + align(flex_align_items_auto) + {} + + virtual ~flex_item() = default; + + bool operator<(const flex_item& b) const + { + if(order < b.order) return true; + if(order == b.order) return src_order < b.src_order; + return false; + } + void init(const litehtml::containing_block_context &self_size, + litehtml::formatting_context *fmt_ctx, flex_align_items align_items); + virtual void apply_main_auto_margins() = 0; + virtual bool apply_cross_auto_margins(int cross_size) = 0; + virtual void set_main_position(int pos) = 0; + virtual void set_cross_position(int pos) = 0; + virtual int get_el_main_size() = 0; + virtual int get_el_cross_size() = 0; + + void place(flex_line &ln, int main_pos, + const containing_block_context &self_size, + formatting_context *fmt_ctx); + int get_last_baseline(baseline::_baseline_type type) const; + int get_first_baseline(baseline::_baseline_type type) const; + + protected: + virtual void direction_specific_init(const litehtml::containing_block_context &self_size, + litehtml::formatting_context *fmt_ctx) = 0; + virtual void align_stretch(flex_line &ln, const containing_block_context &self_size, + formatting_context *fmt_ctx) = 0; + virtual void align_baseline(flex_line &ln, + const containing_block_context &self_size, + formatting_context *fmt_ctx) = 0; + }; + + /** + * Flex item with "flex-direction: row" or " flex-direction: row-reverse" + */ + class flex_item_row_direction : public flex_item + { + public: + explicit flex_item_row_direction(std::shared_ptr &_el) : flex_item(_el) {} + + void apply_main_auto_margins() override; + bool apply_cross_auto_margins(int cross_size) override; + void set_main_position(int pos) override; + void set_cross_position(int pos) override; + int get_el_main_size() override; + int get_el_cross_size() override; + + protected: + void direction_specific_init(const litehtml::containing_block_context &self_size, + litehtml::formatting_context *fmt_ctx) override; + void align_stretch(flex_line &ln, const containing_block_context &self_size, + formatting_context *fmt_ctx) override; + void align_baseline(flex_line &ln, + const containing_block_context &self_size, + formatting_context *fmt_ctx) override; + }; + + /** + * Flex item with "flex-direction: column" or " flex-direction: column-reverse" + */ + class flex_item_column_direction : public flex_item + { + public: + explicit flex_item_column_direction(std::shared_ptr &_el) : flex_item(_el) {} + + void apply_main_auto_margins() override; + bool apply_cross_auto_margins(int cross_size) override; + void set_main_position(int pos) override; + void set_cross_position(int pos) override; + int get_el_main_size() override; + int get_el_cross_size() override; + + protected: + void direction_specific_init(const litehtml::containing_block_context &self_size, + litehtml::formatting_context *fmt_ctx) override; + void align_stretch(flex_line &ln, const containing_block_context &self_size, + formatting_context *fmt_ctx) override; + void align_baseline(flex_line &ln, + const containing_block_context &self_size, + formatting_context *fmt_ctx) override; + }; +} + +#endif //LITEHTML_FLEX_ITEM_H diff --git a/libs/litehtml/include/litehtml/flex_line.h b/libs/litehtml/include/litehtml/flex_line.h new file mode 100644 index 0000000000..c96df86bb5 --- /dev/null +++ b/libs/litehtml/include/litehtml/flex_line.h @@ -0,0 +1,56 @@ +#ifndef LITEHTML_FLEX_LINE_H +#define LITEHTML_FLEX_LINE_H + +#include "formatting_context.h" + +namespace litehtml +{ + class flex_item; + + class flex_line + { + public: + std::list> items; + int cross_start; // for row direction: top. for column direction: left + int main_size; // sum of all items main size + int cross_size; // sum of all items cross size + int base_size; + int total_grow; + int total_shrink; + int num_auto_margin_main_start; // number of items with auto margin left/top + int num_auto_margin_main_end; // number of items with auto margin right/bottom + baseline first_baseline; + baseline last_baseline; + bool reverse_main; + bool reverse_cross; + + flex_line(bool _reverse_main, bool _reverse_cross) : + cross_start(0), + main_size(0), + cross_size(0), + base_size(0), + total_grow(0), + total_shrink(0), + num_auto_margin_main_start(0), + num_auto_margin_main_end(0), + first_baseline(), + last_baseline(), + reverse_main(_reverse_main), + reverse_cross(_reverse_cross) + {} + + void init(int container_main_size, bool fit_container, bool is_row_direction, + const litehtml::containing_block_context &self_size, + litehtml::formatting_context *fmt_ctx); + bool distribute_main_auto_margins(int free_main_size); + int calculate_items_position(int container_main_size, + flex_justify_content justify_content, + bool is_row_direction, + const containing_block_context &self_size, + formatting_context *fmt_ctx); + protected: + void distribute_free_space(int container_main_size); + }; +} + +#endif //LITEHTML_FLEX_LINE_H diff --git a/libs/litehtml/include/litehtml/formatting_context.h b/libs/litehtml/include/litehtml/formatting_context.h new file mode 100644 index 0000000000..eee481dc46 --- /dev/null +++ b/libs/litehtml/include/litehtml/formatting_context.h @@ -0,0 +1,54 @@ +#ifndef LITEHTML_FLOATS_HOLDER_H +#define LITEHTML_FLOATS_HOLDER_H + +#include +#include "types.h" + +namespace litehtml +{ + class formatting_context + { + private: + std::list m_floats_left; + std::list m_floats_right; + int_int_cache m_cache_line_left; + int_int_cache m_cache_line_right; + int m_current_top; + int m_current_left; + + public: + formatting_context() : m_current_top(0), m_current_left(0) {} + + void push_position(int x, int y) + { + m_current_left += x; + m_current_top += y; + } + void pop_position(int x, int y) + { + m_current_left -= x; + m_current_top -= y; + } + + void add_float(const std::shared_ptr &el, int min_width, int context); + void clear_floats(int context); + int find_next_line_top( int top, int width, int def_right ); + int get_floats_height(element_float el_float = float_none) const; + int get_left_floats_height() const; + int get_right_floats_height() const; + int get_line_left( int y ); + void get_line_left_right( int y, int def_right, int& ln_left, int& ln_right ) + { + ln_left = get_line_left(y); + ln_right = get_line_right(y, def_right); + } + int get_line_right( int y, int def_right ); + int get_cleared_top(const std::shared_ptr &el, int line_top) const; + void update_floats(int dy, const std::shared_ptr &parent); + void apply_relative_shift(const containing_block_context &containing_block_size); + int find_min_left(int y, int context_idx); + int find_min_right(int y, int right, int context_idx); + }; +} + +#endif //LITEHTML_FLOATS_HOLDER_H diff --git a/libs/litehtml/include/litehtml/html.h b/libs/litehtml/include/litehtml/html.h new file mode 100644 index 0000000000..818d5ce565 --- /dev/null +++ b/libs/litehtml/include/litehtml/html.h @@ -0,0 +1,88 @@ +#ifndef LH_HTML_H +#define LH_HTML_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "os_types.h" +#include "string_id.h" +#include "types.h" +#include "utf8_strings.h" +#include "background.h" +#include "borders.h" +#include "web_color.h" +#include "media_query.h" +#include "html_tag.h" +#include "document_container.h" +#include "document.h" + +namespace litehtml +{ + void trim(string &s, const string& chars_to_trim = " \n\r\t"); + 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); + + int t_strcasecmp(const char *s1, const char *s2); + int t_strncasecmp(const char *s1, const char *s2, size_t n); + + bool is_number(const string& string, const bool allow_dot = 1); + + inline int t_isdigit(int c) + { + return (c >= '0' && c <= '9'); + } + + 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; + if(val - int_val >= 0.5) + { + int_val++; + } + return int_val; + } + + inline int round_d(double val) + { + int int_val = (int) val; + if(val - int_val >= 0.5) + { + int_val++; + } + 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/libs/litehtml/include/litehtml/html_tag.h b/libs/litehtml/include/litehtml/html_tag.h new file mode 100644 index 0000000000..b085d7dfb2 --- /dev/null +++ b/libs/litehtml/include/litehtml/html_tag.h @@ -0,0 +1,139 @@ +#ifndef LH_HTML_TAG_H +#define LH_HTML_TAG_H + +#include "element.h" +#include "style.h" +#include "background.h" +#include "css_margins.h" +#include "borders.h" +#include "css_selector.h" +#include "stylesheet.h" +#include "line_box.h" +#include "table.h" + +namespace litehtml +{ + + class html_tag : public element + { + friend class elements_iterator; + friend class el_table; + friend class table_grid; + friend class line_box; + public: + typedef std::shared_ptr ptr; + protected: + string_id m_tag; + string_id m_id; + string_vector m_str_classes; + std::vector m_classes; + litehtml::style m_style; + string_map m_attrs; + std::vector m_pseudo_classes; + + void select_all(const css_selector& selector, elements_list& res) override; + + public: + explicit html_tag(const std::shared_ptr& 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; + + 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 &ri) override; + void draw_background(uint_ptr hdc, int x, int y, const position *clip, + const std::shared_ptr &ri) override; + + template + 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; + int get_int_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_list& 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_list select_all(const string& selector) override; + elements_list select_all(const css_selector& selector) override; + + element::ptr select_one(const string& selector) override; + element::ptr select_one(const css_selector& selector) override; + + 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; + 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 init_background_paint(position pos, std::vector& bg_paint, const background* bg, const std::shared_ptr& ri); + void init_one_background_paint(int i, position pos, background_paint& bg_paint, const background* bg, const std::shared_ptr& 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); + + private: + void handle_counter_properties(); + + }; + + /************************************************************************/ + /* Inline Functions */ + /************************************************************************/ + + inline elements_list& litehtml::html_tag::children() + { + return m_children; + } +} + +#endif // LH_HTML_TAG_H diff --git a/libs/litehtml/include/litehtml/iterators.h b/libs/litehtml/include/litehtml/iterators.h new file mode 100644 index 0000000000..b1a678d7b4 --- /dev/null +++ b/libs/litehtml/include/litehtml/iterators.h @@ -0,0 +1,84 @@ +#ifndef LH_ITERATORS_H +#define LH_ITERATORS_H + +#include "types.h" +#include +#include + +namespace litehtml +{ + class render_item; + + class iterator_selector + { + public: + virtual bool select(const std::shared_ptr& 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: + iterator_selector* m_go_inside; + iterator_selector* m_select; + bool m_return_parent; + + /** + * 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& el); + + public: + elements_iterator(bool return_parents, iterator_selector* go_inside, iterator_selector* select); + ~elements_iterator() = default; + + void process(const std::shared_ptr& container, const std::function&, iterator_item_type)>& func); + + private: + void next_idx(); + }; + + class go_inside_inline final : public iterator_selector + { + public: + bool select(const std::shared_ptr& el) override; + }; + + class inline_selector final : public iterator_selector + { + public: + bool select(const std::shared_ptr& el) override; + }; + + class go_inside_table final : public iterator_selector + { + public: + bool select(const std::shared_ptr& el) override; + }; + + class table_rows_selector final : public iterator_selector + { + public: + bool select(const std::shared_ptr& el) override; + }; + + class table_cells_selector final : public iterator_selector + { + public: + bool select(const std::shared_ptr& el) override; + }; +} + +#endif // LH_ITERATORS_H diff --git a/libs/litehtml/include/litehtml/line_box.h b/libs/litehtml/include/litehtml/line_box.h new file mode 100644 index 0000000000..a1e4969c96 --- /dev/null +++ b/libs/litehtml/include/litehtml/line_box.h @@ -0,0 +1,171 @@ +#ifndef LH_LINE_BOX_H +#define LH_LINE_BOX_H + +#include +#include +#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; + } + line_context() : calculatedTop(0), top(0), left(0), right(0) {} + }; + + class line_box_item + { + public: + enum element_type + { + type_text_part, + type_inline_start, + type_inline_continue, + type_inline_end + }; + protected: + std::shared_ptr m_element; + int m_rendered_min_width; + public: + explicit line_box_item(const std::shared_ptr& element) : m_element(element), m_rendered_min_width(0) {} + line_box_item() : m_element(), m_rendered_min_width(0) {}; + 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& 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& 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& 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& 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 > 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_line_height(0), + m_default_line_height(line_height), + m_font_metrics(fm), + m_baseline(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 item); + bool can_hold(const std::unique_ptr& 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 > finish(bool last_box, const containing_block_context &containing_block_size); + std::list< std::unique_ptr > new_width(int left, int right); + std::shared_ptr get_last_text_part() const; + std::shared_ptr get_first_text_part() const; + std::list< std::unique_ptr >& 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/libs/litehtml/include/litehtml/master_css.h b/libs/litehtml/include/litehtml/master_css.h new file mode 100644 index 0000000000..0e7b0ca4e3 --- /dev/null +++ b/libs/litehtml/include/litehtml/master_css.h @@ -0,0 +1,376 @@ +#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; +} + +table[align=left] { + float: left; +} + +table[align=right] { + float: right; +} + +table[align=center] { + margin-left: auto; + margin-right: auto; +} + +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; +} + +figure { + display: block; + margin-top: 1em; + margin-bottom: 1em; + margin-left: 40px; + margin-right: 40px; +} + +figcaption { + display: block; +} + +)##"; } +#endif // LH_MASTER_CSS_H diff --git a/libs/litehtml/include/litehtml/media_query.h b/libs/litehtml/include/litehtml/media_query.h new file mode 100644 index 0000000000..4cb21fc2f6 --- /dev/null +++ b/libs/litehtml/include/litehtml/media_query.h @@ -0,0 +1,77 @@ +#ifndef LH_MEDIA_QUERY_H +#define LH_MEDIA_QUERY_H + +namespace litehtml +{ + struct media_query_expression + { + typedef std::vector vector; + media_feature feature; + int val; + int val2; + bool check_as_bool; + + media_query_expression() + { + check_as_bool = false; + feature = media_feature_none; + val = 0; + val2 = 0; + } + + bool check(const media_features& features) const; + }; + + class media_query + { + public: + typedef std::shared_ptr ptr; + typedef std::vector vector; + private: + media_query_expression::vector m_expressions; + bool m_not; + media_type m_media_type; + public: + media_query(); + media_query(const media_query& val); + + static media_query::ptr create_from_string(const string& str, const std::shared_ptr& doc); + bool check(const media_features& features) const; + }; + + class media_query_list + { + public: + typedef std::shared_ptr ptr; + typedef std::vector vector; + private: + media_query::vector m_queries; + bool m_is_used; + public: + media_query_list(); + media_query_list(const media_query_list& val); + + static media_query_list::ptr create_from_string(const string& str, const std::shared_ptr& doc); + bool is_used() const; + bool apply_media_features(const media_features& features); // returns true if the m_is_used changed + }; + + inline media_query_list::media_query_list(const media_query_list& val) + { + m_is_used = val.m_is_used; + m_queries = val.m_queries; + } + + inline media_query_list::media_query_list() + { + m_is_used = false; + } + + inline bool media_query_list::is_used() const + { + return m_is_used; + } + +} + +#endif // LH_MEDIA_QUERY_H diff --git a/libs/litehtml/include/litehtml/num_cvt.h b/libs/litehtml/include/litehtml/num_cvt.h new file mode 100644 index 0000000000..0eaaa68868 --- /dev/null +++ b/libs/litehtml/include/litehtml/num_cvt.h @@ -0,0 +1,19 @@ +#ifndef NUM_CVT_H +#define NUM_CVT_H + +#include +#include "os_types.h" + +namespace litehtml +{ + namespace num_cvt + { + 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); + } +} + +#endif // NUM_CVT_H \ No newline at end of file diff --git a/libs/litehtml/include/litehtml/os_types.h b/libs/litehtml/include/litehtml/os_types.h new file mode 100644 index 0000000000..bbc2c3cf63 --- /dev/null +++ b/libs/litehtml/include/litehtml/os_types.h @@ -0,0 +1,30 @@ +#ifndef LH_OS_TYPES_H +#define LH_OS_TYPES_H + +#include +#include + +namespace litehtml +{ + using std::string; + typedef std::uintptr_t uint_ptr; + +#if defined( WIN32 ) || defined( _WIN32 ) || defined( WINCE ) + +// noexcept appeared since Visual Studio 2015 +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define noexcept +#endif + + #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 t_itoa(value, buffer, size, radix) snprintf(buffer, size, "%d", value) + #define t_snprintf(s, n, format, ...) snprintf(s, n, format, __VA_ARGS__) + +#endif +} + +#endif // LH_OS_TYPES_H diff --git a/libs/litehtml/include/litehtml/render_block.h b/libs/litehtml/include/litehtml/render_block.h new file mode 100644 index 0000000000..1874be3324 --- /dev/null +++ b/libs/litehtml/include/litehtml/render_block.h @@ -0,0 +1,40 @@ +#ifndef LITEHTML_RENDER_BLOCK_H +#define LITEHTML_RENDER_BLOCK_H + +#include "render_item.h" + +namespace litehtml +{ + class render_item_block : public render_item + { + protected: + /** + * Render block content. + * + * @param x - horizontal position of the content + * @param y - vertical position of the content + * @param second_pass - true is this is the second pass. + * @param ret_width - input minimal width. + * @param self_size - defines calculated size of block + * @return return value is the minimal width of the content in block. Must be greater or equal to ret_width parameter + */ + virtual int _render_content(int /*x*/, int /*y*/, bool /*second_pass*/, const containing_block_context &/*self_size*/, formatting_context* /*fmt_ctx*/) {return 0;} + int _render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) override; + int place_float(const std::shared_ptr &el, int top, const containing_block_context &self_size, formatting_context* fmt_ctx); + virtual void fix_line_width(element_float /*flt*/, + const containing_block_context &/*containing_block_size*/, formatting_context* /*fmt_ctx*/) + {} + + public: + explicit render_item_block(std::shared_ptr src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + std::shared_ptr init() override; + }; +} + +#endif //LITEHTML_RENDER_BLOCK_H diff --git a/libs/litehtml/include/litehtml/render_block_context.h b/libs/litehtml/include/litehtml/render_block_context.h new file mode 100644 index 0000000000..c69389832c --- /dev/null +++ b/libs/litehtml/include/litehtml/render_block_context.h @@ -0,0 +1,31 @@ +#ifndef LITEHTML_RENDER_BLOCK_CONTEXT_H +#define LITEHTML_RENDER_BLOCK_CONTEXT_H + +#include "render_block.h" + +namespace litehtml +{ + /** + * In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a + * containing block. + * https://www.w3.org/TR/CSS22/visuren.html#block-formatting + */ + class render_item_block_context : public render_item_block + { + protected: + int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) override; + + public: + explicit render_item_block_context(std::shared_ptr src_el) : render_item_block(std::move(src_el)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + int get_first_baseline() override; + int get_last_baseline() override; + }; +} + +#endif //LITEHTML_RENDER_BLOCK_CONTEXT_H diff --git a/libs/litehtml/include/litehtml/render_flex.h b/libs/litehtml/include/litehtml/render_flex.h new file mode 100644 index 0000000000..6a03b98ece --- /dev/null +++ b/libs/litehtml/include/litehtml/render_flex.h @@ -0,0 +1,33 @@ +#ifndef LITEHTML_RENDER_FLEX_H +#define LITEHTML_RENDER_FLEX_H + +#include "render_block.h" +#include "flex_item.h" +#include "flex_line.h" + +namespace litehtml +{ + class render_item_flex : public render_item_block + { + std::list m_lines; + + std::list get_lines(const containing_block_context &self_size, formatting_context *fmt_ctx, bool is_row_direction, + int container_main_size, bool single_line); + int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) override; + + public: + explicit render_item_flex(std::shared_ptr src_el) : render_item_block(std::move(src_el)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + std::shared_ptr init() override; + + int get_first_baseline() override; + int get_last_baseline() override; + }; +} + +#endif //LITEHTML_RENDER_FLEX_H diff --git a/libs/litehtml/include/litehtml/render_image.h b/libs/litehtml/include/litehtml/render_image.h new file mode 100644 index 0000000000..e85f487caf --- /dev/null +++ b/libs/litehtml/include/litehtml/render_image.h @@ -0,0 +1,25 @@ +#ifndef LITEHTML_RENDER_IMAGE_H +#define LITEHTML_RENDER_IMAGE_H + +#include "render_item.h" + +namespace litehtml +{ + class render_item_image : public render_item + { + protected: + int calc_max_height(int image_height, int containing_block_height); + int _render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) override; + + public: + explicit render_item_image(std::shared_ptr src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + }; +} + +#endif //LITEHTML_RENDER_IMAGE_H diff --git a/libs/litehtml/include/litehtml/render_inline.h b/libs/litehtml/include/litehtml/render_inline.h new file mode 100644 index 0000000000..666074b90c --- /dev/null +++ b/libs/litehtml/include/litehtml/render_inline.h @@ -0,0 +1,38 @@ +#ifndef LITEHTML_RENDER_INLINE_H +#define LITEHTML_RENDER_INLINE_H + +#include "render_item.h" + +namespace litehtml +{ + class render_item_inline : public render_item + { + protected: + position::vector m_boxes; + + public: + explicit render_item_inline(std::shared_ptr 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_first_baseline() override + { + return src_el()->css().get_font_metrics().height - src_el()->css().get_font_metrics().base_line(); + } + int get_last_baseline() override + { + return src_el()->css().get_font_metrics().height - src_el()->css().get_font_metrics().base_line(); + } + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + }; +} + +#endif //LITEHTML_RENDER_INLINE_H + diff --git a/libs/litehtml/include/litehtml/render_inline_context.h b/libs/litehtml/include/litehtml/render_inline_context.h new file mode 100644 index 0000000000..7d629bc7ff --- /dev/null +++ b/libs/litehtml/include/litehtml/render_inline_context.h @@ -0,0 +1,56 @@ +#ifndef LITEHTML_RENDER_INLINE_CONTEXT_H +#define LITEHTML_RENDER_INLINE_CONTEXT_H + +#include "render_block.h" + +namespace litehtml +{ + /** + * An inline formatting context is established by a block container box that contains no block-level boxes. + * https://www.w3.org/TR/CSS22/visuren.html#inline-formatting + */ + class render_item_inline_context : public render_item_block + { + /** + * Structure contains elements with display: inline + * members: + * - element: render_item with display: inline + * - boxes: rectangles represented inline element content. There are can be many boxes if content + * is split into some lines + * - start_box: the start position of currently calculated box + */ + struct inlines_item + { + std::shared_ptr element; + position::vector boxes; + position start_box; + + explicit inlines_item(const std::shared_ptr& el) : element(el) {} + }; + protected: + std::vector > m_line_boxes; + int m_max_line_width; + + int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) override; + void fix_line_width(element_float flt, + const containing_block_context &self_size, formatting_context* fmt_ctx) override; + + std::list > finish_last_box(bool end_of_render, const containing_block_context &self_size); + void place_inline(std::unique_ptr item, const containing_block_context &self_size, formatting_context* fmt_ctx); + int new_box(const std::unique_ptr& el, line_context& line_ctx, const containing_block_context &self_size, formatting_context* fmt_ctx); + void apply_vertical_align() override; + public: + explicit render_item_inline_context(std::shared_ptr src_el) : render_item_block(std::move(src_el)), m_max_line_width(0) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + + int get_first_baseline() override; + int get_last_baseline() override; + }; +} + +#endif //LITEHTML_RENDER_INLINE_CONTEXT_H diff --git a/libs/litehtml/include/litehtml/render_item.h b/libs/litehtml/include/litehtml/render_item.h new file mode 100644 index 0000000000..8ee3077676 --- /dev/null +++ b/libs/litehtml/include/litehtml/render_item.h @@ -0,0 +1,387 @@ +#ifndef LH_RENDER_ITEM_H +#define LH_RENDER_ITEM_H + +#include +#include +#include +#include +#include "types.h" +#include "line_box.h" +#include "table.h" +#include "formatting_context.h" + +namespace litehtml +{ + class element; + + class render_item : public std::enable_shared_from_this + { + protected: + std::shared_ptr m_element; + std::weak_ptr m_parent; + std::list> m_children; + margins m_margins; + margins m_padding; + margins m_borders; + position m_pos; + bool m_skip; + std::vector> 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; + virtual int _render(int /*x*/, int /*y*/, const containing_block_context& /*containing_block_size*/, formatting_context* /*fmt_ctx*/, bool /*second_pass = false*/) + { + return 0; + } + + public: + explicit render_item(std::shared_ptr src_el); + + virtual ~render_item() = default; + + std::list>& 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.width() + 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 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 + { + if(css().get_box_sizing() == box_sizing_border_box) + { + return m_padding.left + m_borders.left; + } + return 0; + } + + int box_sizing_right() const + { + if(css().get_box_sizing() == box_sizing_border_box) + { + return m_padding.right + m_borders.right; + } + return 0; + } + + int box_sizing_width() const + { + return box_sizing_left() + box_sizing_right(); + } + + int box_sizing_top() const + { + if(css().get_box_sizing() == box_sizing_border_box) + { + return m_padding.top + m_borders.top; + } + return 0; + } + + int box_sizing_bottom() const + { + if(css().get_box_sizing() == box_sizing_border_box) + { + return m_padding.bottom + m_borders.bottom; + } + return 0; + } + + int box_sizing_height() const + { + return box_sizing_top() + box_sizing_bottom(); + } + + void parent(const std::shared_ptr& par) + { + m_parent = par; + } + + const std::shared_ptr& src_el() const + { + return m_element; + } + + const css_properties& css() const + { + return m_element->css(); + } + + void add_child(const std::shared_ptr& ri) + { + m_children.push_back(ri); + ri->parent(shared_from_this()); + } + + 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_flex_item() && + !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); + } + + bool is_flex_item() const + { + auto par = parent(); + if(par && (par->css().get_display() == display_inline_flex || par->css().get_display() == display_flex)) + { + return true; + } + return false; + } + + int render(int x, int y, const containing_block_context& containing_block_size, formatting_context* fmt_ctx, bool second_pass = false); + 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 init(); + virtual void apply_vertical_align() {} + /** + * Get first baseline position. Default position is element bottom without bottom margin. + * @returns offset of the first baseline from element top + */ + virtual int get_first_baseline() { return height() - margin_bottom(); } + /** + * Get last baseline position. Default position is element bottom without bottom margin. + * @returns offset of the last baseline from element top + */ + virtual int get_last_baseline() { return height() - margin_bottom(); } + + virtual std::shared_ptr clone() + { + return std::make_shared(src_el()); + } + std::tuple< + std::shared_ptr, + std::shared_ptr, + std::shared_ptr + > split_inlines(); + bool fetch_positioned(); + void render_positioned(render_type rt = render_all); + void add_positioned(const std::shared_ptr &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 get_child_by_point(int x, int y, int client_x, int client_y, draw_flag flag, int zindex); + std::shared_ptr 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); + }; +} + +#endif //LH_RENDER_ITEM_H diff --git a/libs/litehtml/include/litehtml/render_table.h b/libs/litehtml/include/litehtml/render_table.h new file mode 100644 index 0000000000..57fe435df0 --- /dev/null +++ b/libs/litehtml/include/litehtml/render_table.h @@ -0,0 +1,56 @@ +#ifndef LITEHTML_RENDER_TABLE_H +#define LITEHTML_RENDER_TABLE_H + +#include "render_item.h" + +namespace litehtml +{ + class render_item_table : public render_item + { + protected: + // data for table rendering + std::unique_ptr m_grid; + int m_border_spacing_x; + int m_border_spacing_y; + + int _render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) override; + + public: + explicit render_item_table(std::shared_ptr src_el); + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override; + int get_draw_vertical_offset() override; + std::shared_ptr init() override; + }; + + class render_item_table_part : public render_item + { + public: + explicit render_item_table_part(std::shared_ptr src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + }; + + class render_item_table_row : public render_item + { + public: + explicit render_item_table_row(std::shared_ptr src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr clone() override + { + return std::make_shared(src_el()); + } + void get_inline_boxes( position::vector& boxes ) const override; + }; +} + +#endif //LITEHTML_RENDER_TABLE_H diff --git a/libs/litehtml/include/litehtml/string_id.h b/libs/litehtml/include/litehtml/string_id.h new file mode 100644 index 0000000000..56827a097d --- /dev/null +++ b/libs/litehtml/include/litehtml/string_id.h @@ -0,0 +1,306 @@ +#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_, + + _caption_side_, + _order_, + + _counter_reset_, + _counter_increment_, +) +#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/libs/litehtml/include/litehtml/style.h b/libs/litehtml/include/litehtml/style.h new file mode 100644 index 0000000000..9f25ed7f02 --- /dev/null +++ b/libs/litehtml/include/litehtml/style.h @@ -0,0 +1,215 @@ +#ifndef LH_STYLE_H +#define LH_STYLE_H + +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: + 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) + { + } + property_value(bool important, property_type type) + : m_type(type), m_important(important) + { + } + property_value(const string& str, bool important, property_type type = prop_type_string) + : m_type(type), m_important(important), m_string(str) + { + } + property_value(const string_vector& vec, bool important) + : m_type(prop_type_string_vector), m_important(important), m_string_vector(vec) + { + } + property_value(const css_length& length, bool important) + : m_type(prop_type_length), m_important(important), m_length(length) + { + } + property_value(const length_vector& vec, bool important) + : m_type(prop_type_length_vector), m_important(important), m_length_vector(vec) + { + } + property_value(float number, bool important) + : m_type(prop_type_number), m_important(important), m_number(number) + { + } + property_value(int enum_item, bool important) + : m_type(prop_type_enum_item), m_important(important), m_enum_item(enum_item) + { + } + property_value(const int_vector& vec, bool important) + : m_type(prop_type_enum_item_vector), m_important(important), m_enum_item_vector(vec) + { + } + property_value(web_color color, bool important) + : m_type(prop_type_color), m_important(important), m_color(color) + { + } + property_value(const size_vector& vec, bool important) + : m_type(prop_type_size_vector), m_important(important), m_size_vector(vec) + { + } + ~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; + default: + break; + } + } + property_value& operator=(const property_value& val) + { + 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 props_map; + + class style + { + public: + typedef std::shared_ptr