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/SkColorData.h" 19 #include "include/private/base/SkAssert.h" 20 #include "include/private/base/SkTArray.h" 21 #include "include/private/base/SkTemplates.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 int fColorCount; // length of fColors (and fPositions, if not nullptr) 143 sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops 144 Interpolation fInterpolation; 145 bool fFirstStopIsImplicit; 146 bool fLastStopIsImplicit; 147 colorsAreOpaque()148 bool colorsAreOpaque() const { return fColorsAreOpaque; } 149 getTileMode()150 SkTileMode getTileMode() const { return fTileMode; } 151 cachedBitmap()152 const SkBitmap& cachedBitmap() const { return fColorsAndOffsetsBitmap; } setCachedBitmap(SkBitmap b)153 void setCachedBitmap(SkBitmap b) const { fColorsAndOffsetsBitmap = b; } 154 155 private: 156 // When the number of stops exceeds Graphite's uniform-based limit the colors and offsets 157 // are stored in this bitmap. It is stored in the shader so it can be cached with a stable 158 // id and easily regenerated if purged. 159 // TODO(b/293160919) remove this field when we can store bitmaps in the cache by id. 160 mutable SkBitmap fColorsAndOffsetsBitmap; 161 162 // Reserve inline space for up to 4 stops. 163 inline static constexpr size_t kInlineStopCount = 4; 164 inline static constexpr size_t kInlineStorageSize = 165 (sizeof(SkColor4f) + sizeof(SkScalar)) * kInlineStopCount; 166 skia_private::AutoSTMalloc<kInlineStorageSize, uint8_t> fStorage; 167 168 bool fColorsAreOpaque; 169 }; 170 171 /////////////////////////////////////////////////////////////////////////////// 172 173 struct SkColor4fXformer { 174 SkColor4fXformer(const SkGradientBaseShader* shader, 175 SkColorSpace* dst, 176 bool forceExplicitPositions = false); 177 178 using ColorStorage = skia_private::STArray<4, SkPMColor4f>; 179 using PositionStorage = skia_private::STArray<4, float>; 180 181 ColorStorage fColors; 182 PositionStorage fPositionStorage; 183 float* fPositions; 184 sk_sp<SkColorSpace> fIntermediateColorSpace; 185 }; 186 187 struct SkColorConverter { 188 SkColorConverter(const SkColor* colors, int count); 189 190 skia_private::STArray<2, SkColor4f> fColors4f; 191 }; 192 193 void SkRegisterConicalGradientShaderFlattenable(); 194 void SkRegisterLinearGradientShaderFlattenable(); 195 void SkRegisterRadialGradientShaderFlattenable(); 196 void SkRegisterSweepGradientShaderFlattenable(); 197 198 #endif 199