mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-05-05 22:01:13 +08:00
Fix linear_gradient float precision bug.
This was reported by: https://github.com/ArthurSonzogni/FTXUI/issues/998 Indeed, the `t` interpolation factor, which is itself interpolated might become slightly larger than 1.0. This is due to the float precision. This was supposedly handled, but there was an off-by-one error in the check. Along the way, fix a bug found by a fuzzer. Bug: https://github.com/ArthurSonzogni/FTXUI/issues/998 Fixed: https://github.com/ArthurSonzogni/FTXUI/issues/998
This commit is contained in:
parent
15587dad01
commit
d75108e960
@ -44,6 +44,9 @@ current (development)
|
|||||||
See #932
|
See #932
|
||||||
- Feature: Add `SliderOption::on_change`. This allows to set a callback when the
|
- Feature: Add `SliderOption::on_change`. This allows to set a callback when the
|
||||||
slider value changes. See #938.
|
slider value changes. See #938.
|
||||||
|
- Bugfix: Handle `Dropdown` with no entries.
|
||||||
|
- Bugfix: Fix crash in `LinearGradient` due to float precision and an off-by-one
|
||||||
|
mistake. See #998.
|
||||||
|
|
||||||
### Dom
|
### Dom
|
||||||
- Feature: Add `hscroll_indicator`. It display an horizontal indicator
|
- Feature: Add `hscroll_indicator`. It display an horizontal indicator
|
||||||
|
@ -83,10 +83,6 @@ function(ftxui_set_options library)
|
|||||||
target_compile_options(${library} PRIVATE "-Wpedantic")
|
target_compile_options(${library} PRIVATE "-Wpedantic")
|
||||||
target_compile_options(${library} PRIVATE "-Wshadow")
|
target_compile_options(${library} PRIVATE "-Wshadow")
|
||||||
target_compile_options(${library} PRIVATE "-Wunused")
|
target_compile_options(${library} PRIVATE "-Wunused")
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
|
||||||
target_compile_options(${library} PRIVATE "-Wuseless-cast")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ add_executable(ftxui-tests
|
|||||||
src/ftxui/component/component_test.cpp
|
src/ftxui/component/component_test.cpp
|
||||||
src/ftxui/component/component_test.cpp
|
src/ftxui/component/component_test.cpp
|
||||||
src/ftxui/component/container_test.cpp
|
src/ftxui/component/container_test.cpp
|
||||||
|
src/ftxui/component/dropdown_test.cpp
|
||||||
src/ftxui/component/hoverable_test.cpp
|
src/ftxui/component/hoverable_test.cpp
|
||||||
src/ftxui/component/input_test.cpp
|
src/ftxui/component/input_test.cpp
|
||||||
src/ftxui/component/menu_test.cpp
|
src/ftxui/component/menu_test.cpp
|
||||||
|
@ -47,7 +47,11 @@ Component Dropdown(DropdownOption option) {
|
|||||||
Element Render() override {
|
Element Render() override {
|
||||||
radiobox.selected =
|
radiobox.selected =
|
||||||
util::clamp(radiobox.selected(), 0, int(radiobox.entries.size()) - 1);
|
util::clamp(radiobox.selected(), 0, int(radiobox.entries.size()) - 1);
|
||||||
title_ = radiobox.entries[selected_()];
|
selected_ = util::clamp(selected_(), 0, int(radiobox.entries.size()) - 1);
|
||||||
|
|
||||||
|
if (selected_() >= 0) {
|
||||||
|
title_ = radiobox.entries[selected_()];
|
||||||
|
}
|
||||||
|
|
||||||
return transform(*open_, checkbox_->Render(), radiobox_->Render());
|
return transform(*open_, checkbox_->Render(), radiobox_->Render());
|
||||||
}
|
}
|
||||||
|
34
src/ftxui/component/dropdown_test.cpp
Normal file
34
src/ftxui/component/dropdown_test.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Copyright 2025 Arthur Sonzogni. All rights reserved.
|
||||||
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
|
// the LICENSE file.
|
||||||
|
|
||||||
|
#include "ftxui/component/component.hpp" // for Horizontal, Vertical, Button, Tab
|
||||||
|
#include "ftxui/component/component_base.hpp" // for ComponentBase, Component
|
||||||
|
#include "ftxui/component/event.hpp" // for Event, Event::Tab, Event::TabReverse, Event::ArrowDown, Event::ArrowLeft, Event::ArrowRight, Event::ArrowUp
|
||||||
|
#include "gtest/gtest.h" // for AssertionResult, Message, TestPartResult, EXPECT_EQ, EXPECT_FALSE, Test, EXPECT_TRUE, TEST
|
||||||
|
|
||||||
|
namespace ftxui {
|
||||||
|
|
||||||
|
TEST(DropdownTest, Empty) {
|
||||||
|
std::vector<std::string> list = {};
|
||||||
|
int index = 0;
|
||||||
|
auto dropdown = Dropdown(list, &index);
|
||||||
|
|
||||||
|
dropdown->OnEvent(Event::Return);
|
||||||
|
|
||||||
|
auto screen = Screen(8, 8);
|
||||||
|
auto document = dropdown->Render();
|
||||||
|
Render(screen, document);
|
||||||
|
|
||||||
|
EXPECT_EQ(screen.ToString(),
|
||||||
|
"╭──────╮\r\n"
|
||||||
|
"│↓ │\r\n"
|
||||||
|
"├──────┤\r\n"
|
||||||
|
"│ │\r\n"
|
||||||
|
"│ │\r\n"
|
||||||
|
"│ │\r\n"
|
||||||
|
"│ │\r\n"
|
||||||
|
"╰──────╯");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ftxui
|
@ -97,7 +97,11 @@ Color Interpolate(const LinearGradientNormalized& gradient, float t) {
|
|||||||
// Find the right color in the gradient's stops.
|
// Find the right color in the gradient's stops.
|
||||||
size_t i = 1;
|
size_t i = 1;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (i > gradient.positions.size()) {
|
// Note that `t` might be slightly greater than 1.0 due to floating point
|
||||||
|
// precision. This is why we need to handle the case where `t` is greater
|
||||||
|
// than the last stop's position.
|
||||||
|
// See https://github.com/ArthurSonzogni/FTXUI/issues/998
|
||||||
|
if (i >= gradient.positions.size()) {
|
||||||
const float half = 0.5F;
|
const float half = 0.5F;
|
||||||
return Color::Interpolate(half, gradient.colors.back(),
|
return Color::Interpolate(half, gradient.colors.back(),
|
||||||
gradient.colors.back());
|
gradient.colors.back());
|
||||||
|
Loading…
Reference in New Issue
Block a user