• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 Google LLC
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/SkScalar.h"
9 #include "include/effects/SkBlenders.h"
10 #include "include/effects/SkRuntimeEffect.h"
11 
Arithmetic(float k1,float k2,float k3,float k4,bool enforcePremul)12 sk_sp<SkBlender> SkBlenders::Arithmetic(float k1, float k2, float k3, float k4,
13                                         bool enforcePremul) {
14 #ifdef SK_ENABLE_SKSL
15     if (!SkScalarIsFinite(k1) ||
16         !SkScalarIsFinite(k2) ||
17         !SkScalarIsFinite(k3) ||
18         !SkScalarIsFinite(k4)) {
19         return nullptr;
20     }
21 
22     // Are we nearly a SkBlendMode?
23     const struct {
24         float       k1, k2, k3, k4;
25         SkBlendMode mode;
26     } table[] = {
27         { 0, 1, 0, 0, SkBlendMode::kSrc   },
28         { 0, 0, 1, 0, SkBlendMode::kDst   },
29         { 0, 0, 0, 0, SkBlendMode::kClear },
30     };
31     for (const auto& t : table) {
32         if (SkScalarNearlyEqual(k1, t.k1) &&
33             SkScalarNearlyEqual(k2, t.k2) &&
34             SkScalarNearlyEqual(k3, t.k3) &&
35             SkScalarNearlyEqual(k4, t.k4)) {
36             return SkBlender::Mode(t.mode);
37         }
38     }
39 
40     // If we get here, we need the actual blender effect.
41 
42     static SkRuntimeEffect* gArithmeticEffect = []{
43         const char prog[] = R"(
44             uniform half4   k;
45             uniform half    pmClamp;
46 
47             half4 main(half4 src, half4 dst) {
48                 half4 c = k.x * src * dst + k.y * src + k.z * dst + k.w;
49                 c.rgb = min(c.rgb, max(c.a, pmClamp));
50                 // rely on skia to saturate our alpha
51                 return c;
52             }
53         )";
54         auto result = SkRuntimeEffect::MakeForBlender(SkString(prog));
55         SkASSERTF(result.effect, "SkBlenders::Arithmetic: %s", result.errorText.c_str());
56         return result.effect.release();
57     }();
58 
59     const float array[] = {
60         k1, k2, k3, k4,
61         enforcePremul ? 0.0f : 1.0f,
62     };
63     return gArithmeticEffect->makeBlender(SkData::MakeWithCopy(array, sizeof(array)));
64 #else
65     // TODO(skia:12197)
66     return nullptr;
67 #endif
68 }
69