Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: color: add HSV methods to slint #4819

Merged
merged 5 commits into from
Apr 15, 2024
Merged

feat: color: add HSV methods to slint #4819

merged 5 commits into from
Apr 15, 2024

Conversation

flukejones
Copy link
Contributor

TODO:

  • docs
  • finalize naming (brightness or value for v component
  • methods or properties?

@flukejones
Copy link
Contributor Author

Ref issue #911

@flukejones
Copy link
Contributor Author

I had some extra time to play more with this and tried out making it member-field access instead of function - I don't think there's any kind of easy way for me to do that without a new Type::ColorHsva which I don't want to do.

I also didn't want to add more fields on the Color type as that would affect the struct size.

Unless y'all think that adding a new slint type is a good thing to do? If so, I'd best leave it to the pros, otherwise I will complete this PR soon.

@flukejones flukejones marked this pull request as draft April 4, 2024 09:59
@flukejones flukejones changed the title draft: feat: color: add HSV methods to slint feat: color: add HSV methods to slint Apr 4, 2024
Copy link
Member

@ogoffart ogoffart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much for your work.

I'm a bit busy this week, so I won't comment much on the implementation at this point. But I just want to get the API right.

As is, this PR adds:

  • Functions on the Slint color and brush type:
    • hue()->float (return value between 0.0 and 360.0)
    • saturation()->float (return value between 0.0 and 255.0)
    • brightness()->float (return value between 0.0 and 255.0)
  • Functions in the Colors namespace:
    • hsv and hsva which are alias to eachother. It seems that the hue is a float between 0 and 360, when saturation, value, and alpha are flaot between 0.0 and 1.0
  • Rust API on the Color struct
    /// Converts this color to a tuple of `(hue, saturation, value)`
    pub fn to_hsv(&mut self) -> (f32, f32, f32) 
    
    /// Converts this color to a tuple of `(hue, saturation, value, alpha)`
    pub fn to_hsva(&mut self) -> (f32, f32, f32, f32)
    
    /// Construct a color from the hue, saturation, and value HSV color parameters. The alpha
    /// channel will have the value 1.0.
    pub fn from_hsv(hue: f32, saturation: f32, value: f32) -> Self
    
    /// Construct a color from the hue, saturation, and value HSV color parameters.
    pub fn from_hsva(hue: f32, saturation: f32, value: f32, alpha: f32) -> Self 
    
    
    /// Returns the hue channel of the color as f32 in degrees 0..PI.
    pub fn hue(mut self) -> f32
    
    /// Returns the saturation of the color as u8 in the range 0..255.
    pub fn saturation(mut self) -> f32 
    
    /// Returns the brightness of the color as u8 in the range 0..255.
    pub fn brightness(mut self) -> f32
  • Not included in this patch, but something will be needed in the C++ API as well

One thing to note is that the compiler can do transformations so that the Rust API and the slint API don't have to be the same.
For example, wether or not hue is a field or a function in Slint is just a matter of having an Expression::Call or not in the lookup.rs
(for example, red is a field in slint and is calling BuiltinFunction::ColorRgbaStruct in the generated code before accessing a field)
Also you don't need to add a Type::ColorHsva, you can just use anonymous types such as {a: float, h: angle, s: float, v: float} which
is represented in Rust as a tuple (f32, f32, f32, f32) and in C++ std::tuple<float, float, float, float>. This can be an internal detail
in rust.rs and cpp.rs which is not part of the C++ and Rust API.

Given that, we have much freedom to do anything.

So my comments/questions on the API

  1. for the hue in Slint: should we use the angle type or the float type or the int type? I think i'd go with float since one probably want to do some math on it and not do backround.hue/1deg all the time.
  2. for the brightness and saturation, it is sometimes between 0 and 1 and sometimes between 0 and 255, this is not consistent. I'd use the 0 to 1 range consistently. Although we must also consider what the rgb or alpha values are.
  3. I have commented on the Slint API in this comment Add properties to the color type to get HSV component #911 (comment) , I think it should either be a field: background.hue or a function that return an anonymous type: background.to-hsv().h the later would allow to dinstinguish the saturation between the HSV and HSL color space.
  4. Do we need both Colors.hsv and Colors.hsva? rgb and rgba both exist for consistency with CSS, but there is no hsv in CSS. (there is hsl() and a bunch of other) I'd go with only the former.
  5. For the Rust API, we probably don't need both to_hsv and the getter on each component. I wonder if the best would not be to make the HsvaColor type public and have conversion between these. Otherwise i think a tuple is not that bad. But the range needs to be well documented. (and if we go for the 0..255, it should probably be u8)
  6. Same for the C++ API

@tronical: opinions on the API?

@flukejones
Copy link
Contributor Author

1. for the hue in Slint: should we use the `angle` type or the `float` type or the `int` type? I think i'd go with float since one probably want to do some math on it and not do `backround.hue/1deg` all the time.

I agree with this. The reason I need hsv myself is because I want to do math on it.

2. for the brightness and saturation, it is sometimes between 0 and 1 and sometimes between 0 and 255, this is not consistent.

Documentation mistake by me. Corrected now.

3. I have commented on the Slint API in this comment [Add properties to the color type to get HSV component #911 (comment)](https://github.com/slint-ui/slint/issues/911#issuecomment-1980970787) , I think it should either be a field: `background.hue` or a function that return an anonymous type: `background.to-hsv().h` the later would allow to dinstinguish the saturation between the HSV and HSL color space.

One of my concerns was the addition of extra colourspaces. So I agree with later option.

4. Do we need both Colors.hsv and Colors.hsva? rgb and rgba both exist for consistency with CSS, but there is no hsv in CSS. (there is hsl() and a bunch of other) I'd go with only the former.

No alpha?

5. For the Rust API, we probably don't need both to_hsv and the getter on each component. I wonder if the best would not be to make the `HsvaColor` type public and have conversion between these.  Otherwise i think a tuple is not that bad. But the range needs to be well documented.  (and if we go for the 0..255, it should probably be u8)

I would prefer making HsvaColor public myself. It's already there and opens the door to more types of colour handling.

@flukejones
Copy link
Contributor Author

flukejones commented Apr 8, 2024

I'm afraid I will have to leave this as is now. I have too many tasks at work. I converted to struct member access with the goal of getting to some_colour.hsva().hue but how to accomplish this is not clear to me and I don't have enough time to invest.

If a clear example of how to achieve some_colour.hsva().hue could be provided I might be able to take one more crack at it otherwise..

@tronical or @ogoffart if one of you could please take over?

@flukejones
Copy link
Contributor Author

Please also note I have not touched the C++ bindings - this is not one of my strong suits

@ogoffart ogoffart marked this pull request as ready for review April 15, 2024 11:26
@ogoffart ogoffart requested a review from tronical April 15, 2024 11:26
@ogoffart
Copy link
Member

Updated the pr to add a to-hsv() function

@ogoffart ogoffart merged commit 0f05089 into slint-ui:master Apr 15, 2024
35 of 36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants