SkImageFilter.cpp revision 1a479e7547d4efe2d1d06fab5c9442b77ec6c954
1bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org/*
2bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org * Copyright 2012 The Android Open Source Project
3bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org *
4bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be
5bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org * found in the LICENSE file.
6bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org */
7bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
8bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org#include "SkImageFilter.h"
99f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
109f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org#include "SkBitmap.h"
11118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org#include "SkDevice.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
14bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org#include "SkRect.h"
15f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org#include "SkTDynamicHash.h"
16c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidationUtils.h"
17d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#if SK_SUPPORT_GPU
18d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#include "GrContext.h"
196aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#include "SkGrPixelRef.h"
206aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#include "SkGr.h"
21d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
22bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
231a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.orgSkImageFilter::Cache* gExternalCache;
241a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org
25b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.orgSkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect)
26194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org  : fInputCount(inputCount),
27194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    fInputs(new SkImageFilter*[inputCount]),
28b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
298d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < inputCount; ++i) {
309f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        fInputs[i] = inputs[i];
319f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkSafeRef(fInputs[i]);
329f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
339f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
349f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
35b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.orgSkImageFilter::SkImageFilter(SkImageFilter* input, const CropRect* cropRect)
36194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org  : fInputCount(1),
37194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org    fInputs(new SkImageFilter*[1]),
38b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
39c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    fInputs[0] = input;
40c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    SkSafeRef(fInputs[0]);
41c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org}
42c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org
43b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.orgSkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect)
44194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org  : fInputCount(2), fInputs(new SkImageFilter*[2]),
45b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
46c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    fInputs[0] = input1;
47c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    fInputs[1] = input2;
48c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    SkSafeRef(fInputs[0]);
49c2e8cef4792b478547973d312b26fff4aab7c729senorblanco@chromium.org    SkSafeRef(fInputs[1]);
509f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
519f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
529f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.orgSkImageFilter::~SkImageFilter() {
538d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < fInputCount; i++) {
549f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkSafeUnref(fInputs[i]);
559f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
569f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    delete[] fInputs;
579f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
589f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
598b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgSkImageFilter::SkImageFilter(int inputCount, SkReadBuffer& buffer) {
60ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    fInputCount = buffer.readInt();
61c84728d72a47415929464c5cf062300d86a91246commit-bot@chromium.org    if (buffer.validate((fInputCount >= 0) && ((inputCount < 0) || (fInputCount == inputCount)))) {
62ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        fInputs = new SkImageFilter*[fInputCount];
63ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        for (int i = 0; i < fInputCount; i++) {
64ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            if (buffer.readBool()) {
65ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                fInputs[i] = buffer.readImageFilter();
66ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            } else {
67ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org                fInputs[i] = NULL;
68ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            }
69c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org            if (!buffer.isValid()) {
70c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org                fInputCount = i; // Do not use fInputs past that point in the destructor
71c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org                break;
72c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org            }
73ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        }
74ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        SkRect rect;
75ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        buffer.readRect(&rect);
76c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org        if (buffer.isValid() && buffer.validate(SkIsValidRect(rect))) {
77ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            uint32_t flags = buffer.readUInt();
78ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org            fCropRect = CropRect(rect, flags);
799f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        }
80ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org    } else {
81ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        fInputCount = 0;
82ce33d60187718e7bb01944ee130c9f5d9fb335eccommit-bot@chromium.org        fInputs = NULL;
839f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
849f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
859f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
868b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkImageFilter::flatten(SkWriteBuffer& buffer) const {
878d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    buffer.writeInt(fInputCount);
888d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org    for (int i = 0; i < fInputCount; i++) {
899f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        SkImageFilter* input = getInput(i);
909f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        buffer.writeBool(input != NULL);
919f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        if (input != NULL) {
929f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org            buffer.writeFlattenable(input);
939f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org        }
949f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org    }
953f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    buffer.writeRect(fCropRect.rect());
963f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    buffer.writeUInt(fCropRect.flags());
979f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org}
989f25de79009ce721aa13abe71c38179d5a6710e2senorblanco@chromium.org
99bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
1004cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                const Context& context,
101ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                SkBitmap* result, SkIPoint* offset) const {
102f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    Cache* cache = context.cache();
103bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(result);
1046776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org    SkASSERT(offset);
105f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    SkASSERT(cache);
106f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    if (cache->get(this, result, offset)) {
107f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        return true;
108f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
109bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    /*
110bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     *  Give the proxy first shot at the filter. If it returns false, ask
111bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     *  the filter to do it.
112bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org     */
113f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    if ((proxy && proxy->filterImage(this, src, context, result, offset)) ||
114f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        this->onFilterImage(proxy, src, context, result, offset)) {
115f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        cache->set(this, *result, *offset);
116f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        return true;
117f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
118f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    return false;
119bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
120bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
121bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
122c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                                 SkIRect* dst) const {
123bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(&src);
124bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    SkASSERT(dst);
125bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return this->onFilterBounds(src, ctm, dst);
126bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
127bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
128336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.orgvoid SkImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
129336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (0 == fInputCount) {
130336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        *dst = src;
131336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        return;
132336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
133336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    if (this->getInput(0)) {
134336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        this->getInput(0)->computeFastBounds(src, dst);
135336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    } else {
136336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        *dst = src;
137336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
138336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    for (int i = 1; i < fInputCount; i++) {
139336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        SkImageFilter* input = this->getInput(i);
140336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        if (input) {
141336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            SkRect bounds;
142336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            input->computeFastBounds(src, &bounds);
143336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            dst->join(bounds);
144336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        } else {
145336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org            dst->join(src);
146336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org        }
147336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org    }
148336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org}
149336d1d759590d9bedcbc5a96d0fff79861cf8f7asenorblanco@chromium.org
1504cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const Context&,
151ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                  SkBitmap*, SkIPoint*) const {
152bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return false;
153bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
154bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
155bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::canFilterImageGPU() const {
1567938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    return this->asNewEffect(NULL, NULL, SkMatrix::I(), SkIRect());
157bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
158bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
1594cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
160ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org                                   SkBitmap* result, SkIPoint* offset) const {
161d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#if SK_SUPPORT_GPU
1626aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    SkBitmap input = src;
163d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkASSERT(fInputCount == 1);
164aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    SkIPoint srcOffset = SkIPoint::Make(0, 0);
1656aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    if (this->getInput(0) &&
1664cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        !this->getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) {
167d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org        return false;
168d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    }
169b8d00db075b5ea09e353508a26ef5ced50722a6ccommit-bot@chromium.org    GrTexture* srcTexture = input.getTexture();
1704e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkIRect bounds;
171118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
1724e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org        return false;
1734e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    }
1744e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkRect srcRect = SkRect::Make(bounds);
1754e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    SkRect dstRect = SkRect::MakeWH(srcRect.width(), srcRect.height());
176d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrContext* context = srcTexture->getContext();
177d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org
178d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrTextureDesc desc;
179d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    desc.fFlags = kRenderTarget_GrTextureFlagBit,
1804e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    desc.fWidth = bounds.width();
1814e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    desc.fHeight = bounds.height();
182d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    desc.fConfig = kRGBA_8888_GrPixelConfig;
183d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org
184d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrAutoScratchTexture dst(context, desc);
185d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrContext::AutoMatrix am;
186d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    am.setIdentity(context);
187d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrContext::AutoRenderTarget art(context, dst.texture()->asRenderTarget());
1884e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    GrContext::AutoClip acs(context, dstRect);
189d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrEffectRef* effect;
190aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    offset->fX = bounds.left();
191aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    offset->fY = bounds.top();
192aba651c3f1a1657bbe5367c873500e7c60539a3esenorblanco@chromium.org    bounds.offset(-srcOffset);
1934cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    SkMatrix matrix(ctx.ctm());
194fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
1957938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.org    this->asNewEffect(&effect, srcTexture, matrix, bounds);
196d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkASSERT(effect);
197d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkAutoUnref effectRef(effect);
198d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    GrPaint paint;
19942dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org    paint.addColorEffect(effect);
2004e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org    context->drawRectToRect(paint, dstRect, srcRect);
2014e16bb2a322f2bd16cb1afd2f78c27e420a4b9dbsenorblanco@chromium.org
202d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    SkAutoTUnref<GrTexture> resultTex(dst.detach());
2036aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    WrapTexture(resultTex, bounds.width(), bounds.height(), result);
204d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org    return true;
205d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#else
206c2594f41066102d7a8a73effd3c574142a018b9asenorblanco@chromium.org    return false;
207d043ccee3788ea4192806bd8c94484ed003fa828senorblanco@chromium.org#endif
208bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
209bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
210118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.orgbool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src,
211118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                                  const SkIPoint& srcOffset, SkIRect* bounds) const {
212118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect srcBounds;
213118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    src.getBounds(&srcBounds);
214118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    srcBounds.offset(srcOffset);
215fbaea5336690ffc4fd9ee695608e9457da10eeabsenorblanco@chromium.org    SkRect cropRect;
216118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    ctx.ctm().mapRect(&cropRect, fCropRect.rect());
217b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    SkIRect cropRectI;
218b295fb6ff3222453912dfcb7a1ea5184d40014b5senorblanco@chromium.org    cropRect.roundOut(&cropRectI);
2193f1f2a3a59c43e5bce67ab98e55df45bc7c933a3senorblanco@chromium.org    uint32_t flags = fCropRect.flags();
220118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasLeft_CropEdge) srcBounds.fLeft = cropRectI.fLeft;
221118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasTop_CropEdge) srcBounds.fTop = cropRectI.fTop;
222118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasRight_CropEdge) srcBounds.fRight = cropRectI.fRight;
223118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasBottom_CropEdge) srcBounds.fBottom = cropRectI.fBottom;
224118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!srcBounds.intersect(ctx.clipBounds())) {
225118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return false;
226118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
227118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    *bounds = srcBounds;
228118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    return true;
229118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org}
230118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org
231118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.orgbool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitmap& src,
232118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org                                  SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* dst) const {
233118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect srcBounds;
234118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    src.getBounds(&srcBounds);
235118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    srcBounds.offset(*srcOffset);
236118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkRect cropRect;
237118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    ctx.ctm().mapRect(&cropRect, fCropRect.rect());
238118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    SkIRect cropRectI;
239118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    cropRect.roundOut(&cropRectI);
240118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    uint32_t flags = fCropRect.flags();
241118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    *bounds = srcBounds;
242118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasLeft_CropEdge) bounds->fLeft = cropRectI.fLeft;
243118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasTop_CropEdge) bounds->fTop = cropRectI.fTop;
244118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasRight_CropEdge) bounds->fRight = cropRectI.fRight;
245118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (flags & CropRect::kHasBottom_CropEdge) bounds->fBottom = cropRectI.fBottom;
246118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (!bounds->intersect(ctx.clipBounds())) {
247118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return false;
248118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
249118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    if (srcBounds.contains(*bounds)) {
250118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *dst = src;
251118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return true;
252118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    } else {
253118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), bounds->height()));
254118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        if (!device) {
255118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org            return false;
256118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        }
257118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        SkCanvas canvas(device);
258118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        canvas.clear(0x00000000);
259118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        canvas.drawBitmap(src, srcOffset->x() - bounds->x(), srcOffset->y() - bounds->y());
260118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *srcOffset = SkIPoint::Make(bounds->x(), bounds->y());
261118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        *dst = device->accessBitmap(false);
262118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org        return true;
263118252962f89a80db661a0544f1bd61cbaab6321senorblanco@chromium.org    }
264194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org}
265194d775edcf5fa6e82098a97ad53018d70db1155senorblanco@chromium.org
266bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.orgbool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
267c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org                                   SkIRect* dst) const {
268c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    if (fInputCount < 1) {
269c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        return false;
270c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
271c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
272c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    SkIRect bounds;
273c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    for (int i = 0; i < fInputCount; ++i) {
274c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        SkImageFilter* filter = this->getInput(i);
275c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        SkIRect rect = src;
276c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        if (filter && !filter->filterBounds(src, ctm, &rect)) {
277c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            return false;
278c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        }
279c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        if (0 == i) {
280c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            bounds = rect;
281c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        } else {
282c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org            bounds.join(rect);
283c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org        }
284c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    }
285c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org
286c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // don't modify dst until now, so we don't accidentally change it in the
287c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    // loop, but then return false on the next filter.
288c4b12f19a46946e1c02f3525e0ea4902b09feac5senorblanco@chromium.org    *dst = bounds;
289bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return true;
290bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
291bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org
2927938bae14af94c1d48d122a2d686e123b66411a7senorblanco@chromium.orgbool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*, const SkMatrix&, const SkIRect&) const {
293bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org    return false;
294bf2768bab9f3b21c03a8f9a75dc891231d5857ccsenorblanco@chromium.org}
2958d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org
296a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.combool SkImageFilter::asColorFilter(SkColorFilter**) const {
297a1c511b8704c6c266b90860a4c68f30ca7514f9bsugoi@google.com    return false;
2988d21f6c7a9d0cf4f87d77c235c6da7203620c7e5senorblanco@chromium.org}
2996aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3001a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.orgvoid SkImageFilter::SetExternalCache(Cache* cache) {
3011a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    SkRefCnt_SafeAssign(gExternalCache, cache);
3021a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org}
3031a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org
3041a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.orgSkImageFilter::Cache* SkImageFilter::GetExternalCache() {
3051a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    return gExternalCache;
3061a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org}
3071a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org
3086aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#if SK_SUPPORT_GPU
3096aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3106aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.orgvoid SkImageFilter::WrapTexture(GrTexture* texture, int width, int height, SkBitmap* result) {
3116aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
3126aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    result->setConfig(info);
3136aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    result->setPixelRef(SkNEW_ARGS(SkGrPixelRef, (info, texture)))->unref();
3146aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org}
3156aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org
3166aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.orgbool SkImageFilter::getInputResultGPU(SkImageFilter::Proxy* proxy,
3174cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org                                      const SkBitmap& src, const Context& ctx,
3186aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                                      SkBitmap* result, SkIPoint* offset) const {
3196aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // Ensure that GrContext calls under filterImage and filterImageGPU below will see an identity
3206aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // matrix with no clip and that the matrix, clip, and render target set before this function was
3216aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    // called are restored before we return to the caller.
3226aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    GrContext* context = src.getTexture()->getContext();
3236aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    GrContext::AutoWideOpenIdentityDraw awoid(context, NULL);
3246aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    if (this->canFilterImageGPU()) {
3254cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        return this->filterImageGPU(proxy, src, ctx, result, offset);
3266aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    } else {
3274cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org        if (this->filterImage(proxy, src, ctx, result, offset)) {
3286aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            if (!result->getTexture()) {
3296aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                SkImageInfo info;
3306aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                if (!result->asImageInfo(&info)) {
3316aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                    return false;
3326aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                }
3336aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                GrTexture* resultTex = GrLockAndRefCachedBitmapTexture(context, *result, NULL);
3346aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                result->setPixelRef(new SkGrPixelRef(info, resultTex))->unref();
3356aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org                GrUnlockAndUnrefCachedBitmapTexture(resultTex);
3366aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            }
3376aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            return true;
3386aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org        } else {
3396aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org            return false;
3406aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org        }
3416aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org    }
3426aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org}
3436aa6fec0e332c9246958245bad5fc881fefee68fsenorblanco@chromium.org#endif
344f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
345f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgstatic uint32_t compute_hash(const uint32_t* data, int count) {
346f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    uint32_t hash = 0;
347f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
348f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    for (int i = 0; i < count; ++i) {
349f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        uint32_t k = data[i];
350f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        k *= 0xcc9e2d51;
351f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        k = (k << 15) | (k >> 17);
352f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        k *= 0x1b873593;
353f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
354f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        hash ^= k;
355f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        hash = (hash << 13) | (hash >> 19);
356f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        hash *= 5;
357f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        hash += 0xe6546b64;
358f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
359f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
360f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    //    hash ^= size;
361f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    hash ^= hash >> 16;
362f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    hash *= 0x85ebca6b;
363f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    hash ^= hash >> 13;
364f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    hash *= 0xc2b2ae35;
365f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    hash ^= hash >> 16;
366f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
367f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    return hash;
368f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org}
369f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
370f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgclass CacheImpl : public SkImageFilter::Cache {
371f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgpublic:
372f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    explicit CacheImpl(int minChildren) : fMinChildren(minChildren) {}
373f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    virtual ~CacheImpl();
374f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    bool get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
375f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    void set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& offset) SK_OVERRIDE;
3761a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    void remove(const SkImageFilter* key) SK_OVERRIDE;
377f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgprivate:
378f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    typedef const SkImageFilter* Key;
379f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    struct Value {
380f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        Value(Key key, const SkBitmap& bitmap, const SkIPoint& offset)
381f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            : fKey(key), fBitmap(bitmap), fOffset(offset) {}
382f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        Key fKey;
383f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        SkBitmap fBitmap;
384f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        SkIPoint fOffset;
385f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        static const Key& GetKey(const Value& v) {
386f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            return v.fKey;
387f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        }
388f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        static uint32_t Hash(Key key) {
389f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org            return compute_hash(reinterpret_cast<const uint32_t*>(&key), sizeof(Key) / sizeof(uint32_t));
390f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        }
391f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    };
392f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    SkTDynamicHash<Value, Key> fData;
393f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    int fMinChildren;
394f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org};
395f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
396f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgbool CacheImpl::get(const SkImageFilter* key, SkBitmap* result, SkIPoint* offset) {
397f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    Value* v = fData.find(key);
398f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    if (v) {
399f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        *result = v->fBitmap;
400f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        *offset = v->fOffset;
401f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        return true;
402f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
403f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    return false;
404f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org}
405f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
4061a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.orgvoid CacheImpl::remove(const SkImageFilter* key) {
4071a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    Value* v = fData.find(key);
4081a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    if (v) {
4091a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org        fData.remove(key);
4101a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org        delete v;
4111a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org    }
4121a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org}
4131a479e7547d4efe2d1d06fab5c9442b77ec6c954senorblanco@chromium.org
414f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgvoid CacheImpl::set(const SkImageFilter* key, const SkBitmap& result, const SkIPoint& offset) {
415f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    if (key->getRefCnt() >= fMinChildren) {
416f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        fData.add(new Value(key, result, offset));
417f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
418f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org}
419f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
420f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgSkImageFilter::Cache* SkImageFilter::Cache::Create(int minChildren) {
421f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    return new CacheImpl(minChildren);
422f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org}
423f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
424f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.orgCacheImpl::~CacheImpl() {
425f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    SkTDynamicHash<Value, Key>::Iter iter(&fData);
426f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org
427f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    while (!iter.done()) {
428f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        Value* v = &*iter;
429f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        ++iter;
430f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org        delete v;
431f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org    }
432f7efa502d62af80bd15b03e1131603fb6577c3dfcommit-bot@chromium.org}
433