diff --git a/src/effects/gradients/SkLinearGradient.cpp b/src/effects/gradients/SkLinearGradient.cpp index 1fbd96e40e..cc8875cf8e 100644 --- a/src/effects/gradients/SkLinearGradient.cpp +++ b/src/effects/gradients/SkLinearGradient.cpp @@ -9,7 +9,7 @@ #include "SkLinearGradient.h" // define to test the 4f gradient path -// #define USE_4fGRADIENTS +// #define FORCE_4F_CONTEXT static const float kInv255Float = 1.0f / 255; @@ -47,11 +47,18 @@ static SkMatrix pts_to_unit_matrix(const SkPoint pts[2]) { return matrix; } -static bool use_4f_context(uint32_t flags) { -#ifdef USE_4fGRADIENTS +static bool use_4f_context(const SkShader::ContextRec& rec, uint32_t flags) { +#ifdef FORCE_4F_CONTEXT return true; #else - return SkToBool(flags & SkLinearGradient::kForce4fContext_PrivateFlag); + // Perspective not supported in 4f yet. + if (rec.fMatrix->hasPerspective() + || (rec.fLocalMatrix && rec.fLocalMatrix->hasPerspective())) { + return false; + } + + return rec.fPreferredDstType == SkShader::ContextRec::kPM4f_DstType + || SkToBool(flags & SkLinearGradient::kForce4fContext_PrivateFlag); #endif } @@ -81,14 +88,14 @@ void SkLinearGradient::flatten(SkWriteBuffer& buffer) const { buffer.writePoint(fEnd); } -size_t SkLinearGradient::contextSize(const ContextRec&) const { - return use_4f_context(fGradFlags) +size_t SkLinearGradient::contextSize(const ContextRec& rec) const { + return use_4f_context(rec, fGradFlags) ? sizeof(LinearGradient4fContext) : sizeof(LinearGradientContext); } SkShader::Context* SkLinearGradient::onCreateContext(const ContextRec& rec, void* storage) const { - return use_4f_context(fGradFlags) + return use_4f_context(rec, fGradFlags) ? static_cast(new (storage) LinearGradient4fContext(*this, rec)) : static_cast(new (storage) LinearGradientContext(*this, rec)); } diff --git a/tests/SkColor4fTest.cpp b/tests/SkColor4fTest.cpp index 00581cc1e6..ea9a80f134 100644 --- a/tests/SkColor4fTest.cpp +++ b/tests/SkColor4fTest.cpp @@ -125,23 +125,26 @@ static SkShader* make_cf_sh() { } static void compare_spans(const SkPM4f span4f[], const SkPMColor span4b[], int count, - skiatest::Reporter* reporter) { + skiatest::Reporter* reporter, float tolerance = 1.0f/255) { for (int i = 0; i < count; ++i) { SkPM4f c0 = SkPM4f::FromPMColor(span4b[i]); SkPM4f c1 = span4f[i]; - REPORTER_ASSERT(reporter, nearly_equal(c0, c1, 1.0f/255)); + REPORTER_ASSERT(reporter, nearly_equal(c0, c1, tolerance)); } } DEF_TEST(Color4f_shader, reporter) { struct { - SkShader* (*fFact)(); - bool fSupports4f; + SkShader* (*fFact)(); + bool fSupports4f; + float fTolerance; } recs[] = { - { make_color_sh, true }, - { make_grad_sh, false }, - { make_image_sh, false }, - { make_cf_sh, true }, + { make_color_sh, true, 1.0f/255 }, + // PMColor 4f gradients are interpolated in 255-multiplied values, so we need a + // slightly relaxed tolerance to accommodate the cumulative precision deviation. + { make_grad_sh, true, 1.001f/255 }, + { make_image_sh, false, 1.0f/255 }, + { make_cf_sh, true, 1.0f/255 }, }; SkPaint paint; @@ -161,7 +164,7 @@ DEF_TEST(Color4f_shader, reporter) { ctx->shadeSpan4f(0, 0, buffer4f, N); SkPMColor buffer4b[N]; ctx->shadeSpan(0, 0, buffer4b, N); - compare_spans(buffer4f, buffer4b, N, reporter); + compare_spans(buffer4f, buffer4b, N, reporter, rec.fTolerance); } ctx->~Context(); }