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