xlnt - community edition
color.hpp
1 // Copyright (c) 2014-2022 Thomas Fussell
2 // Copyright (c) 2010-2015 openpyxl
3 // Copyright (c) 2024-2025 xlnt-community
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE
22 //
23 // @license: http://www.opensource.org/licenses/mit-license.php
24 // @author: see AUTHORS file
25 
26 #pragma once
27 
28 #include <array>
29 #include <cstring>
30 #include <functional>
31 
32 #include <xlnt/xlnt_config.hpp>
33 #include <xlnt/utils/optional.hpp>
34 #include <xlnt/utils/hash_combine.hpp>
35 
36 namespace xlnt {
37 
41 class XLNT_API indexed_color
42 {
43 public:
44  //TODO: should this be explicit?
48  indexed_color(std::size_t index);
49 
53  std::size_t index() const;
54 
58  void index(std::size_t index);
59 
60 private:
64  std::size_t index_;
65 };
66 
70 class XLNT_API theme_color
71 {
72 public:
76  theme_color(std::size_t index);
77 
81  std::size_t index() const;
82 
86  void index(std::size_t index);
87 
88 private:
92  std::size_t index_;
93 };
94 
98 class XLNT_API rgb_color
99 {
100 public:
104  rgb_color(const std::string &hex_string);
105 
110  rgb_color(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a = 255);
111 
115  std::string hex_string() const;
116 
120  std::uint8_t red() const;
121 
125  std::uint8_t green() const;
126 
130  std::uint8_t blue() const;
131 
135  std::uint8_t alpha() const;
136 
140  std::array<std::uint8_t, 3> rgb() const;
141 
145  std::array<std::uint8_t, 4> rgba() const;
146 
147 private:
151  std::array<std::uint8_t, 4> rgba_;
152 };
153 
157 enum class color_type
158 {
159  indexed,
160  theme,
161  rgb
162 };
163 
167 class XLNT_API color
168 {
169 public:
173  static const color black();
174 
178  static const color white();
179 
183  static const color red();
184 
188  static const color darkred();
189 
193  static const color blue();
194 
198  static const color darkblue();
199 
203  static const color green();
204 
208  static const color darkgreen();
209 
213  static const color yellow();
214 
218  static const color darkyellow();
219 
223  color();
224 
228  color(const rgb_color &rgb);
229 
233  color(const indexed_color &indexed);
234 
238  color(const theme_color &theme);
239 
243  color_type type() const;
244 
248  bool auto_() const;
249 
253  void auto_(bool value);
254 
259  const rgb_color &rgb() const;
260 
265  rgb_color &rgb();
266 
271  const indexed_color &indexed() const;
272 
277  indexed_color &indexed();
278 
283  const theme_color &theme() const;
284 
289  theme_color &theme();
290 
294  bool has_tint() const;
295 
299  double tint() const;
300 
304  void tint(double tint);
305 
309  bool operator==(const color &other) const;
310 
314  bool operator!=(const color &other) const;
315 
316 private:
320  void assert_type(color_type t) const;
321 
325  color_type type_;
326 
330  rgb_color rgb_;
331 
335  indexed_color indexed_;
336 
340  theme_color theme_;
341 
345  optional<double> tint_;
346 
350  bool auto_color = false;
351 };
352 
353 } // namespace xlnt
354 
355 namespace std {
356 
357 template<>
358 struct hash<xlnt::color>
359 {
360  size_t operator()(const xlnt::color& c) const
361  {
362  size_t seed = 0;
363  // Start by hashing the type to prevent collisions between different color types
364  // that might share an underlying value (e.g., theme(1) vs indexed(1)).
365  xlnt::detail::hash_combine(seed, static_cast<int>(c.type()));
366 
367  // Hash auto color flag
368  xlnt::detail::hash_combine(seed, c.auto_());
369 
370  // Hash tint if present
371  if (c.has_tint())
372  {
373  xlnt::detail::hash_combine(seed, c.tint());
374  }
375 
376  switch (c.type())
377  {
378  case xlnt::color_type::indexed:
379  xlnt::detail::hash_combine(seed, c.indexed().index());
380  break;
381  case xlnt::color_type::theme:
382  xlnt::detail::hash_combine(seed, c.theme().index());
383  break;
384  case xlnt::color_type::rgb:
385  {
386  const auto& rgb = c.rgb();
387  xlnt::detail::hash_combine(seed, rgb.red());
388  xlnt::detail::hash_combine(seed, rgb.green());
389  xlnt::detail::hash_combine(seed, rgb.blue());
390  xlnt::detail::hash_combine(seed, rgb.alpha());
391  break;
392  }
393  }
394  return seed;
395  }
396 };
397 
398 } // namespace std
std::size_t index() const
Returns the index this color points to.
std::size_t index() const
Returns the index of the color in the theme this points to.
const rgb_color & rgb() const
Returns the internal indexed color representing this color. If this is not an RGB color...
Definition: cell_reference.hpp:261
const theme_color & theme() const
Returns the internal indexed color representing this color. If this is not a theme color...
Enumerates the possible types a cell can be determined by it&#39;s current value.
Definition: cell.hpp:36
bool operator!=(std::nullptr_t, const cell &cell)
Returns true if this cell is initialized.
bool auto_() const
Returns true if this color has been set to auto
Colors can be applied to many parts of a cell&#39;s style.
Definition: color.hpp:167
color_type
Some colors are references to colors rather than having a particular RGB value.
Definition: color.hpp:157
bool operator==(std::nullptr_t, const cell &cell)
Returns true if this cell is uninitialized.
A theme is a combination of fonts, colors, and effects. This isn&#39;t really supported yet...
Definition: theme.hpp:35
const indexed_color & indexed() const
Returns the internal indexed color representing this color. If this is not an indexed color...
double tint() const
Returns the tint of this color.
An indexed color encapsulates a simple index to a color in the indexedColors of the stylesheet...
Definition: color.hpp:41
bool has_tint() const
Returns true if tint is set
A theme color encapsulates a color derived from the theme.
Definition: color.hpp:70
An RGB color describes a color in terms of its red, green, blue, and alpha components.
Definition: color.hpp:98
color_type type() const
Returns the type of this color