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