23struct LinearGradientNormalized {
30LinearGradientNormalized Normalize(LinearGradient gradient) {
32 if (gradient.stops.empty()) {
33 return LinearGradientNormalized{
41 if (!gradient.stops.front().position) {
42 gradient.stops.front().position = 0.F;
44 if (!gradient.stops.back().position) {
45 gradient.stops.back().position = 1.F;
49 size_t last_checkpoint = 0;
50 for (
size_t i = 1; i < gradient.stops.size(); ++i) {
51 if (!gradient.stops[i].position) {
55 if (i - last_checkpoint >= 2) {
56 const float min = gradient.stops[i].position.value();
58 gradient.stops[last_checkpoint].position.value();
59 for (
size_t j = last_checkpoint + 1; j < i; ++j) {
60 gradient.stops[j].position = min + (max - min) *
61 float(j - last_checkpoint) /
62 float(i - last_checkpoint);
71 gradient.stops.begin(), gradient.stops.end(),
72 [](
const auto& a,
const auto& b) { return a.position < b.position; });
75 if (gradient.stops.front().position != 0) {
76 gradient.stops.insert(gradient.stops.begin(),
77 {gradient.stops.front().color, 0.F});
80 if (gradient.stops.back().position != 1) {
81 gradient.stops.push_back({gradient.stops.back().color, 1.F});
85 LinearGradientNormalized normalized;
86 const float modulo = 360.F;
88 std::fmod(std::fmod(gradient.angle, modulo) + modulo, modulo);
89 for (
auto& stop : gradient.stops) {
90 normalized.colors.push_back(stop.color);
92 normalized.positions.push_back(stop.position.value());
97Color 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} {}
136 void Render(Screen& screen)
override {
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});
150 const float dX = dx / (max - min);
151 const float dY = dy / (max - min);
152 const float dZ = -min / (max - min);
155 if (background_color_) {
156 for (
int y = box_.y_min; y <= box_.y_max; ++y) {
157 for (
int x = box_.x_min; x <= box_.x_max; ++x) {
158 const float t = float(x) * dX + float(y) * dY + dZ;
159 screen.PixelAt(x, y).background_color = Interpolate(gradient_, t);
163 for (
int y = box_.y_min; y <= box_.y_max; ++y) {
164 for (
int x = box_.x_min; x <= box_.x_max; ++x) {
165 const float t = float(x) * dX + float(y) * dY + dZ;
166 screen.PixelAt(x, y).foreground_color = Interpolate(gradient_, t);
174 LinearGradientNormalized gradient_;
175 bool background_color_;
204 stops.push_back({begin, {}});
205 stops.push_back({end, {}});
220 stops.push_back({c, p});
229 stops.push_back({c, {}});
245 return std::make_shared<LinearGradientColor>(std::move(child), gradient,
261 return std::make_shared<LinearGradientColor>(std::move(child), gradient,
277 [gradient](
Element child) {
return color(gradient, std::move(child)); };
292 [gradient](
Element child) {
return bgcolor(gradient, std::move(child)); };
LinearGradient & Stop(Color color, float position)
グラデーションにカラーストップを追加します。
LinearGradient & Angle(float angle)
グラデーションの角度を設定します。
LinearGradient()
「空の」グラデーションを構築します。これはしばしば LinearGradient::Angle() および LinearGradient::Stop() の呼び出しが続きます。 例:
std::vector< Stop > stops
friend void Render(Screen &screen, Node *node, Selection &selection)
Decorator bgcolor(Color)
背景色を使用して装飾します。
void Render(Screen &screen, const Element &element)
要素をftxui::Screenに表示します。
Decorator color(Color)
前景色を使用して装飾します。
線形グラデーションカラー効果の設定を表すクラスです。
static Color Interpolate(float t, const Color &a, const Color &b)
Colorは、ターミナルユーザーインターフェースにおける色を表すクラスです。
Color
Colorは、ターミナルの色サポートを表す列挙型です。
std::function< Element(Element)> Decorator
std::shared_ptr< Node > Element
std::vector< Color > colors
std::vector< float > positions