Skip to content

Commit 4f26793

Browse files
authored
Update ORBColor API (#19)
1 parent 92f4245 commit 4f26793

File tree

12 files changed

+728
-7
lines changed

12 files changed

+728
-7
lines changed

Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ var sharedCxxSettings: [CXXSetting] = [
176176
]
177177
var sharedSwiftSettings: [SwiftSetting] = [
178178
.swiftLanguageMode(.v5),
179+
.enableUpcomingFeature("InternalImportsByDefault"),
179180
]
180181
if libraryEvolutionCondition {
181182
// NOTE: -enable-library-evolution will cause module verify failure for `swift build`.
@@ -245,7 +246,7 @@ let openRenderBoxTestsTarget = Target.testTarget(
245246
let openRenderBoxCompatibilityTestTarget = Target.testTarget(
246247
name: "OpenRenderBoxCompatibilityTests",
247248
dependencies: [
248-
.product(name: "RealModule", package: "swift-numerics"),
249+
.product(name: "Numerics", package: "swift-numerics"),
249250
],
250251
exclude: ["README.md"],
251252
cSettings: sharedCSettings + [.define("SWIFT_TESTING")],
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
//
2+
// ColorSpace.cpp
3+
// OpenRenderBox
4+
5+
#include <OpenRenderBoxCxx/Color/ColorSpace.hpp>
6+
7+
#if ORB_TARGET_OS_DARWIN
8+
9+
#include <CoreFoundation/CFBase.h>
10+
11+
namespace ORB {
12+
13+
std::optional<ColorSpace> color_space_from_cg_name(CFStringRef name) {
14+
if (name == nullptr) {
15+
return std::nullopt;
16+
} else if (CFEqual(name, kCGColorSpaceSRGB) ||
17+
CFEqual(name, kCGColorSpaceExtendedSRGB)) {
18+
return ColorSpace::SRGB;
19+
} else if (CFEqual(name, kCGColorSpaceLinearSRGB) ||
20+
CFEqual(name, kCGColorSpaceExtendedLinearSRGB)) {
21+
return ColorSpace::LinearSRGB;
22+
} else if (CFEqual(name, kCGColorSpaceDisplayP3) ||
23+
CFEqual(name, kCGColorSpaceExtendedDisplayP3)) {
24+
return ColorSpace::DisplayP3;
25+
} else if (CFEqual(name, kCGColorSpaceLinearDisplayP3) ||
26+
CFEqual(name, kCGColorSpaceExtendedLinearDisplayP3)) {
27+
return ColorSpace::LinearDisplayP3;
28+
} else {
29+
return std::nullopt;
30+
}
31+
}
32+
33+
std::optional<ColorSpace> color_space_from_cg(CGColorSpaceRef colorSpace) {
34+
if (colorSpace == nullptr) {
35+
return std::nullopt;
36+
}
37+
CFStringRef name = CGColorSpaceGetName(colorSpace);
38+
return color_space_from_cg_name(name);
39+
}
40+
41+
CGColorSpaceRef cg_color_space(ColorSpace colorSpace, bool extended) {
42+
switch (colorSpace) {
43+
case ColorSpace::LinearSRGB:
44+
return extended ? extended_linear_srgb_colorspace() : linear_srgb_colorspace();
45+
case ColorSpace::SRGB:
46+
return extended ? extended_srgb_colorspace() : srgb_colorspace();
47+
case ColorSpace::LinearDisplayP3:
48+
return extended ? extended_linear_display_p3_colorspace() : linear_display_p3_colorspace();
49+
case ColorSpace::DisplayP3:
50+
return extended ? extended_display_p3_colorspace() : display_p3_colorspace();
51+
case ColorSpace::PQ:
52+
return pq_colorspace();
53+
case ColorSpace::Unknown:
54+
abort();
55+
}
56+
}
57+
58+
CGColorSpaceRef linear_srgb_colorspace() {
59+
static CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceLinearSRGB);
60+
return colorSpace;
61+
}
62+
63+
CGColorSpaceRef extended_linear_srgb_colorspace() {
64+
static CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceExtendedLinearSRGB);
65+
return colorSpace;
66+
}
67+
68+
CGColorSpaceRef srgb_colorspace() {
69+
static CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
70+
return colorSpace;
71+
}
72+
73+
CGColorSpaceRef extended_srgb_colorspace() {
74+
static CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceExtendedSRGB);
75+
return colorSpace;
76+
}
77+
78+
CGColorSpaceRef linear_display_p3_colorspace() {
79+
static CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceLinearDisplayP3);
80+
return colorSpace;
81+
}
82+
83+
CGColorSpaceRef extended_linear_display_p3_colorspace() {
84+
static CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceExtendedLinearDisplayP3);
85+
return colorSpace;
86+
}
87+
88+
CGColorSpaceRef display_p3_colorspace() {
89+
static CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3);
90+
return colorSpace;
91+
}
92+
93+
CGColorSpaceRef extended_display_p3_colorspace() {
94+
static CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceExtendedDisplayP3);
95+
return colorSpace;
96+
}
97+
98+
CGColorSpaceRef pq_colorspace() {
99+
static CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceITUR_2100_PQ);
100+
return colorSpace;
101+
}
102+
103+
CGColorSpaceRef gray_colorspace() {
104+
static CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericGrayGamma2_2);
105+
return colorSpace;
106+
}
107+
108+
} /* namespace ORB */
109+
110+
std::optional<ORB::ColorSpace> orb_color_space(ORBColorSpace orbColorSpace) {
111+
switch (orbColorSpace) {
112+
case ORBColorSpaceDefault:
113+
return std::nullopt;
114+
case ORBColorSpaceSRGB:
115+
return ORB::ColorSpace::SRGB;
116+
case ORBColorSpaceLinearSRGB:
117+
return ORB::ColorSpace::LinearSRGB;
118+
case ORBColorSpaceDisplayP3:
119+
return ORB::ColorSpace::DisplayP3;
120+
case ORBColorSpaceLinearDisplayP3:
121+
return ORB::ColorSpace::LinearDisplayP3;
122+
default:
123+
return std::nullopt;
124+
}
125+
}
126+
127+
ORBColorSpace orb_color_space(std::optional<ORB::ColorSpace> colorSpace) {
128+
if (!colorSpace.has_value()) {
129+
return ORBColorSpaceDefault;
130+
}
131+
switch (colorSpace.value()) {
132+
case ORB::ColorSpace::LinearSRGB:
133+
return ORBColorSpaceLinearSRGB;
134+
case ORB::ColorSpace::SRGB:
135+
return ORBColorSpaceSRGB;
136+
case ORB::ColorSpace::LinearDisplayP3:
137+
return ORBColorSpaceLinearDisplayP3;
138+
case ORB::ColorSpace::DisplayP3:
139+
return ORBColorSpaceDisplayP3;
140+
case ORB::ColorSpace::Unknown:
141+
case ORB::ColorSpace::PQ:
142+
return ORBColorSpaceDefault;
143+
default:
144+
return ORBColorSpaceLinearSRGB;
145+
}
146+
}
147+
148+
#endif /* ORB_TARGET_OS_DARWIN */
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
//
2+
// ORBColor.cpp
3+
// OpenRenderBox
4+
5+
#include <OpenRenderBox/ORBColor.h>
6+
#include <OpenRenderBoxCxx/Color/ColorSpace.hpp>
7+
#include <math.h>
8+
9+
using namespace ORB;
10+
11+
// Global color constants
12+
const ORBColor ORBColorClear = { 0.0f, 0.0f, 0.0f, 0.0f };
13+
const ORBColor ORBColorBlack = { 0.0f, 0.0f, 0.0f, 1.0f };
14+
const ORBColor ORBColorWhite = { 1.0f, 1.0f, 1.0f, 1.0f };
15+
const ORBColor ORBColorNull = { ORBColorInvalidComponent, ORBColorInvalidComponent, ORBColorInvalidComponent, ORBColorInvalidComponent };
16+
const float ORBColorInvalidComponent = -32768.0f;
17+
18+
// sRGB to linear constants
19+
static const float kSRGBToLinearThreshold = 0.04045f;
20+
static const float kSRGBToLinearScale = 12.92f;
21+
static const float kSRGBToLinearGammaOffset = 0.055f;
22+
static const float kSRGBToLinearGammaScale = 1.055f;
23+
static const float kSRGBToLinearGamma = 2.4f;
24+
25+
// Linear to sRGB constants
26+
static const float kLinearToSRGBThreshold = 0.0031308f;
27+
static const float kLinearToSRGBScale = 12.92f;
28+
static const float kLinearToSRGBGammaScale = 1.055f;
29+
static const float kLinearToSRGBGammaOffset = 0.055f;
30+
static const float kLinearToSRGBGamma = 1.0f / 2.4f;
31+
32+
static inline float sRGBToLinear(float value) {
33+
float absValue = value > 0.0f ? value : -value;
34+
float result;
35+
if (absValue <= kSRGBToLinearThreshold) {
36+
result = absValue / kSRGBToLinearScale;
37+
} else {
38+
result = powf((absValue + kSRGBToLinearGammaOffset) / kSRGBToLinearGammaScale, kSRGBToLinearGamma);
39+
}
40+
return value < 0.0f ? -result : result;
41+
}
42+
43+
static inline float linearToSRGB(float value) {
44+
float absValue = value > 0.0f ? value : -value;
45+
float result;
46+
if (absValue <= kLinearToSRGBThreshold) {
47+
result = absValue * kLinearToSRGBScale;
48+
} else {
49+
result = kLinearToSRGBGammaScale * powf(absValue, kLinearToSRGBGamma) - kLinearToSRGBGammaOffset;
50+
}
51+
return value < 0.0f ? -result : result;
52+
}
53+
54+
ORBColor ORBColorMake(float red, float green, float blue, float alpha) {
55+
return (ORBColor){ red, green, blue, alpha };
56+
}
57+
58+
ORBColor ORBColorMakeLinear(float red, float green, float blue, float alpha) {
59+
return (ORBColor){
60+
sRGBToLinear(red),
61+
sRGBToLinear(green),
62+
sRGBToLinear(blue),
63+
alpha
64+
};
65+
}
66+
67+
ORBColor ORBColorToLinear(ORBColor color) {
68+
return (ORBColor){
69+
sRGBToLinear(color.red),
70+
sRGBToLinear(color.green),
71+
sRGBToLinear(color.blue),
72+
color.alpha
73+
};
74+
}
75+
76+
ORBColor ORBColorFromLinear(ORBColor color) {
77+
return (ORBColor){
78+
linearToSRGB(color.red),
79+
linearToSRGB(color.green),
80+
linearToSRGB(color.blue),
81+
color.alpha
82+
};
83+
}
84+
85+
bool ORBColorEqualToColor(ORBColor lhs, ORBColor rhs) {
86+
return lhs.red == rhs.red &&
87+
lhs.green == rhs.green &&
88+
lhs.blue == rhs.blue &&
89+
lhs.alpha == rhs.alpha;
90+
}
91+
92+
#if ORB_TARGET_OS_DARWIN
93+
94+
#include <CoreGraphics/CGColorSpace.h>
95+
96+
ORBColor ORBColorFromComponents(CGColorSpaceRef colorSpace, const CGFloat *components, bool premultiplied) {
97+
size_t componentCount = premultiplied ? 2 : 1;
98+
return ORBColorFromComponents2(colorSpace, components, componentCount);
99+
}
100+
101+
ORBColor ORBColorFromComponents2(CGColorSpaceRef colorSpace, const CGFloat *components, size_t componentCount) {
102+
// TODO: Implement proper color space conversion
103+
(void)colorSpace;
104+
(void)componentCount;
105+
return (ORBColor){
106+
static_cast<float>(components[0]),
107+
static_cast<float>(components[1]),
108+
static_cast<float>(components[2]),
109+
static_cast<float>(components[3])
110+
};
111+
}
112+
113+
ORBColor ORBColorFromCGColor(CGColorRef color, bool premultiplied) {
114+
CGColorSpaceRef colorSpace = CGColorGetColorSpace(color);
115+
const CGFloat *components = CGColorGetComponents(color);
116+
size_t componentCount = premultiplied ? 2 : 1;
117+
return ORBColorFromComponents2(colorSpace, components, componentCount);
118+
}
119+
120+
ORBColor ORBColorFromCGColor2(CGColorRef color, size_t componentCount) {
121+
CGColorSpaceRef colorSpace = CGColorGetColorSpace(color);
122+
const CGFloat *components = CGColorGetComponents(color);
123+
return ORBColorFromComponents2(colorSpace, components, componentCount);
124+
}
125+
126+
CGColorRef ORBColorCopyCGColor(ORBColor color, ORBColorSpace orbColorSpace) {
127+
CGFloat components[4] = {
128+
static_cast<CGFloat>(color.red),
129+
static_cast<CGFloat>(color.green),
130+
static_cast<CGFloat>(color.blue),
131+
static_cast<CGFloat>(color.alpha)
132+
};
133+
bool isRedOutOfRange = (color.red < 0.0f || color.red > 1.0f);
134+
bool isGreenOutOfRange = (color.green < 0.0f || color.green > 1.0f);
135+
bool isBlueOutOfRange = (color.blue < 0.0f || color.blue > 1.0f);
136+
ORB::ColorSpace colorSpace = orb_color_space(orbColorSpace).value_or(ORB::ColorSpace::LinearSRGB);
137+
bool extended = isRedOutOfRange || isGreenOutOfRange || isBlueOutOfRange;
138+
CGColorSpaceRef cgColorSpace = ORB::cg_color_space(colorSpace, extended);
139+
CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
140+
return cgColor;
141+
}
142+
143+
#endif /* ORB_TARGET_OS_DARWIN */
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// ORBColorMode.cpp
3+
// OpenRenderBox
4+
5+
#include <OpenRenderBox/ORBColorMode.h>
6+
7+
ORBColorSpace ORBColorModeWorkingColorSpace(ORBColorMode mode) {
8+
switch (mode) {
9+
case ORBColorMode0:
10+
case ORBColorMode3:
11+
case ORBColorMode4:
12+
case ORBColorMode5:
13+
case ORBColorMode9:
14+
case ORBColorMode11:
15+
case ORBColorMode12:
16+
case ORBColorMode14:
17+
return ORBColorSpaceSRGB;
18+
case ORBColorMode1:
19+
case ORBColorMode2:
20+
case ORBColorMode6:
21+
case ORBColorMode7:
22+
case ORBColorMode8:
23+
case ORBColorMode10:
24+
case ORBColorMode13:
25+
case ORBColorMode15:
26+
return ORBColorSpaceLinearSRGB;
27+
default:
28+
return ORBColorSpaceDefault;
29+
}
30+
}
31+
32+
bool ORBColorModeHasExtendedRange(ORBColorMode mode) {
33+
switch (mode) {
34+
case ORBColorMode2:
35+
case ORBColorMode11:
36+
case ORBColorMode12:
37+
case ORBColorMode13:
38+
return true;
39+
default:
40+
return false;
41+
}
42+
}

0 commit comments

Comments
 (0)