Skip to content

Commit

Permalink
Add implicit/explicit conversion functions from Rgba<U> to Rgba<T> etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
adamkewley committed Aug 29, 2024
1 parent 44032cd commit 6539793
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 37 deletions.
22 changes: 1 addition & 21 deletions src/oscar/Graphics/Color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,6 @@ Color osc::lerp(const Color& a, const Color& b, float t)
return Color{lerp(Vec4{a}, Vec4{b}, saturate(t))};
}

Color32 osc::to_color32(const Color& color)
{
return to_color32(static_cast<Vec4>(color));
}

Color32 osc::to_color32(const Vec4& vec)
{
return Color32{vec.x, vec.y, vec.z, vec.w};
}

Color32 osc::to_color32(float r, float g, float b, float a)
{
return Color32{r, g, b, a};
Expand All @@ -157,16 +147,6 @@ Color32 osc::to_color32(uint32_t v)
};
}

Color osc::to_color(Color32 color)
{
return Color{
color.r.normalized_value(),
color.g.normalized_value(),
color.b.normalized_value(),
color.a.normalized_value(),
};
}

Color osc::clamp_to_ldr(const Color& color)
{
return Color{saturate(Vec4{color})};
Expand Down Expand Up @@ -229,7 +209,7 @@ std::string osc::to_html_string_rgba(const Color& color)
std::string rv;
rv.reserve(9);
rv.push_back('#');
for (auto component : to_color32(color)) {
for (auto component : Color32{color}) {
auto [nibble_1, nibble_2] = to_hex_chars(static_cast<uint8_t>(component));
rv.push_back(nibble_1);
rv.push_back(nibble_2);
Expand Down
3 changes: 0 additions & 3 deletions src/oscar/Graphics/Color.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,8 @@ namespace osc
Color lerp(const Color& a, const Color& b, float t);

// float-/double-based inputs assume normalized color range (i.e. 0 to 1)
Color32 to_color32(const Color&);
Color32 to_color32(const Vec4&);
Color32 to_color32(float, float, float, float);
Color32 to_color32(uint32_t); // R at MSB
Color to_color(Color32);

// returns the color as a hexadecimal string in the format "#rrggbbaa", as
// commonly-used in web applications, configuration files, etc.
Expand Down
19 changes: 19 additions & 0 deletions src/oscar/Graphics/Rgba.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ namespace osc
r{v.x}, g{v.y}, b{v.z}, a{v.w}
{}

template<ColorComponent U>
requires std::constructible_from<T, const U&>
explicit constexpr Rgba(const Vec<4, U>& v) :
r{static_cast<T>(v.x)},
g{static_cast<T>(v.y)},
b{static_cast<T>(v.z)},
a{static_cast<T>(v.w)}
{}

constexpr Rgba(value_type r_, value_type g_, value_type b_, value_type a_) :
r{r_}, g{g_}, b{b_}, a{a_}
{}
Expand All @@ -152,6 +161,16 @@ namespace osc
r{r_}, g{g_}, b{b_}, a(1.0f)
{}

template<ColorComponent U>
requires std::constructible_from<T, const U&>
explicit (not (std::convertible_to<U, T>))
constexpr Rgba(const Rgba<U>& v) :
r{static_cast<T>(v.r)},
g{static_cast<T>(v.g)},
b{static_cast<T>(v.b)},
a{static_cast<T>(v.a)}
{}

constexpr reference operator[](size_type pos)
{
static_assert(sizeof(Rgba) == 4*sizeof(value_type));
Expand Down
22 changes: 11 additions & 11 deletions tests/testoscar/Graphics/TestColor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ TEST(Color, to_linear_colorspace_followed_by_to_srgb_colorspace_on_Color_returns
ASSERT_NEAR(original_color.a, converted_color.a, tolerance);
}

TEST(Color, to_color32_returns_RGBA32_version_of_the_color)
TEST(Color, conversion_to_Color32_returns_RGBA32_version_of_the_color)
{
const Color color = {0.85f, 0.62f, 0.3f, 0.5f};
const Color32 expected = {
Expand All @@ -265,34 +265,34 @@ TEST(Color, to_color32_returns_RGBA32_version_of_the_color)
static_cast<uint8_t>(color.a * static_cast<float>(0xff)),
};

const Color32 got = to_color32(color);
const Color32 got = Color32{color};

ASSERT_EQ(expected.r, got.r);
ASSERT_EQ(expected.g, got.g);
ASSERT_EQ(expected.b, got.b);
ASSERT_EQ(expected.a, got.a);
}

TEST(Color, to_color32_clamps_HDR_color_components)
TEST(Color, conversion_to_Color32_clamps_HDR_color_components)
{
const Color hdr_color = {1.5f, 0.0f, 2.0f, 1.0f};
const Color32 expected = {0xff, 0x00, 0xff, 0xff};
ASSERT_EQ(to_color32(hdr_color), expected);
ASSERT_EQ(Color32(hdr_color), expected);
}

TEST(Color, to_color32_clamps_negative_color_components)
TEST(Color, conversion_to_Color32_clamps_negative_color_components)
{
const Color color = {-1.0f, 0.0f, 1.0f, 1.0f};
const Color32 expected = {0x00, 0x00, 0xff, 0xff};
ASSERT_EQ(to_color32(color), expected);
ASSERT_EQ(Color32{color}, expected);
}

TEST(Color, to_color_on_Color32_returns_expected_colors)
TEST(Color32, conversion_to_Color_returns_expected_colors)
{
ASSERT_EQ(to_color(Color32(0xff, 0x00, 0x00, 0xff)), Color(1.0f, 0.0f, 0.0f, 1.0f));
ASSERT_EQ(to_color(Color32(0x00, 0xff, 0x00, 0xff)), Color(0.0f, 1.0f, 0.0f, 1.0f));
ASSERT_EQ(to_color(Color32(0x00, 0x00, 0xff, 0xff)), Color(0.0f, 0.0f, 1.0f, 1.0f));
ASSERT_EQ(to_color(Color32(0x00, 0xff, 0xff, 0x00)), Color(0.0f, 1.0f, 1.0f, 0.0f));
ASSERT_EQ(Color(Color32(0xff, 0x00, 0x00, 0xff)), Color(1.0f, 0.0f, 0.0f, 1.0f));
ASSERT_EQ(Color(Color32(0x00, 0xff, 0x00, 0xff)), Color(0.0f, 1.0f, 0.0f, 1.0f));
ASSERT_EQ(Color(Color32(0x00, 0x00, 0xff, 0xff)), Color(0.0f, 0.0f, 1.0f, 1.0f));
ASSERT_EQ(Color(Color32(0x00, 0xff, 0xff, 0x00)), Color(0.0f, 1.0f, 1.0f, 0.0f));
}

TEST(Color, black_returns_black_color)
Expand Down
4 changes: 2 additions & 2 deletions tests/testoscar/Graphics/TestMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1733,7 +1733,7 @@ TEST(Mesh, set_vertex_buffer_params_can_be_used_to_reformat_a_float_attribute_to
});

const auto expected = project_into_vector(colors, [](const Color& c) {
return to_color(to_color32(c));
return Color{Color32{c}};
});

ASSERT_EQ(m.colors(), expected);
Expand Down Expand Up @@ -1863,7 +1863,7 @@ TEST(Mesh, set_vertex_buffer_data_works_as_expected_for_ImGui_style_case)
};
const std::vector<SimilarToImGuiVert> data(16);
const auto expected_vertices = project_into_vector(data, [](const auto& v) { return Vec3{v.pos, 0.0f}; });
const auto expected_colors = project_into_vector(data, [](const auto& v) { return to_color(v.col); });
const auto expected_colors = project_into_vector(data, [](const auto& v) { return Color(v.col); });
const auto expected_texture_coordinates = project_into_vector(data, [](const auto& v) { return v.uv; });

Mesh mesh;
Expand Down
22 changes: 22 additions & 0 deletions tests/testoscar/Graphics/TestRgba.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <gtest/gtest.h>
#include <oscar/Graphics/Unorm8.h>
#include <oscar/Maths/Vec4.h>

#include <sstream>

Expand Down Expand Up @@ -97,3 +98,24 @@ TEST(Rgba, Unorm8_rgba_can_be_hashed)
last_hash = hash;
}
}

TEST(Rgba, can_implicitly_construct_Rgba_from_different_components_if_components_are_implicitly_convertible)
{
const Rgba<float> float_val{0.0f, 0.5f, 1.0f, 1.0f};
const Rgba<Unorm8> unorm8_val = float_val;

ASSERT_EQ(unorm8_val.r, 0.0f);
ASSERT_EQ(unorm8_val.g, Unorm8{127});
ASSERT_EQ(unorm8_val.b, 1.0f);
ASSERT_EQ(unorm8_val.a, Unorm8{0xff});
}

TEST(Rgba, can_explicitly_construct_from_Vec4_of_different_type)
{
const Rgba<Unorm8> unorm8_val{Vec4{0.0f, 0.5f, 1.0f, 1.0f}};

ASSERT_EQ(unorm8_val.r, 0.0f);
ASSERT_EQ(unorm8_val.g, Unorm8{127});
ASSERT_EQ(unorm8_val.b, 1.0f);
ASSERT_EQ(unorm8_val.a, Unorm8{0xff});
}

0 comments on commit 6539793

Please sign in to comment.