1/*
2 * Copyright 2014 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#ifndef SkGatherPixelRefsAndRects_DEFINED
9#define SkGatherPixelRefsAndRects_DEFINED
10
11#include "SkBitmap.h"
12#include "SkDevice.h"
13#include "SkDraw.h"
14#include "SkPictureUtils.h"
15#include "SkRasterClip.h"
16#include "SkRefCnt.h"
17#include "SkRRect.h"
18#include "SkTypes.h"
19
20// This GatherPixelRefs device passes all discovered pixel refs and their
21// device bounds to the user provided SkPixelRefContainer-derived object
22class SkGatherPixelRefsAndRectsDevice : public SkBaseDevice {
23public:
24    SK_DECLARE_INST_COUNT(SkGatherPixelRefsAndRectsDevice)
25
26    SkGatherPixelRefsAndRectsDevice(int width, int height,
27                                    SkPictureUtils::SkPixelRefContainer* prCont) {
28        fSize.set(width, height);
29        fPRCont = prCont;
30        SkSafeRef(fPRCont);
31        fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(width, height));
32    }
33
34    virtual ~SkGatherPixelRefsAndRectsDevice() {
35        SkSafeUnref(fPRCont);
36    }
37
38    virtual SkImageInfo imageInfo() const SK_OVERRIDE {
39        return fEmptyBitmap.info();
40    }
41
42    virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
43
44protected:
45    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
46        return false;
47    }
48    virtual void clear(SkColor color) SK_OVERRIDE {
49        NothingToDo();
50    }
51    virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
52        SkBitmap bm;
53
54        if (GetBitmapFromPaint(paint, &bm)) {
55            SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
56            fPRCont->add(bm.pixelRef(), clipRect);
57        }
58    }
59    virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
60                            const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
61        SkBitmap bm;
62        if (!GetBitmapFromPaint(paint, &bm)) {
63            return;
64        }
65
66        if (0 == count) {
67            return;
68        }
69
70        SkPoint min = points[0];
71        SkPoint max = points[0];
72        for (size_t i = 1; i < count; ++i) {
73            const SkPoint& point = points[i];
74
75            min.set(SkMinScalar(min.x(), point.x()), SkMinScalar(min.y(), point.y()));
76            max.set(SkMaxScalar(max.x(), point.x()), SkMaxScalar(max.y(), point.y()));
77        }
78
79        SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x()+1, max.y()+1);
80
81        this->drawRect(draw, bounds, paint);
82    }
83    virtual void drawRect(const SkDraw& draw, const SkRect& rect,
84                          const SkPaint& paint) SK_OVERRIDE {
85        SkBitmap bm;
86        if (GetBitmapFromPaint(paint, &bm)) {
87            SkRect mappedRect;
88            draw.fMatrix->mapRect(&mappedRect, rect);
89            SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
90            mappedRect.intersect(clipRect);
91            fPRCont->add(bm.pixelRef(), mappedRect);
92        }
93    }
94    virtual void drawOval(const SkDraw& draw, const SkRect& rect,
95                          const SkPaint& paint) SK_OVERRIDE {
96        this->drawRect(draw, rect, paint);
97    }
98    virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
99                           const SkPaint& paint) SK_OVERRIDE {
100        this->drawRect(draw, rrect.rect(), paint);
101    }
102    virtual void drawPath(const SkDraw& draw, const SkPath& path,
103                          const SkPaint& paint, const SkMatrix* prePathMatrix,
104                          bool pathIsMutable) SK_OVERRIDE {
105        SkBitmap bm;
106        if (!GetBitmapFromPaint(paint, &bm)) {
107            return;
108        }
109
110        SkRect pathBounds = path.getBounds();
111        if (NULL != prePathMatrix) {
112            prePathMatrix->mapRect(&pathBounds);
113        }
114
115        this->drawRect(draw, pathBounds, paint);
116    }
117    virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
118                            const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
119        SkMatrix totMatrix;
120        totMatrix.setConcat(*draw.fMatrix, matrix);
121
122        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
123                                           SkIntToScalar(bitmap.height()));
124        SkRect mappedRect;
125        totMatrix.mapRect(&mappedRect, bitmapRect);
126        fPRCont->add(bitmap.pixelRef(), mappedRect);
127
128        SkBitmap paintBitmap;
129        if (GetBitmapFromPaint(paint, &paintBitmap)) {
130            fPRCont->add(paintBitmap.pixelRef(), mappedRect);
131        }
132    }
133    virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
134                            int x, int y, const SkPaint& paint) SK_OVERRIDE {
135        // Sprites aren't affected by current matrix, so we can't reuse drawRect.
136        SkMatrix matrix;
137        matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
138
139        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
140                                           SkIntToScalar(bitmap.height()));
141        SkRect mappedRect;
142        matrix.mapRect(&mappedRect, bitmapRect);
143        fPRCont->add(bitmap.pixelRef(), mappedRect);
144
145        SkBitmap paintBitmap;
146        if (GetBitmapFromPaint(paint, &paintBitmap)) {
147            fPRCont->add(paintBitmap.pixelRef(), mappedRect);
148        }
149    }
150    virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
151                                const SkRect* srcOrNull, const SkRect& dst,
152                                const SkPaint& paint,
153                                SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
154        SkRect bitmapRect = SkRect::MakeWH(SkIntToScalar(bitmap.width()),
155                                           SkIntToScalar(bitmap.height()));
156        SkMatrix matrix;
157        matrix.setRectToRect(bitmapRect, dst, SkMatrix::kFill_ScaleToFit);
158        this->drawBitmap(draw, bitmap, matrix, paint);
159    }
160    virtual void drawText(const SkDraw& draw, const void* text, size_t len,
161                          SkScalar x, SkScalar y,
162                          const SkPaint& paint) SK_OVERRIDE {
163        SkBitmap bitmap;
164        if (!GetBitmapFromPaint(paint, &bitmap)) {
165            return;
166        }
167
168        // Math is borrowed from SkBBoxRecord
169        SkRect bounds;
170        paint.measureText(text, len, &bounds);
171        SkPaint::FontMetrics metrics;
172        paint.getFontMetrics(&metrics);
173
174        if (paint.isVerticalText()) {
175            SkScalar h = bounds.fBottom - bounds.fTop;
176            if (paint.getTextAlign() == SkPaint::kCenter_Align) {
177                bounds.fTop -= h / 2;
178                bounds.fBottom -= h / 2;
179            }
180            bounds.fBottom += metrics.fBottom;
181            bounds.fTop += metrics.fTop;
182        } else {
183            SkScalar w = bounds.fRight - bounds.fLeft;
184            if (paint.getTextAlign() == SkPaint::kCenter_Align) {
185                bounds.fLeft -= w / 2;
186                bounds.fRight -= w / 2;
187            } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
188                bounds.fLeft -= w;
189                bounds.fRight -= w;
190            }
191            bounds.fTop = metrics.fTop;
192            bounds.fBottom = metrics.fBottom;
193        }
194
195        SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
196        bounds.fLeft -= pad;
197        bounds.fRight += pad;
198        bounds.offset(x, y);
199
200        this->drawRect(draw, bounds, paint);
201    }
202    virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
203                             const SkScalar pos[], SkScalar constY,
204                             int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
205        SkBitmap bitmap;
206        if (!GetBitmapFromPaint(paint, &bitmap)) {
207            return;
208        }
209
210        if (0 == len) {
211            return;
212        }
213
214        // Similar to SkDraw asserts.
215        SkASSERT(scalarsPerPos == 1 || scalarsPerPos == 2);
216
217        SkScalar y = scalarsPerPos == 1 ? constY : constY + pos[1];
218
219        SkPoint min, max;
220        min.set(pos[0], y);
221        max.set(pos[0], y);
222
223        for (size_t i = 1; i < len; ++i) {
224            SkScalar x = pos[i * scalarsPerPos];
225            SkScalar y = constY;
226            if (2 == scalarsPerPos) {
227                y += pos[i * scalarsPerPos + 1];
228            }
229
230            min.set(SkMinScalar(x, min.x()), SkMinScalar(y, min.y()));
231            max.set(SkMaxScalar(x, max.x()), SkMaxScalar(y, max.y()));
232        }
233
234        SkRect bounds = SkRect::MakeLTRB(min.x(), min.y(), max.x(), max.y());
235
236        // Math is borrowed from SkBBoxRecord
237        SkPaint::FontMetrics metrics;
238        paint.getFontMetrics(&metrics);
239
240        bounds.fTop += metrics.fTop;
241        bounds.fBottom += metrics.fBottom;
242
243        SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
244        bounds.fLeft -= pad;
245        bounds.fRight += pad;
246
247        this->drawRect(draw, bounds, paint);
248    }
249    virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
250                                const SkPath& path, const SkMatrix* matrix,
251                                const SkPaint& paint) SK_OVERRIDE {
252        SkBitmap bitmap;
253        if (!GetBitmapFromPaint(paint, &bitmap)) {
254            return;
255        }
256
257        // Math is borrowed from SkBBoxRecord
258        SkRect bounds = path.getBounds();
259        SkPaint::FontMetrics metrics;
260        paint.getFontMetrics(&metrics);
261
262        SkScalar pad = metrics.fTop;
263        // TODO: inset?!
264        bounds.fLeft += pad;
265        bounds.fRight -= pad;
266        bounds.fTop += pad;
267        bounds.fBottom -= pad;
268
269        this->drawRect(draw, bounds, paint);
270    }
271    virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount,
272                              const SkPoint verts[], const SkPoint texs[],
273                              const SkColor colors[], SkXfermode* xmode,
274                              const uint16_t indices[], int indexCount,
275                              const SkPaint& paint) SK_OVERRIDE {
276        this->drawPoints(draw, SkCanvas::kPolygon_PointMode, vertexCount, verts, paint);
277    }
278    virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
279                            const SkPaint&) SK_OVERRIDE {
280        NothingToDo();
281    }
282    // TODO: allow this call to return failure, or move to SkBitmapDevice only.
283    virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
284        return fEmptyBitmap;
285    }
286    virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
287    virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
288    virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
289    virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
290    virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
291                             SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
292        return false;
293    }
294
295private:
296    SkPictureUtils::SkPixelRefContainer* fPRCont;
297    SkISize                              fSize;
298
299    SkBitmap                             fEmptyBitmap; // legacy -- need to remove
300
301    static bool GetBitmapFromPaint(const SkPaint &paint, SkBitmap* bitmap) {
302        SkShader* shader = paint.getShader();
303        if (NULL != shader) {
304            if (SkShader::kNone_GradientType == shader->asAGradient(NULL)) {
305                return SkShader::kNone_BitmapType != shader->asABitmap(bitmap, NULL, NULL);
306            }
307        }
308        return false;
309    }
310
311    virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
312        NotSupported();
313    }
314
315    virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
316        // we expect to only get called via savelayer, in which case it is fine.
317        SkASSERT(kSaveLayer_Usage == usage);
318        return SkNEW_ARGS(SkGatherPixelRefsAndRectsDevice,
319                          (info.width(), info.height(), fPRCont));
320    }
321
322    virtual void flush() SK_OVERRIDE {}
323
324    static void NotSupported() {
325        SkDEBUGFAIL("this method should never be called");
326    }
327
328    static void NothingToDo() {}
329
330    typedef SkBaseDevice INHERITED;
331};
332
333#endif // SkGatherPixelRefsAndRects_DEFINED
334