aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuri Kobets <yuri.kobets@gmail.com>2023-12-23 02:32:23 +0300
committerYuri Kobets <yuri.kobets@gmail.com>2023-12-23 02:32:23 +0300
commit5eaf3afbd36af82bdd5d8b2c03a749cd8892816c (patch)
treee3c696b890049db72955284accd232289a10d290
parent4b633c6487ffea61fe34b78325dd436b67f9717f (diff)
flex: added support for the justify-content property
-rw-r--r--src/render_flex.cpp121
1 files changed, 119 insertions, 2 deletions
diff --git a/src/render_flex.cpp b/src/render_flex.cpp
index f3354e39..f2da0b8a 100644
--- a/src/render_flex.cpp
+++ b/src/render_flex.cpp
@@ -2,6 +2,85 @@
#include "types.h"
#include "render_flex.h"
+namespace litehtml
+{
+ class flex_justify_content_spread
+ {
+ flex_justify_content m_type;
+ int m_num_items;
+ int m_free_space;
+ public:
+ flex_justify_content_spread(flex_justify_content type, int num_items, int free_space) :
+ m_type(type), m_num_items(num_items), m_free_space(0)
+ {
+ set_free_space(free_space);
+ }
+
+ void set_free_space(int free_space)
+ {
+ m_free_space = free_space;
+ switch (m_type)
+ {
+
+ 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(m_num_items == 1 || m_free_space < 0) m_type = flex_justify_content_flex_start;
+ break;
+ case flex_justify_content_space_around:
+ // 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(m_num_items == 1 || m_free_space < 0) m_type = flex_justify_content_center;
+ break;
+ default:
+ break;
+ }
+ }
+
+ int start()
+ {
+ switch (m_type)
+ {
+ case flex_justify_content_flex_end:
+ return m_free_space;
+ case flex_justify_content_center:
+ return m_free_space / 2;
+ case flex_justify_content_space_between:
+ case flex_justify_content_space_around:
+ default:
+ // using flex-start b y default
+ return 0;
+ }
+ }
+
+ int before_item()
+ {
+ switch (m_type)
+ {
+ case flex_justify_content_space_between:
+ return 0;
+ case flex_justify_content_space_around:
+ return m_free_space / (m_num_items * 2);
+ default:
+ return 0;
+ }
+ }
+
+ int after_item()
+ {
+ switch (m_type)
+ {
+ case flex_justify_content_space_between:
+ return m_free_space / (m_num_items - 1);
+ case flex_justify_content_space_around:
+ return m_free_space / (m_num_items * 2);
+ default:
+ return 0;
+ }
+ }
+ };
+}
+
int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass, const containing_block_context &self_size, formatting_context* fmt_ctx)
{
bool is_row_direction = true;
@@ -143,21 +222,34 @@ int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass,
ln.cross_size += add_cross_size;
free_cross_size -= add_cross_size;
}
+ flex_justify_content_spread content_spread(css().get_flex_justify_content(),
+ (int) ln.items.size(),
+ container_main_size - ln.main_size);
if(is_row_direction)
{
- el_x = reverse ? container_main_size : 0;
if(is_wrap_reverse)
{
el_y -= ln.cross_size;
}
+ if(reverse)
+ {
+ el_x = container_main_size - content_spread.start();
+ } else
+ {
+ el_x = content_spread.start();
+ }
for (auto &item: ln.items)
{
if(!reverse)
{
+ // justify content [before_item]
+ el_x += content_spread.before_item();
item.el->pos().x = el_x + item.el->content_offset_left();
el_x += item.el->width();
} else
{
+ // justify content [before_item]
+ el_x -= content_spread.before_item();
el_x -= item.el->width();
item.el->pos().x = el_x + item.el->content_offset_left();
}
@@ -181,6 +273,14 @@ int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass,
break;
}
m_pos.height = std::max(m_pos.height, item.el->bottom());
+ // justify content [after_item]
+ if(!reverse)
+ {
+ el_x += content_spread.after_item();
+ } else
+ {
+ el_x -= content_spread.after_item();
+ }
}
if(!is_wrap_reverse)
{
@@ -190,16 +290,19 @@ int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass,
{
if(!reverse)
{
- el_y = 0;
+ el_y = content_spread.start();
} else
{
if(self_size.height.type == containing_block_context::cbc_value_type_auto)
{
+ content_spread.set_free_space(0);
el_y = ln.main_size;
} else
{
+ content_spread.set_free_space(self_size.height - ln.main_size);
el_y = self_size.height;
}
+ el_y -= content_spread.start();
}
if(is_wrap_reverse)
{
@@ -209,10 +312,16 @@ int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass,
{
if(!reverse)
{
+ // justify content [before_item]
+ el_y += content_spread.before_item();
+
item.el->pos().y = el_y + item.el->content_offset_top();
el_y += item.el->height();
} else
{
+ // justify content [before_item]
+ el_y -= content_spread.before_item();
+
el_y -= item.el->height();
item.el->pos().y = el_y + item.el->content_offset_top();
}
@@ -239,6 +348,14 @@ int litehtml::render_item_flex::_render_content(int x, int y, bool second_pass,
break;
}
m_pos.height = std::max(m_pos.height, item.el->bottom());
+ // justify content [after_item]
+ if(!reverse)
+ {
+ el_y += content_spread.after_item();
+ } else
+ {
+ el_y -= content_spread.after_item();
+ }
}
if(!is_wrap_reverse)
{