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