17void SymmetryXY(FlexboxConfig& c) {
18 std::swap(c.gap_x, c.gap_y);
19 switch (c.direction) {
20 case FlexboxConfig::Direction::Row:
21 c.direction = FlexboxConfig::Direction::Column;
23 case FlexboxConfig::Direction::RowInversed:
24 c.direction = FlexboxConfig::Direction::ColumnInversed;
26 case FlexboxConfig::Direction::Column:
27 c.direction = FlexboxConfig::Direction::Row;
29 case FlexboxConfig::Direction::ColumnInversed:
30 c.direction = FlexboxConfig::Direction::RowInversed;
35void SymmetryX(FlexboxConfig& c) {
36 switch (c.direction) {
37 case FlexboxConfig::Direction::Row:
38 c.direction = FlexboxConfig::Direction::RowInversed;
40 case FlexboxConfig::Direction::RowInversed:
41 c.direction = FlexboxConfig::Direction::Row;
48void SymmetryY(FlexboxConfig& c) {
50 case FlexboxConfig::Wrap::NoWrap:
52 case FlexboxConfig::Wrap::Wrap:
53 c.wrap = FlexboxConfig::Wrap::WrapInversed;
55 case FlexboxConfig::Wrap::WrapInversed:
56 c.wrap = FlexboxConfig::Wrap::Wrap;
61void SymmetryXY(
Global& g) {
65 std::swap(b.min_size_x, b.min_size_y);
66 std::swap(b.flex_grow_x, b.flex_grow_y);
67 std::swap(b.flex_shrink_x, b.flex_shrink_y);
69 std::swap(b.dim_x, b.dim_y);
71 for (
auto& l : g.
lines) {
73 std::swap(l.dim_x, l.dim_y);
80 b.x = g.
size_x - b.x - b.dim_x;
82 for (
auto& l : g.
lines) {
83 l.x = g.
size_x - l.x - l.dim_x;
90 b.y = g.
size_y - b.y - b.dim_y;
92 for (
auto& l : g.
lines) {
93 l.y = g.
size_y - l.y - l.dim_y;
98 for (
auto& line : global.
lines) {
99 std::vector<box_helper::Element> elements;
100 elements.reserve(line.blocks.size());
101 for (
auto* block : line.blocks) {
103 element.min_size = block->min_size_x;
105 block->flex_grow_x != 0 || global.
config.justify_content ==
106 FlexboxConfig::JustifyContent::Stretch
109 element.flex_shrink = block->flex_shrink_x;
115 global.
size_x - global.
config.gap_x * (
int(line.blocks.size()) - 1));
118 for (
size_t i = 0; i < line.blocks.size(); ++i) {
119 line.blocks[i]->x = x;
120 line.blocks[i]->dim_x = elements[i].size;
121 x += elements[i].size;
126 for (
auto& line : global.
lines) {
128 line.dim_x = global.
size_x;
134 std::vector<box_helper::Element> elements;
135 elements.reserve(g.
lines.size());
136 for (
auto& line : g.
lines) {
138 element.flex_shrink = line.blocks.front()->flex_shrink_y;
139 element.flex_grow = line.blocks.front()->flex_grow_y;
140 for (
auto* block : line.blocks) {
142 element.flex_shrink = std::min(
element.flex_shrink, block->flex_shrink_y);
143 element.flex_grow = std::min(
element.flex_grow, block->flex_grow_y);
152 std::vector<int> ys(elements.size());
154 for (
size_t i = 0; i < elements.size(); ++i) {
156 y += elements[i].size;
159 int remaining_space = std::max(0, g.
size_y -
y);
160 switch (g.
config.align_content) {
161 case FlexboxConfig::AlignContent::FlexStart: {
165 case FlexboxConfig::AlignContent::FlexEnd: {
166 for (
size_t i = 0; i < ys.size(); ++i) {
167 ys[i] += remaining_space;
172 case FlexboxConfig::AlignContent::Center: {
173 for (
size_t i = 0; i < ys.size(); ++i) {
174 ys[i] += remaining_space / 2;
179 case FlexboxConfig::AlignContent::Stretch: {
180 for (
int i =
static_cast<int>(ys.size()) - 1; i >= 0; --i) {
181 const int shifted = remaining_space * (i + 0) / (i + 1);
183 const int consumed = remaining_space - shifted;
184 elements[i].size += consumed;
185 remaining_space -= consumed;
190 case FlexboxConfig::AlignContent::SpaceBetween: {
191 for (
int i =
static_cast<int>(ys.size()) - 1; i >= 1; --i) {
192 ys[i] += remaining_space;
193 remaining_space = remaining_space * (i - 1) / i;
198 case FlexboxConfig::AlignContent::SpaceAround: {
199 for (
int i =
static_cast<int>(ys.size()) - 1; i >= 0; --i) {
200 ys[i] += remaining_space * (2 * i + 1) / (2 * i + 2);
201 remaining_space = remaining_space * (2 * i) / (2 * i + 2);
206 case FlexboxConfig::AlignContent::SpaceEvenly: {
207 for (
int i =
static_cast<int>(ys.size()) - 1; i >= 0; --i) {
208 ys[i] += remaining_space * (i + 1) / (i + 2);
209 remaining_space = remaining_space * (i + 1) / (i + 2);
216 for (
size_t i = 0; i < g.
lines.size(); ++i) {
218 for (
auto* block : g.
lines[i].blocks) {
220 block->flex_grow_y != 0 ||
221 g.
config.align_content == FlexboxConfig::AlignContent::Stretch;
223 stretch ?
element.size : std::min(
element.size, block->min_size_y);
224 switch (g.
config.align_items) {
225 case FlexboxConfig::AlignItems::FlexStart: {
231 case FlexboxConfig::AlignItems::Center: {
237 case FlexboxConfig::AlignItems::FlexEnd: {
243 case FlexboxConfig::AlignItems::Stretch: {
253 for (
size_t i = 0; i < g.
lines.size(); ++i) {
254 g.
lines[i].y = ys[i];
255 g.
lines[i].dim_y = ys[i + 1] - ys[i];
259void JustifyContent(
Global& g) {
260 for (
auto& line : g.
lines) {
261 Block* last = line.blocks.back();
263 switch (g.
config.justify_content) {
264 case FlexboxConfig::JustifyContent::FlexStart:
265 case FlexboxConfig::JustifyContent::Stretch:
268 case FlexboxConfig::JustifyContent::FlexEnd: {
269 for (
auto* block : line.blocks) {
270 block->x += remaining_space;
275 case FlexboxConfig::JustifyContent::Center: {
276 for (
auto* block : line.blocks) {
277 block->x += remaining_space / 2;
282 case FlexboxConfig::JustifyContent::SpaceBetween: {
283 for (
int i = (
int)line.blocks.size() - 1; i >= 1; --i) {
284 line.blocks[i]->x += remaining_space;
285 remaining_space = remaining_space * (i - 1) / i;
290 case FlexboxConfig::JustifyContent::SpaceAround: {
291 for (
int i = (
int)line.blocks.size() - 1; i >= 0; --i) {
292 line.blocks[i]->x += remaining_space * (2 * i + 1) / (2 * i + 2);
293 remaining_space = remaining_space * (2 * i) / (2 * i + 2);
298 case FlexboxConfig::JustifyContent::SpaceEvenly: {
299 for (
int i = (
int)line.blocks.size() - 1; i >= 0; --i) {
300 line.blocks[i]->x += remaining_space * (i + 1) / (i + 2);
301 remaining_space = remaining_space * (i + 1) / (i + 2);
309void Compute1(
Global& global);
310void Compute2(
Global& global);
311void Compute3(
Global& global);
313void Compute1(
Global& global) {
314 if (global.
config.direction == FlexboxConfig::Direction::RowInversed) {
323void Compute2(
Global& global) {
324 if (global.
config.wrap == FlexboxConfig::Wrap::WrapInversed) {
333void Compute3(
Global& global) {
338 for (
auto& block : global.
blocks) {
341 if (x + block.min_size_x > global.
size_x) {
343 if (!line.
blocks.empty()) {
344 global.
lines.push_back(std::move(line));
349 block.line =
static_cast<int>(global.
lines.size());
350 block.line_position =
static_cast<int>(line.
blocks.size());
351 line.
blocks.push_back(&block);
352 x += block.min_size_x + global.
config.gap_x;
354 if (!line.
blocks.empty()) {
355 global.
lines.push_back(std::move(line));
361 JustifyContent(global);
370 if (global.
config.direction == FlexboxConfig::Direction::Column ||
371 global.
config.direction == FlexboxConfig::Direction::ColumnInversed) {