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