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