22struct LinearGradientNormalized {
29LinearGradientNormalized Normalize(LinearGradient gradient) {
31 if (gradient.stops.empty()) {
32 return LinearGradientNormalized{
40 if (!gradient.stops.front().position) {
41 gradient.stops.front().position = 0.F;
43 if (!gradient.stops.back().position) {
44 gradient.stops.back().position = 1.F;
48 size_t last_checkpoint = 0;
49 for (
size_t i = 1; i < gradient.stops.size(); ++i) {
50 if (!gradient.stops[i].position) {
54 if (i - last_checkpoint >= 2) {
55 const float min = gradient.stops[i].position.value();
57 gradient.stops[last_checkpoint].position.value();
58 for (
size_t j = last_checkpoint + 1; j < i; ++j) {
59 gradient.stops[j].position = min + (max - min) *
60 float(j - last_checkpoint) /
61 float(i - last_checkpoint);
70 gradient.stops.begin(), gradient.stops.end(),
71 [](
const auto& a,
const auto& b) { return a.position < b.position; });
74 if (gradient.stops.front().position != 0) {
75 gradient.stops.insert(gradient.stops.begin(),
76 {gradient.stops.front().color, 0.F});
79 if (gradient.stops.back().position != 1) {
80 gradient.stops.push_back({gradient.stops.back().color, 1.F});
84 LinearGradientNormalized normalized;
85 const float modulo = 360.F;
87 std::fmod(std::fmod(gradient.angle, modulo) + modulo, modulo);
88 for (
auto& stop : gradient.stops) {
89 normalized.colors.push_back(stop.color);
91 normalized.positions.push_back(stop.position.value());
96Color Interpolate(
const LinearGradientNormalized& gradient,
float t) {
104 if (i >= gradient.positions.size()) {
105 const float half = 0.5F;
107 gradient.colors.back());
109 if (t <= gradient.positions[i]) {
115 const float t0 = gradient.positions[i - 1];
116 const float t1 = gradient.positions[i - 0];
117 const float tt = (t - t0) / (t1 - t0);
119 const Color& c0 = gradient.colors[i - 1];
120 const Color& c1 = gradient.colors[i - 0];
126class LinearGradientColor :
public NodeDecorator {
128 explicit LinearGradientColor(
Element child,
129 const LinearGradient& gradient,
130 bool background_color)
131 : NodeDecorator(std::move(child)),
132 gradient_(Normalize(gradient)),
133 background_color_{background_color} {}
137 const float degtorad = 0.01745329251F;
138 const float dx = std::cos(gradient_.angle * degtorad);
139 const float dy = std::sin(gradient_.angle * degtorad);
142 const float p1 = float(box_.x_min) * dx + float(box_.y_min) * dy;
143 const float p2 = float(box_.x_min) * dx + float(box_.y_max) * dy;
144 const float p3 = float(box_.x_max) * dx + float(box_.y_min) * dy;
145 const float p4 = float(box_.x_max) * dx + float(box_.y_max) * dy;
146 const float min = std::min({p1, p2, p3, p4});
147 const float max = std::max({p1, p2, p3, p4});
151 const float dX = dx / (max - min);
152 const float dY = dy / (max - min);
153 const float dZ = -min / (max - min);
156 if (background_color_) {
157 for (
int y = box_.y_min; y <= box_.y_max; ++y) {
158 for (
int x = box_.x_min; x <= box_.x_max; ++x) {
159 const float t = float(x) * dX + float(y) * dY + dZ;
160 screen.PixelAt(x, y).background_color = Interpolate(gradient_, t);
164 for (
int y = box_.y_min; y <= box_.y_max; ++y) {
165 for (
int x = box_.x_min; x <= box_.x_max; ++x) {
166 const float t = float(x) * dX + float(y) * dY + dZ;
167 screen.PixelAt(x, y).foreground_color = Interpolate(gradient_, t);
175 LinearGradientNormalized gradient_;
176 bool background_color_;
205 stops.push_back({begin, {}});
206 stops.push_back({end, {}});
221 stops.push_back({c, p});
230 stops.push_back({c, {}});
246 return std::make_shared<LinearGradientColor>(std::move(child), gradient,
262 return std::make_shared<LinearGradientColor>(std::move(child), gradient,
278 [gradient](
Element child) {
return color(gradient, std::move(child)); };
293 [gradient](
Element child) {
return bgcolor(gradient, std::move(child)); };
LinearGradient & Stop(Color color, float position)
Añade una parada de color al gradiente.
LinearGradient & Angle(float angle)
Establece el ángulo del gradiente.
LinearGradient()
Construye el gradiente "vacío". Esto a menudo es seguido por llamadas a LinearGradient::Angle() y Lin...
std::vector< Stop > stops
friend void Render(Screen &screen, Node *node, Selection &selection)
Decorator bgcolor(Color)
Decora usando un color de fondo.
void Render(Screen &screen, const Element &element)
Muestra un elemento en un ftxui::Screen.
Decorator color(Color)
Decora usando un color de primer plano.
Una clase que representa la configuración para el efecto de color de gradiente lineal.
static Color Interpolate(float t, const Color &a, const Color &b)
Color es una clase que representa un color en la interfaz de usuario de la terminal.
Color
Color es una enumeración que representa el soporte de color de la terminal.
El espacio de nombres ftxui:: de FTXUI.
std::function< Element(Element)> Decorator
std::shared_ptr< Node > Element
std::vector< Color > colors
std::vector< float > positions