1fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com/*
2fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com * Copyright 2012 Google Inc.
3fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com *
4fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com * Use of this source code is governed by a BSD-style license that can be
5fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com * found in the LICENSE file.
6fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com */
7fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
81f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkBitmapDevice.h"
9fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com#include "SkCanvas.h"
10fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com#include "SkData.h"
1181e8739a101ecb0a978850bd45842bc6e6bc05a6robertphillips@google.com#include "SkNoSaveLayerCanvas.h"
121f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkPictureUtils.h"
13fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com#include "SkPixelRef.h"
1450a5cfb1a57961f021b1463679e065dfb1ebf3f9junov@chromium.org#include "SkRRect.h"
151f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com#include "SkShader.h"
16fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
17fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comclass PixelRefSet {
18fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.compublic:
19fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    PixelRefSet(SkTDArray<SkPixelRef*>* array) : fArray(array) {}
20fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
21fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    // This does a linear search on existing pixelrefs, so if this list gets big
22fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    // we should use a more complex sorted/hashy thing.
23fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    //
24fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    void add(SkPixelRef* pr) {
25fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        uint32_t genID = pr->getGenerationID();
26fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        if (fGenID.find(genID) < 0) {
27fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com            *fArray->append() = pr;
28fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com            *fGenID.append() = genID;
29fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com//            SkDebugf("--- adding [%d] %x %d\n", fArray->count() - 1, pr, genID);
30fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        } else {
31fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com//            SkDebugf("--- already have %x %d\n", pr, genID);
32fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        }
33fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
34fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
35fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comprivate:
36fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    SkTDArray<SkPixelRef*>* fArray;
37fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    SkTDArray<uint32_t>     fGenID;
38fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com};
39fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
40fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comstatic void not_supported() {
41330313a8a8343876ee596da39da06a5d69badd9cmtklein@google.com    SkDEBUGFAIL("this method should never be called");
42fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com}
43fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
44fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comstatic void nothing_to_do() {}
45fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
46fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com/**
47fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com *  This device will route all bitmaps (primitives and in shaders) to its PRSet.
48fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com *  It should never actually draw anything, so there need not be any pixels
49ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com *  behind its device.
50fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com */
51ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.comclass GatherPixelRefDevice : public SkBaseDevice {
52ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.compublic:
5356bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com    SK_DECLARE_INST_COUNT(GatherPixelRefDevice)
5456bf6e4bce26710b017b61ddadb13e277aab8a45robertphillips@google.com
55ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    GatherPixelRefDevice(int width, int height, PixelRefSet* prset) {
56ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com        fSize.set(width, height);
57a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org        fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
58ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com        fPRSet = prset;
593f4bf51eddd9271b27e3c709939af1ff9ff1758dreed@google.com    }
604d164709739ae78809125cae9b8de0f3fff0d081reed@google.com
61f252f64f17efddf7235682a96d155d7c86c898e3reed    virtual SkImageInfo imageInfo() const SK_OVERRIDE {
62f252f64f17efddf7235682a96d155d7c86c898e3reed        return SkImageInfo::MakeUnknown(fSize.width(), fSize.height());
63f252f64f17efddf7235682a96d155d7c86c898e3reed    }
64ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
65ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
6681e8739a101ecb0a978850bd45842bc6e6bc05a6robertphillips@google.com        return false;
67ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    }
68ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    // TODO: allow this call to return failure, or move to SkBitmapDevice only.
69ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
70ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com        return fEmptyBitmap;
71ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    }
72ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    virtual void lockPixels() SK_OVERRIDE { nothing_to_do(); }
73ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    virtual void unlockPixels() SK_OVERRIDE { nothing_to_do(); }
74ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org    virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
75ae761f7545d8ebf181d220169afac2056b057b8ccommit-bot@chromium.org    virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
764cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org    virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
77ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com                             SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
78ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com        return false;
79fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
80fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
81fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void clear(SkColor color) SK_OVERRIDE {
82fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        nothing_to_do();
83fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
844cd9e2169e35cd67ee7358acea6541245e1d1744commit-bot@chromium.org
85fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void drawPaint(const SkDraw&, const SkPaint& paint) SK_OVERRIDE {
86fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        this->addBitmapFromPaint(paint);
87fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
88fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void drawPoints(const SkDraw&, SkCanvas::PointMode mode, size_t count,
89fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                            const SkPoint[], const SkPaint& paint) SK_OVERRIDE {
90fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        this->addBitmapFromPaint(paint);
91fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
9272aa79cfea66d0311fe73f7b96dcda99cd168377reed@google.com    virtual void drawRect(const SkDraw&, const SkRect&,
9372aa79cfea66d0311fe73f7b96dcda99cd168377reed@google.com                          const SkPaint& paint) SK_OVERRIDE {
9472aa79cfea66d0311fe73f7b96dcda99cd168377reed@google.com        this->addBitmapFromPaint(paint);
9572aa79cfea66d0311fe73f7b96dcda99cd168377reed@google.com    }
96cac8d01eabd05d11365f56b6af3f30bccb173487scroggo@google.com    virtual void drawRRect(const SkDraw&, const SkRRect&,
97cac8d01eabd05d11365f56b6af3f30bccb173487scroggo@google.com                           const SkPaint& paint) SK_OVERRIDE {
98cac8d01eabd05d11365f56b6af3f30bccb173487scroggo@google.com        this->addBitmapFromPaint(paint);
99cac8d01eabd05d11365f56b6af3f30bccb173487scroggo@google.com    }
10072aa79cfea66d0311fe73f7b96dcda99cd168377reed@google.com    virtual void drawOval(const SkDraw&, const SkRect&,
10172aa79cfea66d0311fe73f7b96dcda99cd168377reed@google.com                          const SkPaint& paint) SK_OVERRIDE {
10272aa79cfea66d0311fe73f7b96dcda99cd168377reed@google.com        this->addBitmapFromPaint(paint);
10372aa79cfea66d0311fe73f7b96dcda99cd168377reed@google.com    }
104fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void drawPath(const SkDraw&, const SkPath& path,
105fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                          const SkPaint& paint, const SkMatrix* prePathMatrix,
106fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                          bool pathIsMutable) SK_OVERRIDE {
107fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        this->addBitmapFromPaint(paint);
108fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
109fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
110ed9866cc8ad9d9687eb0571e45128f1c9422d3f4robertphillips@google.com                            const SkMatrix&, const SkPaint& paint) SK_OVERRIDE {
111fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        this->addBitmap(bitmap);
112c77392ed58ec78ab19fa0e3ff99fb8110854fba2reed        if (kAlpha_8_SkColorType == bitmap.colorType()) {
113ed9866cc8ad9d9687eb0571e45128f1c9422d3f4robertphillips@google.com            this->addBitmapFromPaint(paint);
114ed9866cc8ad9d9687eb0571e45128f1c9422d3f4robertphillips@google.com        }
115fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
116fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void drawBitmapRect(const SkDraw&, const SkBitmap& bitmap,
117fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                                const SkRect* srcOrNull, const SkRect& dst,
118ed9866cc8ad9d9687eb0571e45128f1c9422d3f4robertphillips@google.com                                const SkPaint& paint,
119eed779d866e1e239bfb9ebc6a225b7345a41adf9commit-bot@chromium.org                                SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
120fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        this->addBitmap(bitmap);
121c77392ed58ec78ab19fa0e3ff99fb8110854fba2reed        if (kAlpha_8_SkColorType == bitmap.colorType()) {
122ed9866cc8ad9d9687eb0571e45128f1c9422d3f4robertphillips@google.com            this->addBitmapFromPaint(paint);
123ed9866cc8ad9d9687eb0571e45128f1c9422d3f4robertphillips@google.com        }
124fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
125fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
126fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                            int x, int y, const SkPaint& paint) SK_OVERRIDE {
127fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        this->addBitmap(bitmap);
128fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
129fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void drawText(const SkDraw&, const void* text, size_t len,
130fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                          SkScalar x, SkScalar y,
131fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                          const SkPaint& paint) SK_OVERRIDE {
132fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        this->addBitmapFromPaint(paint);
133fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
134fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void drawPosText(const SkDraw&, const void* text, size_t len,
135fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                             const SkScalar pos[], SkScalar constY,
136fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                             int, const SkPaint& paint) SK_OVERRIDE {
137fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        this->addBitmapFromPaint(paint);
138fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
139fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
140fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                                const SkPath& path, const SkMatrix* matrix,
141fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                                const SkPaint& paint) SK_OVERRIDE {
142fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        this->addBitmapFromPaint(paint);
143fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
144fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
145fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                              const SkPoint verts[], const SkPoint texs[],
146fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                              const SkColor colors[], SkXfermode* xmode,
147fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                              const uint16_t indices[], int indexCount,
148fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                              const SkPaint& paint) SK_OVERRIDE {
149fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        this->addBitmapFromPaint(paint);
150fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
1511f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com    virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
152fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                            const SkPaint&) SK_OVERRIDE {
153fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        nothing_to_do();
154fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
155fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
156fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comprotected:
157ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
158ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com        not_supported();
159ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    }
16015a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org    virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
161ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com        // we expect to only get called via savelayer, in which case it is fine.
162ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com        SkASSERT(kSaveLayer_Usage == usage);
16315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org        return SkNEW_ARGS(GatherPixelRefDevice, (info.width(), info.height(), fPRSet));
164ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    }
165ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    virtual void flush() SK_OVERRIDE {}
166ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com
1671f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.comprivate:
168ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    PixelRefSet*  fPRSet;
169ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    SkBitmap fEmptyBitmap;  // legacy -- need to remove the need for this guy
170ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    SkISize fSize;
171ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com
172ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    void addBitmap(const SkBitmap& bm) {
173ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com      fPRSet->add(bm.pixelRef());
174ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    }
175ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com
176ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    void addBitmapFromPaint(const SkPaint& paint) {
177ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com      SkShader* shader = paint.getShader();
178ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com      if (shader) {
179ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com          SkBitmap bm;
180ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com          // Check whether the shader is a gradient in order to short-circuit
181ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com          // call to asABitmap to prevent generation of bitmaps from
182ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com          // gradient shaders, which implement asABitmap.
183ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com          if (SkShader::kNone_GradientType == shader->asAGradient(NULL) &&
184ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com              shader->asABitmap(&bm, NULL, NULL)) {
185ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com              fPRSet->add(bm.pixelRef());
186ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com          }
187ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com      }
188ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    }
189ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com
190ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    typedef SkBaseDevice INHERITED;
191fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com};
192fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
193fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.comSkData* SkPictureUtils::GatherPixelRefs(SkPicture* pict, const SkRect& area) {
194fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    if (NULL == pict) {
195fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        return NULL;
196fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
197fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
198fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    // this test also handles if either area or pict's width/height are empty
199fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    if (!SkRect::Intersects(area,
200fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                            SkRect::MakeWH(SkIntToScalar(pict->width()),
201fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com                                           SkIntToScalar(pict->height())))) {
202fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        return NULL;
203fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
204fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
205fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    SkTDArray<SkPixelRef*> array;
206fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    PixelRefSet prset(&array);
207fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
208ec3ca87d331c4b7058a0fff376a05e84ae0619careed@google.com    GatherPixelRefDevice device(pict->width(), pict->height(), &prset);
20981e8739a101ecb0a978850bd45842bc6e6bc05a6robertphillips@google.com    SkNoSaveLayerCanvas canvas(&device);
210fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
211fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    canvas.clipRect(area, SkRegion::kIntersect_Op, false);
2129b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips    canvas.drawPicture(pict);
213fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com
214fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    SkData* data = NULL;
215fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    int count = array.count();
216fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    if (count > 0) {
217fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com        data = SkData::NewFromMalloc(array.detach(), count * sizeof(SkPixelRef*));
218fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    }
219fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com    return data;
220fe7b1ed30a75cecfe80d1ba4d1f60295e99aeef0reed@google.com}
221