xref: /aosp_15_r20/external/skia/src/effects/SkBlenders.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/SkBlender.h"
9 #include "include/core/SkRefCnt.h"
10 #include "include/core/SkTypes.h"
11 #include "include/effects/SkBlenders.h"
12 
13 #include "include/core/SkBlendMode.h"
14 #include "include/core/SkData.h"
15 #include "include/core/SkScalar.h"
16 #include "include/effects/SkRuntimeEffect.h"
17 #include "include/private/base/SkFloatingPoint.h"
18 #include "src/core/SkKnownRuntimeEffects.h"
19 
Arithmetic(float k1,float k2,float k3,float k4,bool enforcePremul)20 sk_sp<SkBlender> SkBlenders::Arithmetic(float k1, float k2, float k3, float k4,
21                                         bool enforcePremul) {
22     using namespace SkKnownRuntimeEffects;
23 
24     if (!SkIsFinite(k1, k2, k3, k4)) {
25         return nullptr;
26     }
27 
28     // Are we nearly a SkBlendMode?
29     const struct {
30         float       k1, k2, k3, k4;
31         SkBlendMode mode;
32     } table[] = {
33         { 0, 1, 0, 0, SkBlendMode::kSrc   },
34         { 0, 0, 1, 0, SkBlendMode::kDst   },
35         { 0, 0, 0, 0, SkBlendMode::kClear },
36     };
37     for (const auto& t : table) {
38         if (SkScalarNearlyEqual(k1, t.k1) &&
39             SkScalarNearlyEqual(k2, t.k2) &&
40             SkScalarNearlyEqual(k3, t.k3) &&
41             SkScalarNearlyEqual(k4, t.k4)) {
42             return SkBlender::Mode(t.mode);
43         }
44     }
45 
46     // If we get here, we need the actual blender effect.
47     const SkRuntimeEffect* arithmeticEffect = GetKnownRuntimeEffect(StableKey::kArithmetic);
48 
49     const float array[] = {
50         k1, k2, k3, k4,
51         enforcePremul ? 0.0f : 1.0f,
52     };
53     return arithmeticEffect->makeBlender(SkData::MakeWithCopy(array, sizeof(array)));
54 }
55