SkMergeImageFilter.cpp revision 9ea3d57fde28a5fe4487a111dc3dd49418235e5e
1/* 2 * Copyright 2012 The Android Open Source Project 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 "SkMergeImageFilter.h" 9#include "SkCanvas.h" 10#include "SkDevice.h" 11#include "SkReadBuffer.h" 12#include "SkWriteBuffer.h" 13#include "SkValidationUtils.h" 14 15/////////////////////////////////////////////////////////////////////////////// 16 17void SkMergeImageFilter::initAllocModes() { 18 int inputCount = countInputs(); 19 if (inputCount) { 20 size_t size = sizeof(uint8_t) * inputCount; 21 if (size <= sizeof(fStorage)) { 22 fModes = SkTCast<uint8_t*>(fStorage); 23 } else { 24 fModes = SkTCast<uint8_t*>(sk_malloc_throw(size)); 25 } 26 } else { 27 fModes = NULL; 28 } 29} 30 31void SkMergeImageFilter::initModes(const SkXfermode::Mode modes[]) { 32 if (modes) { 33 this->initAllocModes(); 34 int inputCount = countInputs(); 35 for (int i = 0; i < inputCount; ++i) { 36 fModes[i] = SkToU8(modes[i]); 37 } 38 } else { 39 fModes = NULL; 40 } 41} 42 43SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* filters[], int count, 44 const SkXfermode::Mode modes[], 45 const CropRect* cropRect) : INHERITED(count, filters, cropRect) { 46 SkASSERT(count >= 0); 47 this->initModes(modes); 48} 49 50SkMergeImageFilter::~SkMergeImageFilter() { 51 52 if (fModes != SkTCast<uint8_t*>(fStorage)) { 53 sk_free(fModes); 54 } 55} 56 57bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, 58 const Context& ctx, 59 SkBitmap* result, SkIPoint* offset) const { 60 if (countInputs() < 1) { 61 return false; 62 } 63 64 SkIRect bounds; 65 if (!this->applyCropRect(ctx, src, SkIPoint::Make(0, 0), &bounds)) { 66 return false; 67 } 68 69 const int x0 = bounds.left(); 70 const int y0 = bounds.top(); 71 72 SkAutoTUnref<SkBaseDevice> dst(proxy->createDevice(bounds.width(), bounds.height())); 73 if (NULL == dst) { 74 return false; 75 } 76 SkCanvas canvas(dst); 77 SkPaint paint; 78 79 int inputCount = countInputs(); 80 for (int i = 0; i < inputCount; ++i) { 81 SkBitmap tmp; 82 const SkBitmap* srcPtr; 83 SkIPoint pos = SkIPoint::Make(0, 0); 84 SkImageFilter* filter = getInput(i); 85 if (filter) { 86 if (!filter->filterImage(proxy, src, ctx, &tmp, &pos)) { 87 return false; 88 } 89 srcPtr = &tmp; 90 } else { 91 srcPtr = &src; 92 } 93 94 if (fModes) { 95 paint.setXfermodeMode((SkXfermode::Mode)fModes[i]); 96 } else { 97 paint.setXfermode(NULL); 98 } 99 canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint); 100 } 101 102 offset->fX = bounds.left(); 103 offset->fY = bounds.top(); 104 *result = dst->accessBitmap(false); 105 return true; 106} 107 108void SkMergeImageFilter::flatten(SkWriteBuffer& buffer) const { 109 this->INHERITED::flatten(buffer); 110 111 buffer.writeBool(fModes != NULL); 112 if (fModes) { 113 buffer.writeByteArray(fModes, countInputs() * sizeof(fModes[0])); 114 } 115} 116 117SkMergeImageFilter::SkMergeImageFilter(SkReadBuffer& buffer) 118 : INHERITED(-1, buffer) { 119 bool hasModes = buffer.readBool(); 120 if (hasModes) { 121 this->initAllocModes(); 122 int nbInputs = countInputs(); 123 size_t size = nbInputs * sizeof(fModes[0]); 124 SkASSERT(buffer.getArrayCount() == size); 125 if (buffer.validate(buffer.getArrayCount() == size) && 126 buffer.readByteArray(fModes, size)) { 127 for (int i = 0; i < nbInputs; ++i) { 128 buffer.validate(SkIsValidMode((SkXfermode::Mode)fModes[i])); 129 } 130 } 131 } else { 132 fModes = 0; 133 } 134} 135