xref: /aosp_15_r20/external/skia/src/shaders/gradients/SkConicalGradient.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2012 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 #ifndef SkConicalGradient_DEFINED
8 #define SkConicalGradient_DEFINED
9 
10 #include "include/core/SkFlattenable.h"
11 #include "include/core/SkPoint.h"
12 #include "include/core/SkRefCnt.h"
13 #include "include/core/SkScalar.h"
14 #include "src/shaders/gradients/SkGradientBaseShader.h"
15 
16 class SkArenaAlloc;
17 class SkMatrix;
18 class SkRasterPipeline;
19 class SkReadBuffer;
20 class SkShader;
21 class SkWriteBuffer;
22 
23 // Please see https://skia.org/dev/design/conical for how our shader works.
24 class SkConicalGradient final : public SkGradientBaseShader {
25 public:
26     // See https://skia.org/dev/design/conical for what focal data means and how our shader works.
27     // We make it public so the GPU shader can also use it.
28     struct FocalData {
29         SkScalar fR1;      // r1 after mapping focal point to (0, 0)
30         SkScalar fFocalX;  // f
31         bool fIsSwapped;   // whether we swapped r0, r1
32 
33         // The input r0, r1 are the radii when we map centers to {(0, 0), (1, 0)}.
34         // We'll post concat matrix with our transformation matrix that maps focal point to (0, 0).
35         // Returns true if the set succeeded
36         bool set(SkScalar r0, SkScalar r1, SkMatrix* matrix);
37 
38         // Whether the focal point (0, 0) is on the end circle with center (1, 0) and radius r1. If
39         // this is true, it's as if an aircraft is flying at Mach 1 and all circles (soundwaves)
40         // will go through the focal point (aircraft). In our previous implementations, this was
41         // known as the edge case where the inside circle touches the outside circle (on the focal
42         // point). If we were to solve for t bruteforcely using a quadratic equation, this case
43         // implies that the quadratic equation degenerates to a linear equation.
isFocalOnCircleFocalData44         bool isFocalOnCircle() const { return SkScalarNearlyZero(1 - fR1); }
45 
isSwappedFocalData46         bool isSwapped() const { return fIsSwapped; }
isWellBehavedFocalData47         bool isWellBehaved() const { return !this->isFocalOnCircle() && fR1 > 1; }
isNativelyFocalFocalData48         bool isNativelyFocal() const { return SkScalarNearlyZero(fFocalX); }
49     };
50 
51     enum class Type { kRadial, kStrip, kFocal };
52 
53     static bool MapToUnitX(const SkPoint& startCenter,
54                            const SkPoint& endCenter,
55                            SkMatrix* dstMatrix);
56 
57     static sk_sp<SkShader> Create(const SkPoint& start,
58                                   SkScalar startRadius,
59                                   const SkPoint& end,
60                                   SkScalar endRadius,
61                                   const Descriptor&,
62                                   const SkMatrix* localMatrix);
63 
64     GradientType asGradient(GradientInfo* info, SkMatrix* localMatrix) const override;
65     bool isOpaque() const override;
66 
getCenterX1()67     SkScalar getCenterX1() const { return SkPoint::Distance(fCenter1, fCenter2); }
getStartRadius()68     SkScalar getStartRadius() const { return fRadius1; }
getDiffRadius()69     SkScalar getDiffRadius() const { return fRadius2 - fRadius1; }
getStartCenter()70     const SkPoint& getStartCenter() const { return fCenter1; }
getEndCenter()71     const SkPoint& getEndCenter() const { return fCenter2; }
getEndRadius()72     SkScalar getEndRadius() const { return fRadius2; }
73 
getType()74     Type getType() const { return fType; }
getFocalData()75     const FocalData& getFocalData() const { return fFocalData; }
76 
77     SkConicalGradient(const SkPoint& c0,
78                       SkScalar r0,
79                       const SkPoint& c1,
80                       SkScalar r1,
81                       const Descriptor&,
82                       Type,
83                       const SkMatrix&,
84                       const FocalData&);
85 
86 protected:
87     void flatten(SkWriteBuffer& buffer) const override;
88 
89     void appendGradientStages(SkArenaAlloc* alloc,
90                               SkRasterPipeline* tPipeline,
91                               SkRasterPipeline* postPipeline) const override;
92 
93 private:
94     friend void ::SkRegisterConicalGradientShaderFlattenable();
95     SK_FLATTENABLE_HOOKS(SkConicalGradient)
96 
97     SkPoint fCenter1;
98     SkPoint fCenter2;
99     SkScalar fRadius1;
100     SkScalar fRadius2;
101     Type fType;
102 
103     FocalData fFocalData;
104 };
105 
106 #endif
107