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/SkPaintPriv.h" 13#include "src/core/SkXfermodePriv.h" 14 15class BitmapProcShaderContext : public SkShaderBase::Context { 16public: 17 BitmapProcShaderContext(const SkShaderBase& shader, const SkShaderBase::ContextRec& rec, 18 SkBitmapProcState* state) 19 : INHERITED(shader, rec) 20 , fState(state) 21 , fFlags(0) 22 { 23 if (fState->fPixmap.isOpaque() && (255 == this->getPaintAlpha())) { 24 fFlags |= SkShaderBase::kOpaqueAlpha_Flag; 25 } 26 27 auto only_scale_and_translate = [](const SkMatrix& matrix) { 28 unsigned mask = SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask; 29 return (matrix.getType() & ~mask) == 0; 30 }; 31 32 if (1 == fState->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 void shadeSpan(int x, int y, SkPMColor dstC[], int count) override { 40 const SkBitmapProcState& state = *fState; 41 if (state.getShaderProc32()) { 42 state.getShaderProc32()(&state, x, y, dstC, count); 43 return; 44 } 45 46 const int BUF_MAX = 128; 47 uint32_t buffer[BUF_MAX]; 48 SkBitmapProcState::MatrixProc mproc = state.getMatrixProc(); 49 SkBitmapProcState::SampleProc32 sproc = state.getSampleProc32(); 50 const int max = state.maxCountForBufferSize(sizeof(buffer[0]) * BUF_MAX); 51 52 SkASSERT(state.fPixmap.addr()); 53 54 for (;;) { 55 int n = std::min(count, max); 56 SkASSERT(n > 0 && n < BUF_MAX*2); 57 mproc(state, buffer, n, x, y); 58 sproc(state, buffer, n, dstC); 59 60 if ((count -= n) == 0) { 61 break; 62 } 63 SkASSERT(count > 0); 64 x += n; 65 dstC += n; 66 } 67 } 68 69private: 70 SkBitmapProcState* fState; 71 uint32_t fFlags; 72 73 using INHERITED = SkShaderBase::Context; 74}; 75 76/////////////////////////////////////////////////////////////////////////////////////////////////// 77 78SkShaderBase::Context* SkBitmapProcLegacyShader::MakeContext( 79 const SkShaderBase& shader, SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions& sampling, 80 const SkImage_Base* image, const ContextRec& rec, SkArenaAlloc* alloc) 81{ 82 SkMatrix totalInverse; 83 // Do this first, so we know the matrix can be inverted. 84 if (!shader.computeTotalInverse(*rec.fMatrix, rec.fLocalMatrix, &totalInverse)) { 85 return nullptr; 86 } 87 88 SkBitmapProcState* state = alloc->make<SkBitmapProcState>(image, tmx, tmy); 89 if (!state->setup(totalInverse, rec.fPaintAlpha, sampling)) { 90 return nullptr; 91 } 92 return alloc->make<BitmapProcShaderContext>(shader, rec, state); 93} 94