Program Listing for File sixtyfps_color.h

Return to documentation for file (/home/runner/work/sixtyfps/sixtyfps/api/sixtyfps-cpp/include/sixtyfps_color.h)

/* LICENSE BEGIN
    This file is part of the SixtyFPS Project -- https://sixtyfps.io
    Copyright (c) 2021 Olivier Goffart <olivier.goffart@sixtyfps.io>
    Copyright (c) 2021 Simon Hausmann <simon.hausmann@sixtyfps.io>

    SPDX-License-Identifier: GPL-3.0-only
    This file is also available under commercial licensing terms.
    Please contact info@sixtyfps.io for more information.
LICENSE END */
#pragma once

#include "sixtyfps_color_internal.h"
#include "sixtyfps_properties.h"

#include <stdint.h>

namespace sixtyfps {

namespace private_api {
class LinearGradientBrush;
}

class Color;

template<typename T>
struct RgbaColor
{
    T alpha;
    T red;
    T green;
    T blue;

    RgbaColor(const Color &col);
};

class Color
{
public:
    Color() { inner.red = inner.green = inner.blue = inner.alpha = 0; }
    Color(const RgbaColor<uint8_t> &col)
    {
        inner.red = col.red;
        inner.green = col.green;
        inner.blue = col.blue;
        inner.alpha = col.alpha;
    }
    Color(const RgbaColor<float> &col)
    {
        inner.red = uint8_t(col.red * 255);
        inner.green = uint8_t(col.green * 255);
        inner.blue = uint8_t(col.blue * 255);
        inner.alpha = uint8_t(col.alpha * 255);
    }

    static Color from_argb_encoded(uint32_t argb_encoded)
    {
        Color col;
        col.inner.red = (argb_encoded >> 16) & 0xff;
        col.inner.green = (argb_encoded >> 8) & 0xff;
        col.inner.blue = argb_encoded & 0xff;
        col.inner.alpha = (argb_encoded >> 24) & 0xff;
        return col;
    }

    uint32_t as_argb_encoded() const
    {
        return (uint32_t(inner.red) << 16) | (uint32_t(inner.green) << 8) | uint32_t(inner.blue)
                | (uint32_t(inner.alpha) << 24);
    }

    static Color from_argb_uint8(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue)
    {
        Color col;
        col.inner.alpha = alpha;
        col.inner.red = red;
        col.inner.green = green;
        col.inner.blue = blue;
        return col;
    }

    static Color from_rgb_uint8(uint8_t red, uint8_t green, uint8_t blue)
    {
        return from_argb_uint8(255, red, green, blue);
    }

    static Color from_argb_float(float alpha, float red, float green, float blue)
    {
        Color col;
        col.inner.alpha = uint8_t(alpha * 255);
        col.inner.red = uint8_t(red * 255);
        col.inner.green = uint8_t(green * 255);
        col.inner.blue = uint8_t(blue * 255);
        return col;
    }

    static Color from_rgb_float(float red, float green, float blue)
    {
        return Color::from_argb_float(1.0, red, green, blue);
    }

    inline RgbaColor<uint8_t> to_argb_uint() const;

    inline RgbaColor<float> to_argb_float() const;

    uint8_t red() const { return inner.red; }

    uint8_t green() const { return inner.green; }

    uint8_t blue() const { return inner.blue; }

    uint8_t alpha() const { return inner.alpha; }

    inline Color brighter(float factor) const;
    inline Color darker(float factor) const;

    friend bool operator==(const Color &lhs, const Color &rhs)
    {
        return lhs.inner.red == rhs.inner.red && lhs.inner.green == rhs.inner.green
                && lhs.inner.blue == rhs.inner.blue && lhs.inner.alpha == rhs.inner.alpha;
    }

    friend bool operator!=(const Color &lhs, const Color &rhs) { return !(lhs == rhs); }

    friend std::ostream &operator<<(std::ostream &stream, const Color &color)
    {
        // Cast to uint32_t to avoid the components being interpreted as char.
        return stream << "argb(" << uint32_t(color.inner.alpha) << ", " << uint32_t(color.inner.red)
                      << ", " << uint32_t(color.inner.green) << ", " << uint32_t(color.inner.blue)
                      << ")";
    }

#if !defined(DOXYGEN)
    // FIXME: we need this to create GradientStop
    operator const cbindgen_private::types::Color &() const { return inner; }
#endif

private:
    cbindgen_private::types::Color inner;
    friend class private_api::LinearGradientBrush;
    friend class Brush;
};

inline Color Color::brighter(float factor) const
{
    Color result;
    cbindgen_private::types::sixtyfps_color_brighter(&inner, factor, &result.inner);
    return result;
}

inline Color Color::darker(float factor) const
{
    Color result;
    cbindgen_private::types::sixtyfps_color_darker(&inner, factor, &result.inner);
    return result;
}

template<>
inline RgbaColor<uint8_t>::RgbaColor(const Color &color)
{
    red = color.red();
    green = color.green();
    blue = color.blue();
    alpha = color.alpha();
}

template<>
inline RgbaColor<float>::RgbaColor(const Color &color)
{
    red = float(color.red()) / 255.f;
    green = float(color.green()) / 255.f;
    blue = float(color.blue()) / 255.f;
    alpha = float(color.alpha()) / 255.f;
}

RgbaColor<uint8_t> Color::to_argb_uint() const
{
    return RgbaColor<uint8_t>(*this);
}

RgbaColor<float> Color::to_argb_float() const
{
    return RgbaColor<float>(*this);
}

namespace private_api {

template<>
inline void
Property<Color>::set_animated_value(const Color &new_value,
                                    const cbindgen_private::PropertyAnimation &animation_data) const
{
    cbindgen_private::sixtyfps_property_set_animated_value_color(&inner, value, new_value,
                                                                 &animation_data);
}

} // namespace private_api

} // namespace sixtyfps