diff options
-rw-r--r-- | gm/colorspacexform.cpp | 3 | ||||
-rw-r--r-- | include/core/SkColorSpace.h | 6 | ||||
-rw-r--r-- | src/core/SkColorSpace.cpp | 28 | ||||
-rw-r--r-- | src/effects/gradients/SkGradientShader.cpp | 9 | ||||
-rw-r--r-- | tests/ColorSpaceTest.cpp | 37 | ||||
-rw-r--r-- | tests/SurfaceTest.cpp | 2 |
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; |