/src/skia/src/shaders/SkTransformShader.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2021 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 | | #include "src/shaders/SkTransformShader.h" |
9 | | |
10 | | #include "include/core/SkMatrix.h" |
11 | | #include "src/core/SkEffectPriv.h" |
12 | | #include "src/core/SkRasterPipeline.h" |
13 | | #include "src/core/SkRasterPipelineOpList.h" |
14 | | |
15 | | #include <optional> |
16 | | |
17 | | SkTransformShader::SkTransformShader(const SkShaderBase& shader, bool allowPerspective) |
18 | 292 | : fShader{shader}, fAllowPerspective{allowPerspective} { |
19 | 292 | SkMatrix::I().get9(fMatrixStorage); |
20 | 292 | } |
21 | | |
22 | 142k | bool SkTransformShader::update(const SkMatrix& matrix) { |
23 | 142k | if (!fAllowPerspective && matrix.hasPerspective()) { |
24 | 0 | return false; |
25 | 0 | } |
26 | | |
27 | 142k | matrix.get9(fMatrixStorage); |
28 | 142k | return true; |
29 | 142k | } |
30 | | |
31 | | bool SkTransformShader::appendStages(const SkStageRec& rec, |
32 | 292 | const SkShaders::MatrixRec& mRec) const { |
33 | | // We have to seed and apply any constant matrices before appending our matrix that may |
34 | | // mutate. We could try to add one matrix stage and then incorporate the parent matrix |
35 | | // with the variable matrix in each call to update(). However, in practice our callers |
36 | | // fold the CTM into the update() matrix and don't wrap the transform shader in local matrix |
37 | | // shaders so the call to apply below should just seed the coordinates. If this assert fires |
38 | | // it just indicates an optimization opportunity, not a correctness bug. |
39 | 292 | SkASSERT(!mRec.hasPendingMatrix()); |
40 | 292 | std::optional<SkShaders::MatrixRec> childMRec = mRec.apply(rec); |
41 | 292 | if (!childMRec.has_value()) { |
42 | 0 | return false; |
43 | 0 | } |
44 | | // The matrix we're about to insert gets updated between uses of the pipeline so our children |
45 | | // can't know the total transform when they add their stages. We don't even incorporate this |
46 | | // matrix into the SkShaders::MatrixRec at all. |
47 | 292 | childMRec->markTotalMatrixInvalid(); |
48 | | |
49 | 292 | auto type = fAllowPerspective ? SkRasterPipelineOp::matrix_perspective |
50 | 292 | : SkRasterPipelineOp::matrix_2x3; |
51 | 292 | rec.fPipeline->append(type, fMatrixStorage); |
52 | | |
53 | 292 | fShader.appendStages(rec, *childMRec); |
54 | 292 | return true; |
55 | 292 | } |