mirror of
https://github.com/slint-ui/slint.git
synced 2025-07-15 09:05:39 +00:00
Fix conversion to from float to int
Round the value. The previous behavior is that - For the interpreter, we were rounding (same as new behavior) - for Rust and C++ we were truncating, unless the properties were inlinined and then we were keeping it as float
This commit is contained in:
parent
ef92c1a161
commit
f5d003d1e2
5 changed files with 59 additions and 27 deletions
|
@ -286,9 +286,10 @@ conversions are allowed between some types for convenience.
|
|||
|
||||
The following conversions are possible:
|
||||
|
||||
- `int` can be converted implicitly to `float` and vice-versa
|
||||
- `int` can be converted implicitly to `float` and vice-versa.
|
||||
When converting from `float` to `int`, the value is rounded to the nearest integer.
|
||||
- `int` and `float` can be converted implicitly to `string`
|
||||
- `physical-length` and `length` can be converted implicitly to each other only in
|
||||
- `physical-length`, relative-font-size, and `length` can be converted implicitly to each other only in
|
||||
context where the pixel ratio is known.
|
||||
- the units type (`length`, `physical-length`, `duration`, ...) can't be converted to numbers (`float` or `int`)
|
||||
but they can be divided by themselves to result in a number. Similarly, a number can be multiplied by one of
|
||||
|
@ -297,7 +298,7 @@ The following conversions are possible:
|
|||
- Struct types convert with another struct type if they have the same property names and their types can be converted.
|
||||
The source struct can have either missing properties, or extra properties. But not both.
|
||||
- Arrays generally don't convert between each other. Array literals can be converted if the element types are convertible.
|
||||
- String can be converted to float by using the `to-float` function. That function returns 0 if the string isen't
|
||||
- String can be converted to float by using the `to-float` function. That function returns 0 if the string isn't
|
||||
a valid number. You can check with `is-float()` if the string contains a valid number
|
||||
|
||||
```slint,no-preview
|
||||
|
@ -314,5 +315,6 @@ export component Example {
|
|||
property<string> xxx: "42.1";
|
||||
property<float> xxx1: xxx.to-float(); // 42.1
|
||||
property<bool> xxx2: xxx.is-float(); // true
|
||||
property<int> xxx3: 45.8; // 46
|
||||
}
|
||||
```
|
||||
|
|
|
@ -249,7 +249,7 @@ fn rgb_macro(
|
|||
op: '*',
|
||||
}
|
||||
} else {
|
||||
expr.maybe_convert_to(Type::Int32, &n, diag)
|
||||
expr.maybe_convert_to(Type::Float32, &n, diag)
|
||||
}
|
||||
} else {
|
||||
expr.maybe_convert_to(Type::Float32, &n, diag)
|
||||
|
|
|
@ -345,7 +345,6 @@ use std::num::NonZeroUsize;
|
|||
struct ConditionalIncludes {
|
||||
iostream: Cell<bool>,
|
||||
cstdlib: Cell<bool>,
|
||||
cmath: Cell<bool>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -545,6 +544,7 @@ pub fn generate(
|
|||
file.includes.push("<array>".into());
|
||||
file.includes.push("<limits>".into());
|
||||
file.includes.push("<slint.h>".into());
|
||||
file.includes.push("<cmath>".into());
|
||||
|
||||
for (path, er) in doc.embedded_file_resources.borrow().iter() {
|
||||
match &er.kind {
|
||||
|
@ -879,10 +879,6 @@ pub fn generate(
|
|||
file.includes.push("<cstdlib>".into());
|
||||
}
|
||||
|
||||
if conditional_includes.cmath.get() {
|
||||
file.includes.push("<cmath>".into());
|
||||
}
|
||||
|
||||
file
|
||||
}
|
||||
|
||||
|
@ -2768,11 +2764,14 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
|
|||
Expression::Cast { from, to } => {
|
||||
let f = compile_expression(from, ctx);
|
||||
match (from.ty(ctx), to) {
|
||||
(Type::Float32, Type::Int32) => {
|
||||
format!("std::round({f})")
|
||||
}
|
||||
(from, Type::String) if from.as_unit_product().is_some() => {
|
||||
format!("slint::SharedString::from_number({})", f)
|
||||
}
|
||||
(Type::Float32, Type::Model) | (Type::Int32, Type::Model) => {
|
||||
format!("std::make_shared<slint::private_api::UIntModel>(std::max(0, {}))", f)
|
||||
format!("std::make_shared<slint::private_api::UIntModel>(std::max<int>(0, {}))", f)
|
||||
}
|
||||
(Type::Array(_), Type::Model) => f,
|
||||
(Type::Float32, Type::Color) => {
|
||||
|
@ -3131,59 +3130,45 @@ fn compile_builtin_function_call(
|
|||
format!("std::cout << {} << std::endl;", a.join("<<"))
|
||||
}
|
||||
BuiltinFunction::Mod => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::fmod({}, {})", a.next().unwrap(), a.next().unwrap())
|
||||
}
|
||||
BuiltinFunction::Round => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::round({})", a.next().unwrap())
|
||||
}
|
||||
BuiltinFunction::Ceil => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::ceil({})", a.next().unwrap())
|
||||
}
|
||||
BuiltinFunction::Floor => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::floor({})", a.next().unwrap())
|
||||
}
|
||||
BuiltinFunction::Sqrt => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::sqrt({})", a.next().unwrap())
|
||||
}
|
||||
BuiltinFunction::Abs => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::abs({})", a.next().unwrap())
|
||||
}
|
||||
BuiltinFunction::Log => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::log({}) / std::log({})", a.next().unwrap(), a.next().unwrap())
|
||||
}
|
||||
BuiltinFunction::Pow => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::pow(({}), ({}))", a.next().unwrap(), a.next().unwrap())
|
||||
}
|
||||
BuiltinFunction::Sin => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::sin(({}) * {})", a.next().unwrap(), pi_180)
|
||||
}
|
||||
BuiltinFunction::Cos => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::cos(({}) * {})", a.next().unwrap(), pi_180)
|
||||
}
|
||||
BuiltinFunction::Tan => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::tan(({}) * {})", a.next().unwrap(), pi_180)
|
||||
}
|
||||
BuiltinFunction::ASin => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::asin({}) / {}", a.next().unwrap(), pi_180)
|
||||
}
|
||||
BuiltinFunction::ACos => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::acos({}) / {}", a.next().unwrap(), pi_180)
|
||||
}
|
||||
BuiltinFunction::ATan => {
|
||||
ctx.generator_state.conditional_includes.cmath.set(true);
|
||||
format!("std::atan({}) / {}", a.next().unwrap(), pi_180)
|
||||
}
|
||||
BuiltinFunction::SetFocusItem => {
|
||||
|
|
|
@ -1987,6 +1987,9 @@ fn compile_expression(expr: &Expression, ctx: &EvaluationContext) -> TokenStream
|
|||
Expression::Cast { from, to } => {
|
||||
let f = compile_expression(from, ctx);
|
||||
match (from.ty(ctx), to) {
|
||||
(Type::Float32, Type::Int32) => {
|
||||
quote!(((#f as f32).round() as i32))
|
||||
}
|
||||
(from, Type::String) if from.as_unit_product().is_some() => {
|
||||
quote!(sp::SharedString::from(sp::format!("{}", #f).as_str()))
|
||||
}
|
||||
|
@ -2645,9 +2648,9 @@ fn compile_builtin_function_call(
|
|||
let (r, g, b, a) =
|
||||
(a.next().unwrap(), a.next().unwrap(), a.next().unwrap(), a.next().unwrap());
|
||||
quote!({
|
||||
let r: u8 = (#r as u32).max(0).min(255) as u8;
|
||||
let g: u8 = (#g as u32).max(0).min(255) as u8;
|
||||
let b: u8 = (#b as u32).max(0).min(255) as u8;
|
||||
let r: u8 = (#r as u32).min(255) as u8;
|
||||
let g: u8 = (#g as u32).min(255) as u8;
|
||||
let b: u8 = (#b as u32).min(255) as u8;
|
||||
let a: u8 = (255. * (#a as f32)).max(0.).min(255.) as u8;
|
||||
sp::Color::from_argb_u8(a, r, g, b)
|
||||
})
|
||||
|
|
42
tests/cases/types/int_conversion.slint
Normal file
42
tests/cases/types/int_conversion.slint
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
||||
|
||||
export component TestCase {
|
||||
|
||||
property <float> float-var: 26.7;
|
||||
// Going through a private property of type int should really cast to int
|
||||
private property <int> tens-digit-var: float-var / 10;
|
||||
|
||||
// test that it rounds
|
||||
out property <int> int-val: -7.6;
|
||||
|
||||
out property <string> text: tens-digit-var;
|
||||
out property <bool> test: tens-digit-var == 3 && text == "3" && int-val == -8;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
```cpp
|
||||
auto handle = TestCase::create();
|
||||
const TestCase &instance = *handle;
|
||||
assert_eq(instance.get_text(), "3");
|
||||
assert_eq(instance.get_int_val(), -8);
|
||||
assert(instance.get_test());
|
||||
```
|
||||
|
||||
```rust
|
||||
let instance = TestCase::new().unwrap();
|
||||
assert_eq!(instance.get_text(), "3");
|
||||
assert_eq!(instance.get_int_val(), -8);
|
||||
assert!(instance.get_test());
|
||||
```
|
||||
|
||||
```js
|
||||
var instance = new slint.TestCase({});
|
||||
assert.equal(instance.text, "3");
|
||||
assert.equal(instance.int_val, -8);
|
||||
assert(instance.test);
|
||||
```
|
||||
|
||||
*/
|
Loading…
Add table
Add a link
Reference in a new issue