-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Optional and opaque RGB colors #2472
Changes from 1 commit
5055657
a831e39
2144b51
e3b5353
cfd14f1
c657a9f
af1fdb1
7b6acf0
ef4ce69
cc2e262
a991d23
c298ab3
1b52a67
cac064b
3326c92
ec9a027
30f203d
b6f37c1
3f4ca14
d565a89
439b985
6184663
666422c
bcf18b9
5e41678
b31edfd
bc2fed7
a864454
18b6ffe
fc6a36a
3df8889
dc597b0
14a29f8
f6b781c
06d393e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,8 @@ | |
|
||
#include <QColor> | ||
|
||
#include <optional> | ||
|
||
#include "util/assert.h" | ||
|
||
namespace mixxx { | ||
|
@@ -28,28 +30,39 @@ class RgbColor { | |
// matches an RgbColor! Otherwise a debug assertion will | ||
// be triggered. | ||
/*non-explicit*/ RgbColor(RgbColorCode code) | ||
: m_color(toQColor(code)) { | ||
DEBUG_ASSERT(m_color == normalizeQColor(m_color)); | ||
: m_color(codeToColor(code)) { | ||
DEBUG_ASSERT(m_color == normalizeColor(m_color)); | ||
} | ||
/*non-explicit*/ RgbColor(std::optional<RgbColorCode> optionalCode) | ||
: m_color(optionalCodeToColor(optionalCode)) { | ||
DEBUG_ASSERT(m_color == normalizeColor(m_color)); | ||
} | ||
/*non-explicit*/ RgbColor(QColor color) | ||
: m_color(color) { | ||
DEBUG_ASSERT(m_color == normalizeQColor(m_color)); | ||
DEBUG_ASSERT(m_color == normalizeColor(m_color)); | ||
} | ||
|
||
// Check that the provided color code is valid. | ||
static bool isValidCode(RgbColorCode code) { | ||
return code == (code & kRgbCodeMask); | ||
} | ||
uklotzde marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// Explicit conversions with normalization. | ||
// Explicit conversions with implicit normalization. | ||
// Use these static functions instead of the conversion | ||
// constructors to ensure that the resulting RgbColor is | ||
// well defined. | ||
static RgbColor fromCode(RgbColorCode code) { | ||
return RgbColor(normalizeCode(code)); | ||
return RgbColor(code & kRgbCodeMask); | ||
} | ||
static RgbColor fromOptionalCode(std::optional<RgbColorCode> code) { | ||
if (code.has_value()) { | ||
return fromCode(code.value()); | ||
} else { | ||
return RgbColor(); | ||
} | ||
} | ||
static RgbColor fromQColor(QColor color) { | ||
return RgbColor(normalizeQColor(color)); | ||
static RgbColor fromColor(QColor color) { | ||
return RgbColor(normalizeColor(color)); | ||
} | ||
|
||
// Implicit conversion into the corresponding QColor. | ||
|
@@ -64,22 +77,9 @@ class RgbColor { | |
return m_color.isValid(); | ||
} | ||
|
||
// Returns the corresponding RGB color code of a valid color. | ||
// Validity is a prerequisite and only checked by a debug | ||
// assertion. | ||
RgbColorCode code() const { | ||
DEBUG_ASSERT(isValid()); | ||
return toCode(m_color); | ||
} | ||
|
||
// Returns the corresponding RGB color code of a valid color | ||
// or the provided color code if the color is not valid. | ||
RgbColorCode codeOr(RgbColorCode codeIfNotValid) const { | ||
if (isValid()) { | ||
return code(); | ||
} else { | ||
return codeIfNotValid; | ||
} | ||
// Returns the corresponding, optional RGB color code. | ||
std::optional<RgbColorCode> optionalCode() const { | ||
return colorToOptionalCode(m_color); | ||
} | ||
|
||
friend bool operator==(const RgbColor& lhs, const RgbColor& rhs) { | ||
|
@@ -90,23 +90,36 @@ class RgbColor { | |
static const RgbColorCode kRgbCodeMask = 0x00FFFFFF; | ||
static const RgbColorCode kAlphaCodeMask = 0xFF000000; | ||
|
||
static QColor toQColor(RgbColorCode code) { | ||
static QColor codeToColor(RgbColorCode code) { | ||
DEBUG_ASSERT(isValidCode(code)); | ||
return QColor(code | kAlphaCodeMask); | ||
} | ||
static RgbColorCode normalizeCode(RgbColorCode code) { | ||
return code & kRgbCodeMask; | ||
} | ||
static QColor normalizeQColor(QColor color) { | ||
if (color.isValid()) { | ||
return toQColor(toCode(color)); | ||
static QColor optionalCodeToColor(std::optional<RgbColorCode> optionalCode) { | ||
if (optionalCode.has_value()) { | ||
return codeToColor(optionalCode.value()); | ||
} else { | ||
return QColor(); | ||
} | ||
} | ||
static RgbColorCode toCode(QColor color) { | ||
|
||
static RgbColorCode validColorToCode(QColor color) { | ||
DEBUG_ASSERT(color.isValid()); | ||
return normalizeCode(color.rgb()); | ||
return color.rgb() & kRgbCodeMask; | ||
} | ||
static std::optional<RgbColorCode> colorToOptionalCode(QColor color) { | ||
if (color.isValid()) { | ||
return std::make_optional(validColorToCode(color)); | ||
} else { | ||
return std::nullopt; | ||
} | ||
} | ||
|
||
static QColor normalizeColor(QColor color) { | ||
if (color.isValid()) { | ||
return codeToColor(validColorToCode(color)); | ||
} else { | ||
return QColor(); | ||
} | ||
} | ||
|
||
QColor m_color; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean this: RgbColorCode m_color There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Nope. Alpha = 0x00 is transparent. We agreed on using We could also store There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that was the Idea to keep the whole thing performant. What is the public API you reffering to? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Let's be clear with language. These are not identical concepts. There are contexts in which transparent is a valid value such as track color; calling it invalid would be a misnomer. |
||
|
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.
@uklotzde Is it ok if I move this class into the Color namespace in my cue color branch?
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.
Please coordinate this with @Holzhaus to avoid merge conflicts. Better do it in a separate PR that is expected to be merged quickly.`
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.
Please also note that namespace names should be lowercase:
https://google.github.io/styleguide/cppguide.html#Namespace_Names
The
Color
namespace violates this rule.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.
@ferranpujolcamins Do we actually need a separate
color
namespace withinmixxx
for just a bunch of classes, all with color in their class name?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.
The color namespace was there to group some free functions. We can reuse it to include your class. But it doesn't really matter to me. Just let me know what you think it's best.
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.
With argument dependent lookup and function overloading available in C++ there is no need to hide free functions in artificial namespaces. Or do I miss a use case?
We are free to chose whatever works best for us. However keep an eye on discoverability and developer experience in general.