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 "SkReadBuffer.h"
12 #include "SkWriteBuffer.h"
13 #include "SkValidationUtils.h"
15 ///////////////////////////////////////////////////////////////////////////////
17 void SkMergeImageFilter::initAllocModes() {
18 int inputCount = countInputs();
20 size_t size = sizeof(uint8_t) * inputCount;
21 if (size <= sizeof(fStorage)) {
22 fModes = SkTCast<uint8_t*>(fStorage);
24 fModes = SkTCast<uint8_t*>(sk_malloc_throw(size));
31 void SkMergeImageFilter::initModes(const SkXfermode::Mode modes[]) {
33 this->initAllocModes();
34 int inputCount = countInputs();
35 for (int i = 0; i < inputCount; ++i) {
36 fModes[i] = SkToU8(modes[i]);
43 SkMergeImageFilter::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);
54 SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* filters[], int count,
55 const SkXfermode::Mode modes[],
56 const CropRect* cropRect) : INHERITED(count, filters, cropRect) {
58 this->initModes(modes);
61 SkMergeImageFilter::~SkMergeImageFilter() {
63 if (fModes != SkTCast<uint8_t*>(fStorage)) {
68 bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
70 SkBitmap* result, SkIPoint* offset) const {
71 if (countInputs() < 1) {
76 src.getBounds(&bounds);
77 if (!this->applyCropRect(&bounds, ctm)) {
81 const int x0 = bounds.left();
82 const int y0 = bounds.top();
84 SkAutoTUnref<SkBaseDevice> dst(proxy->createDevice(bounds.width(), bounds.height()));
91 int inputCount = countInputs();
92 for (int i = 0; i < inputCount; ++i) {
94 const SkBitmap* srcPtr;
95 SkIPoint pos = SkIPoint::Make(0, 0);
96 SkImageFilter* filter = getInput(i);
98 if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) {
107 paint.setXfermodeMode((SkXfermode::Mode)fModes[i]);
109 paint.setXfermode(NULL);
111 canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint);
114 offset->fX = bounds.left();
115 offset->fY = bounds.top();
116 *result = dst->accessBitmap(false);
120 void SkMergeImageFilter::flatten(SkWriteBuffer& buffer) const {
121 this->INHERITED::flatten(buffer);
123 buffer.writeBool(fModes != NULL);
125 buffer.writeByteArray(fModes, countInputs() * sizeof(fModes[0]));
129 SkMergeImageFilter::SkMergeImageFilter(SkReadBuffer& buffer)
130 : INHERITED(-1, buffer) {
131 bool hasModes = buffer.readBool();
133 this->initAllocModes();
134 int nbInputs = countInputs();
135 size_t size = nbInputs * sizeof(fModes[0]);
136 SkASSERT(buffer.getArrayCount() == size);
137 if (buffer.validate(buffer.getArrayCount() == size) &&
138 buffer.readByteArray(fModes, size)) {
139 for (int i = 0; i < nbInputs; ++i) {
140 buffer.validate(SkIsValidMode((SkXfermode::Mode)fModes[i]));