SkMergeImageFilter.cpp revision 8b0e8ac5f582de80356019406e2975079bf0829d
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* first, SkImageFilter* second, 44 SkXfermode::Mode mode, 45 const CropRect* cropRect) : INHERITED(first, second, cropRect) { 46 if (SkXfermode::kSrcOver_Mode != mode) { 47 SkXfermode::Mode modes[] = { mode, mode }; 48 this->initModes(modes); 49 } else { 50 fModes = NULL; 51 } 52} 53 54SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* filters[], int count, 55 const SkXfermode::Mode modes[], 56 const CropRect* cropRect) : INHERITED(count, filters, cropRect) { 57 SkASSERT(count >= 0); 58 this->initModes(modes); 59} 60 61SkMergeImageFilter::~SkMergeImageFilter() { 62 63 if (fModes != SkTCast<uint8_t*>(fStorage)) { 64 sk_free(fModes); 65 } 66} 67 68bool SkMergeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 69 SkIRect* dst) { 70 if (countInputs() < 1) { 71 return false; 72 } 73 74 SkIRect totalBounds; 75 76 int inputCount = countInputs(); 77 for (int i = 0; i < inputCount; ++i) { 78 SkImageFilter* filter = getInput(i); 79 SkIRect r; 80 if (filter) { 81 if (!filter->filterBounds(src, ctm, &r)) { 82 return false; 83 } 84 } else { 85 r = src; 86 } 87 if (0 == i) { 88 totalBounds = r; 89 } else { 90 totalBounds.join(r); 91 } 92 } 93 94 // don't modify dst until now, so we don't accidentally change it in the 95 // loop, but then return false on the next filter. 96 *dst = totalBounds; 97 return true; 98} 99 100bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src, 101 const SkMatrix& ctm, 102 SkBitmap* result, SkIPoint* offset) { 103 if (countInputs() < 1) { 104 return false; 105 } 106 107 SkIRect bounds; 108 src.getBounds(&bounds); 109 if (!this->applyCropRect(&bounds, ctm)) { 110 return false; 111 } 112 113 const int x0 = bounds.left(); 114 const int y0 = bounds.top(); 115 116 SkAutoTUnref<SkBaseDevice> dst(proxy->createDevice(bounds.width(), bounds.height())); 117 if (NULL == dst) { 118 return false; 119 } 120 SkCanvas canvas(dst); 121 SkPaint paint; 122 123 int inputCount = countInputs(); 124 for (int i = 0; i < inputCount; ++i) { 125 SkBitmap tmp; 126 const SkBitmap* srcPtr; 127 SkIPoint pos = SkIPoint::Make(0, 0); 128 SkImageFilter* filter = getInput(i); 129 if (filter) { 130 if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) { 131 return false; 132 } 133 srcPtr = &tmp; 134 } else { 135 srcPtr = &src; 136 } 137 138 if (fModes) { 139 paint.setXfermodeMode((SkXfermode::Mode)fModes[i]); 140 } else { 141 paint.setXfermode(NULL); 142 } 143 canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint); 144 } 145 146 offset->fX = bounds.left(); 147 offset->fY = bounds.top(); 148 *result = dst->accessBitmap(false); 149 return true; 150} 151 152void SkMergeImageFilter::flatten(SkWriteBuffer& buffer) const { 153 this->INHERITED::flatten(buffer); 154 155 buffer.writeBool(fModes != NULL); 156 if (fModes) { 157 buffer.writeByteArray(fModes, countInputs() * sizeof(fModes[0])); 158 } 159} 160 161SkMergeImageFilter::SkMergeImageFilter(SkReadBuffer& buffer) 162 : INHERITED(-1, buffer) { 163 bool hasModes = buffer.readBool(); 164 if (hasModes) { 165 this->initAllocModes(); 166 int nbInputs = countInputs(); 167 size_t size = nbInputs * sizeof(fModes[0]); 168 SkASSERT(buffer.getArrayCount() == size); 169 if (buffer.validate(buffer.getArrayCount() == size) && 170 buffer.readByteArray(fModes, size)) { 171 for (int i = 0; i < nbInputs; ++i) { 172 buffer.validate(SkIsValidMode((SkXfermode::Mode)fModes[i])); 173 } 174 } 175 } else { 176 fModes = 0; 177 } 178} 179