1// LAF Gfx Library
2// Copyright (c) 2018-2022 Igara Studio S.A.
3//
4// This file is released under the terms of the MIT license.
5// Read LICENSE.txt for more information.
6
7#ifndef GFX_COLOR_SPACE_H_INCLUDED
8#define GFX_COLOR_SPACE_H_INCLUDED
9#pragma once
10
11#include "base/ref.h"
12
13#include <algorithm>
14#include <cstdint>
15#include <string>
16#include <vector>
17
18#pragma push_macro("None")
19#undef None // Undefine the X11 None macro
20
21namespace gfx {
22
23 class ColorSpace;
24 using ColorSpaceRef = base::Ref<ColorSpace>;
25
26 // Gamut white point and primaries as in Skia's SkColorSpacePrimaries.
27 struct ColorSpacePrimaries {
28 float rx, ry, gx, gy, bx, by; // Red/Green/Blue XY
29 float wx, wy; // White point XY
30 };
31
32 // Transfer coefficients as in Skia's skcms_TransferFunction, to
33 // transform from a curved space to linear:
34 //
35 // LinearVal = C*InputVal + F , for 0.0f <= InputVal < D
36 // LinearVal = (A*InputVal + B)^G + E, for D <= InputVal <= 1.0f
37 //
38 struct ColorSpaceTransferFn {
39 float g, a, b, c, d, e, f;
40 };
41
42 class ColorSpace : public base::RefCountT<ColorSpace> {
43 public:
44 enum Type { None,
45 sRGB,
46 RGB,
47 ICC };
48
49 enum Flag { NoFlags = 0,
50 HasGamma = 1,
51 HasTransferFn = 2,
52 HasPrimaries = 4,
53 HasICC = 8 };
54
55 ColorSpace(const Type type,
56 const Flag flags = NoFlags,
57 const float gamma = 1.0,
58 std::vector<uint8_t>&& rawData = std::vector<uint8_t>());
59
60 static ColorSpaceRef MakeNone(); // Use display color space
61 static ColorSpaceRef MakeSRGB();
62 static ColorSpaceRef MakeLinearSRGB();
63 static ColorSpaceRef MakeSRGBWithGamma(float gamma);
64 static ColorSpaceRef MakeRGB(const ColorSpaceTransferFn& fn,
65 const ColorSpacePrimaries& p);
66 static ColorSpaceRef MakeRGBWithSRGBGamut(const ColorSpaceTransferFn& fn);
67 static ColorSpaceRef MakeRGBWithSRGBGamma(const ColorSpacePrimaries& p);
68 static ColorSpaceRef MakeICC(const void* data, size_t n);
69 static ColorSpaceRef MakeICC(std::vector<uint8_t>&& data);
70
71 Type type() const { return m_type; }
72 Flag flags() const { return m_flags; }
73
74 const std::string& name() const { return m_name; }
75 void setName(const std::string& name) { m_name = name; }
76
77 float gamma() const { return m_gamma; }
78
79 bool hasGamma() const { return has(HasGamma); }
80 bool hasTransferFn() const { return has(HasTransferFn); }
81 bool hasPrimaries() const { return has(HasPrimaries); }
82
83 size_t iccSize() const {
84 if (has(HasICC))
85 return m_data.size();
86 else
87 return 0;
88 }
89
90 const void* iccData() const {
91 if (has(HasICC))
92 return &m_data[0];
93 else
94 return nullptr;
95 }
96
97 const ColorSpaceTransferFn* transferFn() const {
98 if (has(HasTransferFn))
99 return (const ColorSpaceTransferFn*)&m_data[0];
100 else
101 return nullptr;
102 }
103
104 const ColorSpacePrimaries* primaries() const {
105 if (has(HasPrimaries)) {
106 if (has(HasTransferFn))
107 return (const ColorSpacePrimaries*)&m_data[sizeof(ColorSpaceTransferFn)];
108 else
109 return (const ColorSpacePrimaries*)&m_data[0];
110 }
111 else
112 return nullptr;
113 }
114
115 bool operator==(const ColorSpace& that) const = delete;
116 bool operator!=(const ColorSpace& that) const = delete;
117 bool nearlyEqual(const ColorSpace& that) const;
118
119 // This data can be used
120 const std::vector<uint8_t>& rawData() const { return m_data; }
121
122 private:
123 bool has(const Flag flag) const { return (m_flags & int(flag)) == int(flag); }
124
125 Type m_type;
126 Flag m_flags;
127 std::string m_name;
128 float m_gamma = 1.0f;
129 // ColorSpacePrimaries + ColorSpaceTransferFn or raw ICC profile data
130 std::vector<uint8_t> m_data;
131 };
132
133} // namespace gfx
134
135#pragma pop_macro("None")
136
137#endif
138