docs
Loading...
Searching...
No Matches
Color.h
Go to the documentation of this file.
1///
2/// Copyright (C) 2026 Ultralight, Inc. All rights reserved.
3/// A license is required for commercial use. https://ultralig.ht
4///
5#pragma once
6#include <Ultralight/CAPI/CAPI_ColorTypes.h>
8#include <Ultralight/String.h>
9#include <Ultralight/detail/Css.h>
10
11#include <concepts>
12#include <cstddef>
13#include <cstdint>
14#include <type_traits>
15
16namespace ultralight {
17
18/// \cond INTERNAL
19namespace detail {
20
21// A string type that holds UTF-8 bytes it exposes through data() and size() (std::string,
22// std::string_view, String8, ...), so a header-only overload can hand the bytes to an exported
23// function without an STL type crossing the ABI. String is excluded: it has its own overloads.
24template <class T>
25concept Utf8StringLike = !std::is_same_v<std::remove_cvref_t<T>, String>
26 && requires(const T& text) {
27 { text.data() } -> std::convertible_to<const char*>;
28 { text.size() } -> std::convertible_to<size_t>;
29 };
30
31} // namespace detail
32/// \endcond
33
34///
35/// An RGBA color value in a certain color space (with CSS parsing helpers).
36///
37/// Colors are stored as floats [0..1] in the sRGB color space with straight alpha.
38///
39/// ## Creating Colors
40///
41/// You can create Colors from float RGBA (0..1) channels:
42///
43/// ```
44/// Color green = Color(0.0f, 1.0f, 0.0f); // opaque green
45/// Color semi = Color(1.0f, 1.0f, 1.0f, 0.1f); // semi-transparent white
46/// ```
47///
48/// CSS string literals (parsed and validated at compile-time, see below for limitations):
49///
50/// ```
51/// Color ultramarine = "#3f00ff"; // compile-time literal
52/// Color alpaca = "rgb(255, 240, 220)"; // compile-time literal
53/// ```
54///
55/// Runtime CSS strings (supports the full CSS color grammar, including named colors):
56///
57/// ```
58/// Color themed = Color::Parse(user_text); // a String, std::string, std::string_view, ...
59/// ```
60///
61/// ## Limitations of Compile-Time CSS Literals
62///
63/// String literals accept hex, `rgb()` / `rgba()`, and `transparent`; anything else (for example,
64/// `hsl()` or named colors like `purple`) is not supported. Use Parse() if you need the full CSS
65/// color grammar.
66///
67/// @note Default-constructed Colors are unset (test with is_set(), or `if (color)`).
68///
69class Color {
70 public:
71 ///
72 /// The color space of the channels.
73 ///
74 enum Space : uint8_t {
75 kSRGB = 0, ///< sRGB (the only value currently produced or accepted).
76 };
77
78 ///
79 /// State bits carried in `flags`.
80 ///
81 enum Flags : uint8_t {
82 kSet = 1 << 0, ///< Explicitly set (unset means the receiving field's default applies).
83 kInvalid = 1 << 1, ///< Came from a string that failed to parse; ignored with a warning.
84 };
85
86 float r = 0.0f; ///< Red, 0..1, in the space named by `space`.
87 float g = 0.0f; ///< Green, 0..1.
88 float b = 0.0f; ///< Blue, 0..1.
89 float a = 0.0f; ///< Alpha, 0..1, linear (1 is fully opaque).
90 uint8_t space = kSRGB; ///< A Space value.
91 uint8_t flags = 0; ///< A Flags combination (see is_set() and invalid()).
92
93 ///
94 /// Create an unset Color (the receiving field's default applies).
95 ///
96 constexpr Color() = default;
97
98 ///
99 /// Create a set sRGB color from float channels (0..1; alpha 1 is fully opaque).
100 ///
101 constexpr Color(float red, float green, float blue, float alpha = 1.0f)
102 : r(red), g(green), b(blue), a(alpha), flags(kSet) {}
103
104 ///
105 /// Create a Color from a CSS string literal, parsed and validated at compile time.
106 ///
107 /// Accepted forms are hex colors (eg, `#ff00ff`), rgb()/rgba(), and `transparent`. Anything else
108 /// is a compile-time error naming the reason. Only string literals bind here, runtime strings go
109 /// through Parse().
110 ///
111 template <size_t N>
112 UL_CSS_CONSTEVAL Color(const char (&s)[N]) {
113 const detail::CssColor c = detail::ParseCssColor(s, N - 1);
114 if (c.status != detail::CssStatus::Ok) {
115 if (std::is_constant_evaluated())
116 detail::RaiseCssError(c.status);
117 flags = kInvalid;
118 return;
119 }
120 r = c.r;
121 g = c.g;
122 b = c.b;
123 a = c.a;
124 flags = kSet;
125 }
126
127 ///
128 /// Create a Color from its C mirror (implicit; the two carry identical state).
129 ///
130 constexpr Color(const ULColor& c)
131 : r(c.r), g(c.g), b(c.b), a(c.a), space(c.space), flags(c.flags) {}
132
133 ///
134 /// Convert to the C mirror (implicit; the two carry identical state).
135 ///
136 constexpr operator ULColor() const { return ULColor { r, g, b, a, space, flags }; }
137
138 ///
139 /// Parse a CSS color string at runtime: the full CSS color grammar (named colors, hex,
140 /// rgb()/hsl()/hwb()/lab()/oklch()/color(), `transparent`). Wide-gamut input narrows to
141 /// sRGB.
142 ///
143 /// @param css The CSS color text to parse.
144 ///
145 /// @return Returns the parsed color (set) on success, or an invalid Color when the
146 /// string does not parse (see invalid()).
147 ///
148 static UExport Color Parse(const String& css);
149
150 ///
151 /// Parse CSS color text held in any UTF-8 string type with `data()` and `size()` (eg,
152 /// std::string or std::string_view), the same as Parse(const String&).
153 ///
154 /// @param css The CSS color text to parse, as UTF-8.
155 ///
156 /// @return Returns the parsed color (set) on success, or an invalid Color when the
157 /// string does not parse (see invalid()).
158 ///
159 template <detail::Utf8StringLike S>
160 static Color Parse(const S& css) {
161 return Parse(String(css.data(), css.size()));
162 }
163
164 ///
165 /// Serialize this color as CSS hex text: lowercase `#rrggbb`, or `#rrggbbaa` when the
166 /// alpha channel is not fully opaque. Float channels quantize to 8-bit here (the hex
167 /// wire form is 8-bit), so Parse(ToHexString()) round-trips to the quantized channels.
168 ///
169 /// @return Returns the hex text, or an empty string when this color is unset or
170 /// invalid (see is_set() and invalid()).
171 ///
172 /// @see Parse()
173 ///
175
176 ///
177 /// Whether or not this color was explicitly set. An unset color in any options struct or
178 /// setter means the built-in default (writing one to a style property removes the property).
179 ///
180 constexpr bool is_set() const { return (flags & kSet) != 0; }
181
182 ///
183 /// Whether or not this color came from a string that failed to parse (Parse() at runtime,
184 /// or a malformed literal on a compiler where literal validation degrades to a runtime
185 /// flag). Invalid colors are inert-- whatever you pass one to ignores it and logs a warning.
186 ///
187 constexpr bool invalid() const { return (flags & kInvalid) != 0; }
188
189 ///
190 /// Whether or not this color is set and valid.
191 ///
192 constexpr explicit operator bool() const { return is_set() && !invalid(); }
193
194 friend constexpr bool operator==(const Color&, const Color&) = default;
195};
196
197static_assert(sizeof(Color) == sizeof(ULColor), "Color must mirror ULColor");
198
199} // namespace ultralight
#define UExport
Definition Exports.h:22
An RGBA color value in a certain color space (with CSS parsing helpers).
Definition Color.h:69
static Color Parse(const S &css)
Parse CSS color text held in any UTF-8 string type with data() and size() (eg, std::string or std::st...
Definition Color.h:160
static Color Parse(const String &css)
Parse a CSS color string at runtime: the full CSS color grammar (named colors, hex,...
constexpr Color(const ULColor &c)
Create a Color from its C mirror (implicit; the two carry identical state).
Definition Color.h:130
float r
Red, 0..1, in the space named by space.
Definition Color.h:86
Space
The color space of the channels.
Definition Color.h:74
@ kSRGB
sRGB (the only value currently produced or accepted).
Definition Color.h:75
float a
Alpha, 0..1, linear (1 is fully opaque).
Definition Color.h:89
String ToHexString() const
Serialize this color as CSS hex text: lowercase #rrggbb, or #rrggbbaa when the alpha channel is not f...
friend constexpr bool operator==(const Color &, const Color &)=default
constexpr Color(float red, float green, float blue, float alpha=1.0f)
Create a set sRGB color from float channels (0..1; alpha 1 is fully opaque).
Definition Color.h:101
float b
Blue, 0..1.
Definition Color.h:88
float g
Green, 0..1.
Definition Color.h:87
uint8_t flags
A Flags combination (see is_set() and invalid()).
Definition Color.h:91
constexpr bool invalid() const
Whether or not this color came from a string that failed to parse (Parse() at runtime,...
Definition Color.h:187
constexpr Color()=default
Create an unset Color (the receiving field's default applies).
UL_CSS_CONSTEVAL Color(const char(&s)[N])
Create a Color from a CSS string literal, parsed and validated at compile time.
Definition Color.h:112
constexpr bool is_set() const
Whether or not this color was explicitly set.
Definition Color.h:180
Flags
State bits carried in flags.
Definition Color.h:81
@ kSet
Explicitly set (unset means the receiving field's default applies).
Definition Color.h:82
@ kInvalid
Came from a string that failed to parse; ignored with a warning.
Definition Color.h:83
uint8_t space
A Space value.
Definition Color.h:90
Unicode string container with conversions for UTF-8, UTF-16, and UTF-32.
Definition String.h:31
String()
Create empty string.
@ String
UTF-8 text (from strings and enums).
Definition ValueTraits.h:31
Root namespace for every public Ultralight type, function, and enumeration.