xref: /aosp_15_r20/external/skia/src/shaders/SkTriColorShader.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 Google LLC
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 SkTriColorShader_DEFINED
8 #define SkTriColorShader_DEFINED
9 
10 #include "include/core/SkMatrix.h"
11 #include "include/core/SkTypes.h"
12 #include "include/private/SkColorData.h"
13 #include "src/shaders/SkShaderBase.h"
14 
15 struct SkPoint;
16 struct SkStageRec;
17 
18 class SkTriColorShader : public SkShaderBase {
19 public:
SkTriColorShader(bool isOpaque,bool usePersp)20     SkTriColorShader(bool isOpaque, bool usePersp) : fIsOpaque(isOpaque), fUsePersp(usePersp) {}
21 
type()22     ShaderType type() const override { return ShaderType::kTriColor; }
23 
24     // This gets called for each triangle, without re-calling appendStages.
25     bool update(const SkMatrix& ctmInv,
26                 const SkPoint pts[],
27                 const SkPMColor4f colors[],
28                 int index0,
29                 int index1,
30                 int index2);
31 
32 protected:
33     bool appendStages(const SkStageRec& rec, const SkShaders::MatrixRec&) const override;
34 
35 private:
isOpaque()36     bool isOpaque() const override { return fIsOpaque; }
37     // For serialization.  This will never be called.
getFactory()38     Factory getFactory() const override { return nullptr; }
getTypeName()39     const char* getTypeName() const override { return nullptr; }
40 
41     struct Matrix43 {
42         float fMat[12];  // column major
43 
44         // Pass a by value, so we don't have to worry about aliasing with this
setConcatMatrix4345         void setConcat(const Matrix43 a, const SkMatrix& b) {
46             SkASSERT(!b.hasPerspective());
47 
48             fMat[0] = a.dot(0, b.getScaleX(), b.getSkewY());
49             fMat[1] = a.dot(1, b.getScaleX(), b.getSkewY());
50             fMat[2] = a.dot(2, b.getScaleX(), b.getSkewY());
51             fMat[3] = a.dot(3, b.getScaleX(), b.getSkewY());
52 
53             fMat[4] = a.dot(0, b.getSkewX(), b.getScaleY());
54             fMat[5] = a.dot(1, b.getSkewX(), b.getScaleY());
55             fMat[6] = a.dot(2, b.getSkewX(), b.getScaleY());
56             fMat[7] = a.dot(3, b.getSkewX(), b.getScaleY());
57 
58             fMat[8] = a.dot(0, b.getTranslateX(), b.getTranslateY()) + a.fMat[8];
59             fMat[9] = a.dot(1, b.getTranslateX(), b.getTranslateY()) + a.fMat[9];
60             fMat[10] = a.dot(2, b.getTranslateX(), b.getTranslateY()) + a.fMat[10];
61             fMat[11] = a.dot(3, b.getTranslateX(), b.getTranslateY()) + a.fMat[11];
62         }
63 
64     private:
dotMatrix4365         float dot(int index, float x, float y) const {
66             return fMat[index + 0] * x + fMat[index + 4] * y;
67         }
68     };
69 
70     // If fUsePersp, we need both of these matrices,
71     // otherwise we can combine them, and only use fM43
72 
73     Matrix43 fM43;
74     SkMatrix fM33;
75     const bool fIsOpaque;
76     const bool fUsePersp;  // controls our stages, and what we do in update()
77 };
78 
79 #endif
80