From 2f11e963cabb2970ec583a931fc8ceac103d8f4a Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Wed, 6 Aug 2025 17:02:52 +0000 Subject: [PATCH 01/11] Removed unnecessary "after algorithm" space distribution --- src/flex_line.cpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/flex_line.cpp b/src/flex_line.cpp index 4674623d..077f4bf3 100644 --- a/src/flex_line.cpp +++ b/src/flex_line.cpp @@ -139,25 +139,6 @@ void litehtml::flex_line::distribute_free_space(pixel_t container_main_size) if (total_clamped == 0) processed = false; } } - // Distribute remaining after algorithm space - pixel_t sum_main_size = 0; - for(auto &item : items) - { - sum_main_size += item->main_size; - } - - pixel_t free_space = container_main_size - sum_main_size; - - pixel_t ditribute_step = 1; - if(free_space > 0) - { - for(auto &item : items) - { - if(free_space < ditribute_step) break; - item->main_size += ditribute_step; - free_space -= ditribute_step; - } - } } } From 85382c288f238e837e945f434587d1d0ca1f3657 Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Wed, 13 Aug 2025 23:09:54 +0000 Subject: [PATCH 02/11] Fixed flex grow factor sum also counting frozen items --- src/flex_line.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/flex_line.cpp b/src/flex_line.cpp index 077f4bf3..ca10e0f0 100644 --- a/src/flex_line.cpp +++ b/src/flex_line.cpp @@ -48,6 +48,7 @@ void litehtml::flex_line::distribute_free_space(pixel_t container_main_size) while (processed) { pixel_t sum_scaled_flex_shrink_factor = 0; + int sum_flex_grow_factor = 0; pixel_t remaining_free_space = container_main_size; int total_not_frozen = 0; for (auto &item: items) @@ -55,6 +56,7 @@ void litehtml::flex_line::distribute_free_space(pixel_t container_main_size) if (!item->frozen) { sum_scaled_flex_shrink_factor += item->scaled_flex_shrink_factor; + sum_flex_grow_factor += item->grow; remaining_free_space -= item->base_size; total_not_frozen++; } else @@ -115,7 +117,7 @@ void litehtml::flex_line::distribute_free_space(pixel_t container_main_size) // 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 = item->base_size + remaining_free_space * (pixel_t) item->grow / (pixel_t) total_flex_factor; + item->main_size = item->base_size + remaining_free_space * (pixel_t) item->grow / (pixel_t) sum_flex_grow_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 From fffbe5604020b8e220a9bea987131c624f67023c Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Wed, 20 Aug 2025 17:42:45 +0000 Subject: [PATCH 03/11] Fixed explicit flex-basis interpretation --- src/flex_item.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/flex_item.cpp b/src/flex_item.cpp index 8281b534..e10a4f02 100644 --- a/src/flex_item.cpp +++ b/src/flex_item.cpp @@ -199,8 +199,7 @@ void litehtml::flex_item_row_direction::direction_specific_init(const litehtml:: } 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); + el->render_offset_width(); } } @@ -378,9 +377,8 @@ void litehtml::flex_item_column_direction::direction_specific_init(const litehtm } } else { - base_size = (pixel_t) el->css().get_flex_basis().val() + el->content_offset_height(); + base_size = (pixel_t) el->css().get_flex_basis().val() + el->render_offset_height(); } - base_size = std::max(base_size, min_size); } } From 792bfe351c8049ffe5c4855a45cb1c7928935b3e Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Sat, 23 Aug 2025 18:45:59 +0000 Subject: [PATCH 04/11] Use hypothetical main size for collecting lines and choosing factor --- include/litehtml/flex_item.h | 5 ++++- src/flex_item.cpp | 13 ++++++++++++- src/flex_line.cpp | 16 ++++++++-------- src/render_flex.cpp | 3 ++- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/litehtml/flex_item.h b/include/litehtml/flex_item.h index 48582988..1b578589 100644 --- a/include/litehtml/flex_item.h +++ b/include/litehtml/flex_item.h @@ -15,10 +15,13 @@ namespace litehtml { public: std::shared_ptr el; + + // All sizes should be interpreted as outer/margin-box sizes. pixel_t base_size; pixel_t min_size; def_value max_size; - pixel_t main_size; + pixel_t main_size; // Holds the outer hypothetical main size before distribute_free_space, and the used outer main size after. + int grow; int shrink; pixel_t scaled_flex_shrink_factor; diff --git a/src/flex_item.cpp b/src/flex_item.cpp index e10a4f02..f0b8f871 100644 --- a/src/flex_item.cpp +++ b/src/flex_item.cpp @@ -28,7 +28,18 @@ void litehtml::flex_item::init(const litehtml::containing_block_context &self_si { align = el->css().get_flex_align_self(); } - main_size = base_size; + + if (base_size < min_size) + { + main_size = min_size; + } else if (!max_size.is_default() && base_size > max_size) + { + main_size = max_size; + } else + { + main_size = base_size; + } + scaled_flex_shrink_factor = base_size * shrink; frozen = false; } diff --git a/src/flex_line.cpp b/src/flex_line.cpp index ca10e0f0..4a6f9d34 100644 --- a/src/flex_line.cpp +++ b/src/flex_line.cpp @@ -7,7 +7,7 @@ void litehtml::flex_line::distribute_free_space(pixel_t 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. - pixel_t initial_free_space = container_main_size - base_size; + pixel_t initial_free_space = container_main_size - main_size; bool grow; int total_flex_factor; if(initial_free_space < 0) @@ -21,7 +21,7 @@ void litehtml::flex_line::distribute_free_space(pixel_t container_main_size) { for(auto &item : items) { - item->main_size += initial_free_space * item->shrink / 1000; + item->main_size = item->base_size + initial_free_space * item->shrink / 1000; } return; } @@ -36,7 +36,7 @@ void litehtml::flex_line::distribute_free_space(pixel_t container_main_size) { for(auto &item : items) { - item->main_size += initial_free_space * item->grow / 1000; + item->main_size = item->base_size + initial_free_space * item->grow / 1000; } return; } @@ -195,16 +195,16 @@ void litehtml::flex_line::init(pixel_t container_main_size, bool fit_container, 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); } + cross_size = 0; + main_size = 0; + first_baseline.set(0, baseline::baseline_type_none); + last_baseline.set(0, baseline::baseline_type_none); + if(is_row_direction) { def_value first_baseline_top = 0; diff --git a/src/render_flex.cpp b/src/render_flex.cpp index 29291208..8911d222 100644 --- a/src/render_flex.cpp +++ b/src/render_flex.cpp @@ -301,12 +301,13 @@ std::list litehtml::render_item_flex::get_lines(const liteh // Add flex items to lines for(auto& item : items) { - if(!line.items.empty() && !single_line && line.base_size + item->base_size > container_main_size) + if(!line.items.empty() && !single_line && line.main_size + item->main_size > container_main_size) { lines.emplace_back(line); line = flex_line(reverse_main, reverse_cross); } line.base_size += item->base_size; + line.main_size += item->main_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++; From ef9fe7a0484cdcae64ea6fd9b61c062e671f7a88 Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Fri, 29 Aug 2025 21:12:53 +0000 Subject: [PATCH 05/11] Changed space distribution algorithm to match to the spec --- include/litehtml/flex_item.h | 14 ++ include/litehtml/flex_line.h | 3 + src/flex_line.cpp | 337 +++++++++++++++++++++++------------ 3 files changed, 243 insertions(+), 111 deletions(-) diff --git a/include/litehtml/flex_item.h b/include/litehtml/flex_item.h index 1b578589..192b421a 100644 --- a/include/litehtml/flex_item.h +++ b/include/litehtml/flex_item.h @@ -8,6 +8,14 @@ namespace litehtml { class flex_line; + enum flex_clamp_state + { + flex_clamp_state_unclamped, + flex_clamp_state_inflexible, + flex_clamp_state_min_violation, + flex_clamp_state_max_violation + }; + /** * Base class for flex item */ @@ -25,13 +33,18 @@ namespace litehtml int grow; int shrink; pixel_t scaled_flex_shrink_factor; + bool frozen; + flex_clamp_state clamp_state; + int order; int src_order; + def_value auto_margin_main_start; def_value auto_margin_main_end; bool auto_margin_cross_start; bool auto_margin_cross_end; + flex_align_items align; explicit flex_item(std::shared_ptr &_el) : @@ -44,6 +57,7 @@ namespace litehtml shrink(0), scaled_flex_shrink_factor(0), frozen(false), + clamp_state(flex_clamp_state_unclamped), order(0), src_order(0), auto_margin_main_start(0), diff --git a/include/litehtml/flex_line.h b/include/litehtml/flex_line.h index 06cf1bf2..61fdd2a5 100644 --- a/include/litehtml/flex_line.h +++ b/include/litehtml/flex_line.h @@ -50,6 +50,9 @@ namespace litehtml formatting_context *fmt_ctx); protected: void distribute_free_space(pixel_t container_main_size); + void distribute_free_space_grow(pixel_t container_main_size); + void distribute_free_space_shrink(pixel_t container_main_size); + bool fix_min_max_violations(); }; } diff --git a/src/flex_line.cpp b/src/flex_line.cpp index 4a6f9d34..faeb9888 100644 --- a/src/flex_line.cpp +++ b/src/flex_line.cpp @@ -4,144 +4,259 @@ void litehtml::flex_line::distribute_free_space(pixel_t container_main_size) { - // Determine the used flex factor. Sum the outer hypothetical main sizes of all items on the line. + // 1 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. - pixel_t initial_free_space = container_main_size - main_size; - bool grow; - int total_flex_factor; - if(initial_free_space < 0) + + if (main_size < container_main_size) + { + distribute_free_space_grow(container_main_size); + } else { - 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) + distribute_free_space_shrink(container_main_size); + } +} + +void litehtml::flex_line::distribute_free_space_grow(pixel_t container_main_size) +{ + pixel_t initial_free_space = container_main_size; + + for (auto& item : items) + { + // 2. Size inflexible items. Freeze, setting its target main size to its hypothetical main size + // any item that has a flex factor of zero + // if using the flex grow factor: any item that has a flex base size greater than its hypothetical main size + + // 3. Calculate initial free space. Sum the outer sizes of all items on the line, and subtract this + // from the flex container’s inner main size. For frozen items, use their outer target main size; for + // other items, use their outer flex base size. + + if (item->grow == 0 || item->base_size > item->main_size) + { + item->frozen = true; + item->clamp_state = flex_clamp_state_inflexible; + initial_free_space -= item->main_size; + } else { - for(auto &item : items) + initial_free_space -= item->base_size; + } + } + + // 4. Loop: + + // 4.a Check for flexible items. If all the flex items on the line are frozen, free space has been + // distributed; exit this loop. + + while (true) + { + // 4.b Calculate the remaining free space as for initial free space, above. If the sum of the + // unfrozen flex items’ flex factors is less than one, multiply the initial free space by this sum. + // If the magnitude of this value is less than the magnitude of the remaining free space, use + // this as the remaining free space. + + int sum_flex_grow_factor = 0; + pixel_t remaining_free_space = container_main_size; + + for (auto& item : items) + { + if (item->frozen) + { + remaining_free_space -= item->main_size; + } else { - item->main_size = item->base_size + initial_free_space * item->shrink / 1000; + remaining_free_space -= item->base_size; + sum_flex_grow_factor += item->grow; } - 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) + + if (sum_flex_grow_factor < 1000) { - for(auto &item : items) + pixel_t adjusted_free_space = initial_free_space * (pixel_t) sum_flex_grow_factor / (pixel_t) 1000; + if (adjusted_free_space < remaining_free_space) { - item->main_size = item->base_size + initial_free_space * item->grow / 1000; + remaining_free_space = adjusted_free_space; } - return; } + + // 4.c Distribute free space proportional to the flex factors. + + // If the remaining free space is zero + // Do nothing. + + if (remaining_free_space != 0) + { + for (auto& item: items) + { + if (!item->frozen) + { + // 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 = item->base_size + remaining_free_space * (pixel_t) item->grow / (pixel_t) sum_flex_grow_factor; + } + } + } + + if (fix_min_max_violations()) break; } +} + +void litehtml::flex_line::distribute_free_space_shrink(pixel_t container_main_size) +{ + pixel_t initial_free_space = container_main_size; - if(total_flex_factor > 0) + for (auto& item : items) { - bool processed = true; - while (processed) + // 2. Size inflexible items. Freeze, setting its target main size to its hypothetical main size + // any item that has a flex factor of zero + // if using the flex shrink factor: any item that has a flex base size smaller than its hypothetical main size + + // 3. Calculate initial free space. Sum the outer sizes of all items on the line, and subtract this + // from the flex container’s inner main size. For frozen items, use their outer target main size; for + // other items, use their outer flex base size. + + if (item->shrink == 0 || item->base_size < item->main_size) { - pixel_t sum_scaled_flex_shrink_factor = 0; - int sum_flex_grow_factor = 0; - pixel_t remaining_free_space = container_main_size; - int total_not_frozen = 0; - for (auto &item: items) + item->frozen = true; + item->clamp_state = flex_clamp_state_inflexible; + initial_free_space -= item->main_size; + } else + { + initial_free_space -= item->base_size; + } + } + + // 4. Loop: + + // 4.a Check for flexible items. If all the flex items on the line are frozen, free space has been + // distributed; exit this loop. + + while (true) + { + // 4.b Calculate the remaining free space as for initial free space, above. If the sum of the + // unfrozen flex items’ flex factors is less than one, multiply the initial free space by this sum. + // If the magnitude of this value is less than the magnitude of the remaining free space, use + // this as the remaining free space. + + int sum_flex_shrink_factor = 0; + pixel_t sum_scaled_flex_shrink_factor = 0; + pixel_t remaining_free_space = container_main_size; + + for (auto& item : items) + { + if (item->frozen) + { + remaining_free_space -= item->main_size; + } else + { + remaining_free_space -= item->base_size; + sum_flex_shrink_factor += item->shrink; + sum_scaled_flex_shrink_factor += item->scaled_flex_shrink_factor; + } + } + + if (sum_flex_shrink_factor < 1000) + { + pixel_t adjusted_free_space = initial_free_space * (pixel_t) sum_flex_shrink_factor / (pixel_t) 1000; + if (adjusted_free_space > remaining_free_space) + { + remaining_free_space = adjusted_free_space; + } + } + + // 4.c Distribute free space proportional to the flex factors. + + // If the remaining free space is zero + // Do nothing. + + if (remaining_free_space != 0) + { + for (auto& item: items) { if (!item->frozen) { - sum_scaled_flex_shrink_factor += item->scaled_flex_shrink_factor; - sum_flex_grow_factor += item->grow; - remaining_free_space -= item->base_size; - total_not_frozen++; - } else - { - remaining_free_space -= item->main_size; + // 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. + + item->main_size = item->base_size + remaining_free_space * item->scaled_flex_shrink_factor / sum_scaled_flex_shrink_factor; } } - // 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 == 0) + } + + if (fix_min_max_violations()) break; + } +} + +bool litehtml::flex_line::fix_min_max_violations() +{ + // 4.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. + + pixel_t total_violation = 0; + + for (auto& item : items) + { + if (!item->frozen) + { + if (item->main_size < item->min_size) { - processed = false; - } else + total_violation += item->min_size - item->main_size; + item->main_size = item->min_size; + item->clamp_state = flex_clamp_state_min_violation; + } else if (!item->max_size.is_default() && item->main_size > item->max_size) + { + total_violation += item->max_size - item->main_size; + item->main_size = item->max_size; + item->clamp_state = flex_clamp_state_max_violation; + } + } + } + + // 4.e Freeze over-flexed items. The total violation is the sum of the adjustments from the + // previous step ∑(clamped size - unclamped size). If the total violation is: + // Zero: Freeze all items. + // Positive: Freeze all the items with min violations. + // Negative: Freeze all the items with max violations. + + if (total_violation == 0) + { + return true; + } + + bool all_frozen = true; + + flex_clamp_state state_to_freeze = + total_violation > 0 + ? flex_clamp_state_min_violation + : flex_clamp_state_max_violation; + + if (total_violation > 0) + { + for (auto& item : items) + { + if (!item->frozen) { - int total_clamped = 0; - for (auto &item: items) + if (item->clamp_state == state_to_freeze) { - 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. - pixel_t scaled_flex_shrink_factor = item->base_size * item->shrink; - item->main_size = item->base_size - remaining_free_space * scaled_flex_shrink_factor / 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 = item->base_size + remaining_free_space * (pixel_t) item->grow / (pixel_t) sum_flex_grow_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; - } - } - } + item->frozen = true; + } else + { + all_frozen = false; + item->clamp_state = flex_clamp_state_unclamped; } - if (total_clamped == 0) processed = false; } } } + + return all_frozen; } bool litehtml::flex_line::distribute_main_auto_margins(pixel_t free_main_size) From 078bcb8ca2f8f813b851a2276a20ca0a7e9af766 Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Sat, 30 Aug 2025 18:16:04 +0000 Subject: [PATCH 06/11] Fixed max violations not freezing --- src/flex_line.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/flex_line.cpp b/src/flex_line.cpp index faeb9888..ebb1fbd0 100644 --- a/src/flex_line.cpp +++ b/src/flex_line.cpp @@ -238,20 +238,17 @@ bool litehtml::flex_line::fix_min_max_violations() ? flex_clamp_state_min_violation : flex_clamp_state_max_violation; - if (total_violation > 0) + for (auto& item : items) { - for (auto& item : items) + if (!item->frozen) { - if (!item->frozen) + if (item->clamp_state == state_to_freeze) { - if (item->clamp_state == state_to_freeze) - { - item->frozen = true; - } else - { - all_frozen = false; - item->clamp_state = flex_clamp_state_unclamped; - } + item->frozen = true; + } else + { + all_frozen = false; + item->clamp_state = flex_clamp_state_unclamped; } } } From ec4362de2410f13444db1e3d717643d0100545a7 Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Sun, 31 Aug 2025 14:53:52 +0000 Subject: [PATCH 07/11] Exit early if all items are inflexible --- src/flex_line.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/flex_line.cpp b/src/flex_line.cpp index ebb1fbd0..12b7866d 100644 --- a/src/flex_line.cpp +++ b/src/flex_line.cpp @@ -21,6 +21,8 @@ void litehtml::flex_line::distribute_free_space_grow(pixel_t container_main_size { pixel_t initial_free_space = container_main_size; + bool all_inflexible = true; + for (auto& item : items) { // 2. Size inflexible items. Freeze, setting its target main size to its hypothetical main size @@ -39,6 +41,7 @@ void litehtml::flex_line::distribute_free_space_grow(pixel_t container_main_size } else { initial_free_space -= item->base_size; + all_inflexible = false; } } @@ -46,7 +49,9 @@ void litehtml::flex_line::distribute_free_space_grow(pixel_t container_main_size // 4.a Check for flexible items. If all the flex items on the line are frozen, free space has been // distributed; exit this loop. - + + if (all_inflexible) return; + while (true) { // 4.b Calculate the remaining free space as for initial free space, above. If the sum of the @@ -107,6 +112,8 @@ void litehtml::flex_line::distribute_free_space_shrink(pixel_t container_main_si { pixel_t initial_free_space = container_main_size; + bool all_inflexible = true; + for (auto& item : items) { // 2. Size inflexible items. Freeze, setting its target main size to its hypothetical main size @@ -125,6 +132,7 @@ void litehtml::flex_line::distribute_free_space_shrink(pixel_t container_main_si } else { initial_free_space -= item->base_size; + all_inflexible = false; } } @@ -132,7 +140,9 @@ void litehtml::flex_line::distribute_free_space_shrink(pixel_t container_main_si // 4.a Check for flexible items. If all the flex items on the line are frozen, free space has been // distributed; exit this loop. - + + if (all_inflexible) return; + while (true) { // 4.b Calculate the remaining free space as for initial free space, above. If the sum of the From 09caf8a0169b7e21d253f644cf39135404ca2364 Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Sun, 31 Aug 2025 18:54:48 +0000 Subject: [PATCH 08/11] Fixed scaled shrink factor using outer base size instead of inner --- src/flex_item.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/flex_item.cpp b/src/flex_item.cpp index f0b8f871..85ea6de2 100644 --- a/src/flex_item.cpp +++ b/src/flex_item.cpp @@ -40,7 +40,6 @@ void litehtml::flex_item::init(const litehtml::containing_block_context &self_si main_size = base_size; } - scaled_flex_shrink_factor = base_size * shrink; frozen = false; } @@ -212,6 +211,8 @@ void litehtml::flex_item_row_direction::direction_specific_init(const litehtml:: base_size = el->css().get_flex_basis().calc_percent(self_size.render_width) + el->render_offset_width(); } + + scaled_flex_shrink_factor = (base_size - el->render_offset_width()) * shrink; } void litehtml::flex_item_row_direction::apply_main_auto_margins() @@ -391,6 +392,8 @@ void litehtml::flex_item_column_direction::direction_specific_init(const litehtm base_size = (pixel_t) el->css().get_flex_basis().val() + el->render_offset_height(); } } + + scaled_flex_shrink_factor = (base_size - el->render_offset_height()) * shrink; } void litehtml::flex_item_column_direction::apply_main_auto_margins() From 2abf47593fd008b081261df237172d2471b4a1a7 Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Mon, 1 Sep 2025 18:03:23 +0000 Subject: [PATCH 09/11] Removed some unnecessary box sizing checks --- src/render_block.cpp | 5 +---- src/render_flex.cpp | 12 ++---------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/render_block.cpp b/src/render_block.cpp index 9eba62ad..359c0832 100644 --- a/src/render_block.cpp +++ b/src/render_block.cpp @@ -279,10 +279,7 @@ litehtml::pixel_t litehtml::render_item_block::_render(pixel_t x, pixel_t y, con { m_pos.height = self_size.height; } - if (src_el()->css().get_box_sizing() == box_sizing_border_box) - { - m_pos.height -= box_sizing_height(); - } + m_pos.height -= box_sizing_height(); } else if (src_el()->is_block_formatting_context()) { // add the floats' height to the block height diff --git a/src/render_flex.cpp b/src/render_flex.cpp index 8911d222..17b93b8f 100644 --- a/src/render_flex.cpp +++ b/src/render_flex.cpp @@ -35,11 +35,7 @@ litehtml::pixel_t litehtml::render_item_flex::_render_content(pixel_t x, pixel_t { 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(); - } + container_main_size = self_size.height - box_sizing_height(); } else { // Direction columns, height is auto - always in single line @@ -100,11 +96,7 @@ litehtml::pixel_t litehtml::render_item_flex::_render_content(pixel_t x, pixel_t { if (self_size.height.type != containing_block_context::cbc_value_type_auto) { - pixel_t height = self_size.height; - if (src_el()->css().get_box_sizing() == box_sizing_border_box) - { - height -= box_sizing_height(); - } + pixel_t height = self_size.height - box_sizing_height(); free_cross_size = height - sum_cross_size; } } else From b8def98c728ef416e5d26119c0c55c41ce6b7e80 Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Mon, 1 Sep 2025 19:02:54 +0000 Subject: [PATCH 10/11] Fixed more render vs content offset problems --- src/flex_item.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/flex_item.cpp b/src/flex_item.cpp index 85ea6de2..32be8475 100644 --- a/src/flex_item.cpp +++ b/src/flex_item.cpp @@ -147,12 +147,12 @@ void litehtml::flex_item_row_direction::direction_specific_init(const litehtml:: } else { min_size = el->css().get_min_width().calc_percent(self_size.render_width) + - el->content_offset_width(); + el->render_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(); + el->render_offset_width(); } bool flex_basis_predefined = el->css().get_flex_basis().is_predefined(); int predef = flex_basis_auto; @@ -331,12 +331,12 @@ void litehtml::flex_item_column_direction::direction_specific_init(const litehtm } else { min_size = el->css().get_min_height().calc_percent(self_size.height) + - el->content_offset_height(); + el->render_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(); + el->render_offset_height(); } bool flex_basis_predefined = el->css().get_flex_basis().is_predefined(); @@ -362,7 +362,7 @@ void litehtml::flex_item_column_direction::direction_specific_init(const litehtm { case flex_basis_auto: base_size = el->css().get_height().calc_percent(self_size.height) + - el->content_offset_height(); + el->render_offset_height(); break; case flex_basis_max_content: case flex_basis_fit_content: @@ -382,7 +382,7 @@ void litehtml::flex_item_column_direction::direction_specific_init(const litehtm 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(); + el->render_offset_height(); } else { base_size = 0; From 3f67f936dc81711f4025e204e12447e2d1c055e0 Mon Sep 17 00:00:00 2001 From: Kalman Vince <30904009+DRKV333@users.noreply.github.com> Date: Thu, 4 Sep 2025 17:57:46 +0000 Subject: [PATCH 11/11] Removed unused factor sum fields --- include/litehtml/flex_line.h | 6 +----- src/render_flex.cpp | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/include/litehtml/flex_line.h b/include/litehtml/flex_line.h index 61fdd2a5..a5057aed 100644 --- a/include/litehtml/flex_line.h +++ b/include/litehtml/flex_line.h @@ -12,11 +12,9 @@ namespace litehtml public: std::list> items; pixel_t cross_start; // for row direction: top. for column direction: left - pixel_t main_size; // sum of all items main size + pixel_t main_size; // sum of all items main size, initially the sum of hypothetical main sizes pixel_t cross_size; // sum of all items cross size pixel_t 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; @@ -29,8 +27,6 @@ namespace litehtml main_size(0), cross_size(0), base_size(0), - total_grow(0), - total_shrink(0), num_auto_margin_main_start(0), num_auto_margin_main_end(0), first_baseline(), diff --git a/src/render_flex.cpp b/src/render_flex.cpp index 17b93b8f..9f1eb7fd 100644 --- a/src/render_flex.cpp +++ b/src/render_flex.cpp @@ -300,8 +300,6 @@ std::list litehtml::render_item_flex::get_lines(const liteh } line.base_size += item->base_size; line.main_size += item->main_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);