12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/output/render_surface_filters.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <algorithm>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "cc/output/filter_operation.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "cc/output/filter_operations.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "skia/ext/refptr.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkCanvas.h"
1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "third_party/skia/include/core/SkFlattenableBuffers.h"
1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "third_party/skia/include/core/SkImageFilter.h"
160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "third_party/skia/include/effects/SkAlphaThresholdFilter.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/effects/SkBlurImageFilter.h"
1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "third_party/skia/include/effects/SkColorFilterImageFilter.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/effects/SkColorMatrixFilter.h"
2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "third_party/skia/include/effects/SkComposeImageFilter.h"
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "third_party/skia/include/effects/SkDropShadowImageFilter.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/effects/SkMagnifierImageFilter.h"
230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "third_party/skia/include/effects/SkRectShaderImageFilter.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/gpu/SkGpuDevice.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/gpu/SkGrPixelRef.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size_f.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetBrightnessMatrix(float amount, SkScalar matrix[20]) {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Spec implementation
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (http://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#brightnessEquivalent)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // <feFunc[R|G|B] type="linear" slope="[amount]">
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(matrix, 0, 20 * sizeof(SkScalar));
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[0] = matrix[6] = matrix[12] = amount;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[18] = 1.f;
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetSaturatingBrightnessMatrix(float amount, SkScalar matrix[20]) {
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Legacy implementation used by internal clients.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // <feFunc[R|G|B] type="linear" intercept="[amount]"/>
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(matrix, 0, 20 * sizeof(SkScalar));
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[0] = matrix[6] = matrix[12] = matrix[18] = 1.f;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[4] = matrix[9] = matrix[14] = amount * 255.f;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetContrastMatrix(float amount, SkScalar matrix[20]) {
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(matrix, 0, 20 * sizeof(SkScalar));
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[0] = matrix[6] = matrix[12] = amount;
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[4] = matrix[9] = matrix[14] = (-0.5f * amount + 0.5f) * 255.f;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[18] = 1.f;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetSaturateMatrix(float amount, SkScalar matrix[20]) {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note, these values are computed to ensure MatrixNeedsClamping is false
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // for amount in [0..1]
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[0] = 0.213f + 0.787f * amount;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[1] = 0.715f - 0.715f * amount;
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[2] = 1.f - (matrix[0] + matrix[1]);
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[3] = matrix[4] = 0.f;
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[5] = 0.213f - 0.213f * amount;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[6] = 0.715f + 0.285f * amount;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[7] = 1.f - (matrix[5] + matrix[6]);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[8] = matrix[9] = 0.f;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[10] = 0.213f - 0.213f * amount;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[11] = 0.715f - 0.715f * amount;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[12] = 1.f - (matrix[10] + matrix[11]);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[13] = matrix[14] = 0.f;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[18] = 1.f;
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetHueRotateMatrix(float hue, SkScalar matrix[20]) {
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const float kPi = 3.1415926535897932384626433832795f;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float cos_hue = cosf(hue * kPi / 180.f);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  float sin_hue = sinf(hue * kPi / 180.f);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[0] = 0.213f + cos_hue * 0.787f - sin_hue * 0.213f;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[1] = 0.715f - cos_hue * 0.715f - sin_hue * 0.715f;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[2] = 0.072f - cos_hue * 0.072f + sin_hue * 0.928f;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[3] = matrix[4] = 0.f;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[5] = 0.213f - cos_hue * 0.213f + sin_hue * 0.143f;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[6] = 0.715f + cos_hue * 0.285f + sin_hue * 0.140f;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[7] = 0.072f - cos_hue * 0.072f - sin_hue * 0.283f;
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[8] = matrix[9] = 0.f;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[10] = 0.213f - cos_hue * 0.213f - sin_hue * 0.787f;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[11] = 0.715f - cos_hue * 0.715f + sin_hue * 0.715f;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[12] = 0.072f + cos_hue * 0.928f + sin_hue * 0.072f;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[13] = matrix[14] = 0.f;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[15] = matrix[16] = matrix[17] = 0.f;
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[18] = 1.f;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[19] = 0.f;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetInvertMatrix(float amount, SkScalar matrix[20]) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(matrix, 0, 20 * sizeof(SkScalar));
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[0] = matrix[6] = matrix[12] = 1.f - 2.f * amount;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[4] = matrix[9] = matrix[14] = amount * 255.f;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[18] = 1.f;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetOpacityMatrix(float amount, SkScalar matrix[20]) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  memset(matrix, 0, 20 * sizeof(SkScalar));
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[0] = matrix[6] = matrix[12] = 1.f;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[18] = amount;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetGrayscaleMatrix(float amount, SkScalar matrix[20]) {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note, these values are computed to ensure MatrixNeedsClamping is false
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // for amount in [0..1]
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[0] = 0.2126f + 0.7874f * amount;
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[1] = 0.7152f - 0.7152f * amount;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[2] = 1.f - (matrix[0] + matrix[1]);
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[3] = matrix[4] = 0.f;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[5] = 0.2126f - 0.2126f * amount;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[6] = 0.7152f + 0.2848f * amount;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[7] = 1.f - (matrix[5] + matrix[6]);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[8] = matrix[9] = 0.f;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[10] = 0.2126f - 0.2126f * amount;
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[11] = 0.7152f - 0.7152f * amount;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[12] = 1.f - (matrix[10] + matrix[11]);
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[13] = matrix[14] = 0.f;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[18] = 1.f;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void GetSepiaMatrix(float amount, SkScalar matrix[20]) {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[0] = 0.393f + 0.607f * amount;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[1] = 0.769f - 0.769f * amount;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[2] = 0.189f - 0.189f * amount;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[3] = matrix[4] = 0.f;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[5] = 0.349f - 0.349f * amount;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[6] = 0.686f + 0.314f * amount;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[7] = 0.168f - 0.168f * amount;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[8] = matrix[9] = 0.f;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[10] = 0.272f - 0.272f * amount;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[11] = 0.534f - 0.534f * amount;
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[12] = 0.131f + 0.869f * amount;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[13] = matrix[14] = 0.f;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[15] = matrix[16] = matrix[17] = matrix[19] = 0.f;
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  matrix[18] = 1.f;
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)skia::RefPtr<SkImageFilter> CreateMatrixImageFilter(
15368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const SkScalar matrix[20],
15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const skia::RefPtr<SkImageFilter>& input) {
15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  skia::RefPtr<SkColorFilter> color_filter =
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      skia::AdoptRef(SkColorMatrixFilter::Create(matrix));
15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return skia::AdoptRef(
15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      SkColorFilterImageFilter::Create(color_filter.get(), input.get()));
15968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
16068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)skia::RefPtr<SkImageFilter> RenderSurfaceFilters::BuildImageFilter(
16468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const FilterOperations& filters,
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const gfx::SizeF& size) {
16668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  skia::RefPtr<SkImageFilter> image_filter;
16768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  SkScalar matrix[20];
16868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < filters.size(); ++i) {
16968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const FilterOperation& op = filters.at(i);
17068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    switch (op.type()) {
17168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::GRAYSCALE:
17268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        GetGrayscaleMatrix(1.f - op.amount(), matrix);
17368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        image_filter = CreateMatrixImageFilter(matrix, image_filter);
17468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
17568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::SEPIA:
17668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        GetSepiaMatrix(1.f - op.amount(), matrix);
17768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        image_filter = CreateMatrixImageFilter(matrix, image_filter);
17868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
17968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::SATURATE:
18068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        GetSaturateMatrix(op.amount(), matrix);
18168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        image_filter = CreateMatrixImageFilter(matrix, image_filter);
18268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::HUE_ROTATE:
18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        GetHueRotateMatrix(op.amount(), matrix);
18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        image_filter = CreateMatrixImageFilter(matrix, image_filter);
18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::INVERT:
18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        GetInvertMatrix(op.amount(), matrix);
18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        image_filter = CreateMatrixImageFilter(matrix, image_filter);
19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::OPACITY:
19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        GetOpacityMatrix(op.amount(), matrix);
19368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        image_filter = CreateMatrixImageFilter(matrix, image_filter);
19468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::BRIGHTNESS:
19668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        GetBrightnessMatrix(op.amount(), matrix);
19768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        image_filter = CreateMatrixImageFilter(matrix, image_filter);
19868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
19968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::CONTRAST:
20068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        GetContrastMatrix(op.amount(), matrix);
20168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        image_filter = CreateMatrixImageFilter(matrix, image_filter);
20268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
20368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::BLUR:
204a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        image_filter = skia::AdoptRef(SkBlurImageFilter::Create(
20568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            op.amount(), op.amount(), image_filter.get()));
20668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
20768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::DROP_SHADOW:
208a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        image_filter = skia::AdoptRef(SkDropShadowImageFilter::Create(
20968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            SkIntToScalar(op.drop_shadow_offset().x()),
21068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            SkIntToScalar(op.drop_shadow_offset().y()),
21168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            SkIntToScalar(op.amount()),
21268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            op.drop_shadow_color(),
21368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            image_filter.get()));
21468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
21568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::COLOR_MATRIX:
21668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        image_filter = CreateMatrixImageFilter(op.matrix(), image_filter);
21768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
21868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::ZOOM: {
219a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        skia::RefPtr<SkImageFilter> zoom_filter =
220a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            skia::AdoptRef(SkMagnifierImageFilter::Create(
22168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                SkRect::MakeXYWH(
22268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                    (size.width() - (size.width() / op.amount())) / 2.f,
22368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                    (size.height() - (size.height() / op.amount())) / 2.f,
22468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                    size.width() / op.amount(),
22568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                    size.height() / op.amount()),
22668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                op.zoom_inset()));
22768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if (image_filter.get()) {
22868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          // TODO(ajuma): When there's a 1-input version of
22968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          // SkMagnifierImageFilter, use that to handle the input filter
23068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          // instead of using an SkComposeImageFilter.
231a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          image_filter = skia::AdoptRef(SkComposeImageFilter::Create(
23268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)              zoom_filter.get(), image_filter.get()));
23368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        } else {
23468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          image_filter = zoom_filter;
23568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
23668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
23768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
23868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::SATURATING_BRIGHTNESS:
23968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        GetSaturatingBrightnessMatrix(op.amount(), matrix);
24068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        image_filter = CreateMatrixImageFilter(matrix, image_filter);
24168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
24268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      case FilterOperation::REFERENCE: {
24368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if (!op.image_filter())
24468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          break;
24568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        skia::RefPtr<SkColorFilter> cf;
24768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
24868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        {
24968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          SkColorFilter* colorfilter_rawptr = NULL;
25068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          op.image_filter()->asColorFilter(&colorfilter_rawptr);
25168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          cf = skia::AdoptRef(colorfilter_rawptr);
25268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
25368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
25468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        if (cf && cf->asColorMatrix(matrix) &&
25568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            !op.image_filter()->getInput(0)) {
25668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          image_filter = CreateMatrixImageFilter(matrix, image_filter);
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        } else if (image_filter) {
258a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          image_filter = skia::AdoptRef(SkComposeImageFilter::Create(
25968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)              op.image_filter().get(), image_filter.get()));
26068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        } else {
26168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          image_filter = op.image_filter();
26268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        }
26368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        break;
26468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      }
2650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      case FilterOperation::ALPHA_THRESHOLD: {
2660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        skia::RefPtr<SkImageFilter> alpha_filter = skia::AdoptRef(
2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch            SkAlphaThresholdFilter::Create(
2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                op.region(), op.amount(), op.outer_threshold()));
2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        if (image_filter.get()) {
270010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          image_filter = skia::AdoptRef(SkComposeImageFilter::Create(
2710529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch              alpha_filter.get(), image_filter.get()));
2720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        } else {
2730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          image_filter = alpha_filter;
2740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        }
2750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        break;
2760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
27768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
27868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
27968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return image_filter;
28068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
28168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
283