IndexedDB: fsync after transactions.
[chromium-blink-merge.git] / cc / output / render_surface_filters.cc
blobbc13b5eae715997751ac7d545adbd027a7bc839e
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/output/render_surface_filters.h"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "cc/output/filter_operation.h"
11 #include "cc/output/filter_operations.h"
12 #include "skia/ext/refptr.h"
13 #include "third_party/skia/include/core/SkCanvas.h"
14 #include "third_party/skia/include/core/SkFlattenableBuffers.h"
15 #include "third_party/skia/include/core/SkImageFilter.h"
16 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
17 #include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
18 #include "third_party/skia/include/effects/SkColorMatrixFilter.h"
19 #include "third_party/skia/include/effects/SkComposeImageFilter.h"
20 #include "third_party/skia/include/effects/SkDropShadowImageFilter.h"
21 #include "third_party/skia/include/effects/SkMagnifierImageFilter.h"
22 #include "third_party/skia/include/gpu/SkGpuDevice.h"
23 #include "third_party/skia/include/gpu/SkGrPixelRef.h"
24 #include "ui/gfx/size_f.h"
26 namespace cc {
28 namespace {
30 void GetBrightnessMatrix(float amount, SkScalar matrix[20]) {
31 // Spec implementation
32 // (http://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#brightnessEquivalent)
33 // <feFunc[R|G|B] type="linear" slope="[amount]">
34 memset(matrix, 0, 20 * sizeof(SkScalar));
35 matrix[0] = matrix[6] = matrix[12] = amount;
36 matrix[18] = 1.f;
39 void GetSaturatingBrightnessMatrix(float amount, SkScalar matrix[20]) {
40 // Legacy implementation used by internal clients.
41 // <feFunc[R|G|B] type="linear" intercept="[amount]"/>
42 memset(matrix, 0, 20 * sizeof(SkScalar));
43 matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f;
44 matrix[4] = matrix[9] = matrix[14] = amount * 255.f;
47 void GetContrastMatrix(float amount, SkScalar matrix[20]) {
48 memset(matrix, 0, 20 * sizeof(SkScalar));
49 matrix[0] = matrix[6] = matrix[12] = amount;
50 matrix[4] = matrix[9] = matrix[14] = (-0.5f * amount + 0.5f) * 255.f;
51 matrix[18] = 1.f;
54 void GetSaturateMatrix(float amount, SkScalar matrix[20]) {
55 // Note, these values are computed to ensure MatrixNeedsClamping is false
56 // for amount in [0..1]
57 matrix[0] = 0.213f + 0.787f * amount;
58 matrix[1] = 0.715f - 0.715f * amount;
59 matrix[2] = 1.f - (matrix[0] + matrix[1]);
60 matrix[3] = matrix[4] = 0.f;
61 matrix[5] = 0.213f - 0.213f * amount;
62 matrix[6] = 0.715f + 0.285f * amount;
63 matrix[7] = 1.f - (matrix[5] + matrix[6]);
64 matrix[8] = matrix[9] = 0.f;
65 matrix[10] = 0.213f - 0.213f * amount;
66 matrix[11] = 0.715f - 0.715f * amount;
67 matrix[12] = 1.f - (matrix[10] + matrix[11]);
68 matrix[13] = matrix[14] = 0.f;
69 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
70 matrix[18] = 1.f;
73 void GetHueRotateMatrix(float hue, SkScalar matrix[20]) {
74 const float kPi = 3.1415926535897932384626433832795f;
76 float cos_hue = cosf(hue * kPi / 180.f);
77 float sin_hue = sinf(hue * kPi / 180.f);
78 matrix[0] = 0.213f + cos_hue * 0.787f - sin_hue * 0.213f;
79 matrix[1] = 0.715f - cos_hue * 0.715f - sin_hue * 0.715f;
80 matrix[2] = 0.072f - cos_hue * 0.072f + sin_hue * 0.928f;
81 matrix[3] = matrix[4] = 0.f;
82 matrix[5] = 0.213f - cos_hue * 0.213f + sin_hue * 0.143f;
83 matrix[6] = 0.715f + cos_hue * 0.285f + sin_hue * 0.140f;
84 matrix[7] = 0.072f - cos_hue * 0.072f - sin_hue * 0.283f;
85 matrix[8] = matrix[9] = 0.f;
86 matrix[10] = 0.213f - cos_hue * 0.213f - sin_hue * 0.787f;
87 matrix[11] = 0.715f - cos_hue * 0.715f + sin_hue * 0.715f;
88 matrix[12] = 0.072f + cos_hue * 0.928f + sin_hue * 0.072f;
89 matrix[13] = matrix[14] = 0.f;
90 matrix[15] = matrix[16] = matrix[17] = 0.f;
91 matrix[18] = 1.f;
92 matrix[19] = 0.f;
95 void GetInvertMatrix(float amount, SkScalar matrix[20]) {
96 memset(matrix, 0, 20 * sizeof(SkScalar));
97 matrix[0] = matrix[6] = matrix[12] = 1.f - 2.f * amount;
98 matrix[4] = matrix[9] = matrix[14] = amount * 255.f;
99 matrix[18] = 1.f;
102 void GetOpacityMatrix(float amount, SkScalar matrix[20]) {
103 memset(matrix, 0, 20 * sizeof(SkScalar));
104 matrix[0] = matrix[6] = matrix[12] = 1.f;
105 matrix[18] = amount;
108 void GetGrayscaleMatrix(float amount, SkScalar matrix[20]) {
109 // Note, these values are computed to ensure MatrixNeedsClamping is false
110 // for amount in [0..1]
111 matrix[0] = 0.2126f + 0.7874f * amount;
112 matrix[1] = 0.7152f - 0.7152f * amount;
113 matrix[2] = 1.f - (matrix[0] + matrix[1]);
114 matrix[3] = matrix[4] = 0.f;
116 matrix[5] = 0.2126f - 0.2126f * amount;
117 matrix[6] = 0.7152f + 0.2848f * amount;
118 matrix[7] = 1.f - (matrix[5] + matrix[6]);
119 matrix[8] = matrix[9] = 0.f;
121 matrix[10] = 0.2126f - 0.2126f * amount;
122 matrix[11] = 0.7152f - 0.7152f * amount;
123 matrix[12] = 1.f - (matrix[10] + matrix[11]);
124 matrix[13] = matrix[14] = 0.f;
126 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
127 matrix[18] = 1.f;
130 void GetSepiaMatrix(float amount, SkScalar matrix[20]) {
131 matrix[0] = 0.393f + 0.607f * amount;
132 matrix[1] = 0.769f - 0.769f * amount;
133 matrix[2] = 0.189f - 0.189f * amount;
134 matrix[3] = matrix[4] = 0.f;
136 matrix[5] = 0.349f - 0.349f * amount;
137 matrix[6] = 0.686f + 0.314f * amount;
138 matrix[7] = 0.168f - 0.168f * amount;
139 matrix[8] = matrix[9] = 0.f;
141 matrix[10] = 0.272f - 0.272f * amount;
142 matrix[11] = 0.534f - 0.534f * amount;
143 matrix[12] = 0.131f + 0.869f * amount;
144 matrix[13] = matrix[14] = 0.f;
146 matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
147 matrix[18] = 1.f;
150 skia::RefPtr<SkImageFilter> CreateMatrixImageFilter(
151 const SkScalar matrix[20],
152 const skia::RefPtr<SkImageFilter>& input) {
153 skia::RefPtr<SkColorFilter> color_filter =
154 skia::AdoptRef(new SkColorMatrixFilter(matrix));
155 return skia::AdoptRef(
156 SkColorFilterImageFilter::Create(color_filter.get(), input.get()));
159 } // namespace
161 skia::RefPtr<SkImageFilter> RenderSurfaceFilters::BuildImageFilter(
162 const FilterOperations& filters,
163 const gfx::SizeF& size) {
164 skia::RefPtr<SkImageFilter> image_filter;
165 SkScalar matrix[20];
166 for (size_t i = 0; i < filters.size(); ++i) {
167 const FilterOperation& op = filters.at(i);
168 switch (op.type()) {
169 case FilterOperation::GRAYSCALE:
170 GetGrayscaleMatrix(1.f - op.amount(), matrix);
171 image_filter = CreateMatrixImageFilter(matrix, image_filter);
172 break;
173 case FilterOperation::SEPIA:
174 GetSepiaMatrix(1.f - op.amount(), matrix);
175 image_filter = CreateMatrixImageFilter(matrix, image_filter);
176 break;
177 case FilterOperation::SATURATE:
178 GetSaturateMatrix(op.amount(), matrix);
179 image_filter = CreateMatrixImageFilter(matrix, image_filter);
180 break;
181 case FilterOperation::HUE_ROTATE:
182 GetHueRotateMatrix(op.amount(), matrix);
183 image_filter = CreateMatrixImageFilter(matrix, image_filter);
184 break;
185 case FilterOperation::INVERT:
186 GetInvertMatrix(op.amount(), matrix);
187 image_filter = CreateMatrixImageFilter(matrix, image_filter);
188 break;
189 case FilterOperation::OPACITY:
190 GetOpacityMatrix(op.amount(), matrix);
191 image_filter = CreateMatrixImageFilter(matrix, image_filter);
192 break;
193 case FilterOperation::BRIGHTNESS:
194 GetBrightnessMatrix(op.amount(), matrix);
195 image_filter = CreateMatrixImageFilter(matrix, image_filter);
196 break;
197 case FilterOperation::CONTRAST:
198 GetContrastMatrix(op.amount(), matrix);
199 image_filter = CreateMatrixImageFilter(matrix, image_filter);
200 break;
201 case FilterOperation::BLUR:
202 image_filter = skia::AdoptRef(new SkBlurImageFilter(
203 op.amount(), op.amount(), image_filter.get()));
204 break;
205 case FilterOperation::DROP_SHADOW:
206 image_filter = skia::AdoptRef(new SkDropShadowImageFilter(
207 SkIntToScalar(op.drop_shadow_offset().x()),
208 SkIntToScalar(op.drop_shadow_offset().y()),
209 SkIntToScalar(op.amount()),
210 op.drop_shadow_color(),
211 image_filter.get()));
212 break;
213 case FilterOperation::COLOR_MATRIX:
214 image_filter = CreateMatrixImageFilter(op.matrix(), image_filter);
215 break;
216 case FilterOperation::ZOOM: {
217 skia::RefPtr<SkImageFilter> zoom_filter = skia::AdoptRef(
218 new SkMagnifierImageFilter(
219 SkRect::MakeXYWH(
220 (size.width() - (size.width() / op.amount())) / 2.f,
221 (size.height() - (size.height() / op.amount())) / 2.f,
222 size.width() / op.amount(),
223 size.height() / op.amount()),
224 op.zoom_inset()));
225 if (image_filter.get()) {
226 // TODO(ajuma): When there's a 1-input version of
227 // SkMagnifierImageFilter, use that to handle the input filter
228 // instead of using an SkComposeImageFilter.
229 image_filter = skia::AdoptRef(new SkComposeImageFilter(
230 zoom_filter.get(), image_filter.get()));
231 } else {
232 image_filter = zoom_filter;
234 break;
236 case FilterOperation::SATURATING_BRIGHTNESS:
237 GetSaturatingBrightnessMatrix(op.amount(), matrix);
238 image_filter = CreateMatrixImageFilter(matrix, image_filter);
239 break;
240 case FilterOperation::REFERENCE: {
241 if (!op.image_filter())
242 break;
244 skia::RefPtr<SkColorFilter> cf;
247 SkColorFilter* colorfilter_rawptr = NULL;
248 op.image_filter()->asColorFilter(&colorfilter_rawptr);
249 cf = skia::AdoptRef(colorfilter_rawptr);
252 if (cf && cf->asColorMatrix(matrix) &&
253 !op.image_filter()->getInput(0)) {
254 image_filter = CreateMatrixImageFilter(matrix, image_filter);
255 } else if (image_filter) {
256 image_filter = skia::AdoptRef(new SkComposeImageFilter(
257 op.image_filter().get(), image_filter.get()));
258 } else {
259 image_filter = op.image_filter();
261 break;
265 return image_filter;
268 } // namespace cc