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