diff options
| author | George Hazan <george.hazan@gmail.com> | 2024-03-18 12:13:54 +0300 |
|---|---|---|
| committer | George Hazan <george.hazan@gmail.com> | 2024-03-18 12:13:54 +0300 |
| commit | 705c4d24c9c61edffc82864bf9c24384dc29a8d7 (patch) | |
| tree | 4d21f87671db36b99402da3221d45b64c257c1fe /libs/litehtml/include | |
| parent | 5784fc3a62b9136c6690ed45ec7b505f35512e08 (diff) | |
litehtml - lightweight html renderer
Diffstat (limited to 'libs/litehtml/include')
62 files changed, 6699 insertions, 0 deletions
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 <litehtml/html.h> +#include <litehtml/document.h> +#include <litehtml/html_tag.h> +#include <litehtml/stylesheet.h> +#include <litehtml/element.h> +#include <litehtml/utf8_strings.h> + +#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 <string> + +#include "os_types.h" + +namespace litehtml { + +bool is_ascii_codepoint(char c); + +// Returns true if the codepoint is a reserved codepoint for URLs. +// https://datatracker.ietf.org/doc/html/rfc3986#section-2.2 +bool is_url_reserved_codepoint(char c); + +// Returns true if the codepoint is a scheme codepoint for URLs. +// https://datatracker.ietf.org/doc/html/rfc3986#section-3.1 +bool is_url_scheme_codepoint(char c); + +} // namespace litehtml + +#endif // LITEHTML_CODEPOINT_H__ diff --git a/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>; + + // 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<css_size>; +} + +#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<document>& doc); + void compute_background(const element* el, const std::shared_ptr<document>& doc); + void compute_flex(const element* el, const std::shared_ptr<document>& doc); + + public: + css_properties() : + m_el_position(element_position_static), + m_text_align(text_align_left), + m_overflow(overflow_visible), + m_white_space(white_space_normal), + m_display(display_inline), + m_visibility(visibility_visible), + m_box_sizing(box_sizing_content_box), + m_z_index(0), + m_vertical_align(va_baseline), + m_float(float_none), + m_clear(clear_none), + m_css_margins(), + m_css_padding(), + m_css_borders(), + m_css_width(), + m_css_height(), + m_css_min_width(), + m_css_min_height(), + m_css_max_width(), + m_css_max_height(), + m_css_offsets(), + m_css_text_indent(), + m_css_line_height(0), + m_line_height(0), + m_list_style_type(list_style_type_none), + m_list_style_position(list_style_position_outside), + m_bg(), + m_font(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<document>& doc); + std::vector<std::tuple<string, string>> dump_get_attrs(); + + element_position get_position() const; + void set_position(element_position mElPosition); + + text_align get_text_align() const; + void set_text_align(text_align mTextAlign); + + overflow get_overflow() const; + void set_overflow(overflow mOverflow); + + white_space get_white_space() const; + void set_white_space(white_space mWhiteSpace); + + style_display get_display() const; + void set_display(style_display mDisplay); + + visibility get_visibility() const; + void set_visibility(visibility mVisibility); + + box_sizing get_box_sizing() const; + void set_box_sizing(box_sizing mBoxSizing); + + int get_z_index() const; + void set_z_index(int mZIndex); + + vertical_align get_vertical_align() const; + void set_vertical_align(vertical_align mVerticalAlign); + + element_float get_float() const; + void set_float(element_float mFloat); + + element_clear get_clear() const; + void set_clear(element_clear mClear); + + const css_margins &get_margins() const; + void set_margins(const css_margins &mCssMargins); + + const css_margins &get_padding() const; + void set_padding(const css_margins &mCssPadding); + + const css_borders &get_borders() const; + void set_borders(const css_borders &mCssBorders); + + const css_length &get_width() const; + void set_width(const css_length &mCssWidth); + + const css_length &get_height() const; + void set_height(const css_length &mCssHeight); + + const css_length &get_min_width() const; + void set_min_width(const css_length &mCssMinWidth); + + const css_length &get_min_height() const; + void set_min_height(const css_length &mCssMinHeight); + + const css_length &get_max_width() const; + void set_max_width(const css_length &mCssMaxWidth); + + const css_length &get_max_height() const; + void set_max_height(const css_length &mCssMaxHeight); + + const css_offsets &get_offsets() const; + void set_offsets(const css_offsets &mCssOffsets); + + const css_length &get_text_indent() const; + void set_text_indent(const css_length &mCssTextIndent); + + int get_line_height() const; + void set_line_height(int mLineHeight); + + list_style_type get_list_style_type() const; + void set_list_style_type(list_style_type mListStyleType); + + list_style_position get_list_style_position() const; + void set_list_style_position(list_style_position mListStylePosition); + + string get_list_style_image() const; + void set_list_style_image(const string& url); + + string get_list_style_image_baseurl() const; + void set_list_style_image_baseurl(const string& url); + + const background &get_bg() const; + void set_bg(const background &mBg); + + int get_font_size() const; + void set_font_size(int mFontSize); + + uint_ptr get_font() const; + void set_font(uint_ptr mFont); + + const font_metrics& get_font_metrics() const; + void set_font_metrics(const font_metrics& mFontMetrics); + + text_transform get_text_transform() const; + void set_text_transform(text_transform mTextTransform); + + web_color get_color() const; + void set_color(web_color color); + + string get_cursor() const; + void set_cursor(const string& cursor); + + string get_content() const; + void set_content(const string& content); + + border_collapse get_border_collapse() const; + void set_border_collapse(border_collapse mBorderCollapse); + + const css_length& get_border_spacing_x() const ; + void set_border_spacing_x(const css_length& mBorderSpacingX); + + const css_length& get_border_spacing_y() const; + void set_border_spacing_y(const css_length& mBorderSpacingY); + + 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<css_attribute_selector> vector; + + attr_select_type type; + string_id name; // .name, #name, [name], :name + string val; // [name=val], :lang(val) + + std::shared_ptr<css_element_selector> sel; // :not(sel) + int a, b; // :nth-child(an+b) + + css_attribute_selector() + { + 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<css_selector> ptr; + typedef std::vector<css_selector::ptr> 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<css_selector>(*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<used_selector> ptr; + typedef std::vector<used_selector::ptr> 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<css_text> 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<document> + { + public: + typedef std::shared_ptr<document> ptr; + typedef std::weak_ptr<document> weak_ptr; + private: + std::shared_ptr<element> m_root; + std::shared_ptr<render_item> m_root_render; + document_container* m_container; + fonts_map m_fonts; + css_text::vector m_css; + litehtml::css m_styles; + litehtml::web_color m_def_color; + litehtml::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<std::shared_ptr<render_item>> 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<render_item>& 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<render_item>& el_ptr, style_display disp, const char* disp_str); + void fix_table_parent(const std::shared_ptr<render_item> & el_ptr, style_display disp, const char* disp_str); + }; + + inline element::ptr document::root() + { + return m_root; + } + inline void document::add_tabular(const std::shared_ptr<render_item>& 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 <memory> +#include <functional> + +namespace litehtml +{ + struct list_marker + { + string image; + const char* baseurl; + list_style_type marker_type; + web_color color; + position pos; + int index; + uint_ptr font; + }; + + // call back interface to draw text, images and other elements + class document_container + { + public: + virtual litehtml::uint_ptr create_font(const char* faceName, int size, int weight, litehtml::font_style italic, unsigned int decoration, litehtml::font_metrics* fm) = 0; + virtual void delete_font(litehtml::uint_ptr hFont) = 0; + virtual int text_width(const char* text, litehtml::uint_ptr hFont) = 0; + virtual void draw_text(litehtml::uint_ptr hdc, const char* text, litehtml::uint_ptr hFont, litehtml::web_color color, const litehtml::position& pos) = 0; + virtual int pt_to_px(int pt) const = 0; + virtual int get_default_font_size() const = 0; + virtual const char* get_default_font_name() const = 0; + virtual void draw_list_marker(litehtml::uint_ptr hdc, const litehtml::list_marker& marker) = 0; + virtual void load_image(const char* src, const char* baseurl, bool redraw_on_ready) = 0; + virtual void get_image_size(const char* src, const char* baseurl, litehtml::size& sz) = 0; + // Note: regular <img> images are also drawn with draw_background + // bg is guaranteed to have at least one item. + // backgrounds in bg are in CSS order - the last one is the farthest from the user. + // only the last background has valid background-color. + virtual void draw_background(litehtml::uint_ptr hdc, const std::vector<litehtml::background_paint>& bg) = 0; + virtual void draw_borders(litehtml::uint_ptr hdc, const litehtml::borders& borders, const litehtml::position& draw_pos, bool root) = 0; + + virtual void set_caption(const char* caption) = 0; + virtual void set_base_url(const char* base_url) = 0; + virtual void link(const std::shared_ptr<litehtml::document>& doc, const litehtml::element::ptr& el) = 0; + virtual void on_anchor_click(const char* url, const litehtml::element::ptr& el) = 0; + virtual void set_cursor(const char* cursor) = 0; + virtual void transform_text(litehtml::string& text, litehtml::text_transform tt) = 0; + virtual void import_css(litehtml::string& text, const litehtml::string& url, litehtml::string& baseurl) = 0; + virtual void set_clip(const litehtml::position& pos, const litehtml::border_radiuses& bdr_radius) = 0; + virtual void del_clip() = 0; + virtual void get_client_rect(litehtml::position& client) const = 0; + virtual litehtml::element::ptr create_element( const char* tag_name, + const litehtml::string_map& attributes, + const std::shared_ptr<litehtml::document>& doc) = 0; + + virtual void get_media_features(litehtml::media_features& media) const = 0; + virtual void get_language(litehtml::string& language, litehtml::string& culture) const = 0; + virtual litehtml::string resolve_color(const litehtml::string& /*color*/) const { return litehtml::string(); } + virtual void split_text(const char* text, const std::function<void(const char*)>& on_word, const std::function<void(const char*)>& on_space); + + protected: + ~document_container() = default; + }; +} + +#endif // LH_DOCUMENT_CONTAINER_H diff --git a/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<litehtml::document>& 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<litehtml::document>& 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<document>& 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<document>& doc) : el_before_after_base(doc, true) + { + + } + }; + + class el_after : public el_before_after_base + { + public: + explicit el_after(const std::shared_ptr<document>& 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<litehtml::document>& 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<litehtml::document>& 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<document>& 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<document>& doc); + + bool is_comment() const override; + void get_text(string& text) override; + void set_data(const char* data) override; + std::shared_ptr<render_item> create_render_item(const std::shared_ptr<render_item>& /*parent_ri*/) override + { + // Comments are not rendered + return nullptr; + } + }; +} + +#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<litehtml::document>& 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<litehtml::document>& 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<render_item> &ri) override; + void get_content_size(size& sz, int max_width) override; + string dump_get_name() override; + + std::shared_ptr<render_item> create_render_item(const std::shared_ptr<render_item>& parent_ri) override; + + 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<litehtml::document>& 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<litehtml::document>& 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<document>& 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<document>& 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<document>& 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<litehtml::document>& 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<litehtml::document>& 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<render_item> &ri) override; + string dump_get_name() override; + std::vector<std::tuple<string, string>> 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<litehtml::document>& 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<litehtml::document>& 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 <memory> +#include <tuple> +#include <list> +#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<element> + { + friend class line_box; + friend class html_tag; + friend class el_table; + friend class document; + public: + typedef std::shared_ptr<element> ptr; + typedef std::shared_ptr<const element> const_ptr; + typedef std::weak_ptr<element> weak_ptr; + protected: + std::weak_ptr<element> m_parent; + std::weak_ptr<document> m_doc; + elements_list m_children; + css_properties m_css; + std::list<std::weak_ptr<render_item>> m_renders; + used_selector::vector m_used_styles; + + virtual void select_all(const css_selector& selector, elements_list& res); + element::ptr _add_before_after(int type, const style& style); + + private: + std::map<string_id, int> m_counter_values; + + public: + explicit element(const std::shared_ptr<document>& 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<document> get_document() const; + const std::list<std::shared_ptr<element>>& 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<render_item>& ri); + virtual void draw_background(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri); + virtual int get_enum_property (string_id name, bool inherited, int default_value, uint_ptr css_properties_member_offset) const; + virtual 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<std::tuple<string, string>> dump_get_attrs(); + void dump(litehtml::dumper& cout); + + std::tuple<element::ptr, element::ptr, element::ptr> split_inlines(); + virtual std::shared_ptr<render_item> create_render_item(const std::shared_ptr<render_item>& parent_ri); + bool requires_styles_update(); + void add_render(const std::shared_ptr<render_item>& ri); + bool find_styles_changes( position::vector& redraw_boxes); + element::ptr add_pseudo_before(const style& style) + { + return _add_before_after(0, style); + } + element::ptr add_pseudo_after(const style& style) + { + return _add_before_after(1, style); + } + + 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<element::ptr> get_siblings_before() const; + bool find_counter(const string_id& counter_name_id, std::map<string_id, int>::iterator& map_iterator); + void parse_counter_tokens(const string_vector& tokens, const int default_value, std::function<void(const string_id&, const int)> 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<document> 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<std::shared_ptr<element>>& 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 <functional> +#include "formatting_context.h" + +namespace litehtml +{ + class flex_line; + + /** + * Base class for flex item + */ + class flex_item + { + public: + std::shared_ptr<render_item> el; + int base_size; + int min_size; + def_value<int> max_size; + int main_size; + int grow; + int shrink; + int scaled_flex_shrink_factor; + bool frozen; + int order; + int src_order; + def_value<int> auto_margin_main_start; + def_value<int> auto_margin_main_end; + bool auto_margin_cross_start; + bool auto_margin_cross_end; + flex_align_items align; + + explicit flex_item(std::shared_ptr<render_item> &_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<render_item> &_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<render_item> &_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<std::shared_ptr<flex_item>> 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 <list> +#include "types.h" + +namespace litehtml +{ + class formatting_context + { + private: + std::list<floated_box> m_floats_left; + std::list<floated_box> m_floats_right; + int_int_cache m_cache_line_left; + int_int_cache m_cache_line_right; + int m_current_top; + int m_current_left; + + public: + formatting_context() : m_current_top(0), m_current_left(0) {} + + void push_position(int x, int y) + { + m_current_left += x; + m_current_top += y; + } + void pop_position(int x, int y) + { + m_current_left -= x; + m_current_top -= y; + } + + void add_float(const std::shared_ptr<render_item> &el, int min_width, int context); + void clear_floats(int context); + int find_next_line_top( int top, int width, int def_right ); + int get_floats_height(element_float el_float = float_none) const; + int get_left_floats_height() const; + int get_right_floats_height() const; + int get_line_left( int y ); + void get_line_left_right( int y, int def_right, int& ln_left, int& ln_right ) + { + ln_left = get_line_left(y); + ln_right = get_line_right(y, def_right); + } + int get_line_right( int y, int def_right ); + int get_cleared_top(const std::shared_ptr<render_item> &el, int line_top) const; + void update_floats(int dy, const std::shared_ptr<render_item> &parent); + void apply_relative_shift(const containing_block_context &containing_block_size); + int find_min_left(int y, int context_idx); + int find_min_right(int y, int right, int context_idx); + }; +} + +#endif //LITEHTML_FLOATS_HOLDER_H diff --git a/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 <stdlib.h> +#include <string> +#include <ctype.h> +#include <vector> +#include <map> +#include <cstring> +#include <algorithm> +#include <functional> +#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<html_tag> ptr; + protected: + string_id m_tag; + string_id m_id; + string_vector m_str_classes; + std::vector<string_id> m_classes; + litehtml::style m_style; + string_map m_attrs; + std::vector<string_id> m_pseudo_classes; + + void select_all(const css_selector& selector, elements_list& res) override; + + public: + explicit html_tag(const std::shared_ptr<document>& doc); + // constructor for anonymous wrapper boxes + explicit html_tag(const element::ptr& parent, const string& style = "display: block"); + + bool appendChild(const element::ptr &el) override; + bool removeChild(const element::ptr &el) override; + void clearRecursive() override; + string_id tag() const override; + string_id id() const override; + const char* get_tagName() const override; + void set_tagName(const char* tag) override; + void set_data(const char* data) override; + + void set_attr(const char* name, const char* val) override; + const char* get_attr(const char* name, const char* def = nullptr) const override; + void apply_stylesheet(const litehtml::css& stylesheet) override; + void refresh_styles() override; + + bool is_white_space() const override; + bool is_body() const override; + bool is_break() const override; + + bool on_mouse_over() override; + bool on_mouse_leave() override; + bool on_lbutton_down() override; + bool on_lbutton_up() override; + void on_click() override; + bool set_pseudo_class(string_id cls, bool add) override; + bool set_class(const char* pclass, bool add) override; + bool is_replaced() const override; + void compute_styles(bool recursive = true) override; + void draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri) override; + void draw_background(uint_ptr hdc, int x, int y, const position *clip, + const std::shared_ptr<render_item> &ri) override; + + template<class Type, property_type property_value_type, Type property_value::* property_value_member> + const Type& get_property_impl (string_id name, bool inherited, const Type& default_value, uint_ptr css_properties_member_offset) const; + int get_enum_property (string_id name, bool inherited, int default_value, uint_ptr css_properties_member_offset) const override; + 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<background_paint>& bg_paint, const background* bg, const std::shared_ptr<render_item>& ri); + void init_one_background_paint(int i, position pos, background_paint& bg_paint, const background* bg, const std::shared_ptr<render_item>& ri); + void draw_list_marker( uint_ptr hdc, const position &pos ); + string get_list_marker_text(int index); + element::ptr get_element_before(const style& style, bool create); + element::ptr get_element_after(const style& style, bool create); + + 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 <list> +#include <functional> + +namespace litehtml +{ + class render_item; + + class iterator_selector + { + public: + virtual bool select(const std::shared_ptr<render_item>& el) = 0; + + protected: + ~iterator_selector() = default; + }; + + enum iterator_item_type + { + iterator_item_type_child, + iterator_item_type_start_parent, + iterator_item_type_end_parent + }; + + class elements_iterator + { + private: + 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<render_item>& el); + + public: + elements_iterator(bool return_parents, iterator_selector* go_inside, iterator_selector* select); + ~elements_iterator() = default; + + void process(const std::shared_ptr<render_item>& container, const std::function<void (std::shared_ptr<render_item>&, iterator_item_type)>& func); + + private: + void next_idx(); + }; + + class go_inside_inline final : public iterator_selector + { + public: + bool select(const std::shared_ptr<render_item>& el) override; + }; + + class inline_selector final : public iterator_selector + { + public: + bool select(const std::shared_ptr<render_item>& el) override; + }; + + class go_inside_table final : public iterator_selector + { + public: + bool select(const std::shared_ptr<render_item>& el) override; + }; + + class table_rows_selector final : public iterator_selector + { + public: + bool select(const std::shared_ptr<render_item>& el) override; + }; + + class table_cells_selector final : public iterator_selector + { + public: + bool select(const std::shared_ptr<render_item>& 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 <vector> +#include <memory> +#include "os_types.h" +#include "types.h" + +namespace litehtml +{ + class render_item; + + struct line_context + { + int calculatedTop; + int top; + int left; + int right; + + int width() const + { + return right - left; + } + void fix_top() + { + calculatedTop = top; + } + 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<render_item> m_element; + int m_rendered_min_width; + public: + explicit line_box_item(const std::shared_ptr<render_item>& element) : m_element(element), m_rendered_min_width(0) {} + line_box_item() : 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<render_item>& get_el() const { return m_element; } + virtual position& pos(); + virtual void place_to(int x, int y); + virtual int width() const; + virtual int top() const; + virtual int bottom() const; + virtual int right() const; + virtual int left() const; + virtual element_type get_type() const { return type_text_part; } + virtual int get_rendered_min_width() const { return m_rendered_min_width; } + virtual void set_rendered_min_width(int min_width) { m_rendered_min_width = min_width; } + }; + + class lbi_start : public line_box_item + { + protected: + position m_pos; + public: + explicit lbi_start(const std::shared_ptr<render_item>& element); + + void place_to(int x, int y) override; + int width() const override; + position& pos() override { return m_pos; } + int top() const override; + int bottom() const override; + int right() const override; + int left() const override; + element_type get_type() const override { return type_inline_start; } + int get_rendered_min_width() const override { return width(); } + }; + + class lbi_end : public lbi_start + { + public: + explicit lbi_end(const std::shared_ptr<render_item>& element); + + void place_to(int x, int y) override; + int right() const override; + int left() const override; + element_type get_type() const override { return type_inline_end; } + }; + + class lbi_continue : public lbi_start + { + public: + explicit lbi_continue(const std::shared_ptr<render_item>& element); + + void place_to(int x, int y) override; + int right() const override; + int left() const override; + int width() const override; + element_type get_type() const override { return type_inline_continue; } + }; + + class line_box + { + struct va_context + { + int baseline; + font_metrics fm; + + va_context() : baseline(0) {} + }; + + int m_top; + int m_left; + int m_right; + int m_height; + int m_width; + int m_line_height; + int m_default_line_height; + font_metrics m_font_metrics; + int m_baseline; + text_align m_text_align; + int m_min_width; + std::list< std::unique_ptr<line_box_item> > m_items; + public: + line_box(int top, int left, int right, int line_height, const font_metrics& fm, text_align align) : + m_top(top), + m_left(left), + m_right(right), + m_height(0), + m_width(0), + m_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<line_box_item> item); + bool can_hold(const std::unique_ptr<line_box_item>& item, white_space ws) const; + bool is_empty() const; + int baseline() const; + int top_margin() const; + int bottom_margin() const; + void y_shift(int shift); + std::list< std::unique_ptr<line_box_item> > finish(bool last_box, const containing_block_context &containing_block_size); + std::list< std::unique_ptr<line_box_item> > new_width(int left, int right); + std::shared_ptr<render_item> get_last_text_part() const; + std::shared_ptr<render_item> get_first_text_part() const; + std::list< std::unique_ptr<line_box_item> >& items() { return m_items; } + private: + bool have_last_space() const; + bool is_break_only() const; + static int calc_va_baseline(const va_context& current, vertical_align va, const font_metrics& new_font, int top, int bottom); + }; +} + +#endif //LH_LINE_BOX_H diff --git a/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<media_query_expression> 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<media_query> ptr; + typedef std::vector<media_query::ptr> 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<document>& doc); + bool check(const media_features& features) const; + }; + + class media_query_list + { + public: + typedef std::shared_ptr<media_query_list> ptr; + typedef std::vector<media_query_list::ptr> 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<document>& 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 <string> +#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 <string> +#include <cstdint> + +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<render_item> &el, int top, const containing_block_context &self_size, formatting_context* fmt_ctx); + virtual void fix_line_width(element_float /*flt*/, + const containing_block_context &/*containing_block_size*/, formatting_context* /*fmt_ctx*/) + {} + + public: + explicit render_item_block(std::shared_ptr<element> src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr<render_item> clone() override + { + return std::make_shared<render_item_block>(src_el()); + } + std::shared_ptr<render_item> init() override; + }; +} + +#endif //LITEHTML_RENDER_BLOCK_H diff --git a/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<element> src_el) : render_item_block(std::move(src_el)) + {} + + std::shared_ptr<render_item> clone() override + { + return std::make_shared<render_item_block_context>(src_el()); + } + 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<flex_line> m_lines; + + std::list<flex_line> 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<element> src_el) : render_item_block(std::move(src_el)) + {} + + std::shared_ptr<render_item> clone() override + { + return std::make_shared<render_item_flex>(src_el()); + } + std::shared_ptr<render_item> 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<element> src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr<render_item> clone() override + { + return std::make_shared<render_item_image>(src_el()); + } + }; +} + +#endif //LITEHTML_RENDER_IMAGE_H diff --git a/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<element> src_el) : render_item(std::move(src_el)) + {} + + void get_inline_boxes( position::vector& boxes ) const override { boxes = m_boxes; } + void set_inline_boxes( position::vector& boxes ) override { m_boxes = boxes; } + void add_inline_box( const position& box ) override { m_boxes.emplace_back(box); }; + void clear_inline_boxes() override { m_boxes.clear(); } + int get_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<render_item> clone() override + { + return std::make_shared<render_item_inline>(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<render_item> element; + position::vector boxes; + position start_box; + + explicit inlines_item(const std::shared_ptr<render_item>& el) : element(el) {} + }; + protected: + std::vector<std::unique_ptr<litehtml::line_box> > m_line_boxes; + int m_max_line_width; + + int _render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx) override; + void fix_line_width(element_float flt, + const containing_block_context &self_size, formatting_context* fmt_ctx) override; + + std::list<std::unique_ptr<line_box_item> > finish_last_box(bool end_of_render, const containing_block_context &self_size); + void place_inline(std::unique_ptr<line_box_item> item, const containing_block_context &self_size, formatting_context* fmt_ctx); + int new_box(const std::unique_ptr<line_box_item>& el, line_context& line_ctx, const containing_block_context &self_size, formatting_context* fmt_ctx); + void apply_vertical_align() override; + public: + explicit render_item_inline_context(std::shared_ptr<element> src_el) : render_item_block(std::move(src_el)), m_max_line_width(0) + {} + + std::shared_ptr<render_item> clone() override + { + return std::make_shared<render_item_inline_context>(src_el()); + } + + int get_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 <memory> +#include <utility> +#include <list> +#include <tuple> +#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<render_item> + { + protected: + std::shared_ptr<element> m_element; + std::weak_ptr<render_item> m_parent; + std::list<std::shared_ptr<render_item>> m_children; + margins m_margins; + margins m_padding; + margins m_borders; + position m_pos; + bool m_skip; + std::vector<std::shared_ptr<render_item>> m_positioned; + + containing_block_context calculate_containing_block_context(const containing_block_context& cb_context); + void calc_cb_length(const css_length& len, int percent_base, containing_block_context::typed_int& out_value) const; + virtual int _render(int /*x*/, int /*y*/, const containing_block_context& /*containing_block_size*/, formatting_context* /*fmt_ctx*/, bool /*second_pass = false*/) + { + return 0; + } + + public: + explicit render_item(std::shared_ptr<element> src_el); + + virtual ~render_item() = default; + + std::list<std::shared_ptr<render_item>>& children() + { + return m_children; + } + + position& pos() + { + return m_pos; + } + + bool skip() const + { + return m_skip; + } + + void skip(bool val) + { + m_skip = val; + } + + int right() const + { + return left() + width(); + } + + int left() const + { + return m_pos.left() - m_margins.left - m_padding.left - m_borders.left; + } + + int top() const + { + return m_pos.top() - m_margins.top - m_padding.top - m_borders.top; + } + + int bottom() const + { + return top() + height(); + } + + int height() const + { + return m_pos.height + m_margins.height() + m_padding.height() + m_borders.height(); + } + + int width() const + { + return m_pos.width + m_margins.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<render_item> parent() const + { + return m_parent.lock(); + } + + margins& get_margins() + { + return m_margins; + } + + margins& get_paddings() + { + return m_padding; + } + + void set_paddings(const margins& val) + { + m_padding = val; + } + + margins& get_borders() + { + return m_borders; + } + + /** + * Top offset to the element content. Includes paddings, margins and borders. + */ + int content_offset_top() const + { + return m_margins.top + m_padding.top + m_borders.top; + } + + /** + * Bottom offset to the element content. Includes paddings, margins and borders. + */ + inline int content_offset_bottom() const + { + return m_margins.bottom + m_padding.bottom + m_borders.bottom; + } + + /** + * Left offset to the element content. Includes paddings, margins and borders. + */ + int content_offset_left() const + { + return m_margins.left + m_padding.left + m_borders.left; + } + + /** + * Right offset to the element content. Includes paddings, margins and borders. + */ + int content_offset_right() const + { + return m_margins.right + m_padding.right + m_borders.right; + } + + /** + * Sum of left and right offsets to the element content. Includes paddings, margins and borders. + */ + int content_offset_width() const + { + return content_offset_left() + content_offset_right(); + } + + /** + * Sum of top and bottom offsets to the element content. Includes paddings, margins and borders. + */ + int content_offset_height() const + { + return content_offset_top() + content_offset_bottom(); + } + + int box_sizing_left() const + { + 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<render_item>& par) + { + m_parent = par; + } + + const std::shared_ptr<element>& src_el() const + { + return m_element; + } + + const css_properties& css() const + { + return m_element->css(); + } + + void add_child(const std::shared_ptr<render_item>& ri) + { + m_children.push_back(ri); + ri->parent(shared_from_this()); + } + + 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<render_item> 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<render_item> clone() + { + return std::make_shared<render_item>(src_el()); + } + std::tuple< + std::shared_ptr<litehtml::render_item>, + std::shared_ptr<litehtml::render_item>, + std::shared_ptr<litehtml::render_item> + > split_inlines(); + bool fetch_positioned(); + void render_positioned(render_type rt = render_all); + void add_positioned(const std::shared_ptr<litehtml::render_item> &el); + void get_redraw_box(litehtml::position& pos, int x = 0, int y = 0); + void calc_document_size( litehtml::size& sz, litehtml::size& content_size, int x = 0, int y = 0 ); + virtual void get_inline_boxes( position::vector& /*boxes*/ ) const {}; + virtual void set_inline_boxes( position::vector& /*boxes*/ ) {}; + virtual void add_inline_box( const position& /*box*/ ) {}; + virtual void clear_inline_boxes() {}; + void draw_stacking_context( uint_ptr hdc, int x, int y, const position* clip, bool with_positioned ); + virtual void draw_children( uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex ); + virtual int get_draw_vertical_offset() { return 0; } + virtual std::shared_ptr<element> get_child_by_point(int x, int y, int client_x, int client_y, draw_flag flag, int zindex); + std::shared_ptr<element> get_element_by_point(int x, int y, int client_x, int client_y); + bool is_point_inside( int x, int y ); + void dump(litehtml::dumper& cout); + position get_placement() const; + /** + * Returns the boxes of rendering element. All coordinates are absolute + * + * @param redraw_boxes [out] resulting rendering boxes + * @return + */ + void get_rendering_boxes( position::vector& redraw_boxes); + }; +} + +#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<table_grid> m_grid; + int m_border_spacing_x; + int m_border_spacing_y; + + int _render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass) override; + + public: + explicit render_item_table(std::shared_ptr<element> src_el); + + std::shared_ptr<render_item> clone() override + { + return std::make_shared<render_item_table>(src_el()); + } + void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override; + int get_draw_vertical_offset() override; + std::shared_ptr<render_item> init() override; + }; + + class render_item_table_part : public render_item + { + public: + explicit render_item_table_part(std::shared_ptr<element> src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr<render_item> clone() override + { + return std::make_shared<render_item_table_part>(src_el()); + } + }; + + class render_item_table_row : public render_item + { + public: + explicit render_item_table_row(std::shared_ptr<element> src_el) : render_item(std::move(src_el)) + {} + + std::shared_ptr<render_item> clone() override + { + return std::make_shared<render_item_table_row>(src_el()); + } + void get_inline_boxes( position::vector& boxes ) const override; + }; +} + +#endif //LITEHTML_RENDER_TABLE_H diff --git a/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<string_id, property_value> props_map; + + class style + { + public: + typedef std::shared_ptr<style> ptr; + typedef std::vector<style::ptr> vector; + private: + props_map m_properties; + static std::map<string_id, string> m_valid_values; + public: + void add(const string& txt, const string& baseurl = "", document_container* container = nullptr) + { + parse(txt, baseurl, container); + } + + void add_property(string_id name, const string& val, const string& baseurl = "", bool important = false, document_container* container = nullptr); + + const property_value& get_property(string_id name) const; + + void combine(const style& src); + void clear() + { + m_properties.clear(); + } + + void subst_vars(const element* el); + + private: + void parse_property(const string& txt, const string& baseurl, document_container* container); + void parse(const string& txt, const string& baseurl, document_container* container); + void parse_background(const string& val, const string& baseurl, bool important, document_container* container); + bool parse_one_background(const string& val, document_container* container, background& bg); + void parse_background_image(const string& val, const string& baseurl, bool important); + // parse comma-separated list of keywords + void parse_keyword_comma_list(string_id name, const string& val, bool important); + void parse_background_position(const string& val, bool important); + bool parse_one_background_position(const string& val, css_length& x, css_length& y); + void parse_background_size(const string& val, bool important); + bool parse_one_background_size(const string& val, css_size& size); + void parse_font(const string& val, bool important); + void parse_flex(const string& val, bool important); + void parse_align_self(string_id name, const string& val, bool important); + static css_length parse_border_width(const string& str); + static void parse_two_lengths(const string& str, css_length len[2]); + static int parse_four_lengths(const string& str, css_length len[4]); + static void subst_vars_(string& str, const element* el); + + void add_parsed_property(string_id name, const property_value& propval); + void remove_property(string_id name, bool important); + }; +} + +#endif // LH_STYLE_H diff --git a/libs/litehtml/include/litehtml/stylesheet.h b/libs/litehtml/include/litehtml/stylesheet.h new file mode 100644 index 0000000000..923853d768 --- /dev/null +++ b/libs/litehtml/include/litehtml/stylesheet.h @@ -0,0 +1,47 @@ +#ifndef LH_STYLESHEET_H +#define LH_STYLESHEET_H + +#include "style.h" +#include "css_selector.h" + +namespace litehtml +{ + class document_container; + + class css + { + css_selector::vector m_selectors; + public: + css() = default; + ~css() = default; + + const css_selector::vector& selectors() const + { + return m_selectors; + } + + void clear() + { + m_selectors.clear(); + } + + void parse_stylesheet(const char* str, const char* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media); + void sort_selectors(); + static void parse_css_url(const string& str, string& url); + + private: + void parse_atrule(const string& text, const char* baseurl, const std::shared_ptr<document>& doc, const media_query_list::ptr& media); + void add_selector(const css_selector::ptr& selector); + bool parse_selectors(const string& txt, const style::ptr& styles, const media_query_list::ptr& media); + + }; + + inline void litehtml::css::add_selector( const css_selector::ptr& selector ) + { + selector->m_order = (int) m_selectors.size(); + m_selectors.push_back(selector); + } + +} + +#endif // LH_STYLESHEET_H diff --git a/libs/litehtml/include/litehtml/table.h b/libs/litehtml/include/litehtml/table.h new file mode 100644 index 0000000000..d738b63ebf --- /dev/null +++ b/libs/litehtml/include/litehtml/table.h @@ -0,0 +1,248 @@ +#ifndef LH_TABLE_H +#define LH_TABLE_H + +#include <vector> +#include <memory> +#include "css_length.h" + +namespace litehtml +{ + class render_item; + + struct table_row + { + typedef std::vector<table_row> vector; + + int height; + int border_top; + int border_bottom; + std::shared_ptr<render_item> el_row; + int top; + int bottom; + css_length css_height; + int min_height; + + table_row() + { + min_height = 0; + top = 0; + bottom = 0; + border_bottom = 0; + border_top = 0; + height = 0; + el_row = nullptr; + css_height.predef(0); + } + + table_row(int h, const std::shared_ptr<render_item>& row); + + table_row(const table_row& val) + { + min_height = val.min_height; + top = val.top; + bottom = val.bottom; + border_bottom = val.border_bottom; + border_top = val.border_top; + height = val.height; + css_height = val.css_height; + el_row = val.el_row; + } + + table_row(table_row&& val) noexcept + { + min_height = val.min_height; + top = val.top; + bottom = val.bottom; + border_bottom = val.border_bottom; + border_top = val.border_top; + height = val.height; + css_height = val.css_height; + el_row = std::move(val.el_row); + } + }; + + struct table_column + { + typedef std::vector<table_column> vector; + + int min_width; + int max_width; + int width; + css_length css_width; + int border_left; + int border_right; + int left; + int right; + + table_column() + { + left = 0; + right = 0; + border_left = 0; + border_right = 0; + min_width = 0; + max_width = 0; + width = 0; + css_width.predef(0); + } + + table_column(int min_w, int max_w) + { + left = 0; + right = 0; + border_left = 0; + border_right = 0; + max_width = max_w; + min_width = min_w; + width = 0; + css_width.predef(0); + } + + table_column(const table_column& val) + { + left = val.left; + right = val.right; + border_left = val.border_left; + border_right = val.border_right; + max_width = val.max_width; + min_width = val.min_width; + width = val.width; + css_width = val.css_width; + } + }; + + class table_column_accessor + { + public: + virtual int& get(table_column& col) = 0; + + protected: + ~table_column_accessor() = default; + }; + + class table_column_accessor_max_width final : public table_column_accessor + { + public: + int& get(table_column& col) override; + }; + + class table_column_accessor_min_width final : public table_column_accessor + { + public: + int& get(table_column& col) override; + }; + + class table_column_accessor_width final : public table_column_accessor + { + public: + int& get(table_column& col) override; + }; + + struct table_cell + { + std::shared_ptr<render_item> el; + int colspan; + int rowspan; + int min_width; + int min_height; + int max_width; + int max_height; + int width; + int height; + margins borders; + + table_cell() + { + min_width = 0; + min_height = 0; + max_width = 0; + max_height = 0; + width = 0; + height = 0; + colspan = 1; + rowspan = 1; + el = nullptr; + } + + table_cell(const table_cell& val) + { + el = val.el; + colspan = val.colspan; + rowspan = val.rowspan; + width = val.width; + height = val.height; + min_width = val.min_width; + min_height = val.min_height; + max_width = val.max_width; + max_height = val.max_height; + borders = val.borders; + } + + table_cell(table_cell&& val) noexcept + { + el = std::move(val.el); + colspan = val.colspan; + rowspan = val.rowspan; + width = val.width; + height = val.height; + min_width = val.min_width; + min_height = val.min_height; + max_width = val.max_width; + max_height = val.max_height; + borders = val.borders; + } + }; + + class table_grid + { + public: + typedef std::vector< std::vector<table_cell> > rows; + private: + int m_rows_count; + int m_cols_count; + rows m_cells; + table_column::vector m_columns; + table_row::vector m_rows; + std::vector<std::shared_ptr<render_item>> m_captions; + int m_top_captions_height; + int m_bottom_captions_height; + public: + + table_grid() : + m_rows_count(0), + m_cols_count(0), + m_top_captions_height(0), + m_bottom_captions_height(0) + { + } + + void clear(); + void begin_row(const std::shared_ptr<render_item>& row); + void add_cell(const std::shared_ptr<render_item>& el); + bool is_rowspanned(int r, int c); + void finish(); + table_cell* cell(int t_col, int t_row); + table_column& column(int c) { return m_columns[c]; } + table_row& row(int r) { return m_rows[r]; } + std::vector<std::shared_ptr<render_item>>& captions() { return m_captions; } + + int rows_count() const { return m_rows_count; } + int cols_count() const { return m_cols_count; } + + void top_captions_height(int height) { m_top_captions_height = height; } + int top_captions_height() const { return m_top_captions_height; } + void bottom_captions_height(int height) { m_bottom_captions_height = height; } + int bottom_captions_height() const { return m_bottom_captions_height; } + + void distribute_max_width(int width, int start, int end); + void distribute_min_width(int width, int start, int end); + void distribute_width(int width, int start, int end); + void distribute_width(int width, int start, int end, table_column_accessor* acc); + int calc_table_width(int block_width, bool is_auto, int& min_table_width, int& max_table_width); + void calc_horizontal_positions(const margins& table_borders, border_collapse bc, int bdr_space_x); + void calc_vertical_positions(const margins& table_borders, border_collapse bc, int bdr_space_y); + void calc_rows_height(int blockHeight, int borderSpacingY); + }; +} + +#endif // LH_TABLE_H diff --git a/libs/litehtml/include/litehtml/tstring_view.h b/libs/litehtml/include/litehtml/tstring_view.h new file mode 100644 index 0000000000..384c8d7df5 --- /dev/null +++ b/libs/litehtml/include/litehtml/tstring_view.h @@ -0,0 +1,136 @@ +// Copyright (C) 2020-2021 Primate Labs Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the names of the copyright holders nor the names of their +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LITEHTML_TSTRING_VIEW_H__ +#define LITEHTML_TSTRING_VIEW_H__ + +#include <cstddef> +#include <ostream> + +#include "os_types.h" + +namespace litehtml { + +// tstring_view is a string reference type that provides a view into a string +// that is owned elsewhere (e.g., by a std::string object). + +// tstring_view implements the same interface as std::base_string_view in the +// standard library. When litehtml moves to C++17 consider replacing the +// tstring_view implementation with the standard library implementations +// (e.g., via a using statement). + +class tstring_view { +public: + using value_type = char; + + using pointer = char*; + + using const_pointer = const char*; + + using reference = char&; + + using const_reference = const char&; + + using iterator = const_pointer; + + using const_iterator = const_pointer; + + using size_type = size_t; + + using difference_type = std::ptrdiff_t; + +public: + tstring_view() = default; + + tstring_view(const tstring_view& other) = default; + + tstring_view(const_pointer s, size_type size) + : data_(s) + , size_(size) + { + } + + constexpr const_iterator begin() const + { + return data_; + } + + constexpr const_iterator cbegin() const + { + return data_; + } + + constexpr const_iterator end() const + { + return data_ + size_; + } + + constexpr const_iterator cend() const + { + return data_ + size_; + } + + constexpr const_reference operator[](size_type offset) const + { + return *(data_ + offset); + } + + constexpr const_pointer data() const + { + return data_; + } + + size_type size() const + { + return size_; + } + + size_type length() const + { + return size_; + } + + bool empty() const + { + return (size_ == 0); + } + +private: + const_pointer data_ = nullptr; + + size_type size_ = 0; +}; + +std::basic_ostream<tstring_view::value_type>& operator<<( + std::basic_ostream<tstring_view::value_type>&, + tstring_view str); + +} // namespace litehtml + +#endif // LITEHTML_TSTRING_VIEW_H__ diff --git a/libs/litehtml/include/litehtml/types.h b/libs/litehtml/include/litehtml/types.h new file mode 100644 index 0000000000..bfcaa6c3ac --- /dev/null +++ b/libs/litehtml/include/litehtml/types.h @@ -0,0 +1,1000 @@ +#ifndef LH_TYPES_H +#define LH_TYPES_H + +#include <cstdlib> +#include <memory> +#include <map> +#include <vector> +#include <list> + +namespace litehtml +{ + class document; + class element; + + typedef std::map<string, string> string_map; + typedef std::list< std::shared_ptr<element> > elements_list; + typedef std::vector<int> int_vector; + typedef std::vector<string> string_vector; + + const unsigned int font_decoration_none = 0x00; + const unsigned int font_decoration_underline = 0x01; + const unsigned int font_decoration_linethrough = 0x02; + const unsigned int font_decoration_overline = 0x04; + + typedef unsigned char byte; + typedef unsigned int ucode_t; + + struct margins + { + int left; + int right; + int top; + int bottom; + + margins() + { + left = right = top = bottom = 0; + } + + int width() const { return left + right; } + int height() const { return top + bottom; } + }; + + struct size + { + int width; + int height; + + size(int w, int h) : width(w), height(h) + { + } + + size() : width(0), height(0) + { + } + }; + + struct position + { + typedef std::vector<position> vector; + + int x; + int y; + int width; + int height; + + position() + { + x = y = width = height = 0; + } + + position(int x, int y, int width, int height) + { + this->x = x; + this->y = y; + this->width = width; + this->height = height; + } + + int right() const { return x + width; } + int bottom() const { return y + height; } + int left() const { return x; } + int top() const { return y; } + + void operator+=(const margins& mg) + { + x -= mg.left; + y -= mg.top; + width += mg.left + mg.right; + height += mg.top + mg.bottom; + } + void operator-=(const margins& mg) + { + x += mg.left; + y += mg.top; + width -= mg.left + mg.right; + height -= mg.top + mg.bottom; + } + + void clear() + { + x = y = width = height = 0; + } + + void operator=(const size& sz) + { + width = sz.width; + height = sz.height; + } + + void move_to(int x, int y) + { + this->x = x; + this->y = y; + } + + bool does_intersect(const position* val) const + { + if(!val) return true; + + return ( + left() <= val->right() && + right() >= val->left() && + bottom() >= val->top() && + top() <= val->bottom() ) + || ( + val->left() <= right() && + val->right() >= left() && + val->bottom() >= top() && + val->top() <= bottom() ); + } + + bool empty() const + { + if(!width && !height) + { + return true; + } + return false; + } + + bool is_point_inside(int x, int y) const + { + if(x >= left() && x <= right() && y >= top() && y <= bottom()) + { + return true; + } + return false; + } + }; + + struct font_metrics + { + int height; + int ascent; + int descent; + int x_height; + bool draw_spaces; + + font_metrics() + { + height = 0; + ascent = 0; + descent = 0; + x_height = 0; + draw_spaces = true; + } + int base_line() const { return descent; } + }; + + struct font_item + { + uint_ptr font; + font_metrics metrics; + }; + + typedef std::map<string, font_item> fonts_map; + + enum draw_flag + { + draw_root, + draw_block, + draw_floats, + draw_inlines, + draw_positioned, + }; + + struct containing_block_context + { + enum cbc_value_type + { + cbc_value_type_absolute, // width/height of containing block is defined as absolute value + cbc_value_type_percentage, // width/height of containing block is defined as percentage + cbc_value_type_auto, // width/height of containing block is defined as auto + cbc_value_type_none, // min/max width/height of containing block is defined as none + }; + + enum cbc_size_mode + { + size_mode_normal = 0x00, + size_mode_exact_width = 0x01, + size_mode_exact_height = 0x02, + size_mode_content = 0x04, + }; + + struct typed_int + { + int value; + cbc_value_type type; + + typed_int(int val, cbc_value_type tp) + { + value = val; + type = tp; + } + + operator int() const + { + return value; + } + + typed_int& operator=(int val) + { + value = val; + return *this; + } + + typed_int& operator=(const typed_int& v) + { + value = v.value; + type = v.type; + return *this; + } + }; + + typed_int width; // width of the containing block + typed_int render_width; + typed_int min_width; + typed_int max_width; + + typed_int height; // height of the containing block + typed_int min_height; + typed_int max_height; + + int context_idx; + uint32_t size_mode; + + containing_block_context() : + width(0, cbc_value_type_auto), + render_width(0, cbc_value_type_auto), + min_width(0, cbc_value_type_none), + max_width(0, cbc_value_type_none), + height(0, cbc_value_type_auto), + min_height(0, cbc_value_type_none), + max_height(0, cbc_value_type_none), + context_idx(0), + size_mode(size_mode_normal) + {} + + containing_block_context new_width(int w, uint32_t _size_mode = size_mode_normal) const + { + containing_block_context ret = *this; + ret.render_width = w - (ret.width - ret.render_width); + ret.width = w; + ret.size_mode = _size_mode; + return ret; + } + + containing_block_context new_width_height(int w, int h, uint32_t _size_mode = size_mode_normal) const + { + containing_block_context ret = *this; + ret.render_width = w - (ret.width - ret.render_width); + ret.width = w; + ret.height = h; + ret.size_mode = _size_mode; + return ret; + } + }; + +#define style_display_strings "none;block;inline;inline-block;inline-table;list-item;table;table-caption;table-cell;table-column;table-column-group;table-footer-group;table-header-group;table-row;table-row-group;inline-text;flex;inline-flex" + + enum style_display + { + display_none, + display_block, + display_inline, + display_inline_block, + display_inline_table, + display_list_item, + display_table, + display_table_caption, + display_table_cell, + display_table_column, + display_table_column_group, + display_table_footer_group, + display_table_header_group, + display_table_row, + display_table_row_group, + display_inline_text, + display_flex, + display_inline_flex, + }; + +#define font_size_strings "xx-small;x-small;small;medium;large;x-large;xx-large;smaller;larger" + + enum font_size + { + font_size_xx_small, + font_size_x_small, + font_size_small, + font_size_medium, + font_size_large, + font_size_x_large, + font_size_xx_large, + font_size_smaller, + font_size_larger, + }; + +#define line_height_strings "normal" + + enum line_height + { + line_height_normal + }; + +#define font_style_strings "normal;italic" + + enum font_style + { + font_style_normal, + font_style_italic + }; + +#define font_variant_strings "normal;small-caps" + + enum font_variant + { + font_variant_normal, + font_variant_small_caps + }; + +#define font_weight_strings "normal;bold;bolder;lighter;100;200;300;400;500;600;700;800;900" + + enum font_weight + { + font_weight_normal, + font_weight_bold, + font_weight_bolder, + font_weight_lighter, + font_weight_100, + font_weight_200, + font_weight_300, + font_weight_400, + font_weight_500, + font_weight_600, + font_weight_700, + font_weight_800, + font_weight_900 + }; + +#define list_style_type_strings "none;circle;disc;square;armenian;cjk-ideographic;decimal;decimal-leading-zero;georgian;hebrew;hiragana;hiragana-iroha;katakana;katakana-iroha;lower-alpha;lower-greek;lower-latin;lower-roman;upper-alpha;upper-latin;upper-roman" + + enum list_style_type + { + list_style_type_none, + list_style_type_circle, + list_style_type_disc, + list_style_type_square, + list_style_type_armenian, + list_style_type_cjk_ideographic, + list_style_type_decimal, + list_style_type_decimal_leading_zero, + list_style_type_georgian, + list_style_type_hebrew, + list_style_type_hiragana, + list_style_type_hiragana_iroha, + list_style_type_katakana, + list_style_type_katakana_iroha, + list_style_type_lower_alpha, + list_style_type_lower_greek, + list_style_type_lower_latin, + list_style_type_lower_roman, + list_style_type_upper_alpha, + list_style_type_upper_latin, + list_style_type_upper_roman, + }; + +#define list_style_position_strings "inside;outside" + + enum list_style_position + { + list_style_position_inside, + list_style_position_outside + }; + +#define vertical_align_strings "baseline;sub;super;top;text-top;middle;bottom;text-bottom" + + enum vertical_align + { + va_baseline, + va_sub, + va_super, + va_top, + va_text_top, + va_middle, + va_bottom, + va_text_bottom + }; + +#define border_width_strings "thin;medium;thick" + + enum border_width + { + border_width_thin, + border_width_medium, + border_width_thick + }; + + const float border_width_thin_value = 1; + const float border_width_medium_value = 3; + const float border_width_thick_value = 5; + const float border_width_values[] = { border_width_thin_value, border_width_medium_value, border_width_thick_value }; + +#define border_style_strings "none;hidden;dotted;dashed;solid;double;groove;ridge;inset;outset" + + enum border_style + { + border_style_none, + border_style_hidden, + border_style_dotted, + border_style_dashed, + border_style_solid, + border_style_double, + border_style_groove, + border_style_ridge, + border_style_inset, + border_style_outset + }; + +#define element_float_strings "none;left;right" + + enum element_float + { + float_none, + float_left, + float_right + }; + +#define element_clear_strings "none;left;right;both" + + enum element_clear + { + clear_none, + clear_left, + clear_right, + clear_both + }; + +#define css_units_strings "none;%;in;cm;mm;em;ex;pt;pc;px;dpi;dpcm;vw;vh;vmin;vmax;rem" + + enum css_units : byte + { + css_units_none, + css_units_percentage, + css_units_in, + css_units_cm, + css_units_mm, + css_units_em, + css_units_ex, + css_units_pt, + css_units_pc, + css_units_px, + css_units_dpi, + css_units_dpcm, + css_units_vw, + css_units_vh, + css_units_vmin, + css_units_vmax, + css_units_rem, + }; + +#define background_attachment_strings "scroll;fixed" + + enum background_attachment + { + background_attachment_scroll, + background_attachment_fixed + }; + +#define background_repeat_strings "repeat;repeat-x;repeat-y;no-repeat" + + enum background_repeat + { + background_repeat_repeat, + background_repeat_repeat_x, + background_repeat_repeat_y, + background_repeat_no_repeat + }; + +#define background_box_strings "border-box;padding-box;content-box" + + enum background_box + { + background_box_border, + background_box_padding, + background_box_content + }; + +#define background_position_strings "top;bottom;left;right;center" + + enum background_position + { + background_position_top, + background_position_bottom, + background_position_left, + background_position_right, + background_position_center, + }; + +#define element_position_strings "static;relative;absolute;fixed" + + enum element_position + { + element_position_static, + element_position_relative, + element_position_absolute, + element_position_fixed, + }; + +#define text_align_strings "left;right;center;justify" + + enum text_align + { + text_align_left, + text_align_right, + text_align_center, + text_align_justify + }; + +#define text_transform_strings "none;capitalize;uppercase;lowercase" + + enum text_transform + { + text_transform_none, + text_transform_capitalize, + text_transform_uppercase, + text_transform_lowercase + }; + +#define white_space_strings "normal;nowrap;pre;pre-line;pre-wrap" + + enum white_space + { + white_space_normal, + white_space_nowrap, + white_space_pre, + white_space_pre_line, + white_space_pre_wrap + }; + +#define overflow_strings "visible;hidden;scroll;auto;no-display;no-content" + + enum overflow + { + overflow_visible, + overflow_hidden, + overflow_scroll, + overflow_auto, + overflow_no_display, + overflow_no_content + }; + +#define background_size_strings "auto;cover;contain" + + enum background_size + { + background_size_auto, + background_size_cover, + background_size_contain, + }; + +#define visibility_strings "visible;hidden;collapse" + + enum visibility + { + visibility_visible, + visibility_hidden, + visibility_collapse, + }; + +#define border_collapse_strings "collapse;separate" + + enum border_collapse + { + border_collapse_collapse, + border_collapse_separate, + }; + +#define content_property_string "none;normal;open-quote;close-quote;no-open-quote;no-close-quote" + + enum content_property + { + content_property_none, + content_property_normal, + content_property_open_quote, + content_property_close_quote, + content_property_no_open_quote, + content_property_no_close_quote, + }; + + class render_item; + + struct floated_box + { + position pos; + element_float float_side; + element_clear clear_floats; + std::shared_ptr<render_item> el; + int context; + int min_width; + + floated_box() = default; + floated_box(const floated_box& val) + { + pos = val.pos; + float_side = val.float_side; + clear_floats = val.clear_floats; + el = val.el; + context = val.context; + min_width = val.min_width; + } + floated_box& operator=(const floated_box& val) + { + pos = val.pos; + float_side = val.float_side; + clear_floats = val.clear_floats; + el = val.el; + context = val.context; + min_width = val.min_width; + return *this; + } + floated_box(floated_box&& val) + { + pos = val.pos; + float_side = val.float_side; + clear_floats = val.clear_floats; + el = std::move(val.el); + context = val.context; + min_width = val.min_width; + } + void operator=(floated_box&& val) + { + pos = val.pos; + float_side = val.float_side; + clear_floats = val.clear_floats; + el = std::move(val.el); + context = val.context; + min_width = val.min_width; + } + }; + + struct int_int_cache + { + int hash; + int val; + bool is_valid; + bool is_default; + + int_int_cache() + { + hash = 0; + val = 0; + is_valid = false; + is_default = false; + } + void invalidate() + { + is_valid = false; + is_default = false; + } + void set_value(int vHash, int vVal) + { + hash = vHash; + val = vVal; + is_valid = true; + } + }; + + enum select_result + { + select_no_match = 0x00, + select_match = 0x01, + select_match_pseudo_class = 0x02, + select_match_with_before = 0x10, + select_match_with_after = 0x20, + }; + + template<class T> + class def_value + { + T m_val; + bool m_is_default; + public: + def_value(T def_val) + { + m_is_default = true; + m_val = def_val; + } + void reset(T def_val) + { + m_is_default = true; + m_val = def_val; + } + bool is_default() const + { + return m_is_default; + } + T operator=(T new_val) + { + m_val = new_val; + m_is_default = false; + return m_val; + } + operator T() const + { + return m_val; + } + }; + + class baseline + { + public: + enum _baseline_type + { + baseline_type_none, + baseline_type_top, + baseline_type_bottom, + }; + + public: + baseline() : m_value(0), m_type(baseline_type_none) {} + baseline(int _value, _baseline_type _type) : m_value(_value), m_type(_type) {} + + int value() const { return m_value; } + void value(int _value) { m_value = _value; } + _baseline_type type() const { return m_type; } + void type(_baseline_type _type) { m_type = _type; } + + operator int() const { return m_value; } + baseline& operator=(int _value) { m_value = _value; return *this; } + + void set(int _value, _baseline_type _type) { m_value = _value; m_type =_type; } + /** + * Get baseline offset from top of element with specified height + * @param height - element height + * @return baseline offset + */ + int get_offset_from_top(int height) const + { + if(m_type == baseline_type_top) return m_value; + return height - m_value; + } + /** + * Get baseline offset from bottom of element with specified height + * @param height - element height + * @return baseline offset + */ + int get_offset_from_bottom(int height) const + { + if(m_type == baseline_type_bottom) return m_value; + return height - m_value; + } + /** + * Calculate baseline by top and bottom positions of element aligned by baseline == 0 + * @param top - top of the aligned element + * @param bottom - bottom of the aligned element + */ + void calc(int top, int bottom) + { + if(m_type == baseline_type_top) + m_value = -top; + else if(m_type == baseline_type_bottom) + m_value = bottom; + } + private: + int m_value; + _baseline_type m_type; + }; + + +#define media_orientation_strings "portrait;landscape" + + enum media_orientation + { + media_orientation_portrait, + media_orientation_landscape, + }; + +#define media_feature_strings "none;width;min-width;max-width;height;min-height;max-height;device-width;min-device-width;max-device-width;device-height;min-device-height;max-device-height;orientation;aspect-ratio;min-aspect-ratio;max-aspect-ratio;device-aspect-ratio;min-device-aspect-ratio;max-device-aspect-ratio;color;min-color;max-color;color-index;min-color-index;max-color-index;monochrome;min-monochrome;max-monochrome;resolution;min-resolution;max-resolution" + + enum media_feature + { + media_feature_none, + + media_feature_width, + media_feature_min_width, + media_feature_max_width, + + media_feature_height, + media_feature_min_height, + media_feature_max_height, + + media_feature_device_width, + media_feature_min_device_width, + media_feature_max_device_width, + + media_feature_device_height, + media_feature_min_device_height, + media_feature_max_device_height, + + media_feature_orientation, + + media_feature_aspect_ratio, + media_feature_min_aspect_ratio, + media_feature_max_aspect_ratio, + + media_feature_device_aspect_ratio, + media_feature_min_device_aspect_ratio, + media_feature_max_device_aspect_ratio, + + media_feature_color, + media_feature_min_color, + media_feature_max_color, + + media_feature_color_index, + media_feature_min_color_index, + media_feature_max_color_index, + + media_feature_monochrome, + media_feature_min_monochrome, + media_feature_max_monochrome, + + media_feature_resolution, + media_feature_min_resolution, + media_feature_max_resolution, + }; + +#define box_sizing_strings "content-box;border-box" + + enum box_sizing + { + box_sizing_content_box, + box_sizing_border_box, + }; + + +#define media_type_strings "none;all;screen;print;braille;embossed;handheld;projection;speech;tty;tv" + + enum media_type + { + media_type_none, + media_type_all, + media_type_screen, + media_type_print, + media_type_braille, + media_type_embossed, + media_type_handheld, + media_type_projection, + media_type_speech, + media_type_tty, + media_type_tv, + }; + + struct media_features + { + media_type type; + int width; // (pixels) For continuous media, this is the width of the viewport including the size of a rendered scroll bar (if any). For paged media, this is the width of the page box. + int height; // (pixels) The height of the targeted display area of the output device. For continuous media, this is the height of the viewport including the size of a rendered scroll bar (if any). For paged media, this is the height of the page box. + int device_width; // (pixels) The width of the rendering surface of the output device. For continuous media, this is the width of the screen. For paged media, this is the width of the page sheet size. + int device_height; // (pixels) The height of the rendering surface of the output device. For continuous media, this is the height of the screen. For paged media, this is the height of the page sheet size. + int color; // The number of bits per color component of the output device. If the device is not a color device, the value is zero. + int color_index; // The number of entries in the color lookup table of the output device. If the device does not use a color lookup table, the value is zero. + int monochrome; // The number of bits per pixel in a monochrome frame buffer. If the device is not a monochrome device, the output device value will be 0. + int resolution; // The resolution of the output device (in DPI) + + media_features() + { + type = media_type::media_type_none, + width =0; + height = 0; + device_width = 0; + device_height = 0; + color = 0; + color_index = 0; + monochrome = 0; + resolution = 0; + } + }; + + enum render_type + { + render_all, + render_no_fixed, + render_fixed_only, + }; + + // List of the Void Elements (can't have any contents) + const char* const void_elements = "area;base;br;col;command;embed;hr;img;input;keygen;link;meta;param;source;track;wbr"; + +#define flex_direction_strings "row;row-reverse;column;column-reverse" + + enum flex_direction + { + flex_direction_row, + flex_direction_row_reverse, + flex_direction_column, + flex_direction_column_reverse + }; + +#define flex_wrap_strings "nowrap;wrap;wrap-reverse" + + enum flex_wrap + { + flex_wrap_nowrap, + flex_wrap_wrap, + flex_wrap_wrap_reverse + }; + +#define flex_justify_content_strings "normal;flex-start;flex-end;center;space-between;space-around;start;end;left;right;space-evenly;stretch" + + enum flex_justify_content + { + flex_justify_content_normal, + flex_justify_content_flex_start, + flex_justify_content_flex_end, + flex_justify_content_center, + flex_justify_content_space_between, + flex_justify_content_space_around, + flex_justify_content_start, + flex_justify_content_end, + flex_justify_content_left, + flex_justify_content_right, + flex_justify_content_space_evenly, + flex_justify_content_stretch, + }; + +#define flex_align_items_strings "normal;flex-start;flex-end;center;start;end;baseline;stretch;auto" + + enum flex_align_items + { + flex_align_items_flex_normal, + flex_align_items_flex_start, + flex_align_items_flex_end, + flex_align_items_center, + flex_align_items_start, + flex_align_items_end, + flex_align_items_baseline, + flex_align_items_stretch, + flex_align_items_auto, // used for align-self property only + flex_align_items_first = 0x100, + flex_align_items_last = 0x200, + flex_align_items_unsafe = 0x400, + flex_align_items_safe = 0x800, + }; + +#define flex_align_content_strings "flex-start;start;flex-end;end;center;space-between;space-around;stretch" + + enum flex_align_content + { + flex_align_content_flex_start, + flex_align_content_start, + flex_align_content_flex_end, + flex_align_content_end, + flex_align_content_center, + flex_align_content_space_between, + flex_align_content_space_around, + flex_align_content_stretch + }; + +#define flex_basis_strings "auto;content;fit-content;min-content;max-content" + + enum flex_basis + { + flex_basis_auto, + flex_basis_content, + flex_basis_fit_content, + flex_basis_min_content, + flex_basis_max_content, + }; + +#define caption_side_strings "top;bottom" + + enum caption_side + { + caption_side_top, + caption_side_bottom + }; +} + +#endif // LH_TYPES_H diff --git a/libs/litehtml/include/litehtml/url.h b/libs/litehtml/include/litehtml/url.h new file mode 100644 index 0000000000..bd0cdc63c9 --- /dev/null +++ b/libs/litehtml/include/litehtml/url.h @@ -0,0 +1,139 @@ +// Copyright (C) 2020-2021 Primate Labs Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the names of the copyright holders nor the names of their +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LITEHTML_URL_H__ +#define LITEHTML_URL_H__ + +#include <ostream> + +#include "os_types.h" + +// https://datatracker.ietf.org/doc/html/rfc3986 + +namespace litehtml { + +class url { +public: + url() = default; + + explicit url(const string& str); + + url(const string& scheme, + const string& authority, + const string& path, + const string& query, + const string& fragment); + + const string& str() const + { + return str_; + } + + const string& scheme() const + { + return scheme_; + } + + bool has_scheme() const + { + return !scheme_.empty(); + } + + const string& authority() const + { + return authority_; + } + + bool has_authority() const + { + return !authority_.empty(); + } + + const string& path() const + { + return path_; + } + + bool has_path() const + { + return !path_.empty(); + } + + const string& query() const + { + return query_; + } + + bool has_query() const + { + return !query_.empty(); + } + + const string& fragment() const + { + return fragment_; + } + + bool has_fragment() const + { + return !fragment_.empty(); + } + +protected: + string str_; + + // Assume URLs are relative by default. See RFC 3986 Section 4.3 for + // information on which URLs are considered relative and which URLs are + // considered absolute: + // + // https://datatracker.ietf.org/doc/html/rfc3986#section-4.3 + + bool absolute_ = false; + + string scheme_; + + string authority_; + + string path_; + + string query_; + + string fragment_; +}; + +// Returns a URL that is resolved from the reference URL that might be +// relative to the base URL. For example, given <https://www.twitter.com/> as +// the base URL and </foo> as the relative URL, resolve() will return the URL +// <https://www.twitter.com/foo>. + +url resolve(const url& base, const url& reference); + +} // namespace litehtml + +#endif // LITEHTML_URL_H__ diff --git a/libs/litehtml/include/litehtml/url_path.h b/libs/litehtml/include/litehtml/url_path.h new file mode 100644 index 0000000000..6b102139d4 --- /dev/null +++ b/libs/litehtml/include/litehtml/url_path.h @@ -0,0 +1,51 @@ +// Copyright (C) 2020-2021 Primate Labs Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the names of the copyright holders nor the names of their +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LITEHTML_URL_PATH_H__ +#define LITEHTML_URL_PATH_H__ + +#include <ostream> + +#include "os_types.h" + +namespace litehtml { + +bool is_url_path_absolute(const string& path); + +string url_path_directory_name(const string& path); + +string url_path_base_name(const string& path); + +string url_path_append(const string& base, const string& path); + +string url_path_resolve(const string& base, const string& path); + +} // namespace litehtml + +#endif // LITEHTML_URL_PATH_H__ diff --git a/libs/litehtml/include/litehtml/utf8_strings.h b/libs/litehtml/include/litehtml/utf8_strings.h new file mode 100644 index 0000000000..72969fd3d7 --- /dev/null +++ b/libs/litehtml/include/litehtml/utf8_strings.h @@ -0,0 +1,52 @@ +#ifndef LH_UTF8_STRINGS_H +#define LH_UTF8_STRINGS_H + +#include "os_types.h" +#include "types.h" + +namespace litehtml +{ + class utf8_to_wchar + { + const byte* m_utf8; + std::wstring m_str; + public: + utf8_to_wchar(const char* val); + operator const wchar_t*() const + { + return m_str.c_str(); + } + private: + ucode_t getb() + { + if (!(*m_utf8)) return 0; + return *m_utf8++; + } + ucode_t get_next_utf8(ucode_t val) + { + return (val & 0x3f); + } + ucode_t get_char(); + }; + + class wchar_to_utf8 + { + std::string m_str; + public: + wchar_to_utf8(const std::wstring& val); + operator const char*() const + { + return m_str.c_str(); + } + + const char* c_str() const + { + return m_str.c_str(); + } + }; + +#define litehtml_from_wchar(str) litehtml::wchar_to_utf8(str) +#define litehtml_to_wchar(str) litehtml::utf8_to_wchar(str) +} + +#endif // LH_UTF8_STRINGS_H diff --git a/libs/litehtml/include/litehtml/web_color.h b/libs/litehtml/include/litehtml/web_color.h new file mode 100644 index 0000000000..a6006d391e --- /dev/null +++ b/libs/litehtml/include/litehtml/web_color.h @@ -0,0 +1,63 @@ +#ifndef LH_WEB_COLOR_H +#define LH_WEB_COLOR_H + +namespace litehtml +{ + struct def_color + { + const char* name; + const char* rgb; + }; + + extern def_color g_def_colors[]; + + class document_container; + + struct web_color + { + byte red; + byte green; + byte blue; + byte alpha; + + static const web_color transparent; + static const web_color black; + static const web_color white; + + web_color(byte r, byte g, byte b, byte a = 255) + { + red = r; + green = g; + blue = b; + alpha = a; + } + + web_color() + { + red = 0; + green = 0; + blue = 0; + alpha = 0xFF; + } + + bool operator==(web_color color) const { return red == color.red && green == color.green && blue == color.blue && alpha == color.alpha; } + bool operator!=(web_color color) const { return !(*this == color); } + + string to_string() const; + static web_color from_string(const string& str, document_container* callback); + static string resolve_name(const string& name, document_container* callback); + static bool is_color(const string& str, document_container* callback); + web_color darken(double fraction) const + { + int v_red = (int) red; + int v_blue = (int) blue; + int v_green = (int) green; + v_red = (int) std::max(v_red - (v_red * fraction), 0.0); + v_blue = (int) std::max(v_blue - (v_blue * fraction), 0.0); + v_green = (int) std::max(v_green - (v_green * fraction), 0.0); + return {(byte) v_red, (byte) v_green, (byte) v_blue, alpha}; + } + }; +} + +#endif // LH_WEB_COLOR_H |
