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