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