2 * Copyright 2012 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkMergeImageFilter.h"
11 #include "SkFlattenableBuffers.h"
12 #include "SkValidationUtils.h"
14 ///////////////////////////////////////////////////////////////////////////////
16 void SkMergeImageFilter::initAllocModes() {
17 int inputCount = countInputs();
19 size_t size = sizeof(uint8_t) * inputCount;
20 if (size <= sizeof(fStorage)) {
21 fModes = SkTCast<uint8_t*>(fStorage);
23 fModes = SkTCast<uint8_t*>(sk_malloc_throw(size));
30 void SkMergeImageFilter::initModes(const SkXfermode::Mode modes[]) {
32 this->initAllocModes();
33 int inputCount = countInputs();
34 for (int i = 0; i < inputCount; ++i) {
35 fModes[i] = SkToU8(modes[i]);
42 SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* first, SkImageFilter* second,
43 SkXfermode::Mode mode,
44 const CropRect* cropRect) : INHERITED(first, second, cropRect) {
45 if (SkXfermode::kSrcOver_Mode != mode) {
46 SkXfermode::Mode modes[] = { mode, mode };
47 this->initModes(modes);
53 SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* filters[], int count,
54 const SkXfermode::Mode modes[],
55 const CropRect* cropRect) : INHERITED(count, filters, cropRect) {
56 this->initModes(modes);
59 SkMergeImageFilter::~SkMergeImageFilter() {
61 if (fModes != SkTCast<uint8_t*>(fStorage)) {
66 bool SkMergeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
68 if (countInputs() < 1) {
74 int inputCount = countInputs();
75 for (int i = 0; i < inputCount; ++i) {
76 SkImageFilter* filter = getInput(i);
79 if (!filter->filterBounds(src, ctm, &r)) {
92 // don't modify dst until now, so we don't accidentally change it in the
93 // loop, but then return false on the next filter.
98 bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
100 SkBitmap* result, SkIPoint* loc) {
101 if (countInputs() < 1) {
106 src.getBounds(&bounds);
107 if (!this->applyCropRect(&bounds, ctm)) {
111 const int x0 = bounds.left();
112 const int y0 = bounds.top();
114 SkAutoTUnref<SkBaseDevice> dst(proxy->createDevice(bounds.width(), bounds.height()));
118 SkCanvas canvas(dst);
121 int inputCount = countInputs();
122 for (int i = 0; i < inputCount; ++i) {
124 const SkBitmap* srcPtr;
125 SkIPoint pos = SkIPoint::Make(0, 0);
126 SkImageFilter* filter = getInput(i);
128 if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) {
137 paint.setXfermodeMode((SkXfermode::Mode)fModes[i]);
139 paint.setXfermode(NULL);
141 canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint);
144 loc->fX += bounds.left();
145 loc->fY += bounds.top();
146 *result = dst->accessBitmap(false);
150 void SkMergeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
151 this->INHERITED::flatten(buffer);
153 buffer.writeBool(fModes != NULL);
155 buffer.writeByteArray(fModes, countInputs() * sizeof(fModes[0]));
159 SkMergeImageFilter::SkMergeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
160 bool hasModes = buffer.readBool();
162 this->initAllocModes();
163 int nbInputs = countInputs();
164 size_t size = nbInputs * sizeof(fModes[0]);
165 SkASSERT(buffer.getArrayCount() == size);
166 buffer.readByteArray(fModes, size);
167 for (int i = 0; i < nbInputs; ++i) {
168 buffer.validate(SkIsValidMode((SkXfermode::Mode)fModes[i]));