21struct LinearGradientNormalized {
28LinearGradientNormalized Normalize(LinearGradient gradient) {
30 if (gradient.stops.empty()) {
31 return LinearGradientNormalized{
39 if (!gradient.stops.front().position) {
40 gradient.stops.front().position = 0.F;
42 if (!gradient.stops.back().position) {
43 gradient.stops.back().position = 1.F;
47 size_t last_checkpoint = 0;
48 for (
size_t i = 1; i < gradient.stops.size(); ++i) {
49 if (!gradient.stops[i].position) {
53 if (i - last_checkpoint >= 2) {
54 const float min = gradient.stops[i].position.value();
56 gradient.stops[last_checkpoint].position.value();
57 for (
size_t j = last_checkpoint + 1; j < i; ++j) {
58 gradient.stops[j].position = min + (max - min) *
59 float(j - last_checkpoint) /
60 float(i - last_checkpoint);
69 gradient.stops.begin(), gradient.stops.end(),
70 [](
const auto& a,
const auto& b) { return a.position < b.position; });
73 if (gradient.stops.front().position != 0) {
74 gradient.stops.insert(gradient.stops.begin(),
75 {gradient.stops.front().color, 0.F});
78 if (gradient.stops.back().position != 1) {
79 gradient.stops.push_back({gradient.stops.back().color, 1.F});
83 LinearGradientNormalized normalized;
84 const float modulo = 360.F;
86 std::fmod(std::fmod(gradient.angle, modulo) + modulo, modulo);
87 for (
auto& stop : gradient.stops) {
88 normalized.colors.push_back(stop.color);
90 normalized.positions.push_back(stop.position.value());
95Color Interpolate(
const LinearGradientNormalized& gradient,
float t) {
102 const float half = 0.5F;
104 gradient.colors.back());
106 if (t <= gradient.positions[i]) {
112 const float t0 = gradient.positions[i - 1];
113 const float t1 = gradient.positions[i - 0];
114 const float tt = (t - t0) / (t1 - t0);
116 const Color& c0 = gradient.colors[i - 1];
117 const Color& c1 = gradient.colors[i - 0];
123class LinearGradientColor :
public NodeDecorator {
125 explicit LinearGradientColor(
Element child,
126 const LinearGradient& gradient,
127 bool background_color)
129 gradient_(Normalize(gradient)),
130 background_color_{background_color} {}
133 void Render(Screen& screen)
override {
134 const float degtorad = 0.01745329251F;
135 const float dx = std::cos(gradient_.angle * degtorad);
136 const float dy = std::sin(gradient_.angle * degtorad);
143 const float min = std::min({p1, p2, p3, p4});
144 const float max = std::max({p1, p2, p3, p4});
147 const float dY = dy / (max - min);
148 const float dZ = -min / (max - min);
151 if (background_color_) {
154 const float t = float(x) * dX + float(y) * dY + dZ;
155 screen.PixelAt(x, y).background_color = Interpolate(gradient_, t);
161 const float t = float(x) * dX + float(y) * dY + dZ;
162 screen.PixelAt(x, y).foreground_color = Interpolate(gradient_, t);
170 LinearGradientNormalized gradient_;
171 bool background_color_;
186LinearGradient::LinearGradient() =
default;
191LinearGradient::LinearGradient(Color begin, Color end)
192 : LinearGradient(0, begin, end) {}
198LinearGradient::LinearGradient(
float a, Color begin, Color end) :
angle(a) {
199 stops.push_back({begin, {}});
200 stops.push_back({end, {}});
215 stops.push_back({c, p});
223LinearGradient& LinearGradient::Stop(Color c) {
224 stops.push_back({c, {}});
239Element
color(
const LinearGradient& gradient, Element child) {
240 return std::make_shared<LinearGradientColor>(std::move(child), gradient,
255Element
bgcolor(
const LinearGradient& gradient, Element child) {
256 return std::make_shared<LinearGradientColor>(std::move(child), gradient,
270Decorator
color(
const LinearGradient& gradient) {
272 [gradient](Element child) {
return color(gradient, std::move(child)); };
285Decorator
bgcolor(
const LinearGradient& gradient) {
287 [gradient](Element child) {
return bgcolor(gradient, std::move(child)); };
NodeDecorator(Element child)
friend void Render(Screen &screen, Node *node, Selection &selection)
Element color(const LinearGradient &gradient, Element child)
使用线性渐变效果设置元素的前景色。
Element bgcolor(const LinearGradient &gradient, Element child)
使用线性渐变效果设置元素的背景色。
static Color Interpolate(float t, const Color &a, const Color &b)
Color
Color 是一个表示终端颜色支持的枚举。
#include "ftxui/component/component_base.hpp" // 用于 ComponentBase
std::shared_ptr< Node > Element
std::vector< Color > colors
std::vector< float > positions