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