Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
Add Color::hlc constructor #70
Add Color::hlc constructor #70
Changes from 1 commit
e45d8d0
74b867c
d03cba2
41bcc03
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a useful function, but it's weird in the context of the other color constructors, which take
u32
.Thinking about this a bit more, I think that having those other constructors accept
u32
is a mistake, especially in light of the new hlc constructor. It would make more sense ifrgb
just took threeu8
s, andrgba
took four.This also makes me wonder if we couldn't have a
ColorComponent
and/orAlphaComponent
trait, that could be implemented forf64
and foru8
. It would also be nice if we had bounded numeric types (not sure if there's a better term here) so we could havef64<0..=1>
andf64<0..=100>
or something similar to verify inputs.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this is all deep waters. Color is one of those fantastically deep and complex topics, and I consciously want to avoid that - most actual 2D rendering API's represent it with 32 bits of state, and I want to respect that.
Adding extra traits gives me a YAGNI feeling. My feeling here is that we need to start with the requirements of what it actually does, (to which there's virtually no bottom), then design the type to support that. What it does today is a 32 bit RGBA value.
I hope I've addressed some of your uneasiness by having the low level constructors named with the number of bits. The ones that don't have specific bit naming take higher level, less representation-specific components.
This is tricky territory, and I don't mean to fight. I'm very open to improvements that don't bring in needless complexity or performance issues and move us towards a more principled approach to color. But I think it's not obvious now what that is, and I'd like to defer the deep stuff until we actually need it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would having an additional
with_alpha8
feel more orthogonal? Then most of the basic constructors have both 8 bit per sample and float variants.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I'm happy to represent this with 32 bits internally, but it isn't clear that there's any advantage to taking a
u32
instead of 1, 3, or 4u8
s. In particular, I find that needing to include type information in the method name is unidiomatic, when we could easily have that information contained in the signature; i.e. withrgb(r: u8, b: u8, g: u8) -> Color
, andrgba(r: u8, b: u8, g: u8, a: u8) -> Color
.When I think about adding a new trait, my main thinking is that it would be nice to say
with_alpha(0xAA)
orwith_alpha(0.66)
; a minor point of convenience.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I think I see the point. I think a sticking point for me is how
1
should be interpreted. Currently it'sInto<f64>
so becomes 1.0. Having1
and1.0
behave (very) differently seems maybe confusing.Btw, with the ranged types, for wide gamut values outside the normal range are potentially useful.
To me the advantage of u32 is that you can pass around in a single scalar, rather than doing byte packing and unpacking.
I get what you're saying about the type info in the method name being unidiomatic, but it feels okay to me because it's a very specific representation. To me, the goal of the color type is not to create an abstraction, but to make the existing low level representation a bit more principled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the particular argument for splitting up the input argument for
rgb
is that it lets us have all of our constructor signatures match.Also, in use when I type
Color::rgb24(0x_FF_00_00)
I'm already basically typing three different arguments, I'm just separating them with_
instead of,
; and for legibility I'm generally going to need to include all the fields, so I'm never going to be writing likeColor::rgb24(1337)
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so yea, let's limit this discussion to whether or not it is better, in constructor functions, to take arguments as a single
u32
or multipleu8
s. I am happy to store a singleu32
internally, and I'm happy to shelve any talk about fancy traits, at least for the time being.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I take your ergonomics point about the value of having
(r: u8, g: u8, b: u8)
as one possible constructor signature, and would be open to renaming the existingrgba32
methodfrom_rgba32
to emphasize that it's more of a representation conversion than a constructor. But then what happens to the float constructor? I'm looking at CSS and not feeling a lot of guidance, their rgb function takes threeu8
as you're requesting. It feels maybe a little crufty?What would you say to having
rgb8(u8, u8, u8)
(and similarly 4xu8 for rgba8) and otherwise keeping it as it is (or maybe prefixingfrom_
to the big scalar constructors)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, sorry to clarify my previous point I'm happy to shelve any talk of float constructors for rgb, although I reserve the right to propose something down the road.
In any case, I think that this should probably be a separate PR; this PR mostly just highlighted the discrepancy.
I think I would just call the
(r: u8, g: u8, b: u8)
constructorrgb
, and the(r: u8, g: u8, b: u8, a: u8)
onergba
, e.g. not include the8
; I think they're unambiguous.