aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/colorspacexform.cpp3
-rw-r--r--include/core/SkColorSpace.h6
-rw-r--r--src/core/SkColorSpace.cpp28
-rw-r--r--src/effects/gradients/SkGradientShader.cpp9
-rw-r--r--tests/ColorSpaceTest.cpp37
-rw-r--r--tests/SurfaceTest.cpp2
6 files changed, 68 insertions, 17 deletions
diff --git a/gm/colorspacexform.cpp b/gm/colorspacexform.cpp
index 7e3285efbd..34abdc4b79 100644
--- a/gm/colorspacexform.cpp
+++ b/gm/colorspacexform.cpp
@@ -60,8 +60,7 @@ protected:
canvas->save();
for (int i = 0; i < kNumColors; i++) {
- sk_sp<SkColorSpace> space =
- SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named)->makeLinearGamma();
+ sk_sp<SkColorSpace> space = SkColorSpace::NewNamed(SkColorSpace::kSRGBLinear_Named);
sk_sp<SkShader> s = SkShader::MakeColorShader(colors[i], space);
SkPaint paint;
paint.setShader(s);
diff --git a/include/core/SkColorSpace.h b/include/core/SkColorSpace.h
index b2b005e4aa..a6a800d140 100644
--- a/include/core/SkColorSpace.h
+++ b/include/core/SkColorSpace.h
@@ -31,6 +31,12 @@ public:
* Often used by images and monitors.
*/
kAdobeRGB_Named,
+
+ /**
+ * Colorspace with the sRGB primaries, but a linear (1.0) gamma. Commonly used for
+ * half-float surfaces, and high precision individual colors (gradient stops, etc...)
+ */
+ kSRGBLinear_Named,
};
enum RenderTargetGamma : uint8_t {
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
index 90fc96e111..225cfe1464 100644
--- a/src/core/SkColorSpace.cpp
+++ b/src/core/SkColorSpace.cpp
@@ -113,6 +113,11 @@ sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(SkGammaNamed gammaNamed, const SkM
return SkColorSpace::NewNamed(kAdobeRGB_Named);
}
break;
+ case kLinear_SkGammaNamed:
+ if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) {
+ return SkColorSpace::NewNamed(kSRGBLinear_Named);
+ }
+ break;
case kNonStandard_SkGammaNamed:
// This is not allowed.
return nullptr;
@@ -136,10 +141,12 @@ sk_sp<SkColorSpace> SkColorSpace::NewRGB(RenderTargetGamma gamma, const SkMatrix
static SkColorSpace* gAdobeRGB;
static SkColorSpace* gSRGB;
+static SkColorSpace* gSRGBLinear;
sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
static SkOnce sRGBOnce;
static SkOnce adobeRGBOnce;
+ static SkOnce sRGBLinearOnce;
switch (named) {
case kSRGB_Named: {
@@ -164,6 +171,17 @@ sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
});
return sk_ref_sp<SkColorSpace>(gAdobeRGB);
}
+ case kSRGBLinear_Named: {
+ sRGBLinearOnce([] {
+ SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
+ srgbToxyzD50.set3x3RowMajorf(gSRGB_toXYZD50);
+
+ // Force the mutable type mask to be computed. This avoids races.
+ (void)srgbToxyzD50.getType();
+ gSRGBLinear = new SkColorSpace_Base(kLinear_SkGammaNamed, srgbToxyzD50);
+ });
+ return sk_ref_sp<SkColorSpace>(gSRGBLinear);
+ }
default:
break;
}
@@ -238,7 +256,7 @@ struct ColorSpaceHeader {
SkASSERT(k0_Version == version);
header.fVersion = (uint8_t) version;
- SkASSERT(named <= SkColorSpace::kAdobeRGB_Named);
+ SkASSERT(named <= SkColorSpace::kSRGBLinear_Named);
header.fNamed = (uint8_t) named;
SkASSERT(gammaNamed <= kNonStandard_SkGammaNamed);
@@ -273,6 +291,14 @@ size_t SkColorSpace::writeToMemory(void* memory) const {
ColorSpaceHeader::Pack(k0_Version, kAdobeRGB_Named,
as_CSB(this)->fGammaNamed, 0);
}
+ return sizeof(ColorSpaceHeader);
+ } else if (this == gSRGBLinear) {
+ if (memory) {
+ *((ColorSpaceHeader*)memory) =
+ ColorSpaceHeader::Pack(k0_Version, kSRGBLinear_Named,
+ as_CSB(this)->fGammaNamed, 0);
+ }
+ return sizeof(ColorSpaceHeader);
}
// If we have a named gamma, write the enum and the matrix.
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index 31ff9ab877..0faf006d73 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -141,7 +141,7 @@ SkGradientShaderBase::SkGradientShaderBase(const Descriptor& desc, const SkMatri
}
// Color space refers to fColors4f, so it's always linear gamma
- fColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named)->makeLinearGamma();
+ fColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGBLinear_Named);
} else {
SkASSERT(desc.fColors4f && desc.fColorSpace && desc.fColorSpace->gammaIsLinear());
@@ -683,10 +683,9 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap,
SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named));
break;
case GradientBitmapType::kHalfFloat:
- info = SkImageInfo::Make(kCache32Count, 1, kRGBA_F16_SkColorType,
- kPremul_SkAlphaType,
- SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named)
- ->makeLinearGamma());
+ info = SkImageInfo::Make(
+ kCache32Count, 1, kRGBA_F16_SkColorType, kPremul_SkAlphaType,
+ SkColorSpace::NewNamed(SkColorSpace::kSRGBLinear_Named));
break;
default:
SkFAIL("Unexpected bitmap type");
diff --git a/tests/ColorSpaceTest.cpp b/tests/ColorSpaceTest.cpp
index 7e247d304d..d749931de1 100644
--- a/tests/ColorSpaceTest.cpp
+++ b/tests/ColorSpaceTest.cpp
@@ -115,6 +115,29 @@ DEF_TEST(ColorSpaceSRGBCompare, r) {
REPORTER_ASSERT(r, strangeColorSpace != namedColorSpace);
}
+DEF_TEST(ColorSpaceSRGBLinearCompare, r) {
+ // Create the linear sRGB color space by name
+ sk_sp<SkColorSpace> namedColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGBLinear_Named);
+
+ // Create the linear sRGB color space via the sRGB color space's makeLinearGamma()
+ sk_sp<SkColorSpace> viaSrgbColorSpace =
+ SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named)->makeLinearGamma();
+ REPORTER_ASSERT(r, namedColorSpace == viaSrgbColorSpace);
+
+ // Create a linear sRGB color space by value
+ SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
+ srgbToxyzD50.set3x3RowMajorf(g_sRGB_XYZ);
+ sk_sp<SkColorSpace> rgbColorSpace =
+ SkColorSpace::NewRGB(SkColorSpace::kLinear_RenderTargetGamma, srgbToxyzD50);
+ REPORTER_ASSERT(r, rgbColorSpace == namedColorSpace);
+
+ // Change a single value from the sRGB matrix
+ srgbToxyzD50.set(2, 2, 0.5f);
+ sk_sp<SkColorSpace> strangeColorSpace =
+ SkColorSpace::NewRGB(SkColorSpace::kLinear_RenderTargetGamma, srgbToxyzD50);
+ REPORTER_ASSERT(r, strangeColorSpace != namedColorSpace);
+}
+
class ColorSpaceTest {
public:
static sk_sp<SkData> WriteToICC(SkColorSpace* space) {
@@ -150,21 +173,18 @@ DEF_TEST(ColorSpaceWriteICC, r) {
DEF_TEST(ColorSpace_Named, r) {
const struct {
SkColorSpace::Named fNamed;
- bool fIsSRGB;
+ SkGammaNamed fExpectedGamma;
} recs[] {
- { SkColorSpace::kSRGB_Named, true },
- { SkColorSpace::kAdobeRGB_Named, false },
+ { SkColorSpace::kSRGB_Named, kSRGB_SkGammaNamed },
+ { SkColorSpace::kAdobeRGB_Named, k2Dot2Curve_SkGammaNamed },
+ { SkColorSpace::kSRGBLinear_Named, kLinear_SkGammaNamed },
};
for (auto rec : recs) {
auto cs = SkColorSpace::NewNamed(rec.fNamed);
REPORTER_ASSERT(r, cs);
if (cs) {
- if (rec.fIsSRGB) {
- REPORTER_ASSERT(r, kSRGB_SkGammaNamed == as_CSB(cs)->gammaNamed());
- } else {
- REPORTER_ASSERT(r, k2Dot2Curve_SkGammaNamed == as_CSB(cs)->gammaNamed());
- }
+ REPORTER_ASSERT(r, rec.fExpectedGamma == as_CSB(cs)->gammaNamed());
}
}
@@ -194,6 +214,7 @@ static void test_serialize(skiatest::Reporter* r, SkColorSpace* space, bool isNa
DEF_TEST(ColorSpace_Serialize, r) {
test_serialize(r, SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named).get(), true);
test_serialize(r, SkColorSpace::NewNamed(SkColorSpace::kAdobeRGB_Named).get(), true);
+ test_serialize(r, SkColorSpace::NewNamed(SkColorSpace::kSRGBLinear_Named).get(), true);
sk_sp<SkData> monitorData = SkData::MakeFromFileName(
GetResourcePath("icc_profiles/HP_ZR30w.icc").c_str());
diff --git a/tests/SurfaceTest.cpp b/tests/SurfaceTest.cpp
index 775b8c6c05..6706fef7e4 100644
--- a/tests/SurfaceTest.cpp
+++ b/tests/SurfaceTest.cpp
@@ -924,7 +924,7 @@ static void test_surface_creation_and_snapshot_with_color_space(
SkMatrix44 srgbMatrix = srgbColorSpace->toXYZD50();
const float oddGamma[] = { 2.4f, 2.4f, 2.4f };
auto oddColorSpace = SkColorSpace_Base::NewRGB(oddGamma, srgbMatrix);
- auto linearColorSpace = srgbColorSpace->makeLinearGamma();
+ auto linearColorSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGBLinear_Named);
const struct {
SkColorType fColorType;