-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathglue.cpp
More file actions
64 lines (55 loc) · 2.46 KB
/
glue.cpp
File metadata and controls
64 lines (55 loc) · 2.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// if the width_diff is positive
// find the highest order for which the sum of all stretch glues in the node list is non-zero
// return the sum and the corresponding order
// result is glue_param{.scale = width_diff / sum, .order = order}
//
// if the width_diff is negative, do the same for the shrink glues and return scale reciprocal
//
// if the width_diff is zero, or the node list does not contain any glue, return scale of one and order normal
//
#include "node/glue.hpp"
namespace mfl
{
namespace
{
dist_t sum_of_glue_by_order(const infinity_order order, glue_scale glue_spec::*scale,
const std::vector<node_variant>& nodes)
{
dist_t glue_sum = 0;
for (const auto& n : nodes)
{
std::visit(overload{[&](const glue_spec& glue) {
if (const auto& [value, scale_order] = glue.*scale; scale_order == order)
glue_sum += value;
},
[](const auto&) {}},
n);
}
return glue_sum;
}
auto highest_order_total_glue(glue_scale glue_spec::*scale, const std::vector<node_variant>& nodes)
{
using enum infinity_order;
for (const auto order : {filll, fill, fil, normal})
{
if (const auto glue_sum = sum_of_glue_by_order(order, scale, nodes); glue_sum != 0)
return std::pair(order, glue_sum);
}
return std::pair(normal, dist_t{0});
}
glue_param calculate_glue_param(const dist_t width_diff, const std::vector<node_variant>& nodes,
glue_scale glue_spec::*scale_direction, const double sign)
{
const auto [order, sum] = highest_order_total_glue(scale_direction, nodes);
if (sum == 0) return {};
const auto scale = sign * static_cast<double>(width_diff) / static_cast<double>(sum);
return {.scale = scale, .order = order};
}
}
glue_param calculate_glue(const dist_t width_diff, const std::vector<node_variant>& nodes)
{
if (width_diff > 0) return calculate_glue_param(width_diff, nodes, &glue_spec::stretch, 1.0);
if (width_diff < 0) return calculate_glue_param(width_diff, nodes, &glue_spec::shrink, -1.0);
return {};
}
}