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 8 #ifndef SkGradientShaderPriv_DEFINED 9 #define SkGradientShaderPriv_DEFINED 10 11 #include "include/core/SkBitmap.h" 12 #include "include/core/SkColor.h" 13 #include "include/core/SkColorSpace.h" 14 #include "include/core/SkMatrix.h" 15 #include "include/core/SkRefCnt.h" 16 #include "include/core/SkScalar.h" 17 #include "include/effects/SkGradientShader.h" 18 #include "include/private/base/SkAssert.h" 19 #include "include/private/base/SkTArray.h" 20 #include "include/private/base/SkTemplates.h" 21 #include "src/core/SkColorData.h" 22 #include "src/shaders/SkShaderBase.h" 23 24 #include <cstddef> 25 #include <cstdint> 26 27 class SkArenaAlloc; 28 class SkRasterPipeline; 29 class SkReadBuffer; 30 class SkShader; 31 class SkWriteBuffer; 32 enum class SkTileMode; 33 struct SkStageRec; 34 35 class SkGradientBaseShader : public SkShaderBase { 36 public: 37 using Interpolation = SkGradientShader::Interpolation; 38 39 struct Descriptor { 40 Descriptor(); 41 ~Descriptor(); 42 43 Descriptor(const SkColor4f colors[], 44 sk_sp<SkColorSpace> colorSpace, 45 const SkScalar positions[], 46 int colorCount, 47 SkTileMode mode, 48 const Interpolation& interpolation); 49 50 const SkColor4f* fColors; 51 sk_sp<SkColorSpace> fColorSpace; 52 const SkScalar* fPositions; 53 int fColorCount; // length of fColors (and fPositions, if not nullptr) 54 SkTileMode fTileMode; 55 Interpolation fInterpolation; 56 }; 57 58 class DescriptorScope : public Descriptor { 59 public: DescriptorScope()60 DescriptorScope() {} 61 62 bool unflatten(SkReadBuffer&, SkMatrix* legacyLocalMatrix); 63 64 private: 65 skia_private::STArray<16, SkColor4f> fColorStorage; 66 skia_private::STArray<16, SkScalar> fPositionStorage; 67 }; 68 69 SkGradientBaseShader(const Descriptor& desc, const SkMatrix& ptsToUnit); 70 ~SkGradientBaseShader() override; 71 type()72 ShaderType type() const final { return ShaderType::kGradientBase; } 73 74 bool isOpaque() const override; 75 interpolateInPremul()76 bool interpolateInPremul() const { 77 return fInterpolation.fInPremul == SkGradientShader::Interpolation::InPremul::kYes; 78 } 79 getGradientMatrix()80 const SkMatrix& getGradientMatrix() const { return fPtsToUnit; } getColorCount()81 int getColorCount() const { return fColorCount; } getPositions()82 const float* getPositions() const { return fPositions; } getInterpolation()83 const Interpolation& getInterpolation() const { return fInterpolation; } 84 85 static bool ValidGradient(const SkColor4f colors[], 86 int count, 87 SkTileMode tileMode, 88 const Interpolation& interpolation); 89 90 static sk_sp<SkShader> MakeDegenerateGradient(const SkColor4f colors[], 91 const SkScalar pos[], 92 int colorCount, 93 sk_sp<SkColorSpace> colorSpace, 94 SkTileMode mode); 95 96 // The default SkScalarNearlyZero threshold of .0024 is too big and causes regressions for svg 97 // gradients defined in the wild. 98 static constexpr SkScalar kDegenerateThreshold = SK_Scalar1 / (1 << 15); 99 100 protected: 101 void flatten(SkWriteBuffer&) const override; 102 103 void commonAsAGradient(GradientInfo*) const; 104 105 bool onAsLuminanceColor(SkColor4f*) const override; 106 107 bool appendStages(const SkStageRec&, const SkShaders::MatrixRec&) const override; 108 109 virtual void appendGradientStages(SkArenaAlloc* alloc, 110 SkRasterPipeline* tPipeline, 111 SkRasterPipeline* postPipeline) const = 0; 112 113 const SkMatrix fPtsToUnit; 114 SkTileMode fTileMode; 115 116 public: 117 static void AppendGradientFillStages(SkRasterPipeline* p, 118 SkArenaAlloc* alloc, 119 const SkPMColor4f* colors, 120 const SkScalar* positions, 121 int count); 122 123 static void AppendInterpolatedToDstStages(SkRasterPipeline* p, 124 SkArenaAlloc* alloc, 125 bool colorsAreOpaque, 126 const Interpolation& interpolation, 127 const SkColorSpace* intermediateColorSpace, 128 const SkColorSpace* dstColorSpace); 129 getPos(int i)130 SkScalar getPos(int i) const { 131 SkASSERT(i < fColorCount); 132 return fPositions ? fPositions[i] : SkIntToScalar(i) / (fColorCount - 1); 133 } 134 getLegacyColor(int i)135 SkColor getLegacyColor(int i) const { 136 SkASSERT(i < fColorCount); 137 return fColors[i].toSkColor(); 138 } 139 140 SkColor4f* fColors; // points into fStorage 141 SkScalar* fPositions; // points into fStorage, or nullptr 142 sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops 143 Interpolation fInterpolation; 144 145 int fColorCount; // length of fColors (and fPositions, if not nullptr) 146 bool fFirstStopIsImplicit; 147 bool fLastStopIsImplicit; 148 colorsAreOpaque()149 bool colorsAreOpaque() const { return fColorsAreOpaque; } 150 getTileMode()151 SkTileMode getTileMode() const { return fTileMode; } 152 cachedBitmap()153 const SkBitmap& cachedBitmap() const { return fColorsAndOffsetsBitmap; } setCachedBitmap(SkBitmap b)154 void setCachedBitmap(SkBitmap b) const { fColorsAndOffsetsBitmap = b; } 155 156 private: 157 // When the number of stops exceeds Graphite's uniform-based limit the colors and offsets 158 // are stored in this bitmap. It is stored in the shader so it can be cached with a stable 159 // id and easily regenerated if purged. 160 // TODO(b/293160919) remove this field when we can store bitmaps in the cache by id. 161 mutable SkBitmap fColorsAndOffsetsBitmap; 162 163 // Reserve inline space for up to 4 stops. 164 inline static constexpr size_t kInlineStopCount = 4; 165 inline static constexpr size_t kInlineStorageSize = 166 (sizeof(SkColor4f) + sizeof(SkScalar)) * kInlineStopCount; 167 skia_private::AutoSTMalloc<kInlineStorageSize, uint8_t> fStorage; 168 169 bool fColorsAreOpaque; 170 }; 171 172 /////////////////////////////////////////////////////////////////////////////// 173 174 struct SkColor4fXformer { 175 SkColor4fXformer(const SkGradientBaseShader* shader, 176 SkColorSpace* dst, 177 bool forceExplicitPositions = false); 178 179 using ColorStorage = skia_private::STArray<4, SkPMColor4f>; 180 using PositionStorage = skia_private::STArray<4, float>; 181 182 ColorStorage fColors; 183 PositionStorage fPositionStorage; 184 float* fPositions; 185 sk_sp<SkColorSpace> fIntermediateColorSpace; 186 }; 187 188 struct SkColorConverter { 189 SkColorConverter(const SkColor* colors, int count); 190 191 skia_private::STArray<2, SkColor4f> fColors4f; 192 }; 193 194 void SkRegisterConicalGradientShaderFlattenable(); 195 void SkRegisterLinearGradientShaderFlattenable(); 196 void SkRegisterRadialGradientShaderFlattenable(); 197 void SkRegisterSweepGradientShaderFlattenable(); 198 199 #endif 200