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