[Commits] [SCM] claws branch, master, updated. 4.2.0-71-g2ab815a91
jonathan at claws-mail.org
jonathan at claws-mail.org
Mon Mar 25 03:07:31 UTC 2024
The branch, master has been updated
via 2ab815a9115fbad6b25f07c7e3b67ba1f79c4257 (commit)
from 357c5342dd3e36a8a629929918dda7196e3f906d (commit)
Summary of changes:
src/plugins/litehtml_viewer/container_linux.cpp | 270 ++++++------
src/plugins/litehtml_viewer/litehtml/Makefile.am | 5 +-
src/plugins/litehtml_viewer/litehtml/borders.h | 30 ++
.../litehtml_viewer/litehtml/css_properties.cpp | 17 +-
.../litehtml_viewer/litehtml/css_properties.h | 25 +-
.../litehtml_viewer/litehtml/el_before_after.cpp | 13 +-
src/plugins/litehtml_viewer/litehtml/element.cpp | 127 ++++++
src/plugins/litehtml_viewer/litehtml/element.h | 15 +
src/plugins/litehtml_viewer/litehtml/flex_item.cpp | 488 +++++++++++++++++++++
src/plugins/litehtml_viewer/litehtml/flex_item.h | 137 ++++++
src/plugins/litehtml_viewer/litehtml/flex_line.cpp | 454 +++++++++++++++++++
src/plugins/litehtml_viewer/litehtml/flex_line.h | 56 +++
src/plugins/litehtml_viewer/litehtml/html.cpp | 17 +-
src/plugins/litehtml_viewer/litehtml/html.h | 6 +-
src/plugins/litehtml_viewer/litehtml/html_tag.cpp | 29 ++
src/plugins/litehtml_viewer/litehtml/html_tag.h | 5 +
src/plugins/litehtml_viewer/litehtml/line_box.cpp | 25 +-
.../litehtml_viewer/litehtml/media_query.cpp | 3 +-
.../litehtml_viewer/litehtml/render_block.cpp | 80 +++-
.../litehtml/render_block_context.cpp | 55 ++-
.../litehtml/render_block_context.h | 2 +
.../litehtml_viewer/litehtml/render_flex.cpp | 377 +++++++++++++++-
src/plugins/litehtml_viewer/litehtml/render_flex.h | 29 +-
.../litehtml_viewer/litehtml/render_image.cpp | 17 +-
.../litehtml_viewer/litehtml/render_inline.cpp | 3 -
.../litehtml_viewer/litehtml/render_inline.h | 10 +-
.../litehtml/render_inline_context.cpp | 41 +-
.../litehtml/render_inline_context.h | 3 +-
.../litehtml_viewer/litehtml/render_item.cpp | 150 ++++---
src/plugins/litehtml_viewer/litehtml/render_item.h | 53 ++-
.../litehtml_viewer/litehtml/render_table.cpp | 8 +-
src/plugins/litehtml_viewer/litehtml/string_id.h | 4 +
src/plugins/litehtml_viewer/litehtml/style.cpp | 118 +++--
src/plugins/litehtml_viewer/litehtml/style.h | 1 +
src/plugins/litehtml_viewer/litehtml/types.h | 135 ++++--
35 files changed, 2425 insertions(+), 383 deletions(-)
create mode 100644 src/plugins/litehtml_viewer/litehtml/flex_item.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/flex_item.h
create mode 100644 src/plugins/litehtml_viewer/litehtml/flex_line.cpp
create mode 100644 src/plugins/litehtml_viewer/litehtml/flex_line.h
delete mode 100644 src/plugins/litehtml_viewer/litehtml/render_inline.cpp
- Log -----------------------------------------------------------------
commit 2ab815a9115fbad6b25f07c7e3b67ba1f79c4257
Author: Jonathan Boeing <jonathan at claws-mail.org>
Date: Sun Mar 24 16:48:14 2024 -0700
Update to LiteHTML v0.9
diff --git a/src/plugins/litehtml_viewer/container_linux.cpp b/src/plugins/litehtml_viewer/container_linux.cpp
index 498f90152..19d226202 100644
--- a/src/plugins/litehtml_viewer/container_linux.cpp
+++ b/src/plugins/litehtml_viewer/container_linux.cpp
@@ -382,6 +382,8 @@ void container_linux::draw_background( litehtml::uint_ptr hdc, const std::vector
{
const auto& bg = bgvec[i];
+ if(bg.image_size.height == 0 || bg.image_size.width == 0) continue;
+
cairo_rectangle(cr, bg.clip_box.x, bg.clip_box.y, bg.clip_box.width, bg.clip_box.height);
cairo_clip(cr);
@@ -513,57 +515,54 @@ void container_linux::draw_borders(litehtml::uint_ptr hdc, const litehtml::borde
{
set_color(cr, borders.right.color);
- double r_top = borders.radius.top_right_x;
- double r_bottom = borders.radius.bottom_right_x;
-
- if(r_top)
+ if(borders.radius.top_right_x && borders.radius.top_right_y)
{
double end_angle = 2 * M_PI;
double start_angle = end_angle - M_PI / 2.0 / ((double) bdr_top / (double) bdr_right + 1);
add_path_arc(cr,
- draw_pos.right() - r_top,
- draw_pos.top() + r_top,
- r_top - bdr_right,
- r_top - bdr_right + (bdr_right - bdr_top),
- end_angle,
- start_angle, true);
+ draw_pos.right() - borders.radius.top_right_x,
+ draw_pos.top() + borders.radius.top_right_y,
+ borders.radius.top_right_x - bdr_right,
+ borders.radius.top_right_y - bdr_right + (bdr_right - bdr_top),
+ end_angle,
+ start_angle, true);
add_path_arc(cr,
- draw_pos.right() - r_top,
- draw_pos.top() + r_top,
- r_top,
- r_top,
- start_angle,
- end_angle, false);
+ draw_pos.right() - borders.radius.top_right_x,
+ draw_pos.top() + borders.radius.top_right_y,
+ borders.radius.top_right_x,
+ borders.radius.top_right_y,
+ start_angle,
+ end_angle, false);
} else
{
cairo_move_to(cr, draw_pos.right() - bdr_right, draw_pos.top() + bdr_top);
cairo_line_to(cr, draw_pos.right(), draw_pos.top());
}
- if(r_bottom)
+ if(borders.radius.bottom_right_x && borders.radius.bottom_right_y)
{
- cairo_line_to(cr, draw_pos.right(), draw_pos.bottom() - r_bottom);
+ cairo_line_to(cr, draw_pos.right(), draw_pos.bottom() - borders.radius.bottom_right_y);
double start_angle = 0;
double end_angle = start_angle + M_PI / 2.0 / ((double) bdr_bottom / (double) bdr_right + 1);
add_path_arc(cr,
- draw_pos.right() - r_bottom,
- draw_pos.bottom() - r_bottom,
- r_bottom,
- r_bottom,
- start_angle,
- end_angle, false);
+ draw_pos.right() - borders.radius.bottom_right_x,
+ draw_pos.bottom() - borders.radius.bottom_right_y,
+ borders.radius.bottom_right_x,
+ borders.radius.bottom_right_y,
+ start_angle,
+ end_angle, false);
add_path_arc(cr,
- draw_pos.right() - r_bottom,
- draw_pos.bottom() - r_bottom,
- r_bottom - bdr_right,
- r_bottom - bdr_right + (bdr_right - bdr_bottom),
- end_angle,
- start_angle, true);
+ draw_pos.right() - borders.radius.bottom_right_x,
+ draw_pos.bottom() - borders.radius.bottom_right_y,
+ borders.radius.bottom_right_x - bdr_right,
+ borders.radius.bottom_right_y - bdr_right + (bdr_right - bdr_bottom),
+ end_angle,
+ start_angle, true);
} else
{
cairo_line_to(cr, draw_pos.right(), draw_pos.bottom());
@@ -578,57 +577,54 @@ void container_linux::draw_borders(litehtml::uint_ptr hdc, const litehtml::borde
{
set_color(cr, borders.bottom.color);
- double r_left = borders.radius.bottom_left_x;
- double r_right = borders.radius.bottom_right_x;
-
- if(r_left)
+ if(borders.radius.bottom_left_x && borders.radius.bottom_left_y)
{
double start_angle = M_PI / 2.0;
double end_angle = start_angle + M_PI / 2.0 / ((double) bdr_left / (double) bdr_bottom + 1);
add_path_arc(cr,
- draw_pos.left() + r_left,
- draw_pos.bottom() - r_left,
- r_left - bdr_bottom + (bdr_bottom - bdr_left),
- r_left - bdr_bottom,
- start_angle,
- end_angle, false);
+ draw_pos.left() + borders.radius.bottom_left_x,
+ draw_pos.bottom() - borders.radius.bottom_left_y,
+ borders.radius.bottom_left_x - bdr_bottom + (bdr_bottom - bdr_left),
+ borders.radius.bottom_left_y - bdr_bottom,
+ start_angle,
+ end_angle, false);
add_path_arc(cr,
- draw_pos.left() + r_left,
- draw_pos.bottom() - r_left,
- r_left,
- r_left,
- end_angle,
- start_angle, true);
+ draw_pos.left() + borders.radius.bottom_left_x,
+ draw_pos.bottom() - borders.radius.bottom_left_y,
+ borders.radius.bottom_left_x,
+ borders.radius.bottom_left_y,
+ end_angle,
+ start_angle, true);
} else
{
cairo_move_to(cr, draw_pos.left(), draw_pos.bottom());
cairo_line_to(cr, draw_pos.left() + bdr_left, draw_pos.bottom() - bdr_bottom);
}
- if(r_right)
+ if(borders.radius.bottom_right_x && borders.radius.bottom_right_y)
{
- cairo_line_to(cr, draw_pos.right() - r_right, draw_pos.bottom());
+ cairo_line_to(cr, draw_pos.right() - borders.radius.bottom_right_x, draw_pos.bottom());
double end_angle = M_PI / 2.0;
double start_angle = end_angle - M_PI / 2.0 / ((double) bdr_right / (double) bdr_bottom + 1);
add_path_arc(cr,
- draw_pos.right() - r_right,
- draw_pos.bottom() - r_right,
- r_right,
- r_right,
- end_angle,
- start_angle, true);
+ draw_pos.right() - borders.radius.bottom_right_x,
+ draw_pos.bottom() - borders.radius.bottom_right_y,
+ borders.radius.bottom_right_x,
+ borders.radius.bottom_right_y,
+ end_angle,
+ start_angle, true);
add_path_arc(cr,
- draw_pos.right() - r_right,
- draw_pos.bottom() - r_right,
- r_right - bdr_bottom + (bdr_bottom - bdr_right),
- r_right - bdr_bottom,
- start_angle,
- end_angle, false);
+ draw_pos.right() - borders.radius.bottom_right_x,
+ draw_pos.bottom() - borders.radius.bottom_right_y,
+ borders.radius.bottom_right_x - bdr_bottom + (bdr_bottom - bdr_right),
+ borders.radius.bottom_right_y - bdr_bottom,
+ start_angle,
+ end_angle, false);
} else
{
cairo_line_to(cr, draw_pos.right() - bdr_right, draw_pos.bottom() - bdr_bottom);
@@ -643,57 +639,54 @@ void container_linux::draw_borders(litehtml::uint_ptr hdc, const litehtml::borde
{
set_color(cr, borders.top.color);
- double r_left = borders.radius.top_left_x;
- double r_right = borders.radius.top_right_x;
-
- if(r_left)
+ if(borders.radius.top_left_x && borders.radius.top_left_y)
{
double end_angle = M_PI * 3.0 / 2.0;
double start_angle = end_angle - M_PI / 2.0 / ((double) bdr_left / (double) bdr_top + 1);
add_path_arc(cr,
- draw_pos.left() + r_left,
- draw_pos.top() + r_left,
- r_left,
- r_left,
- end_angle,
- start_angle, true);
+ draw_pos.left() + borders.radius.top_left_x,
+ draw_pos.top() + borders.radius.top_left_y,
+ borders.radius.top_left_x,
+ borders.radius.top_left_y,
+ end_angle,
+ start_angle, true);
add_path_arc(cr,
- draw_pos.left() + r_left,
- draw_pos.top() + r_left,
- r_left - bdr_top + (bdr_top - bdr_left),
- r_left - bdr_top,
- start_angle,
- end_angle, false);
+ draw_pos.left() + borders.radius.top_left_x,
+ draw_pos.top() + borders.radius.top_left_y,
+ borders.radius.top_left_x - bdr_top + (bdr_top - bdr_left),
+ borders.radius.top_left_y - bdr_top,
+ start_angle,
+ end_angle, false);
} else
{
cairo_move_to(cr, draw_pos.left(), draw_pos.top());
cairo_line_to(cr, draw_pos.left() + bdr_left, draw_pos.top() + bdr_top);
}
- if(r_right)
+ if(borders.radius.top_right_x && borders.radius.top_right_y)
{
- cairo_line_to(cr, draw_pos.right() - r_right, draw_pos.top() + bdr_top);
+ cairo_line_to(cr, draw_pos.right() - borders.radius.top_right_x, draw_pos.top() + bdr_top);
double start_angle = M_PI * 3.0 / 2.0;
double end_angle = start_angle + M_PI / 2.0 / ((double) bdr_right / (double) bdr_top + 1);
add_path_arc(cr,
- draw_pos.right() - r_right,
- draw_pos.top() + r_right,
- r_right - bdr_top + (bdr_top - bdr_right),
- r_right - bdr_top,
- start_angle,
- end_angle, false);
+ draw_pos.right() - borders.radius.top_right_x,
+ draw_pos.top() + borders.radius.top_right_y,
+ borders.radius.top_right_x - bdr_top + (bdr_top - bdr_right),
+ borders.radius.top_right_y - bdr_top,
+ start_angle,
+ end_angle, false);
add_path_arc(cr,
- draw_pos.right() - r_right,
- draw_pos.top() + r_right,
- r_right,
- r_right,
- end_angle,
- start_angle, true);
+ draw_pos.right() - borders.radius.top_right_x,
+ draw_pos.top() + borders.radius.top_right_y,
+ borders.radius.top_right_x,
+ borders.radius.top_right_y,
+ end_angle,
+ start_angle, true);
} else
{
cairo_line_to(cr, draw_pos.right() - bdr_right, draw_pos.top() + bdr_top);
@@ -708,57 +701,54 @@ void container_linux::draw_borders(litehtml::uint_ptr hdc, const litehtml::borde
{
set_color(cr, borders.left.color);
- double r_top = borders.radius.top_left_x;
- double r_bottom = borders.radius.bottom_left_x;
-
- if(r_top)
+ if(borders.radius.top_left_x && borders.radius.top_left_y)
{
double start_angle = M_PI;
double end_angle = start_angle + M_PI / 2.0 / ((double) bdr_top / (double) bdr_left + 1);
add_path_arc(cr,
- draw_pos.left() + r_top,
- draw_pos.top() + r_top,
- r_top - bdr_left,
- r_top - bdr_left + (bdr_left - bdr_top),
- start_angle,
- end_angle, false);
+ draw_pos.left() + borders.radius.top_left_x,
+ draw_pos.top() + borders.radius.top_left_y,
+ borders.radius.top_left_x - bdr_left,
+ borders.radius.top_left_y - bdr_left + (bdr_left - bdr_top),
+ start_angle,
+ end_angle, false);
add_path_arc(cr,
- draw_pos.left() + r_top,
- draw_pos.top() + r_top,
- r_top,
- r_top,
- end_angle,
- start_angle, true);
+ draw_pos.left() + borders.radius.top_left_x,
+ draw_pos.top() + borders.radius.top_left_y,
+ borders.radius.top_left_x,
+ borders.radius.top_left_y,
+ end_angle,
+ start_angle, true);
} else
{
cairo_move_to(cr, draw_pos.left() + bdr_left, draw_pos.top() + bdr_top);
cairo_line_to(cr, draw_pos.left(), draw_pos.top());
}
- if(r_bottom)
+ if(borders.radius.bottom_left_x && borders.radius.bottom_left_y)
{
- cairo_line_to(cr, draw_pos.left(), draw_pos.bottom() - r_bottom);
+ cairo_line_to(cr, draw_pos.left(), draw_pos.bottom() - borders.radius.bottom_left_y);
double end_angle = M_PI;
double start_angle = end_angle - M_PI / 2.0 / ((double) bdr_bottom / (double) bdr_left + 1);
add_path_arc(cr,
- draw_pos.left() + r_bottom,
- draw_pos.bottom() - r_bottom,
- r_bottom,
- r_bottom,
- end_angle,
- start_angle, true);
+ draw_pos.left() + borders.radius.bottom_left_x,
+ draw_pos.bottom() - borders.radius.bottom_left_y,
+ borders.radius.bottom_left_x,
+ borders.radius.bottom_left_y,
+ end_angle,
+ start_angle, true);
add_path_arc(cr,
- draw_pos.left() + r_bottom,
- draw_pos.bottom() - r_bottom,
- r_bottom - bdr_left,
- r_bottom - bdr_left + (bdr_left - bdr_bottom),
- start_angle,
- end_angle, false);
+ draw_pos.left() + borders.radius.bottom_left_x,
+ draw_pos.bottom() - borders.radius.bottom_left_y,
+ borders.radius.bottom_left_x - bdr_left,
+ borders.radius.bottom_left_y - bdr_left + (bdr_left - bdr_bottom),
+ start_angle,
+ end_angle, false);
} else
{
cairo_line_to(cr, draw_pos.left(), draw_pos.bottom());
@@ -940,9 +930,15 @@ std::shared_ptr<litehtml::element> container_linux::create_element(const char *t
void container_linux::rounded_rectangle( cairo_t* cr, const litehtml::position &pos, const litehtml::border_radiuses &radius )
{
cairo_new_path(cr);
- if(radius.top_left_x)
+ if(radius.top_left_x && radius.top_left_y)
{
- cairo_arc(cr, pos.left() + radius.top_left_x, pos.top() + radius.top_left_x, radius.top_left_x, M_PI, M_PI * 3.0 / 2.0);
+ add_path_arc(cr,
+ pos.left() + radius.top_left_x,
+ pos.top() + radius.top_left_y,
+ radius.top_left_x,
+ radius.top_left_y,
+ M_PI,
+ M_PI * 3.0 / 2.0, false);
} else
{
cairo_move_to(cr, pos.left(), pos.top());
@@ -950,23 +946,41 @@ void container_linux::rounded_rectangle( cairo_t* cr, const litehtml::position &
cairo_line_to(cr, pos.right() - radius.top_right_x, pos.top());
- if(radius.top_right_x)
+ if(radius.top_right_x && radius.top_right_y)
{
- cairo_arc(cr, pos.right() - radius.top_right_x, pos.top() + radius.top_right_x, radius.top_right_x, M_PI * 3.0 / 2.0, 2.0 * M_PI);
+ add_path_arc(cr,
+ pos.right() - radius.top_right_x,
+ pos.top() + radius.top_right_y,
+ radius.top_right_x,
+ radius.top_right_y,
+ M_PI * 3.0 / 2.0,
+ 2.0 * M_PI, false);
}
cairo_line_to(cr, pos.right(), pos.bottom() - radius.bottom_right_x);
- if(radius.bottom_right_x)
+ if(radius.bottom_right_x && radius.bottom_right_y)
{
- cairo_arc(cr, pos.right() - radius.bottom_right_x, pos.bottom() - radius.bottom_right_x, radius.bottom_right_x, 0, M_PI / 2.0);
+ add_path_arc(cr,
+ pos.right() - radius.bottom_right_x,
+ pos.bottom() - radius.bottom_right_y,
+ radius.bottom_right_x,
+ radius.bottom_right_y,
+ 0,
+ M_PI / 2.0, false);
}
cairo_line_to(cr, pos.left() - radius.bottom_left_x, pos.bottom());
- if(radius.bottom_left_x)
+ if(radius.bottom_left_x && radius.bottom_left_y)
{
- cairo_arc(cr, pos.left() + radius.bottom_left_x, pos.bottom() - radius.bottom_left_x, radius.bottom_left_x, M_PI / 2.0, M_PI);
+ add_path_arc(cr,
+ pos.left() + radius.bottom_left_x,
+ pos.bottom() - radius.bottom_left_y,
+ radius.bottom_left_x,
+ radius.bottom_left_y,
+ M_PI / 2.0,
+ M_PI, false);
}
}
diff --git a/src/plugins/litehtml_viewer/litehtml/Makefile.am b/src/plugins/litehtml_viewer/litehtml/Makefile.am
index e4b5ac94a..0429ffe22 100644
--- a/src/plugins/litehtml_viewer/litehtml/Makefile.am
+++ b/src/plugins/litehtml_viewer/litehtml/Makefile.am
@@ -76,6 +76,10 @@ liblitehtml_la_SOURCES = \
el_title.h \
el_tr.cpp \
el_tr.h \
+ flex_item.cpp \
+ flex_item.h \
+ flex_line.cpp \
+ flex_line.h \
formatting_context.cpp \
formatting_context.h \
html.cpp \
@@ -104,7 +108,6 @@ liblitehtml_la_SOURCES = \
render_image.h \
render_inline_context.cpp \
render_inline_context.h \
- render_inline.cpp \
render_inline.h \
render_item.cpp \
render_item.h \
diff --git a/src/plugins/litehtml_viewer/litehtml/borders.h b/src/plugins/litehtml_viewer/litehtml/borders.h
index e690db6d3..9c47abca0 100644
--- a/src/plugins/litehtml_viewer/litehtml/borders.h
+++ b/src/plugins/litehtml_viewer/litehtml/borders.h
@@ -157,6 +157,35 @@ namespace litehtml
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
@@ -213,6 +242,7 @@ namespace litehtml
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;
}
};
diff --git a/src/plugins/litehtml_viewer/litehtml/css_properties.cpp b/src/plugins/litehtml_viewer/litehtml/css_properties.cpp
index 2696ae28f..a3b458ebf 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_properties.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/css_properties.cpp
@@ -240,6 +240,8 @@ void litehtml::css_properties::compute(const element* el, const document::ptr& d
doc->container()->load_image(m_list_style_image.c_str(), m_list_style_image_baseurl.c_str(), true);
}
+ m_order = el->get_int_property(_order_, false, 0, offset(m_order));
+
compute_background(el, doc);
compute_flex(el, doc);
}
@@ -391,22 +393,27 @@ void litehtml::css_properties::compute_background(const element* el, const docum
void litehtml::css_properties::compute_flex(const element* el, const document::ptr& doc)
{
- if (m_display == display_flex)
+ if (m_display == display_flex || m_display == display_inline_flex)
{
m_flex_direction = (flex_direction) el->get_enum_property(_flex_direction_, false, flex_direction_row, offset(m_flex_direction));
m_flex_wrap = (flex_wrap) el->get_enum_property(_flex_wrap_, false, flex_wrap_nowrap, offset(m_flex_wrap));
m_flex_justify_content = (flex_justify_content) el->get_enum_property(_justify_content_, false, flex_justify_content_flex_start, offset(m_flex_justify_content));
- m_flex_align_items = (flex_align_items) el->get_enum_property(_align_items_, false, flex_align_items_stretch, offset(m_flex_align_items));
+ m_flex_align_items = (flex_align_items) el->get_enum_property(_align_items_, false, flex_align_items_flex_normal, offset(m_flex_align_items));
m_flex_align_content = (flex_align_content) el->get_enum_property(_align_content_, false, flex_align_content_stretch, offset(m_flex_align_content));
}
+ m_flex_align_self = (flex_align_items) el->get_enum_property(_align_self_, false, flex_align_items_auto, offset(m_flex_align_self));
auto parent = el->parent();
- if (parent && parent->css().m_display == display_flex)
+ if (parent && (parent->css().m_display == display_flex || parent->css().m_display == display_inline_flex))
{
m_flex_grow = el->get_number_property(_flex_grow_, false, 0, offset(m_flex_grow));
m_flex_shrink = el->get_number_property(_flex_shrink_, false, 1, offset(m_flex_shrink));
- m_flex_align_self = (flex_align_self) el->get_enum_property(_align_self_, false, flex_align_self_auto, offset(m_flex_align_self));
- m_flex_basis = el->get_length_property(_flex_shrink_, false, css_length::predef_value(flex_basis_auto), offset(m_flex_basis));
+ m_flex_basis = el->get_length_property(_flex_basis_, false, css_length::predef_value(flex_basis_auto), offset(m_flex_basis));
+ if(!m_flex_basis.is_predefined() && m_flex_basis.units() == css_units_none && m_flex_basis.val() != 0)
+ {
+ // flex-basis property must contain units
+ m_flex_basis.predef(flex_basis_auto);
+ }
doc->cvt_units(m_flex_basis, get_font_size());
if(m_display == display_inline || m_display == display_inline_block)
{
diff --git a/src/plugins/litehtml_viewer/litehtml/css_properties.h b/src/plugins/litehtml_viewer/litehtml/css_properties.h
index 739e35fc2..a5609a9b1 100644
--- a/src/plugins/litehtml_viewer/litehtml/css_properties.h
+++ b/src/plugins/litehtml_viewer/litehtml/css_properties.h
@@ -67,11 +67,13 @@ namespace litehtml
flex_wrap m_flex_wrap;
flex_justify_content m_flex_justify_content;
flex_align_items m_flex_align_items;
- flex_align_self m_flex_align_self;
+ flex_align_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);
@@ -119,8 +121,9 @@ namespace litehtml
m_flex_wrap(flex_wrap_nowrap),
m_flex_justify_content(flex_justify_content_flex_start),
m_flex_align_items(flex_align_items_stretch),
- m_flex_align_self(flex_align_self_auto),
- m_flex_align_content(flex_align_content_stretch)
+ 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);
@@ -250,8 +253,11 @@ namespace litehtml
flex_wrap get_flex_wrap() const;
flex_justify_content get_flex_justify_content() const;
flex_align_items get_flex_align_items() const;
- flex_align_self get_flex_align_self() const;
+ flex_align_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
@@ -634,7 +640,7 @@ namespace litehtml
return m_flex_align_items;
}
- inline flex_align_self css_properties::get_flex_align_self() const
+ inline flex_align_items css_properties::get_flex_align_self() const
{
return m_flex_align_self;
}
@@ -653,6 +659,15 @@ namespace litehtml
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/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp b/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp
index 8c24eec98..c7c2d680b 100644
--- a/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/el_before_after.cpp
@@ -133,7 +133,7 @@ void litehtml::el_before_after_base::add_text( const string& txt )
void litehtml::el_before_after_base::add_function( const string& fnc, const string& params )
{
- int idx = value_index(fnc, "attr;counter;url");
+ int idx = value_index(fnc, "attr;counter;counters;url");
switch(idx)
{
// attr
@@ -155,9 +155,18 @@ void litehtml::el_before_after_base::add_function( const string& fnc, const stri
break;
// counter
case 1:
+ add_text(get_counter_value(params));
break;
- // url
+ // counters
case 2:
+ {
+ string_vector tokens;
+ split_string(params, tokens, ",");
+ add_text(get_counters_value(tokens));
+ }
+ break;
+ // url
+ case 3:
{
string p_url = params;
trim(p_url);
diff --git a/src/plugins/litehtml_viewer/litehtml/element.cpp b/src/plugins/litehtml_viewer/litehtml/element.cpp
index 1d0a509b1..16b4b5878 100644
--- a/src/plugins/litehtml_viewer/litehtml/element.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/element.cpp
@@ -274,8 +274,18 @@ element::ptr element::_add_before_after(int type, const style& style)
bool element::is_block_formatting_context() const
{
+ if(m_css.get_display() == display_block)
+ {
+ auto par = parent();
+ if(par && (par->css().get_display() == display_inline_flex || par->css().get_display() == display_flex))
+ {
+ return true;
+ }
+ }
if( m_css.get_display() == display_inline_block ||
m_css.get_display() == display_table_cell ||
+ m_css.get_display() == display_inline_flex ||
+ m_css.get_display() == display_flex ||
m_css.get_display() == display_table_caption ||
is_root() ||
m_css.get_float() != float_none ||
@@ -288,6 +298,122 @@ bool element::is_block_formatting_context() const
return false;
}
+litehtml::string litehtml::element::get_counter_value(const string& counter_name)
+{
+ std::map<string_id, int>::iterator i;
+ if (find_counter(_id(counter_name), i))
+ {
+ return std::to_string(i->second);
+ }
+ return "0";
+}
+
+string litehtml::element::get_counters_value(const string_vector& parameters)
+{
+ string result = "";
+ if (parameters.size() >= 2) {
+ const string_id counter_name_id = _id(parameters[0]);
+ string delims = parameters[1];
+ litehtml::trim(delims, "\"'");
+
+ string_vector values;
+
+ element::ptr current = shared_from_this();
+ while (current != nullptr)
+ {
+ auto map_iterator = current->m_counter_values.find(counter_name_id);
+ if (map_iterator != current->m_counter_values.end()) {
+ values.push_back(std::to_string(map_iterator->second));
+ }
+ current = current->parent();
+ }
+ if (values.empty()) {
+ // if no counter is found, instanciate one with value '0'
+ shared_from_this()->m_counter_values[counter_name_id] = 0;
+ result = "0";
+ }
+ else {
+ std::reverse(values.begin(), values.end());
+ litehtml::join_string(result, values, delims);
+ }
+ }
+ return result;
+}
+
+
+bool litehtml::element::find_counter(const string_id& counter_name_id, std::map<string_id, int>::iterator& map_iterator) {
+ element::ptr current = shared_from_this();
+
+ while (current != nullptr)
+ {
+ map_iterator = current->m_counter_values.find(counter_name_id);
+ if (map_iterator != current->m_counter_values.end()) {
+ return true;
+ }
+
+ // on each level, search previous siblings too
+ std::vector<element::ptr> siblings = current->get_siblings_before();
+ std::reverse(siblings.begin(), siblings.end());
+ for (const element::ptr& sibling : siblings) {
+ map_iterator = sibling->m_counter_values.find(counter_name_id);
+ if (map_iterator != sibling->m_counter_values.end()) {
+ return true;
+ }
+ }
+ current = current->parent();
+ }
+
+ return false;
+}
+
+std::vector<element::ptr> litehtml::element::get_siblings_before() const
+{
+ std::vector<element::ptr> siblings;
+ if (parent() != nullptr) {
+ for (const element::ptr& sybling : parent()->children()) {
+ if (sybling == shared_from_this()) {
+ break;
+ }
+ siblings.push_back(sybling);
+ }
+ }
+ return siblings;
+}
+
+
+void litehtml::element::parse_counter_tokens(const string_vector& tokens, const int default_value, std::function<void(const string_id&, const int)> handler) const {
+ int pos = 0;
+ while (pos < tokens.size()) {
+ string name = tokens[pos];
+ int value = default_value;
+ if (pos < tokens.size() - 1 && litehtml::is_number(tokens[pos + 1], 0)) {
+ value = atoi(tokens[pos + 1].c_str());
+ pos += 2;
+ }
+ else {
+ pos += 1;
+ }
+ handler(_id(name), value);
+ }
+}
+
+void litehtml::element::increment_counter(const string_id& counter_name_id, const int increment)
+{
+ std::map<string_id, int>::iterator i;
+ if (find_counter(counter_name_id, i)) {
+ i->second = i->second + increment;
+ }
+ else {
+ // if counter is not found, initialize one on this element
+ m_counter_values[counter_name_id] = increment;
+ }
+}
+
+void litehtml::element::reset_counter(const string_id& counter_name_id, const int value)
+{
+ m_counter_values[counter_name_id] = value;
+}
+
const background* element::get_background(bool own_only) LITEHTML_RETURN_FUNC(nullptr)
void element::add_style( const style& style) LITEHTML_EMPTY_FUNC
void element::select_all(const css_selector& selector, elements_list& res) LITEHTML_EMPTY_FUNC
@@ -332,6 +458,7 @@ bool element::is_replaced() const LITEHTML_RETURN_FUNC(false)
void element::draw(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri) LITEHTML_EMPTY_FUNC
void element::draw_background(uint_ptr hdc, int x, int y, const position *clip, const std::shared_ptr<render_item> &ri) LITEHTML_EMPTY_FUNC
int element::get_enum_property (string_id name, bool inherited, int defval, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC(0)
+int element::get_int_property (string_id name, bool inherited, int defval, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC(0)
css_length element::get_length_property (string_id name, bool inherited, css_length defval, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC(0)
web_color element::get_color_property (string_id name, bool inherited, web_color defval, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC(web_color())
string element::get_string_property (string_id name, bool inherited, const string& defval, uint_ptr css_properties_member_offset) const LITEHTML_RETURN_FUNC("")
diff --git a/src/plugins/litehtml_viewer/litehtml/element.h b/src/plugins/litehtml_viewer/litehtml/element.h
index e330b5c01..4d244736b 100644
--- a/src/plugins/litehtml_viewer/litehtml/element.h
+++ b/src/plugins/litehtml_viewer/litehtml/element.h
@@ -35,6 +35,10 @@ namespace litehtml
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;
@@ -99,6 +103,7 @@ namespace litehtml
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;
@@ -142,6 +147,16 @@ namespace litehtml
{
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;
};
//////////////////////////////////////////////////////////////////////////
diff --git a/src/plugins/litehtml_viewer/litehtml/flex_item.cpp b/src/plugins/litehtml_viewer/litehtml/flex_item.cpp
new file mode 100644
index 000000000..d0fbaecd7
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/flex_item.cpp
@@ -0,0 +1,488 @@
+#include "html.h"
+#include "flex_item.h"
+#include "render_item.h"
+#include "flex_line.h"
+#include <cmath>
+
+void litehtml::flex_item::init(const litehtml::containing_block_context &self_size,
+ litehtml::formatting_context *fmt_ctx, flex_align_items align_items)
+{
+ grow = (int) std::nearbyint(el->css().get_flex_grow() * 1000.0);
+ // Negative numbers are invalid.
+ // https://www.w3.org/TR/css-flexbox-1/#valdef-flex-grow-number
+ if(grow < 0) grow = 0;
+
+ shrink = (int) std::nearbyint(el->css().get_flex_shrink() * 1000.0);
+ // Negative numbers are invalid.
+ // https://www.w3.org/TR/css-flexbox-1/#valdef-flex-shrink-number
+ if(shrink < 0) shrink = 1000;
+
+ el->calc_outlines(self_size.render_width);
+ order = el->css().get_order();
+
+ direction_specific_init(self_size, fmt_ctx);
+
+ if (el->css().get_flex_align_self() == flex_align_items_auto)
+ {
+ align = align_items;
+ } else
+ {
+ align = el->css().get_flex_align_self();
+ }
+ main_size = base_size;
+ scaled_flex_shrink_factor = base_size * shrink;
+ frozen = false;
+}
+
+void litehtml::flex_item::place(flex_line &ln, int main_pos,
+ const containing_block_context &self_size,
+ formatting_context *fmt_ctx)
+{
+ apply_main_auto_margins();
+ set_main_position(main_pos);
+ if(!apply_cross_auto_margins(ln.cross_size))
+ {
+ switch (align & 0xFF)
+ {
+ case flex_align_items_baseline:
+ align_baseline(ln, self_size, fmt_ctx);
+ break;
+ case flex_align_items_flex_end:
+ if(ln.reverse_cross)
+ {
+ set_cross_position(ln.cross_start);
+ break; /// If cross axis is reversed position item from start
+ }
+ case flex_align_items_end:
+ set_cross_position(ln.cross_start + ln.cross_size - get_el_cross_size());
+ break;
+ case flex_align_items_center:
+ set_cross_position(ln.cross_start + ln.cross_size / 2 - get_el_cross_size() / 2);
+ break;
+ case flex_align_items_flex_start:
+ if(ln.reverse_cross) /// If cross axis is reversed position item from end
+ {
+ set_cross_position(ln.cross_start + ln.cross_size - get_el_cross_size());
+ break;
+ }
+ case flex_align_items_start:
+ set_cross_position(ln.cross_start);
+ break;
+ default:
+ align_stretch(ln, self_size, fmt_ctx);
+ break;
+ }
+ }
+}
+
+int litehtml::flex_item::get_last_baseline(baseline::_baseline_type type) const
+{
+ if(type == baseline::baseline_type_top)
+ {
+ return el->get_last_baseline();
+ } else if(type == baseline::baseline_type_bottom)
+ {
+ return el->height() - el->get_last_baseline();
+ }
+ return 0;
+}
+
+int litehtml::flex_item::get_first_baseline(litehtml::baseline::_baseline_type type) const
+{
+ if(type == baseline::baseline_type_top)
+ {
+ return el->get_first_baseline();
+ } else if(type == baseline::baseline_type_bottom)
+ {
+ return el->height() - el->get_first_baseline();
+ }
+ return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////
+
+void litehtml::flex_item_row_direction::direction_specific_init(const litehtml::containing_block_context &self_size,
+ litehtml::formatting_context *fmt_ctx)
+{
+ if(el->css().get_margins().left.is_predefined())
+ {
+ auto_margin_main_start = 0;
+ }
+ if(el->css().get_margins().right.is_predefined())
+ {
+ auto_margin_main_end = 0;
+ }
+ if(el->css().get_margins().top.is_predefined())
+ {
+ auto_margin_cross_start = true;
+ }
+ if(el->css().get_margins().bottom.is_predefined())
+ {
+ auto_margin_cross_end = true;
+ }
+ def_value<int> content_size(0);
+ if (el->css().get_min_width().is_predefined())
+ {
+ min_size = el->render(0, 0,
+ self_size.new_width(el->content_offset_width(),
+ containing_block_context::size_mode_content), fmt_ctx);
+ content_size = min_size;
+ } else
+ {
+ min_size = el->css().get_min_width().calc_percent(self_size.render_width) +
+ el->content_offset_width();
+ }
+ if (!el->css().get_max_width().is_predefined())
+ {
+ max_size = el->css().get_max_width().calc_percent(self_size.render_width) +
+ el->content_offset_width();
+ }
+ bool flex_basis_predefined = el->css().get_flex_basis().is_predefined();
+ int predef = flex_basis_auto;
+ if(flex_basis_predefined)
+ {
+ predef = el->css().get_flex_basis().predef();
+ } else
+ {
+ if(el->css().get_flex_basis().val() < 0)
+ {
+ flex_basis_predefined = true;
+ }
+ }
+
+ if (flex_basis_predefined)
+ {
+ switch (predef)
+ {
+ case flex_basis_auto:
+ if (!el->css().get_width().is_predefined())
+ {
+ base_size = el->css().get_width().calc_percent(self_size.render_width) +
+ el->content_offset_width();
+ break;
+ }
+ // if width is not predefined, use content size as base size
+ case flex_basis_fit_content:
+ case flex_basis_content:
+ base_size = el->render(0, 0, self_size.new_width(self_size.render_width + el->content_offset_width(),
+ containing_block_context::size_mode_content |
+ containing_block_context::size_mode_exact_width),
+ fmt_ctx);
+ break;
+ case flex_basis_min_content:
+ if(content_size.is_default())
+ {
+ content_size = el->render(0, 0,
+ self_size.new_width(el->content_offset_width(),
+ containing_block_context::size_mode_content),
+ fmt_ctx);
+ }
+ base_size = content_size;
+ break;
+ case flex_basis_max_content:
+ el->render(0, 0, self_size, fmt_ctx);
+ base_size = el->width();
+ break;
+ default:
+ base_size = 0;
+ break;
+ }
+ } else
+ {
+ base_size = el->css().get_flex_basis().calc_percent(self_size.render_width) +
+ el->content_offset_width();
+ base_size = std::max(base_size, min_size);
+ }
+}
+
+void litehtml::flex_item_row_direction::apply_main_auto_margins()
+{
+ // apply auto margins to item
+ if(!auto_margin_main_start.is_default())
+ {
+ el->get_margins().left = auto_margin_main_start;
+ el->pos().x += auto_margin_main_start;
+ }
+ if(!auto_margin_main_end.is_default()) el->get_margins().right = auto_margin_main_end;
+}
+
+bool litehtml::flex_item_row_direction::apply_cross_auto_margins(int cross_size)
+{
+ if(auto_margin_cross_end || auto_margin_cross_start)
+ {
+ int margins_num = 0;
+ if(auto_margin_cross_end)
+ {
+ margins_num++;
+ }
+ if(auto_margin_cross_start)
+ {
+ margins_num++;
+ }
+ int margin = (cross_size - el->height()) / margins_num;
+ if(auto_margin_cross_start)
+ {
+ el->get_margins().top = margin;
+ el->pos().y = el->content_offset_top();
+ }
+ if(auto_margin_cross_end)
+ {
+ el->get_margins().bottom = margin;
+ }
+ return true;
+ }
+ return false;
+}
+
+void litehtml::flex_item_row_direction::set_main_position(int pos)
+{
+ el->pos().x = pos + el->content_offset_left();
+}
+
+void litehtml::flex_item_row_direction::set_cross_position(int pos)
+{
+ el->pos().y = pos + el->content_offset_top();
+}
+
+void litehtml::flex_item_row_direction::align_stretch(flex_line &ln, const containing_block_context &self_size,
+ formatting_context *fmt_ctx)
+{
+ set_cross_position(ln.cross_start);
+ if (el->css().get_height().is_predefined())
+ {
+ el->render(el->left(), el->top(), self_size.new_width_height(
+ el->pos().width + el->box_sizing_width(),
+ ln.cross_size - el->content_offset_height() + el->box_sizing_height(),
+ containing_block_context::size_mode_exact_width |
+ containing_block_context::size_mode_exact_height
+ ), fmt_ctx);
+ apply_main_auto_margins();
+ }
+}
+
+void litehtml::flex_item_row_direction::align_baseline(litehtml::flex_line &ln,
+ const containing_block_context &self_size,
+ formatting_context *fmt_ctx)
+{
+ if (align & flex_align_items_last)
+ {
+ set_cross_position(ln.cross_start + ln.last_baseline.get_offset_from_top(ln.cross_size) - el->get_last_baseline());
+ } else
+ {
+ set_cross_position(ln.cross_start + ln.first_baseline.get_offset_from_top(ln.cross_size) - el->get_first_baseline());
+ }
+}
+
+int litehtml::flex_item_row_direction::get_el_main_size()
+{
+ return el->width();
+}
+
+int litehtml::flex_item_row_direction::get_el_cross_size()
+{
+ return el->height();
+}
+
+////////////////////////////////////////////////////////////////////////////////////
+
+void litehtml::flex_item_column_direction::direction_specific_init(const litehtml::containing_block_context &self_size,
+ litehtml::formatting_context *fmt_ctx)
+{
+ if(el->css().get_margins().top.is_predefined())
+ {
+ auto_margin_main_start = 0;
+ }
+ if(el->css().get_margins().bottom.is_predefined())
+ {
+ auto_margin_main_end = 0;
+ }
+ if(el->css().get_margins().left.is_predefined())
+ {
+ auto_margin_cross_start = true;
+ }
+ if(el->css().get_margins().right.is_predefined())
+ {
+ auto_margin_cross_end = true;
+ }
+ if (el->css().get_min_height().is_predefined())
+ {
+ el->render(0, 0, self_size.new_width(self_size.render_width, containing_block_context::size_mode_content), fmt_ctx);
+ min_size = el->height();
+ } else
+ {
+ min_size = el->css().get_min_height().calc_percent(self_size.height) +
+ el->content_offset_height();
+ }
+ if (!el->css().get_max_height().is_predefined())
+ {
+ max_size = el->css().get_max_height().calc_percent(self_size.height) +
+ el->content_offset_width();
+ }
+
+ bool flex_basis_predefined = el->css().get_flex_basis().is_predefined();
+ int predef = flex_basis_auto;
+ if(flex_basis_predefined)
+ {
+ predef = el->css().get_flex_basis().predef();
+ } else
+ {
+ if(el->css().get_flex_basis().val() < 0)
+ {
+ flex_basis_predefined = true;
+ }
+ }
+
+ if (flex_basis_predefined)
+ {
+ switch (predef)
+ {
+ case flex_basis_auto:
+ if (!el->css().get_height().is_predefined())
+ {
+ base_size = el->css().get_height().calc_percent(self_size.height) +
+ el->content_offset_height();
+ break;
+ }
+ case flex_basis_max_content:
+ case flex_basis_fit_content:
+ el->render(0, 0, self_size, fmt_ctx);
+ base_size = el->height();
+ break;
+ case flex_basis_min_content:
+ base_size = min_size;
+ break;
+ default:
+ base_size = 0;
+ }
+ } else
+ {
+ if(el->css().get_flex_basis().units() == css_units_percentage)
+ {
+ if(self_size.height.type == containing_block_context::cbc_value_type_absolute)
+ {
+ base_size = el->css().get_flex_basis().calc_percent(self_size.height) +
+ el->content_offset_height();
+ } else
+ {
+ base_size = 0;
+ }
+ } else
+ {
+ base_size = (int) el->css().get_flex_basis().val() + el->content_offset_height();
+ }
+ base_size = std::max(base_size, min_size);
+ }
+}
+
+void litehtml::flex_item_column_direction::apply_main_auto_margins()
+{
+ // apply auto margins to item
+ if(!auto_margin_main_start.is_default())
+ {
+ el->get_margins().top = auto_margin_main_start;
+ el->pos().y += auto_margin_main_start;
+ }
+ if(!auto_margin_main_end.is_default()) el->get_margins().bottom = auto_margin_main_end;
+}
+
+bool litehtml::flex_item_column_direction::apply_cross_auto_margins(int cross_size)
+{
+ if(auto_margin_cross_end || auto_margin_cross_start)
+ {
+ int margins_num = 0;
+ if(auto_margin_cross_end)
+ {
+ margins_num++;
+ }
+ if(auto_margin_cross_start)
+ {
+ margins_num++;
+ }
+ int margin = (cross_size - el->width()) / margins_num;
+ if(auto_margin_cross_start)
+ {
+ el->get_margins().left = margin;
+ el->pos().x += el->content_offset_left();
+ }
+ if(auto_margin_cross_end)
+ {
+ el->get_margins().right = margin;
+ }
+ }
+ return false;
+}
+
+void litehtml::flex_item_column_direction::set_main_position(int pos)
+{
+ el->pos().y = pos + el->content_offset_top();
+}
+
+void litehtml::flex_item_column_direction::set_cross_position(int pos)
+{
+ el->pos().x = pos + el->content_offset_left();
+}
+
+void litehtml::flex_item_column_direction::align_stretch(flex_line &ln, const containing_block_context &self_size,
+ formatting_context *fmt_ctx)
+{
+ /// MAIN: Y
+ /// CROSS: X
+ if (!el->css().get_width().is_predefined())
+ {
+ el->render(ln.cross_start,
+ el->pos().y - el->content_offset_top(),
+ self_size.new_width_height(ln.cross_size - el->content_offset_width() + el->box_sizing_width(),
+ main_size - el->content_offset_height() + el->box_sizing_height(),
+ containing_block_context::size_mode_exact_height),
+ fmt_ctx, false);
+ } else
+ {
+ el->render(ln.cross_start,
+ el->pos().y - el->content_offset_top(),
+ self_size.new_width_height(
+ ln.cross_size - el->content_offset_width() + el->box_sizing_width(),
+ main_size - el->content_offset_height() + el->box_sizing_height(),
+ containing_block_context::size_mode_exact_width |
+ containing_block_context::size_mode_exact_height),
+ fmt_ctx, false);
+ }
+ /// Apply auto margins after rendering
+ apply_main_auto_margins();
+}
+
+void litehtml::flex_item_column_direction::align_baseline(litehtml::flex_line &ln,
+ const containing_block_context &self_size,
+ formatting_context *fmt_ctx)
+{
+ // The fallback alignment for first baseline is start, the one for last baseline is end.
+ if(align & flex_align_items_last)
+ {
+ if(ln.reverse_cross)
+ {
+ set_cross_position(ln.cross_start);
+ } else
+ {
+ set_cross_position(ln.cross_start + ln.cross_size - get_el_cross_size());
+ }
+ } else
+ {
+ if(!ln.reverse_cross)
+ {
+ set_cross_position(ln.cross_start);
+ } else
+ {
+ set_cross_position(ln.cross_start + ln.cross_size - get_el_cross_size());
+ }
+ }
+}
+
+int litehtml::flex_item_column_direction::get_el_main_size()
+{
+ return el->height();
+}
+
+int litehtml::flex_item_column_direction::get_el_cross_size()
+{
+ return el->width();
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/flex_item.h b/src/plugins/litehtml_viewer/litehtml/flex_item.h
new file mode 100644
index 000000000..a2b3426f1
--- /dev/null
+++ b/src/plugins/litehtml_viewer/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),
+ align(flex_align_items_auto),
+ grow(0),
+ base_size(0),
+ shrink(0),
+ min_size(0),
+ frozen(false),
+ main_size(0),
+ max_size(0),
+ order(0),
+ src_order(0),
+ scaled_flex_shrink_factor(0),
+ auto_margin_main_start(0),
+ auto_margin_main_end(0),
+ auto_margin_cross_start(false),
+ auto_margin_cross_end(false)
+ {}
+
+ 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/src/plugins/litehtml_viewer/litehtml/flex_line.cpp b/src/plugins/litehtml_viewer/litehtml/flex_line.cpp
new file mode 100644
index 000000000..5f966b3b1
--- /dev/null
+++ b/src/plugins/litehtml_viewer/litehtml/flex_line.cpp
@@ -0,0 +1,454 @@
+#include "html.h"
+#include "flex_line.h"
+#include "flex_item.h"
+#include "render_item.h"
+
+void litehtml::flex_line::distribute_free_space(int container_main_size)
+{
+ // Determine the used flex factor. Sum the outer hypothetical main sizes of all items on the line.
+ // If the sum is less than the flex container’s inner main size, use the flex grow factor for the
+ // rest of this algorithm; otherwise, use the flex shrink factor.
+ int initial_free_space = container_main_size - base_size;
+ bool grow;
+ int total_flex_factor;
+ if(initial_free_space < 0)
+ {
+ grow = false;
+ total_flex_factor = total_shrink;
+ // Flex values between 0 and 1 have a somewhat special behavior: when the sum of the flex values on the line
+ // is less than 1, they will take up less than 100% of the free space.
+ // https://www.w3.org/TR/css-flexbox-1/#valdef-flex-flex-grow
+ if(total_flex_factor < 1000)
+ {
+ for(auto &item : items)
+ {
+ item->main_size += initial_free_space * item->shrink / 1000;
+ }
+ return;
+ }
+ } else
+ {
+ grow = true;
+ total_flex_factor = total_grow;
+ // Flex values between 0 and 1 have a somewhat special behavior: when the sum of the flex values on the line
+ // is less than 1, they will take up less than 100% of the free space.
+ // https://www.w3.org/TR/css-flexbox-1/#valdef-flex-flex-grow
+ if(total_flex_factor < 1000)
+ {
+ for(auto &item : items)
+ {
+ item->main_size += initial_free_space * item->grow / 1000;
+ }
+ return;
+ }
+ }
+
+ if(total_flex_factor > 0)
+ {
+ bool processed = true;
+ while (processed)
+ {
+ int sum_scaled_flex_shrink_factor = 0;
+ int sum_flex_factors = 0;
+ int remaining_free_space = container_main_size;
+ int total_not_frozen = 0;
+ for (auto &item: items)
+ {
+ if (!item->frozen)
+ {
+ sum_scaled_flex_shrink_factor += item->scaled_flex_shrink_factor;
+ if(grow)
+ {
+ sum_flex_factors += item->grow;
+ } else
+ {
+ sum_flex_factors += item->shrink;
+ }
+ remaining_free_space -= item->base_size;
+ total_not_frozen++;
+ } else
+ {
+ remaining_free_space -= item->main_size;
+ }
+ }
+ // Check for flexible items. If all the flex items on the line are frozen, free space has
+ // been distributed; exit this loop.
+ if (!total_not_frozen) break;
+
+ remaining_free_space = abs(remaining_free_space);
+ // c. Distribute free space proportional to the flex factors.
+ // If the remaining free space is zero
+ // Do nothing.
+ if (!remaining_free_space)
+ {
+ processed = false;
+ } else
+ {
+ int total_clamped = 0;
+ for (auto &item: items)
+ {
+ if (!item->frozen)
+ {
+ if(!grow)
+ {
+ // If using the flex shrink factor
+ // For every unfrozen item on the line, multiply its flex shrink factor by its
+ // inner flex base size, and note this as its scaled flex shrink factor. Find
+ // the ratio of the item’s scaled flex shrink factor to the sum of the scaled
+ // flex shrink factors of all unfrozen items on the line. Set the item’s target
+ // main size to its flex base size minus a fraction of the absolute value of the
+ // remaining free space proportional to the ratio.
+ int scaled_flex_shrink_factor = item->base_size * item->shrink;
+ item->main_size = (int) ((float) item->base_size - (float) remaining_free_space *
+ (float) scaled_flex_shrink_factor /
+ (float) sum_scaled_flex_shrink_factor);
+
+ // d. Fix min/max violations. Clamp each non-frozen item’s target main size by its used
+ // min and max main sizes and floor its content-box size at zero. If the item’s target
+ // main size was made smaller by this, it’s a max violation. If the item’s target main
+ // size was made larger by this, it’s a min violation.
+ if (item->main_size <= item->min_size)
+ {
+ total_clamped++;
+ item->main_size = item->min_size;
+ item->frozen = true;
+ }
+ if(!item->max_size.is_default() && item->main_size >= item->max_size)
+ {
+ total_clamped++;
+ item->main_size = item->max_size;
+ item->frozen = true;
+ }
+ } else
+ {
+ // If using the flex grow factor
+ // Find the ratio of the item’s flex grow factor to the sum of the flex grow
+ // factors of all unfrozen items on the line. Set the item’s target main size to
+ // its flex base size plus a fraction of the remaining free space proportional
+ // to the ratio.
+ item->main_size = (int) ((float) item->base_size +
+ (float) remaining_free_space * (float) item->grow /
+ (float) total_flex_factor);
+ // d. Fix min/max violations. Clamp each non-frozen item’s target main size by its used
+ // min and max main sizes and floor its content-box size at zero. If the item’s target
+ // main size was made smaller by this, it’s a max violation. If the item’s target main
+ // size was made larger by this, it’s a min violation.
+ if (item->main_size >= container_main_size)
+ {
+ total_clamped++;
+ item->main_size = container_main_size;
+ item->frozen = true;
+ }
+ if(!item->max_size.is_default() && item->main_size >= item->max_size)
+ {
+ total_clamped++;
+ item->main_size = item->max_size;
+ item->frozen = true;
+ }
+ }
+ }
+ }
+ if (total_clamped == 0) processed = false;
+ }
+ }
+ // Distribute remaining after algorithm space
+ int sum_main_size = 0;
+ for(auto &item : items)
+ {
+ sum_main_size += item->main_size;
+ }
+ int free_space = container_main_size - sum_main_size;
+ if(free_space > 0)
+ {
+ for(auto &item : items)
+ {
+ if(free_space == 0) break;
+ item->main_size++;
+ free_space--;
+ }
+ }
+ }
+}
+
+bool litehtml::flex_line::distribute_main_auto_margins(int free_main_size)
+{
+ if(free_main_size > 0 && (num_auto_margin_main_start || num_auto_margin_main_end))
+ {
+ int add = (int) (free_main_size / (items.size() * 2));
+ for (auto &item: items)
+ {
+ if(!item->auto_margin_main_start.is_default())
+ {
+ item->auto_margin_main_start = add;
+ item->main_size += add;
+ main_size += add;
+ free_main_size -= add;
+ }
+ if(!item->auto_margin_main_end.is_default())
+ {
+ item->auto_margin_main_end = add;
+ item->main_size += add;
+ main_size += add;
+ free_main_size -= add;
+ }
+ }
+ while (free_main_size > 0)
+ {
+ for (auto &item: items)
+ {
+ if(!item->auto_margin_main_start.is_default())
+ {
+ item->auto_margin_main_start = item->auto_margin_main_start + 1;
+ free_main_size--;
+ if(!free_main_size) break;
+ }
+ if(!item->auto_margin_main_end.is_default())
+ {
+ item->auto_margin_main_end = item->auto_margin_main_end + 1;
+ free_main_size--;
+ if(!free_main_size) break;
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+void litehtml::flex_line::init(int container_main_size, bool fit_container, bool is_row_direction,
+ const litehtml::containing_block_context &self_size,
+ litehtml::formatting_context *fmt_ctx)
+{
+ cross_size = 0;
+ main_size = 0;
+ first_baseline.set(0, baseline::baseline_type_none);
+ last_baseline.set(0, baseline::baseline_type_none);
+
+ if(!fit_container)
+ {
+ distribute_free_space(container_main_size);
+ }
+
+ if(is_row_direction)
+ {
+ def_value<int> first_baseline_top = 0;
+ def_value<int> first_baseline_bottom = 0;
+ def_value<int> last_baseline_top = 0;
+ def_value<int> last_baseline_bottom = 0;
+ int non_baseline_height = 0;
+
+ // Calculate maximum cross size
+ def_value<int> max_cross_size(0);
+ if(self_size.height.type != containing_block_context::cbc_value_type_auto)
+ {
+ max_cross_size = self_size.height;
+ }
+ if(self_size.max_height.type != containing_block_context::cbc_value_type_none)
+ {
+ if(max_cross_size.is_default())
+ {
+ max_cross_size = self_size.max_height;
+ } else
+ {
+ max_cross_size = std::max((int) max_cross_size, (int) self_size.max_height);
+ }
+ }
+
+ /// Render items into new size
+ /// Find line cross_size
+ /// Find line first/last baseline
+ for (auto &item: items)
+ {
+ item->el->render(0,
+ 0,
+ self_size.new_width(item->main_size - item->el->content_offset_width(), containing_block_context::size_mode_exact_width), fmt_ctx, false);
+
+ if((item->align & 0xFF) == flex_align_items_baseline)
+ {
+ if(item->align & flex_align_items_last)
+ {
+ last_baseline.type(reverse_cross ? baseline::baseline_type_top : baseline::baseline_type_bottom);
+
+ int top = -item->el->get_last_baseline();
+ int bottom = top + item->el->height();
+
+ if(last_baseline_top.is_default()) last_baseline_top = top;
+ else last_baseline_top = std::min((int) last_baseline_top, top);
+
+ if(last_baseline_bottom.is_default()) last_baseline_bottom = bottom;
+ else last_baseline_bottom = std::max((int)last_baseline_bottom, bottom);
+ } else
+ {
+ first_baseline.type(reverse_cross ? baseline::baseline_type_bottom : baseline::baseline_type_top);
+ int top = -item->el->get_first_baseline();
+ int bottom = top + item->el->height();
+
+ if(first_baseline_top.is_default()) first_baseline_top = top;
+ else first_baseline_top = std::min((int) first_baseline_top, top);
+
+ if(first_baseline_bottom.is_default()) first_baseline_bottom = bottom;
+ else first_baseline_bottom = std::max((int) first_baseline_bottom, bottom);
+ }
+ } else
+ {
+ non_baseline_height = std::max(non_baseline_height, item->el->height());
+ }
+ main_size += item->el->width();
+ }
+
+ cross_size = std::max(first_baseline_bottom - first_baseline_top,last_baseline_bottom - last_baseline_top);
+ cross_size = std::max(cross_size, non_baseline_height);
+ if(!max_cross_size.is_default() && cross_size > max_cross_size)
+ {
+ cross_size = max_cross_size;
+ }
+
+ first_baseline.calc(first_baseline_top, first_baseline_bottom);
+ last_baseline.calc(last_baseline_top, last_baseline_bottom);
+ } else
+ {
+ // Calculate maximum cross size
+ def_value<int> max_cross_size(0);
+ if(self_size.width.type != containing_block_context::cbc_value_type_auto)
+ {
+ max_cross_size = self_size.width;
+ }
+ if(self_size.max_width.type != containing_block_context::cbc_value_type_none)
+ {
+ if(max_cross_size.is_default())
+ {
+ max_cross_size = self_size.max_width;
+ } else
+ {
+ max_cross_size = std::max((int) max_cross_size, (int) self_size.max_width);
+ }
+ }
+
+ for (auto &item: items)
+ {
+ int el_ret_width = item->el->render(0,
+ 0,
+ self_size, fmt_ctx, false);
+ item->el->render(0,
+ 0,
+ self_size.new_width_height(el_ret_width - item->el->content_offset_width(),
+ item->main_size - item->el->content_offset_height(),
+ containing_block_context::size_mode_exact_width |
+ containing_block_context::size_mode_exact_height),
+ fmt_ctx, false);
+ main_size += item->el->height();
+ cross_size = std::max(cross_size, item->el->width());
+ }
+ if(!max_cross_size.is_default() && cross_size > max_cross_size)
+ {
+ cross_size = max_cross_size;
+ }
+ }
+}
+
+int litehtml::flex_line::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)
+{
+ /// Distribute main axis free space for auto-margins
+ int free_main_size = container_main_size - main_size;
+ distribute_main_auto_margins(free_main_size);
+ free_main_size = container_main_size - main_size;
+
+ /// Fix justify-content property
+ switch (justify_content)
+ {
+ case flex_justify_content_left:
+ case flex_justify_content_right:
+ if(!is_row_direction)
+ {
+ justify_content = flex_justify_content_start;
+ }
+ break;
+ case flex_justify_content_space_between:
+ // If the leftover free-space is negative or there is only a single flex item on the line, this
+ // value is identical to flex-start.
+ if(items.size() == 1 || free_main_size < 0) justify_content = flex_justify_content_flex_start;
+ break;
+ case flex_justify_content_space_around:
+ case flex_justify_content_space_evenly:
+ // If the leftover free-space is negative or there is only a single flex item on the line, this
+ // value is identical to center
+ if(items.size() == 1 || free_main_size < 0) justify_content = flex_justify_content_center;
+ break;
+ default:
+ break;
+ }
+
+ /// Distribute free main size using justify-content property
+ int main_pos = 0;
+ int add_before_item = 0;
+ int add_after_item = 0;
+ int item_remainder = 0;
+
+ /// find initial main position and spaces between items
+ switch (justify_content)
+ {
+
+ case flex_justify_content_right:
+ main_pos = free_main_size;
+ break;
+ case flex_justify_content_left:
+ case flex_justify_content_start:
+ main_pos = 0;
+ break;
+ case flex_justify_content_end:
+ main_pos = free_main_size;
+ break;
+ case flex_justify_content_flex_end:
+ if(!reverse_main)
+ {
+ main_pos = free_main_size;
+ }
+ break;
+ case flex_justify_content_center:
+ main_pos = free_main_size / 2;
+ break;
+ case flex_justify_content_space_between:
+ add_after_item = free_main_size / ((int) items.size() - 1);
+ item_remainder = free_main_size - (add_after_item * ((int) items.size() - 1));
+ break;
+ case flex_justify_content_space_around:
+ add_after_item = add_before_item = free_main_size / ((int) items.size() * 2);
+ item_remainder = free_main_size - (add_after_item * (int) items.size() * 2);
+ break;
+ case flex_justify_content_space_evenly:
+ add_before_item = free_main_size / ((int) items.size() + 1);
+ item_remainder = free_main_size - add_before_item * ((int) items.size() + 1);
+ break;
+ default:
+ if(reverse_main)
+ {
+ main_pos = free_main_size;
+ }
+ break;
+ }
+
+ /// Place all items in main and cross positions
+ int height = 0;
+ for(auto &item : items)
+ {
+ main_pos += add_before_item;
+ if(add_before_item > 0 && item_remainder > 0)
+ {
+ main_pos++;
+ item_remainder--;
+ }
+ item->place(*this, main_pos, self_size, fmt_ctx);
+ main_pos += item->get_el_main_size() + add_after_item;
+ if(add_after_item > 0 && item_remainder > 0)
+ {
+ main_pos++;
+ item_remainder--;
+ }
+ height = std::max(height, item->el->bottom());
+ }
+ return height;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/flex_line.h b/src/plugins/litehtml_viewer/litehtml/flex_line.h
new file mode 100644
index 000000000..4803d2386
--- /dev/null
+++ b/src/plugins/litehtml_viewer/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_size(0),
+ cross_start(0),
+ total_grow(0),
+ base_size(0),
+ total_shrink(0),
+ main_size(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/src/plugins/litehtml_viewer/litehtml/html.cpp b/src/plugins/litehtml_viewer/litehtml/html.cpp
index 9695180a7..ee8ddad8d 100644
--- a/src/plugins/litehtml_viewer/litehtml/html.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/html.cpp
@@ -2,9 +2,9 @@
#include "types.h"
#include "utf8_strings.h"
-void litehtml::trim(string &s)
+void litehtml::trim(string &s, const string& chars_to_trim)
{
- string::size_type pos = s.find_first_not_of(" \n\r\t");
+ string::size_type pos = s.find_first_not_of(chars_to_trim);
if(pos != string::npos)
{
s.erase(s.begin(), s.begin() + pos);
@@ -14,7 +14,7 @@ void litehtml::trim(string &s)
s = "";
return;
}
- pos = s.find_last_not_of(" \n\r\t");
+ pos = s.find_last_not_of(chars_to_trim);
if(pos != string::npos)
{
s.erase(s.begin() + pos + 1, s.end());
@@ -277,3 +277,14 @@ litehtml::string litehtml::get_escaped_string(const string& in_str)
}
return ret;
}
+
+bool litehtml::is_number(const string& string, const bool allow_dot) {
+ for (auto ch : string)
+ {
+ if (!(t_isdigit(ch) || (allow_dot && ch == '.')))
+ {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/html.h b/src/plugins/litehtml_viewer/litehtml/html.h
index b184ac30a..818d5ce56 100644
--- a/src/plugins/litehtml_viewer/litehtml/html.h
+++ b/src/plugins/litehtml_viewer/litehtml/html.h
@@ -23,7 +23,7 @@
namespace litehtml
{
- void trim(string &s);
+ 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 = ';');
@@ -36,7 +36,9 @@ namespace litehtml
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');
diff --git a/src/plugins/litehtml_viewer/litehtml/html_tag.cpp b/src/plugins/litehtml_viewer/litehtml/html_tag.cpp
index 0b978f56a..1814e9c3a 100644
--- a/src/plugins/litehtml_viewer/litehtml/html_tag.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/html_tag.cpp
@@ -367,6 +367,11 @@ int litehtml::html_tag::get_enum_property(string_id name, bool inherited, int de
return get_property_impl<int, prop_type_enum_item, &property_value::m_enum_item>(name, inherited, default_value, css_properties_member_offset);
}
+int litehtml::html_tag::get_int_property(string_id name, bool inherited, int default_value, uint_ptr css_properties_member_offset) const
+{
+ return get_property_impl<int, prop_type_enum_item, &property_value::m_enum_item>(name, inherited, default_value, css_properties_member_offset);
+}
+
litehtml::css_length litehtml::html_tag::get_length_property(string_id name, bool inherited, css_length default_value, uint_ptr css_properties_member_offset) const
{
return get_property_impl<css_length, prop_type_length, &property_value::m_length>(name, inherited, default_value, css_properties_member_offset);
@@ -1548,9 +1553,33 @@ litehtml::element::ptr litehtml::html_tag::get_element_after(const style& style,
return nullptr;
}
+
+void litehtml::html_tag::handle_counter_properties()
+{
+ const auto& reset_property = m_style.get_property(string_id::_counter_reset_);
+ if (reset_property.m_type == prop_type_string_vector) {
+ auto reset_function = [&](const string_id&name_id, const int value) {
+ reset_counter(name_id, value);
+ };
+ parse_counter_tokens(reset_property.m_string_vector, 0, reset_function);
+ return;
+ }
+
+ const auto& inc_property = m_style.get_property(string_id::_counter_increment_);
+ if (inc_property.m_type == prop_type_string_vector) {
+ auto inc_function = [&](const string_id&name_id, const int value) {
+ increment_counter(name_id, value);
+ };
+ parse_counter_tokens(inc_property.m_string_vector, 1, inc_function);
+ return;
+ }
+}
+
+
void litehtml::html_tag::add_style(const style& style)
{
m_style.combine(style);
+ handle_counter_properties();
}
void litehtml::html_tag::refresh_styles()
diff --git a/src/plugins/litehtml_viewer/litehtml/html_tag.h b/src/plugins/litehtml_viewer/litehtml/html_tag.h
index 9148031b2..b085d7dfb 100644
--- a/src/plugins/litehtml_viewer/litehtml/html_tag.h
+++ b/src/plugins/litehtml_viewer/litehtml/html_tag.h
@@ -72,6 +72,7 @@ namespace litehtml
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;
@@ -119,6 +120,10 @@ namespace litehtml
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();
+
};
/************************************************************************/
diff --git a/src/plugins/litehtml_viewer/litehtml/line_box.cpp b/src/plugins/litehtml_viewer/litehtml/line_box.cpp
index 1ca9c85d7..e739e63c8 100644
--- a/src/plugins/litehtml_viewer/litehtml/line_box.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/line_box.cpp
@@ -363,7 +363,7 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish
case va_super:
{
int bl = calc_va_baseline(current_context, lbi->get_el()->css().get_vertical_align(), current_context.fm, line_top, line_bottom);
- lbi->pos().y = bl - lbi->get_el()->height() + lbi->get_el()->get_base_line() +
+ lbi->pos().y = bl - lbi->get_el()->get_last_baseline() +
lbi->get_el()->content_offset_top();
}
break;
@@ -374,7 +374,7 @@ std::list< std::unique_ptr<litehtml::line_box_item> > litehtml::line_box::finish
lbi->pos().y = line_top + lbi->get_el()->content_offset_top();
break;
case va_baseline:
- lbi->pos().y = current_context.baseline - lbi->get_el()->height() + lbi->get_el()->get_base_line() +
+ lbi->pos().y = current_context.baseline - lbi->get_el()->get_last_baseline() +
lbi->get_el()->content_offset_top();
break;
case va_text_top:
@@ -555,10 +555,23 @@ bool litehtml::line_box::can_hold(const std::unique_ptr<line_box_item>& item, wh
if(item->get_type() == line_box_item::type_text_part)
{
+ // force new line on floats clearing
+ if (item->get_el()->src_el()->is_break() && item->get_el()->src_el()->css().get_clear() != clear_none)
+ {
+ return false;
+ }
+
auto last_el = get_last_text_part();
+ // the first word is always can be hold
+ if(!last_el)
+ {
+ return true;
+ }
+
// force new line if the last placed element was line break
- if (last_el && last_el->src_el()->is_break())
+ // Skip If there are the only break item - this is float clearing
+ if (last_el && last_el->src_el()->is_break() && m_items.size() > 1)
{
return false;
}
@@ -597,6 +610,12 @@ bool litehtml::line_box::have_last_space() const
bool litehtml::line_box::is_empty() const
{
if(m_items.empty()) return true;
+ if(m_items.size() == 1 &&
+ m_items.front()->get_el()->src_el()->is_break() &&
+ m_items.front()->get_el()->src_el()->css().get_clear() != clear_none)
+ {
+ return true;
+ }
for (const auto& el : m_items)
{
if(el->get_type() == line_box_item::type_text_part)
diff --git a/src/plugins/litehtml_viewer/litehtml/media_query.cpp b/src/plugins/litehtml_viewer/litehtml/media_query.cpp
index 7cddb15a2..8c2afff27 100644
--- a/src/plugins/litehtml_viewer/litehtml/media_query.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/media_query.cpp
@@ -88,8 +88,7 @@ litehtml::media_query::ptr litehtml::media_query::create_from_string(const strin
}
} else
{
- query->m_media_type = (media_type) value_index(token, media_type_strings, media_type_all);
-
+ query->m_media_type = (media_type) value_index(token, media_type_strings, media_type_none);
}
}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_block.cpp b/src/plugins/litehtml_viewer/litehtml/render_block.cpp
index d653f3114..c170c341f 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_block.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_block.cpp
@@ -208,24 +208,21 @@ int litehtml::render_item_block::_render(int x, int y, const containing_block_co
bool requires_rerender = false; // when true, the second pass for content rendering is required
// Set block width
- if(self_size.width.type == containing_block_context::cbc_value_type_absolute)
+ if(!(containing_block_size.size_mode & containing_block_context::size_mode_content))
{
- ret_width = m_pos.width = self_size.render_width;
- } else if(self_size.width.type == containing_block_context::cbc_value_type_percentage)
- {
- m_pos.width = self_size.render_width;
+ if(self_size.width.type == containing_block_context::cbc_value_type_absolute)
+ {
+ ret_width = m_pos.width = self_size.render_width;
+ } else
+ {
+ m_pos.width = self_size.render_width;
+ }
} else
{
- m_pos.width = self_size.render_width;
- }
-
- // Fix width with min-width attribute
- if(self_size.min_width.type != containing_block_context::cbc_value_type_none)
- {
- if(m_pos.width < self_size.min_width)
+ m_pos.width = ret_width;
+ if(self_size.width.type == containing_block_context::cbc_value_type_absolute && ret_width > self_size.width)
{
- m_pos.width = self_size.min_width;
- requires_rerender = true;
+ ret_width = self_size.width;
}
}
@@ -239,6 +236,19 @@ int litehtml::render_item_block::_render(int x, int y, const containing_block_co
}
}
+ // Fix width with min-width attribute
+ if(self_size.min_width.type != containing_block_context::cbc_value_type_none)
+ {
+ if(m_pos.width < self_size.min_width)
+ {
+ m_pos.width = self_size.min_width;
+ requires_rerender = true;
+ }
+ } else if(m_pos.width < 0)
+ {
+ m_pos.width = 0;
+ }
+
// re-render content with new width if required
if (requires_rerender && !second_pass && !is_root())
{
@@ -254,25 +264,44 @@ int litehtml::render_item_block::_render(int x, int y, const containing_block_co
}
// Set block height
- if (self_size.height.type != containing_block_context::cbc_value_type_auto)
+ if (self_size.height.type != containing_block_context::cbc_value_type_auto &&
+ !(containing_block_size.size_mode & containing_block_context::size_mode_content))
{
- if(self_size.height > 0)
+ // TODO: Something wrong here
+ // Percentage height from undefined containing block height is usually <= 0
+ if(self_size.height.type == containing_block_context::cbc_value_type_percentage)
+ {
+ if (self_size.height > 0)
+ {
+ m_pos.height = self_size.height;
+ }
+ } else
{
m_pos.height = self_size.height;
}
- if(src_el()->css().get_box_sizing() == box_sizing_border_box)
+ if (src_el()->css().get_box_sizing() == box_sizing_border_box)
{
m_pos.height -= box_sizing_height();
}
} else if (src_el()->is_block_formatting_context())
- {
+ {
// add the floats' height to the block height
- int floats_height = fmt_ctx->get_floats_height();
- if (floats_height > m_pos.height)
- {
- m_pos.height = floats_height;
- }
- }
+ int floats_height = fmt_ctx->get_floats_height();
+ if (floats_height > m_pos.height)
+ {
+ m_pos.height = floats_height;
+ }
+ }
+ if(containing_block_size.size_mode & containing_block_context::size_mode_content)
+ {
+ if(self_size.height.type == containing_block_context::cbc_value_type_absolute)
+ {
+ if(m_pos.height > self_size.height)
+ {
+ m_pos.height = self_size.height;
+ }
+ }
+ }
// Fix height with min-height attribute
if(self_size.min_height.type != containing_block_context::cbc_value_type_none)
@@ -281,6 +310,9 @@ int litehtml::render_item_block::_render(int x, int y, const containing_block_co
{
m_pos.height = self_size.min_height;
}
+ } else if(m_pos.height < 0)
+ {
+ m_pos.height = 0;
}
// Fix width with max-width attribute
diff --git a/src/plugins/litehtml_viewer/litehtml/render_block_context.cpp b/src/plugins/litehtml_viewer/litehtml/render_block_context.cpp
index 7591378c2..bf6b09277 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_block_context.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_block_context.cpp
@@ -47,20 +47,26 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco
// Collapse top margin
if(is_first && collapse_top_margin())
{
- child_top -= el->get_margins().top;
- if(el->get_margins().top > get_margins().top)
- {
- m_margins.top = el->get_margins().top;
- }
+ if(el->get_margins().top > 0)
+ {
+ child_top -= el->get_margins().top;
+ if (el->get_margins().top > get_margins().top)
+ {
+ m_margins.top = el->get_margins().top;
+ }
+ }
} else
{
- if(last_margin > el->get_margins().top)
- {
- child_top -= el->get_margins().top;
- } else
- {
- child_top -= last_margin;
- }
+ if(el->get_margins().top > 0)
+ {
+ if (last_margin > el->get_margins().top)
+ {
+ child_top -= el->get_margins().top;
+ } else
+ {
+ child_top -= last_margin;
+ }
+ }
}
if(el->src_el()->is_replaced() || el->src_el()->is_block_formatting_context() || el->src_el()->css().get_display() == display_table)
@@ -104,10 +110,9 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco
}
}
- int block_height = 0;
- if (get_predefined_height(block_height, self_size.height))
+ if (self_size.height.type != containing_block_context::cbc_value_type_auto && self_size.height > 0)
{
- m_pos.height = block_height;
+ m_pos.height = self_size.height;
} else
{
m_pos.height = child_top;
@@ -127,3 +132,23 @@ int litehtml::render_item_block_context::_render_content(int x, int y, bool seco
return ret_width;
}
+
+int litehtml::render_item_block_context::get_first_baseline()
+{
+ if(m_children.empty())
+ {
+ return height() - margin_bottom();
+ }
+ const auto &item = m_children.front();
+ return content_offset_top() + item->top() + item->get_first_baseline();
+}
+
+int litehtml::render_item_block_context::get_last_baseline()
+{
+ if(m_children.empty())
+ {
+ return height() - margin_bottom();
+ }
+ const auto &item = m_children.back();
+ return content_offset_top() + item->top() + item->get_last_baseline();
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_block_context.h b/src/plugins/litehtml_viewer/litehtml/render_block_context.h
index 3b5192261..c69389832 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_block_context.h
+++ b/src/plugins/litehtml_viewer/litehtml/render_block_context.h
@@ -23,6 +23,8 @@ namespace litehtml
{
return std::make_shared<render_item_block_context>(src_el());
}
+ int get_first_baseline() override;
+ int get_last_baseline() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_flex.cpp b/src/plugins/litehtml_viewer/litehtml/render_flex.cpp
index 2cab59e04..d0170e650 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_flex.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_flex.cpp
@@ -4,12 +4,327 @@
int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx)
{
- return 0;
+ bool is_row_direction = true;
+ bool reverse = false;
+ int container_main_size = self_size.render_width;
+
+ switch (css().get_flex_direction())
+ {
+ case flex_direction_column:
+ is_row_direction = false;
+ reverse = false;
+ break;
+ case flex_direction_column_reverse:
+ is_row_direction = false;
+ reverse = true;
+ break;
+ case flex_direction_row:
+ is_row_direction = true;
+ reverse = false;
+ break;
+ case flex_direction_row_reverse:
+ is_row_direction = true;
+ reverse = true;
+ break;
+ }
+
+ bool single_line = css().get_flex_wrap() == flex_wrap_nowrap;
+ bool fit_container = false;
+
+ if(!is_row_direction)
+ {
+ if(self_size.height.type != containing_block_context::cbc_value_type_auto)
+ {
+ container_main_size = self_size.height;
+ if (css().get_box_sizing() == box_sizing_border_box)
+ {
+ container_main_size -= box_sizing_height();
+ }
+ } else
+ {
+ // Direction columns, height is auto - always in single line
+ container_main_size = 0;
+ single_line = true;
+ fit_container = true;
+ }
+ if(self_size.min_height.type != containing_block_context::cbc_value_type_auto && self_size.min_height > container_main_size)
+ {
+ container_main_size = self_size.min_height;
+ }
+ if(self_size.max_height.type != containing_block_context::cbc_value_type_auto && self_size.max_height > container_main_size)
+ {
+ container_main_size = self_size.max_height;
+ single_line = false;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////////
+ /// Split flex items to lines
+ /////////////////////////////////////////////////////////////////
+ m_lines = get_lines(self_size, fmt_ctx, is_row_direction, container_main_size, single_line);
+
+ int el_y = 0;
+ int el_x = 0;
+ int sum_cross_size = 0;
+ int sum_main_size = 0;
+ int ret_width = 0;
+
+ /////////////////////////////////////////////////////////////////
+ /// Resolving Flexible Lengths
+ /// REF: https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths
+ /////////////////////////////////////////////////////////////////
+ for(auto& ln : m_lines)
+ {
+ if(is_row_direction)
+ {
+ ret_width += ln.base_size;
+ }
+ ln.init(container_main_size, fit_container, is_row_direction, self_size, fmt_ctx);
+ sum_cross_size += ln.cross_size;
+ sum_main_size = std::max(sum_main_size, ln.main_size);
+ if(reverse)
+ {
+ ln.items.reverse();
+ }
+ }
+
+ int free_cross_size = 0;
+ int cross_start = 0;
+ bool is_wrap_reverse = css().get_flex_wrap() == flex_wrap_wrap_reverse;
+ if(container_main_size == 0)
+ {
+ container_main_size = sum_main_size;
+ }
+
+ /////////////////////////////////////////////////////////////////
+ /// Calculate free cross size
+ /////////////////////////////////////////////////////////////////
+ if (is_row_direction)
+ {
+ cross_start = content_offset_top();
+ if (self_size.height.type != containing_block_context::cbc_value_type_auto)
+ {
+ int height = self_size.height;
+ if (src_el()->css().get_box_sizing() == box_sizing_border_box)
+ {
+ height -= box_sizing_height();
+ }
+ free_cross_size = height - sum_cross_size;
+ }
+ } else
+ {
+ cross_start = content_offset_left();
+ free_cross_size = self_size.render_width - sum_cross_size;
+ ret_width = sum_cross_size;
+ }
+
+ /////////////////////////////////////////////////////////////////
+ /// Fix align-content property
+ /////////////////////////////////////////////////////////////////
+ flex_align_content align_content = css().get_flex_align_content();
+ if(align_content == flex_align_content_space_between)
+ {
+ // If the leftover free-space is negative or there is only a single flex line in the flex
+ // container, this value is identical to flex-start.
+ if (m_lines.size() == 1 || free_cross_size < 0) align_content = flex_align_content_flex_start;
+ }
+ if(align_content == flex_align_content_space_around)
+ {
+ // If the leftover free-space is negative or there is only a single flex line in the flex
+ // container, this value is identical to flex-start.
+ if (m_lines.size() == 1 || free_cross_size < 0) align_content = flex_align_content_center;
+ }
+
+ /////////////////////////////////////////////////////////////////
+ /// Distribute free cross size for align-content: stretch
+ /////////////////////////////////////////////////////////////////
+ if(css().get_flex_align_content() == flex_align_content_stretch && free_cross_size > 0)
+ {
+ int add = (int)((double) free_cross_size / (double) m_lines.size());
+ if(add > 0)
+ {
+ for (auto &ln: m_lines)
+ {
+ ln.cross_size += add;
+ free_cross_size -= add;
+ }
+ }
+ if(!m_lines.empty())
+ {
+ while (free_cross_size > 0)
+ {
+ for (auto &ln: m_lines)
+ {
+ ln.cross_size++;
+ free_cross_size--;
+ }
+ }
+ }
+ }
+
+ /// Reverse lines for flex-wrap: wrap-reverse
+ if(css().get_flex_wrap() == flex_wrap_wrap_reverse)
+ {
+ m_lines.reverse();
+ }
+
+ /////////////////////////////////////////////////////////////////
+ /// Align flex lines
+ /////////////////////////////////////////////////////////////////
+ int line_pos = 0;
+ int add_before_line = 0;
+ int add_after_line = 0;
+ switch (align_content)
+ {
+ case flex_align_content_flex_start:
+ if(is_wrap_reverse)
+ {
+ line_pos = free_cross_size;
+ }
+ break;
+ case flex_align_content_flex_end:
+ if(!is_wrap_reverse)
+ {
+ line_pos = free_cross_size;
+ }
+ break;
+ case flex_align_content_end:
+ line_pos = free_cross_size;
+ break;
+ case flex_align_content_center:
+ line_pos = free_cross_size / 2;
+ break;
+ case flex_align_content_space_between:
+ add_after_line = free_cross_size / ((int) m_lines.size() - 1);
+ break;
+ case flex_align_content_space_around:
+ add_before_line = add_after_line = free_cross_size / ((int) m_lines.size() * 2);
+ break;
+ default:
+ if(is_wrap_reverse)
+ {
+ line_pos = free_cross_size;
+ }
+ break;
+ }
+ for(auto &ln : m_lines)
+ {
+ line_pos += add_before_line;
+ ln.cross_start = line_pos;
+ line_pos += ln.cross_size + add_after_line;
+ }
+
+ /// Fix justify-content property
+ flex_justify_content justify_content = css().get_flex_justify_content();
+ if((justify_content == flex_justify_content_right || justify_content == flex_justify_content_left) && !is_row_direction)
+ {
+ justify_content = flex_justify_content_start;
+ }
+
+ /////////////////////////////////////////////////////////////////
+ /// Align flex items in flex lines
+ /////////////////////////////////////////////////////////////////
+ int line_num = 0;
+ for(auto &ln : m_lines)
+ {
+ int height = ln.calculate_items_position(container_main_size,
+ justify_content,
+ is_row_direction,
+ self_size,
+ fmt_ctx);
+ line_num++;
+ m_pos.height = std::max(m_pos.height, height);
+ }
+
+ // calculate the final position
+ m_pos.move_to(x, y);
+ m_pos.x += content_offset_left();
+ m_pos.y += content_offset_top();
+
+ return ret_width;
}
-void litehtml::render_item_flex::draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex)
+std::list<litehtml::flex_line> litehtml::render_item_flex::get_lines(const litehtml::containing_block_context &self_size,
+ litehtml::formatting_context *fmt_ctx,
+ bool is_row_direction, int container_main_size,
+ bool single_line)
{
+ bool reverse_main;
+ bool reverse_cross = css().get_flex_wrap() == flex_wrap_wrap_reverse;
+
+ if(is_row_direction)
+ {
+ reverse_main = css().get_flex_direction() == flex_direction_row_reverse;
+ } else
+ {
+ reverse_main = css().get_flex_direction() == flex_direction_column_reverse;
+ }
+
+ std::list<flex_line> lines;
+ flex_line line(reverse_main, reverse_cross);
+ std::list<std::shared_ptr<flex_item>> items;
+ int src_order = 0;
+ bool sort_required = false;
+ def_value<int> prev_order(0);
+
+ for( auto& el : m_children)
+ {
+ std::shared_ptr<flex_item> item = nullptr;
+ if(is_row_direction)
+ {
+ item = std::make_shared<flex_item_row_direction>(el);
+ } else
+ {
+ item = std::make_shared<flex_item_column_direction>(el);
+ }
+ item->init(self_size, fmt_ctx, css().get_flex_align_items());
+ item->src_order = src_order++;
+ if(prev_order.is_default())
+ {
+ prev_order = item->order;
+ } else if(!sort_required && item->order != prev_order)
+ {
+ sort_required = true;
+ }
+
+ items.emplace_back(item);
+ }
+
+ if(sort_required)
+ {
+ items.sort([](const std::shared_ptr<flex_item>& item1, const std::shared_ptr<flex_item>& item2)
+ {
+ if(item1->order < item2->order) return true;
+ if(item1->order == item2->order)
+ {
+ return item1->src_order < item2->src_order;
+ }
+ return false;
+ });
+ }
+
+ // Add flex items to lines
+ for(auto& item : items)
+ {
+ if(!line.items.empty() && !single_line && line.base_size + item->base_size > container_main_size)
+ {
+ lines.emplace_back(line);
+ line = flex_line(reverse_main, reverse_cross);
+ }
+ line.base_size += item->base_size;
+ line.total_grow += item->grow;
+ line.total_shrink += item->shrink;
+ if(!item->auto_margin_main_start.is_default()) line.num_auto_margin_main_start++;
+ if(!item->auto_margin_main_end.is_default()) line.num_auto_margin_main_end++;
+ line.items.push_back(item);
+ }
+ // Add the last line to the lines list
+ if(!line.items.empty())
+ {
+ lines.emplace_back(line);
+ }
+ return lines;
}
std::shared_ptr<litehtml::render_item> litehtml::render_item_flex::init()
@@ -81,10 +396,60 @@ std::shared_ptr<litehtml::render_item> litehtml::render_item_flex::init()
}
convert_inlines();
children() = new_children;
- for(const auto& el : children())
- {
- m_flex_items.emplace_back(new flex_item(el));
- }
return shared_from_this();
}
+
+int litehtml::render_item_flex::get_first_baseline()
+{
+ if(css().get_flex_direction() == flex_direction_row || css().get_flex_direction() == flex_direction_row_reverse)
+ {
+ if(!m_lines.empty())
+ {
+ const auto &first_line = m_lines.front();
+ if(first_line.first_baseline.type() != baseline::baseline_type_none)
+ {
+ return first_line.cross_start + first_line.first_baseline.get_offset_from_top(first_line.cross_size) + content_offset_top();
+ }
+ if(first_line.last_baseline.type() != baseline::baseline_type_none)
+ {
+ return first_line.cross_start + first_line.last_baseline.get_offset_from_top(first_line.cross_size) + content_offset_top();
+ }
+ }
+ }
+ if(!m_lines.empty())
+ {
+ if(!m_lines.front().items.empty())
+ {
+ return m_lines.front().items.front()->el->get_first_baseline() + content_offset_top();
+ }
+ }
+ return height();
+}
+
+int litehtml::render_item_flex::get_last_baseline()
+{
+ if(css().get_flex_direction() == flex_direction_row || css().get_flex_direction() == flex_direction_row_reverse)
+ {
+ if(!m_lines.empty())
+ {
+ const auto &first_line = m_lines.front();
+ if(first_line.last_baseline.type() != baseline::baseline_type_none)
+ {
+ return first_line.cross_start + first_line.last_baseline.get_offset_from_top(first_line.cross_size) + content_offset_top();
+ }
+ if(first_line.first_baseline.type() != baseline::baseline_type_none)
+ {
+ return first_line.cross_start + first_line.first_baseline.get_offset_from_top(first_line.cross_size) + content_offset_top();
+ }
+ }
+ }
+ if(!m_lines.empty())
+ {
+ if(!m_lines.front().items.empty())
+ {
+ return m_lines.front().items.front()->el->get_last_baseline() + content_offset_top();
+ }
+ }
+ return height();
+}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_flex.h b/src/plugins/litehtml_viewer/litehtml/render_flex.h
index 5d31bc9bf..6a03b98ec 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_flex.h
+++ b/src/plugins/litehtml_viewer/litehtml/render_flex.h
@@ -2,32 +2,17 @@
#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
{
- struct flex_item
- {
- std::shared_ptr<render_item> el;
- int base_size;
- int main_size;
- int min_width;
- int max_width;
- int line;
-
- explicit flex_item(std::shared_ptr<render_item> _el) :
- el(std::move(_el)),
- min_width(0),
- max_width(0),
- line(0),
- base_size(0),
- main_size(0)
- {}
- };
- protected:
- std::list<std::unique_ptr<flex_item>> m_flex_items;
+ 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:
@@ -38,8 +23,10 @@ namespace litehtml
{
return std::make_shared<render_item_flex>(src_el());
}
- void draw_children(uint_ptr hdc, int x, int y, const position* clip, draw_flag flag, int zindex) override;
std::shared_ptr<render_item> init() override;
+
+ int get_first_baseline() override;
+ int get_last_baseline() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_image.cpp b/src/plugins/litehtml_viewer/litehtml/render_image.cpp
index 63e622d7b..1ff4574bb 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_image.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_image.cpp
@@ -5,6 +5,7 @@
int litehtml::render_item_image::_render(int x, int y, const containing_block_context &containing_block_size, formatting_context* fmt_ctx, bool second_pass)
{
int parent_width = containing_block_size.width;
+ containing_block_context self_size = calculate_containing_block_context(containing_block_size);
calc_outlines(parent_width);
@@ -60,10 +61,10 @@ int litehtml::render_item_image::_render(int x, int y, const containing_block_co
}
} else if(!src_el()->css().get_height().is_predefined() && src_el()->css().get_width().is_predefined())
{
- if (!get_predefined_height(m_pos.height, containing_block_size.height))
- {
- m_pos.height = (int)src_el()->css().get_height().val();
- }
+ if(self_size.height.type != containing_block_context::cbc_value_type_auto && self_size.height > 0)
+ {
+ m_pos.height = self_size.height;
+ }
// check for max-height
if(!src_el()->css().get_max_height().is_predefined())
@@ -107,10 +108,10 @@ int litehtml::render_item_image::_render(int x, int y, const containing_block_co
{
m_pos.width = (int) src_el()->css().get_width().calc_percent(parent_width);
m_pos.height = 0;
- if (!get_predefined_height(m_pos.height, containing_block_size.height))
- {
- m_pos.height = (int)src_el()->css().get_height().val();
- }
+ if(self_size.height.type != containing_block_context::cbc_value_type_auto && self_size.height > 0)
+ {
+ m_pos.height = self_size.height;
+ }
// check for max-height
if(!src_el()->css().get_max_height().is_predefined())
diff --git a/src/plugins/litehtml_viewer/litehtml/render_inline.cpp b/src/plugins/litehtml_viewer/litehtml/render_inline.cpp
deleted file mode 100644
index 0ea24b17d..000000000
--- a/src/plugins/litehtml_viewer/litehtml/render_inline.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "html.h"
-#include "render_item.h"
-
diff --git a/src/plugins/litehtml_viewer/litehtml/render_inline.h b/src/plugins/litehtml_viewer/litehtml/render_inline.h
index 476011563..666074b90 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_inline.h
+++ b/src/plugins/litehtml_viewer/litehtml/render_inline.h
@@ -18,7 +18,14 @@ namespace litehtml
void set_inline_boxes( position::vector& boxes ) override { m_boxes = boxes; }
void add_inline_box( const position& box ) override { m_boxes.emplace_back(box); };
void clear_inline_boxes() override { m_boxes.clear(); }
- int get_base_line() override { return src_el()->css().get_font_metrics().base_line(); }
+ 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
{
@@ -28,3 +35,4 @@ namespace litehtml
}
#endif //LITEHTML_RENDER_INLINE_H
+
diff --git a/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp b/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp
index 2d8f2e173..4f5d77015 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_inline_context.cpp
@@ -382,21 +382,30 @@ void litehtml::render_item_inline_context::apply_vertical_align()
}
}
-int litehtml::render_item_inline_context::get_base_line()
+int litehtml::render_item_inline_context::get_first_baseline()
{
- auto el_parent = parent();
- if(el_parent && src_el()->css().get_display() == display_inline_flex)
- {
- return el_parent->get_base_line();
- }
- if(src_el()->is_replaced())
- {
- return 0;
- }
- int bl = 0;
- if(!m_line_boxes.empty())
- {
- bl = m_line_boxes.back()->baseline() + content_offset_bottom();
- }
- return bl;
+ int bl;
+ if(!m_line_boxes.empty())
+ {
+ const auto &line = m_line_boxes.front();
+ bl = line->bottom() - line->baseline() + content_offset_top();
+ } else
+ {
+ bl = height() - margin_bottom();
+ }
+ return bl;
+}
+
+int litehtml::render_item_inline_context::get_last_baseline()
+{
+ int bl;
+ if(!m_line_boxes.empty())
+ {
+ const auto &line = m_line_boxes.back();
+ bl = line->bottom() - line->baseline() + content_offset_top();
+ } else
+ {
+ bl = height() - margin_bottom();
+ }
+ return bl;
}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_inline_context.h b/src/plugins/litehtml_viewer/litehtml/render_inline_context.h
index 894cfe989..7d629bc7f 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_inline_context.h
+++ b/src/plugins/litehtml_viewer/litehtml/render_inline_context.h
@@ -48,7 +48,8 @@ namespace litehtml
return std::make_shared<render_item_inline_context>(src_el());
}
- int get_base_line() override;
+ int get_first_baseline() override;
+ int get_last_baseline() override;
};
}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_item.cpp b/src/plugins/litehtml_viewer/litehtml/render_item.cpp
index 4eb25757d..0af172807 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_item.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_item.cpp
@@ -138,37 +138,6 @@ void litehtml::render_item::apply_relative_shift(const containing_block_context
}
}
-bool litehtml::render_item::get_predefined_height(int& p_height, int containing_block_height) const
-{
- css_length h = src_el()->css().get_height();
- if(h.is_predefined())
- {
- p_height = m_pos.height;
- return false;
- }
- if(h.units() == css_units_percentage)
- {
- p_height = h.calc_percent(containing_block_height);
- return containing_block_height > 0;
- }
- p_height = src_el()->get_document()->to_pixels(h, src_el()->css().get_font_size());
- return p_height > 0;
-}
-
-int litehtml::render_item::calc_width(int defVal, int containing_block_width) const
-{
- css_length w = src_el()->css().get_width();
- if(w.is_predefined() || src_el()->css().get_display() == display_table_cell)
- {
- return defVal;
- }
- if(w.units() == css_units_percentage)
- {
- return w.calc_percent(containing_block_width);
- }
- return src_el()->get_document()->to_pixels(w, src_el()->css().get_font_size());
-}
-
std::tuple<
std::shared_ptr<litehtml::render_item>,
std::shared_ptr<litehtml::render_item>,
@@ -679,7 +648,7 @@ void litehtml::render_item::draw_children(uint_ptr hdc, int x, int y, const posi
if (el->src_el()->is_inline() && el->src_el()->css().get_float() == float_none && !el->src_el()->is_positioned())
{
el->src_el()->draw(hdc, pos.x, pos.y, clip, el);
- if (el->src_el()->css().get_display() == display_inline_block)
+ if (el->src_el()->css().get_display() == display_inline_block || el->src_el()->css().get_display() == display_inline_flex)
{
el->draw_stacking_context(hdc, pos.x, pos.y, clip, false);
process = false;
@@ -816,7 +785,7 @@ std::shared_ptr<litehtml::element> litehtml::render_item::get_child_by_point(in
} else
{
if( el->src_el()->css().get_float() == float_none &&
- el->src_el()->css().get_display() != display_inline_block)
+ el->src_el()->css().get_display() != display_inline_block && el->src_el()->css().get_display() != display_inline_flex)
{
element::ptr child = el->get_child_by_point(el_pos.x, el_pos.y, client_x, client_y, flag, zindex);
if(child)
@@ -845,25 +814,23 @@ std::shared_ptr<litehtml::element> litehtml::render_item::get_element_by_point(i
z_indexes[i->src_el()->css().get_z_index()];
}
- for(const auto& zindex : z_indexes)
+ for(auto iter = z_indexes.rbegin(); iter != z_indexes.rend(); iter++)
{
- if(zindex.first > 0)
+ if(iter->first > 0)
{
- ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, zindex.first);
- break;
+ ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, iter->first);
+ if(ret) return ret;
}
}
- if(ret) return ret;
for(const auto& z_index : z_indexes)
{
if(z_index.first == 0)
{
ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, z_index.first);
- break;
+ if(ret) return ret;
}
}
- if(ret) return ret;
ret = get_child_by_point(x, y, client_x, client_y, draw_inlines, 0);
if(ret) return ret;
@@ -875,15 +842,14 @@ std::shared_ptr<litehtml::element> litehtml::render_item::get_element_by_point(i
if(ret) return ret;
- for(const auto& z_index : z_indexes)
- {
- if(z_index.first < 0)
+ for(auto iter = z_indexes.rbegin(); iter != z_indexes.rend(); iter++)
+ {
+ if(iter->first < 0)
{
- ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, z_index.first);
- break;
+ ret = get_child_by_point(x, y, client_x, client_y, draw_positioned, iter->first);
+ if(ret) return ret;
}
}
- if(ret) return ret;
if(src_el()->css().get_position() == element_position_fixed)
{
@@ -1042,8 +1008,55 @@ litehtml::containing_block_context litehtml::render_item::calculate_containing_b
// We have to use aut value for display_table_cell also.
if (src_el()->css().get_display() != display_table_cell)
{
- calc_cb_length(src_el()->css().get_width(), cb_context.width, ret.width);
- calc_cb_length(src_el()->css().get_height(), cb_context.height, ret.height);
+ auto par = parent();
+ if(cb_context.size_mode & containing_block_context::size_mode_exact_width)
+ {
+ ret.width.value = cb_context.width;
+ ret.width.type = containing_block_context::cbc_value_type_absolute;
+ } else
+ {
+ auto *width = &css().get_width();
+ if(par && (par->css().get_display() == display_flex || par->css().get_display() == display_inline_flex))
+ {
+ if(!css().get_flex_basis().is_predefined() && css().get_flex_basis().val() >= 0)
+ {
+ if(par->css().get_flex_direction() == flex_direction_row || par->css().get_flex_direction() == flex_direction_row_reverse)
+ {
+ ret.width.type = containing_block_context::cbc_value_type_auto;
+ ret.width.value = 0;
+ width = nullptr;
+ }
+ }
+ }
+ if(width)
+ {
+ calc_cb_length(*width, cb_context.width, ret.width);
+ }
+ }
+ if(cb_context.size_mode & containing_block_context::size_mode_exact_height)
+ {
+ ret.height.value = cb_context.height;
+ ret.height.type = containing_block_context::cbc_value_type_absolute;
+ } else
+ {
+ auto *height = &css().get_height();
+ if(par && (par->css().get_display() == display_flex || par->css().get_display() == display_inline_flex))
+ {
+ if(!css().get_flex_basis().is_predefined() && css().get_flex_basis().val() >= 0)
+ {
+ if(par->css().get_flex_direction() == flex_direction_column || par->css().get_flex_direction() == flex_direction_column_reverse)
+ {
+ ret.height.type = containing_block_context::cbc_value_type_auto;
+ ret.height.value = 0;
+ height = nullptr;
+ }
+ }
+ }
+ if(height)
+ {
+ calc_cb_length(*height, cb_context.height, ret.height);
+ }
+ }
if (ret.width.type != containing_block_context::cbc_value_type_auto && (src_el()->css().get_display() == display_table || src_el()->is_root()))
{
ret.width.value -= content_offset_width();
@@ -1061,28 +1074,27 @@ litehtml::containing_block_context litehtml::render_item::calculate_containing_b
calc_cb_length(src_el()->css().get_min_height(), cb_context.height, ret.min_height);
calc_cb_length(src_el()->css().get_max_height(), cb_context.height, ret.max_height);
- if (src_el()->css().get_box_sizing() == box_sizing_border_box)
+ // Fix box sizing
+ if(ret.width.type != containing_block_context::cbc_value_type_auto)
{
- if(ret.width.type != containing_block_context::cbc_value_type_auto)
- {
- ret.render_width = ret.width - box_sizing_width();
- }
- if(ret.min_width.type != containing_block_context::cbc_value_type_none)
- {
- ret.min_width.value -= box_sizing_width();
- }
- if(ret.max_width.type != containing_block_context::cbc_value_type_none)
- {
- ret.max_width.value -= box_sizing_width();
- }
- if(ret.min_height.type != containing_block_context::cbc_value_type_none)
- {
- ret.min_height.value -= box_sizing_height();
- }
- if(ret.max_height.type != containing_block_context::cbc_value_type_none)
- {
- ret.max_height.value -= box_sizing_height();
- }
+ ret.render_width = ret.width - box_sizing_width();
+ }
+ if(ret.min_width.type != containing_block_context::cbc_value_type_none)
+ {
+ ret.min_width.value -= box_sizing_width();
}
+ if(ret.max_width.type != containing_block_context::cbc_value_type_none)
+ {
+ ret.max_width.value -= box_sizing_width();
+ }
+ if(ret.min_height.type != containing_block_context::cbc_value_type_none)
+ {
+ ret.min_height.value -= box_sizing_height();
+ }
+ if(ret.max_height.type != containing_block_context::cbc_value_type_none)
+ {
+ ret.max_height.value -= box_sizing_height();
+ }
+
return ret;
}
diff --git a/src/plugins/litehtml_viewer/litehtml/render_item.h b/src/plugins/litehtml_viewer/litehtml/render_item.h
index 9d4561e5a..ac8a9f4c6 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_item.h
+++ b/src/plugins/litehtml_viewer/litehtml/render_item.h
@@ -86,7 +86,7 @@ namespace litehtml
int width() const
{
- return m_pos.width + m_margins.left + m_margins.right + m_padding.width() + m_borders.width();
+ return m_pos.width + m_margins.width() + m_padding.width() + m_borders.width();
}
int padding_top() const
@@ -224,27 +224,43 @@ namespace litehtml
int box_sizing_left() const
{
- return m_padding.left + m_borders.left;
+ if(css().get_box_sizing() == box_sizing_border_box)
+ {
+ return m_padding.left + m_borders.left;
+ }
+ return 0;
}
int box_sizing_right() const
{
- return m_padding.right + m_borders.right;
+ 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_left();
+ return box_sizing_left() + box_sizing_right();
}
int box_sizing_top() const
{
- return m_padding.top + m_borders.top;
+ if(css().get_box_sizing() == box_sizing_border_box)
+ {
+ return m_padding.top + m_borders.top;
+ }
+ return 0;
}
int box_sizing_bottom() const
{
- return m_padding.bottom + m_borders.bottom;
+ if(css().get_box_sizing() == box_sizing_border_box)
+ {
+ return m_padding.bottom + m_borders.bottom;
+ }
+ return 0;
}
int box_sizing_height() const
@@ -285,6 +301,7 @@ namespace litehtml
m_element->in_normal_flow() &&
m_element->css().get_float() == float_none &&
m_margins.top >= 0 &&
+ !is_flex_item() &&
!is_root();
}
@@ -303,16 +320,34 @@ namespace litehtml
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);
- int calc_width(int defVal, int containing_block_width) const;
- bool get_predefined_height(int& p_height, int containing_block_height) const;
void apply_relative_shift(const containing_block_context &containing_block_size);
void calc_outlines( int parent_width );
int calc_auto_margins(int parent_width); // returns left margin
virtual std::shared_ptr<render_item> init();
virtual void apply_vertical_align() {}
- virtual int get_base_line() { return 0; }
+ /**
+ * 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());
diff --git a/src/plugins/litehtml_viewer/litehtml/render_table.cpp b/src/plugins/litehtml_viewer/litehtml/render_table.cpp
index 1a3859641..fdff1f826 100644
--- a/src/plugins/litehtml_viewer/litehtml/render_table.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/render_table.cpp
@@ -261,10 +261,10 @@ int litehtml::render_item_table::_render(int x, int y, const containing_block_co
// calculate block height
int block_height = 0;
- if (get_predefined_height(block_height, containing_block_size.height))
- {
- block_height -= m_padding.height() + m_borders.height();
- }
+ if(self_size.height.type != containing_block_context::cbc_value_type_auto && self_size.height > 0)
+ {
+ block_height = self_size.height - (m_padding.height() + m_borders.height());
+ }
// calculate minimum height from m_css.get_min_height()
int min_height = 0;
diff --git a/src/plugins/litehtml_viewer/litehtml/string_id.h b/src/plugins/litehtml_viewer/litehtml/string_id.h
index 60d30f5e4..2c90fc659 100644
--- a/src/plugins/litehtml_viewer/litehtml/string_id.h
+++ b/src/plugins/litehtml_viewer/litehtml/string_id.h
@@ -289,6 +289,10 @@ STRING_ID(
_flex_basis_,
_caption_side_,
+ _order_,
+
+ _counter_reset_,
+ _counter_increment_,
);
#undef STRING_ID
extern const string_id empty_id; // _id("")
diff --git a/src/plugins/litehtml_viewer/litehtml/style.cpp b/src/plugins/litehtml_viewer/litehtml/style.cpp
index 5642d36c4..356f49afc 100644
--- a/src/plugins/litehtml_viewer/litehtml/style.cpp
+++ b/src/plugins/litehtml_viewer/litehtml/style.cpp
@@ -43,7 +43,7 @@ std::map<string_id, string> style::m_valid_values =
{ _justify_content_, flex_justify_content_strings },
{ _align_items_, flex_align_items_strings },
{ _align_content_, flex_align_content_strings },
- { _align_self_, flex_align_self_strings },
+ { _align_self_, flex_align_items_strings },
{ _caption_side_, caption_side_strings },
};
@@ -128,9 +128,7 @@ void style::add_property(string_id name, const string& val, const string& baseur
case _flex_direction_:
case _flex_wrap_:
case _justify_content_:
- case _align_items_:
case _align_content_:
- case _align_self_:
case _caption_side_:
@@ -141,6 +139,11 @@ void style::add_property(string_id name, const string& val, const string& baseur
}
break;
+ case _align_items_:
+ case _align_self_:
+ parse_align_self(name, val, important);
+ break;
+
// <length>
case _text_indent_:
case _padding_left_:
@@ -536,6 +539,25 @@ void style::add_property(string_id name, const string& val, const string& baseur
add_parsed_property(_flex_basis_, property_value(length, important));
break;
+ case _order_: // <integer>
+ {
+ char* end;
+ int int_val = (int) strtol(val.c_str(), &end, 10);
+ if(end[0] == '\0')
+ {
+ add_parsed_property(name, property_value(int_val, important));
+ }
+ }
+ break;
+ case _counter_increment_:
+ case _counter_reset_:
+ {
+ string_vector tokens;
+ split_string(val, tokens, " ");
+ add_parsed_property(name, property_value(tokens, important));
+ break;
+ }
+
default:
add_parsed_property(name, property_value(val, important));
}
@@ -972,14 +994,16 @@ void style::parse_font(const string& val, bool important)
{
string_vector szlh;
split_string(token, szlh, "/");
-
- auto size = css_length::from_string(szlh[0], font_size_strings, -1);
- add_parsed_property(_font_size_, property_value(size, important));
-
- if(szlh.size() == 2)
+ if(!szlh.empty())
{
- auto height = css_length::from_string(szlh[1], "normal", -1);
- add_parsed_property(_line_height_, property_value(height, important));
+ auto size = css_length::from_string(szlh[0], font_size_strings, -1);
+ add_parsed_property(_font_size_, property_value(size, important));
+
+ if (szlh.size() == 2)
+ {
+ auto height = css_length::from_string(szlh[1], "normal", -1);
+ add_parsed_property(_line_height_, property_value(height, important));
+ }
}
} else
{
@@ -992,18 +1016,6 @@ void style::parse_font(const string& val, bool important)
void style::parse_flex(const string& val, bool important)
{
- auto is_number = [](const string& val)
- {
- for (auto ch : val)
- {
- if ((ch < '0' || ch > '9') && ch != '.')
- {
- return false;
- }
- }
- return true;
- };
-
css_length _auto = css_length::predef_value(flex_basis_auto);
if (val == "initial")
@@ -1036,6 +1048,10 @@ void style::parse_flex(const string& val, bool important)
float grow = t_strtof(tokens[0]);
float shrink = t_strtof(tokens[1]);
auto basis = css_length::from_string(tokens[2], flex_basis_strings, -1);
+ if(!basis.is_predefined() && basis.units() == css_units_none && basis.val() == 0)
+ {
+ basis.set_value(basis.val(), css_units_px);
+ }
add_parsed_property(_flex_grow_, property_value(grow, important));
add_parsed_property(_flex_shrink_, property_value(shrink, important));
@@ -1046,10 +1062,11 @@ void style::parse_flex(const string& val, bool important)
float grow = t_strtof(tokens[0]);
add_parsed_property(_flex_grow_, property_value(grow, important));
- if (is_number(tokens[1]))
+ if (litehtml::is_number(tokens[1]))
{
float shrink = t_strtof(tokens[1]);
add_parsed_property(_flex_shrink_, property_value(shrink, important));
+ add_parsed_property(_flex_basis_, property_value(css_length(0), important));
}
else
{
@@ -1063,22 +1080,65 @@ void style::parse_flex(const string& val, bool important)
{
float grow = t_strtof(tokens[0]);
add_parsed_property(_flex_grow_, property_value(grow, important));
-
- if (grow >= 1)
- {
- add_parsed_property(_flex_shrink_, property_value(1.f, important));
- add_parsed_property(_flex_basis_, property_value(css_length(0), important));
- }
+ add_parsed_property(_flex_shrink_, property_value(1.f, important));
+ add_parsed_property(_flex_basis_, property_value(css_length(0), important));
}
else
{
auto basis = css_length::from_string(tokens[0], flex_basis_strings, -1);
+ add_parsed_property(_flex_grow_, property_value(1.f, important));
+ add_parsed_property(_flex_shrink_, property_value(1.f, important));
add_parsed_property(_flex_basis_, property_value(basis, important));
}
}
}
}
+void style::parse_align_self(string_id name, const string& val, bool important)
+{
+ string_vector tokens;
+ split_string(val, tokens, " ");
+ if(tokens.size() == 1)
+ {
+ int idx = value_index(val, m_valid_values[name]);
+ if (idx >= 0)
+ {
+ add_parsed_property(name, property_value(idx, important));
+ }
+ } else
+ {
+ int val1 = 0;
+ int val2 = -1;
+ for(auto &token : tokens)
+ {
+ if(token == "first")
+ {
+ val1 |= flex_align_items_first;
+ } else if(token == "last")
+ {
+ val1 |= flex_align_items_last;
+ } else if(token == "safe")
+ {
+ val1 |= flex_align_items_safe;
+ } else if(token == "unsafe")
+ {
+ val1 |= flex_align_items_unsafe;
+ } else
+ {
+ int idx = value_index(token, m_valid_values[name]);
+ if(idx >= 0)
+ {
+ val2 = idx;
+ }
+ }
+ }
+ if(val2 >= 0)
+ {
+ add_parsed_property(name, property_value(val1 | val2, important));
+ }
+ }
+}
+
void style::add_parsed_property( string_id name, const property_value& propval )
{
auto prop = m_properties.find(name);
diff --git a/src/plugins/litehtml_viewer/litehtml/style.h b/src/plugins/litehtml_viewer/litehtml/style.h
index c83876ad6..2e04059f2 100644
--- a/src/plugins/litehtml_viewer/litehtml/style.h
+++ b/src/plugins/litehtml_viewer/litehtml/style.h
@@ -199,6 +199,7 @@ namespace litehtml
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]);
diff --git a/src/plugins/litehtml_viewer/litehtml/types.h b/src/plugins/litehtml_viewer/litehtml/types.h
index b1feeeea6..bfcaa6c3a 100644
--- a/src/plugins/litehtml_viewer/litehtml/types.h
+++ b/src/plugins/litehtml_viewer/litehtml/types.h
@@ -195,6 +195,14 @@ namespace litehtml
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;
@@ -235,6 +243,7 @@ namespace litehtml
typed_int max_height;
int context_idx;
+ uint32_t size_mode;
containing_block_context() :
width(0, cbc_value_type_auto),
@@ -244,17 +253,26 @@ namespace litehtml
height(0, cbc_value_type_auto),
min_height(0, cbc_value_type_none),
max_height(0, cbc_value_type_none),
- context_idx(0)
+ context_idx(0),
+ size_mode(size_mode_normal)
{}
- containing_block_context new_width(int w) const
+ containing_block_context new_width(int w, uint32_t _size_mode = size_mode_normal) const
{
containing_block_context ret = *this;
- //if(ret.width.type != cbc_value_type_absolute)
- {
- ret.render_width = w - (ret.width - ret.render_width);
- ret.width = w;
- }
+ 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;
}
};
@@ -693,7 +711,7 @@ namespace litehtml
m_is_default = true;
m_val = def_val;
}
- bool is_default()
+ bool is_default() const
{
return m_is_default;
}
@@ -703,12 +721,72 @@ namespace litehtml
m_is_default = false;
return m_val;
}
- operator T()
+ 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"
@@ -848,46 +926,51 @@ namespace litehtml
flex_wrap_wrap_reverse
};
-#define flex_justify_content_strings "flex-start;flex-end;center;space-between;space-around"
+#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_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 "flex-start;flex-end;center;baseline;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
- };
-
-#define flex_align_self_strings "auto;flex-start;flex-end;center;baseline;stretch"
-
- enum flex_align_self
- {
- flex_align_self_auto,
- flex_align_self_flex_start,
- flex_align_self_flex_end,
- flex_align_self_center,
- flex_align_self_baseline,
- flex_align_self_stretch
+ 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;flex-end;center;space-between;space-around;stretch"
+#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,
-----------------------------------------------------------------------
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list