1 | /* |
2 | * Copyright 2011 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/SkBitmapProcShader.h" |
9 | |
10 | #include "src/core/SkArenaAlloc.h" |
11 | #include "src/core/SkBitmapProcState.h" |
12 | #include "src/core/SkXfermodePriv.h" |
13 | |
14 | static bool only_scale_and_translate(const SkMatrix& matrix) { |
15 | unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; |
16 | return (matrix.getType() & ~mask) == 0; |
17 | } |
18 | |
19 | class BitmapProcInfoContext : public SkShaderBase::Context { |
20 | public: |
21 | // The info has been allocated elsewhere, but we are responsible for calling its destructor. |
22 | BitmapProcInfoContext(const SkShaderBase& shader, const SkShaderBase::ContextRec& rec, |
23 | SkBitmapProcInfo* info) |
24 | : INHERITED(shader, rec) |
25 | , fInfo(info) |
26 | { |
27 | fFlags = 0; |
28 | if (fInfo->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) { |
29 | fFlags |= SkShaderBase::kOpaqueAlpha_Flag; |
30 | } |
31 | |
32 | if (1 == fInfo->fPixmap.height() && only_scale_and_translate(this->getTotalInverse())) { |
33 | fFlags |= SkShaderBase::kConstInY32_Flag; |
34 | } |
35 | } |
36 | |
37 | uint32_t getFlags() const override { return fFlags; } |
38 | |
39 | private: |
40 | SkBitmapProcInfo* fInfo; |
41 | uint32_t fFlags; |
42 | |
43 | typedef SkShaderBase::Context INHERITED; |
44 | }; |
45 | |
46 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
47 | |
48 | class BitmapProcShaderContext : public BitmapProcInfoContext { |
49 | public: |
50 | BitmapProcShaderContext(const SkShaderBase& shader, const SkShaderBase::ContextRec& rec, |
51 | SkBitmapProcState* state) |
52 | : INHERITED(shader, rec, state) |
53 | , fState(state) |
54 | {} |
55 | |
56 | void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { |
57 | const SkBitmapProcState& state = *fState; |
58 | if (state.getShaderProc32()) { |
59 | state.getShaderProc32()(&state, x, y, dstC, count); |
60 | return; |
61 | } |
62 | |
63 | const int BUF_MAX = 128; |
64 | uint32_t buffer[BUF_MAX]; |
65 | SkBitmapProcState::MatrixProc mproc = state.getMatrixProc(); |
66 | SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32(); |
67 | const int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX); |
68 | |
69 | SkASSERT(state.fPixmap.addr()); |
70 | |
71 | for (;;) { |
72 | int n = std::min(count, max); |
73 | SkASSERT(n > 0 && n < BUF_MAX*2); |
74 | mproc(state, buffer, n, x, y); |
75 | sproc(state, buffer, n, dstC); |
76 | |
77 | if ((count -= n) == 0) { |
78 | break; |
79 | } |
80 | SkASSERT(count > 0); |
81 | x += n; |
82 | dstC += n; |
83 | } |
84 | } |
85 | |
86 | private: |
87 | SkBitmapProcState* fState; |
88 | |
89 | typedef BitmapProcInfoContext INHERITED; |
90 | }; |
91 | |
92 | /////////////////////////////////////////////////////////////////////////////////////////////////// |
93 | |
94 | SkShaderBase::Context* SkBitmapProcLegacyShader::MakeContext( |
95 | const SkShaderBase& shader, SkTileMode tmx, SkTileMode tmy, |
96 | const SkImage_Base* image, const ContextRec& rec, SkArenaAlloc* alloc) |
97 | { |
98 | SkMatrix totalInverse; |
99 | // Do this first, so we know the matrix can be inverted. |
100 | if (!shader.computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &totalInverse)) { |
101 | return nullptr; |
102 | } |
103 | |
104 | SkBitmapProcState* state = alloc->make<SkBitmapProcState>(image, tmx, tmy); |
105 | if (!state->setup(totalInverse, *rec.fPaint)) { |
106 | return nullptr; |
107 | } |
108 | return alloc->make<BitmapProcShaderContext>(shader, rec, state); |
109 | } |
110 | |