• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7 
8 #include "include/core/SkString.h"
9 #include "include/effects/SkHighContrastFilter.h"
10 #include "include/effects/SkRuntimeEffect.h"
11 #include "include/private/SkTPin.h"
12 #include "src/core/SkColorFilterPriv.h"
13 #include "src/core/SkRuntimeEffectPriv.h"
14 
Make(const SkHighContrastConfig & config)15 sk_sp<SkColorFilter> SkHighContrastFilter::Make(const SkHighContrastConfig& config) {
16 #ifdef SK_ENABLE_SKSL
17     if (!config.isValid()) {
18         return nullptr;
19     }
20 
21     struct Uniforms { float grayscale, invertStyle, contrast; };
22 
23     SkString code{R"(
24         uniform half grayscale, invertStyle, contrast;
25     )"};
26     code += kRGB_to_HSL_sksl;
27     code += kHSL_to_RGB_sksl;
28     code += R"(
29         half4 main(half4 inColor) {
30             half4 c = inColor;  // linear unpremul RGBA in dst gamut.
31             if (grayscale == 1) {
32                 c.rgb = dot(half3(0.2126, 0.7152, 0.0722), c.rgb).rrr;
33             }
34             if (invertStyle == 1/*brightness*/) {
35                 c.rgb = 1 - c.rgb;
36             } else if (invertStyle == 2/*lightness*/) {
37                 c.rgb = rgb_to_hsl(c.rgb);
38                 c.b = 1 - c.b;
39                 c.rgb = hsl_to_rgb(c.rgb);
40             }
41             c.rgb = mix(half3(0.5), c.rgb, contrast);
42             return half4(saturate(c.rgb), c.a);
43         }
44     )";
45 
46     sk_sp<SkRuntimeEffect> effect = SkMakeCachedRuntimeEffect(SkRuntimeEffect::MakeForColorFilter,
47                                                               std::move(code));
48     SkASSERT(effect);
49 
50     // A contrast setting of exactly +1 would divide by zero (1+c)/(1-c), so pull in to +1-ε.
51     // I'm not exactly sure why we've historically pinned -1 up to -1+ε, maybe just symmetry?
52     float c = SkTPin(config.fContrast,
53                      -1.0f + FLT_EPSILON,
54                      +1.0f - FLT_EPSILON);
55 
56     Uniforms uniforms = {
57         config.fGrayscale ? 1.0f : 0.0f,
58         (float)config.fInvertStyle,  // 0.0f for none, 1.0f for brightness, 2.0f for lightness
59         (1+c)/(1-c),
60     };
61 
62     skcms_TransferFunction linear = SkNamedTransferFn::kLinear;
63     SkAlphaType          unpremul = kUnpremul_SkAlphaType;
64     return SkColorFilterPriv::WithWorkingFormat(
65             effect->makeColorFilter(SkData::MakeWithCopy(&uniforms,sizeof(uniforms))),
66             &linear, nullptr/*use dst gamut*/, &unpremul);
67 #else
68     // TODO(skia:12197)
69     return nullptr;
70 #endif
71 }
72 
73