Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / effects / SkMergeImageFilter.cpp
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
17 void 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
31 void 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
43 SkMergeImageFilter::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
50 SkMergeImageFilter::~SkMergeImageFilter() {
51
52     if (fModes != SkTCast<uint8_t*>(fStorage)) {
53         sk_free(fModes);
54     }
55 }
56
57 bool 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
108 void 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
117 SkMergeImageFilter::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 }