Fix invalid cast in AppCacheGroup::AddUpdateObserver.
[chromium-blink-merge.git] / skia / ext / pixel_ref_utils.cc
blobfa5f29984948e93b54e86dc441ee84f272a88c1d
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "skia/ext/pixel_ref_utils.h"
7 #include <algorithm>
9 #include "third_party/skia/include/core/SkBitmapDevice.h"
10 #include "third_party/skia/include/core/SkCanvas.h"
11 #include "third_party/skia/include/core/SkData.h"
12 #include "third_party/skia/include/core/SkDraw.h"
13 #include "third_party/skia/include/core/SkPath.h"
14 #include "third_party/skia/include/core/SkPixelRef.h"
15 #include "third_party/skia/include/core/SkRRect.h"
16 #include "third_party/skia/include/core/SkRect.h"
17 #include "third_party/skia/include/core/SkShader.h"
18 #include "third_party/skia/include/utils/SkNoSaveLayerCanvas.h"
19 #include "third_party/skia/src/core/SkRasterClip.h"
21 namespace skia {
23 namespace {
25 // URI label for a discardable SkPixelRef.
26 const char kLabelDiscardable[] = "discardable";
28 class DiscardablePixelRefSet {
29 public:
30 DiscardablePixelRefSet(
31 std::vector<PixelRefUtils::PositionPixelRef>* pixel_refs)
32 : pixel_refs_(pixel_refs) {}
34 void Add(SkPixelRef* pixel_ref,
35 const SkRect& rect,
36 const SkMatrix& matrix,
37 SkFilterQuality filter_quality) {
38 // Only save discardable pixel refs.
39 if (pixel_ref->getURI() &&
40 !strcmp(pixel_ref->getURI(), kLabelDiscardable)) {
41 PixelRefUtils::PositionPixelRef position_pixel_ref;
42 position_pixel_ref.pixel_ref = pixel_ref;
43 position_pixel_ref.pixel_ref_rect = rect;
44 position_pixel_ref.matrix = matrix;
45 position_pixel_ref.filter_quality = filter_quality;
46 pixel_refs_->push_back(position_pixel_ref);
50 private:
51 std::vector<PixelRefUtils::PositionPixelRef>* pixel_refs_;
54 class GatherPixelRefDevice : public SkBitmapDevice {
55 public:
56 GatherPixelRefDevice(const SkBitmap& bm,
57 DiscardablePixelRefSet* pixel_ref_set)
58 : SkBitmapDevice(bm), pixel_ref_set_(pixel_ref_set) {}
60 void drawPaint(const SkDraw& draw, const SkPaint& paint) override {
61 SkBitmap bitmap;
62 if (GetBitmapFromPaint(paint, &bitmap)) {
63 SkRect clip_rect = SkRect::Make(draw.fRC->getBounds());
64 AddBitmap(bitmap, clip_rect, *draw.fMatrix, paint.getFilterQuality());
68 void drawPoints(const SkDraw& draw,
69 SkCanvas::PointMode mode,
70 size_t count,
71 const SkPoint points[],
72 const SkPaint& paint) override {
73 SkBitmap bitmap;
74 if (!GetBitmapFromPaint(paint, &bitmap))
75 return;
77 if (count == 0)
78 return;
80 SkPoint min_point = points[0];
81 SkPoint max_point = points[0];
82 for (size_t i = 1; i < count; ++i) {
83 const SkPoint& point = points[i];
84 min_point.set(std::min(min_point.x(), point.x()),
85 std::min(min_point.y(), point.y()));
86 max_point.set(std::max(max_point.x(), point.x()),
87 std::max(max_point.y(), point.y()));
90 SkRect bounds = SkRect::MakeLTRB(
91 min_point.x(), min_point.y(), max_point.x(), max_point.y());
93 GatherPixelRefDevice::drawRect(draw, bounds, paint);
95 void drawRect(const SkDraw& draw,
96 const SkRect& rect,
97 const SkPaint& paint) override {
98 SkBitmap bitmap;
99 if (GetBitmapFromPaint(paint, &bitmap)) {
100 SkRect mapped_rect;
101 draw.fMatrix->mapRect(&mapped_rect, rect);
102 if (mapped_rect.intersect(SkRect::Make(draw.fRC->getBounds()))) {
103 AddBitmap(bitmap, mapped_rect, *draw.fMatrix, paint.getFilterQuality());
107 void drawOval(const SkDraw& draw,
108 const SkRect& rect,
109 const SkPaint& paint) override {
110 GatherPixelRefDevice::drawRect(draw, rect, paint);
112 void drawRRect(const SkDraw& draw,
113 const SkRRect& rect,
114 const SkPaint& paint) override {
115 GatherPixelRefDevice::drawRect(draw, rect.rect(), paint);
117 void drawPath(const SkDraw& draw,
118 const SkPath& path,
119 const SkPaint& paint,
120 const SkMatrix* pre_path_matrix,
121 bool path_is_mutable) override {
122 SkBitmap bitmap;
123 if (!GetBitmapFromPaint(paint, &bitmap))
124 return;
126 SkRect path_bounds = path.getBounds();
127 SkRect final_rect;
128 if (pre_path_matrix != NULL)
129 pre_path_matrix->mapRect(&final_rect, path_bounds);
130 else
131 final_rect = path_bounds;
133 GatherPixelRefDevice::drawRect(draw, final_rect, paint);
135 void drawBitmap(const SkDraw& draw,
136 const SkBitmap& bitmap,
137 const SkMatrix& matrix,
138 const SkPaint& paint) override {
139 SkMatrix total_matrix;
140 total_matrix.setConcat(*draw.fMatrix, matrix);
142 SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
143 SkRect mapped_rect;
144 total_matrix.mapRect(&mapped_rect, bitmap_rect);
145 AddBitmap(bitmap, mapped_rect, total_matrix, paint.getFilterQuality());
147 SkBitmap paint_bitmap;
148 if (GetBitmapFromPaint(paint, &paint_bitmap)) {
149 AddBitmap(paint_bitmap, mapped_rect, total_matrix,
150 paint.getFilterQuality());
153 void drawBitmapRect(const SkDraw& draw,
154 const SkBitmap& bitmap,
155 const SkRect* src_or_null,
156 const SkRect& dst,
157 const SkPaint& paint,
158 SkCanvas::SrcRectConstraint) override {
159 SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
160 SkMatrix matrix;
161 matrix.setRectToRect(bitmap_rect, dst, SkMatrix::kFill_ScaleToFit);
162 GatherPixelRefDevice::drawBitmap(draw, bitmap, matrix, paint);
164 void drawSprite(const SkDraw& draw,
165 const SkBitmap& bitmap,
166 int x,
167 int y,
168 const SkPaint& paint) override {
169 // Sprites aren't affected by current matrix, so we can't reuse drawRect.
170 SkMatrix matrix;
171 matrix.setTranslate(x, y);
173 SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
174 SkRect mapped_rect;
175 matrix.mapRect(&mapped_rect, bitmap_rect);
177 SkMatrix identity;
178 identity.setIdentity();
179 // Sprites aren't affected by current matrix, so use the identity matrix.
180 AddBitmap(bitmap, mapped_rect, identity, paint.getFilterQuality());
181 SkBitmap paint_bitmap;
182 if (GetBitmapFromPaint(paint, &paint_bitmap))
183 AddBitmap(paint_bitmap, mapped_rect, identity, paint.getFilterQuality());
185 void drawText(const SkDraw& draw,
186 const void* text,
187 size_t len,
188 SkScalar x,
189 SkScalar y,
190 const SkPaint& paint) override {
191 SkBitmap bitmap;
192 if (!GetBitmapFromPaint(paint, &bitmap))
193 return;
195 // Math is borrowed from SkBBoxRecord
196 SkRect bounds;
197 paint.measureText(text, len, &bounds);
198 SkPaint::FontMetrics metrics;
199 paint.getFontMetrics(&metrics);
201 if (paint.isVerticalText()) {
202 SkScalar h = bounds.fBottom - bounds.fTop;
203 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
204 bounds.fTop -= h / 2;
205 bounds.fBottom -= h / 2;
207 bounds.fBottom += metrics.fBottom;
208 bounds.fTop += metrics.fTop;
209 } else {
210 SkScalar w = bounds.fRight - bounds.fLeft;
211 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
212 bounds.fLeft -= w / 2;
213 bounds.fRight -= w / 2;
214 } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
215 bounds.fLeft -= w;
216 bounds.fRight -= w;
218 bounds.fTop = metrics.fTop;
219 bounds.fBottom = metrics.fBottom;
222 SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
223 bounds.fLeft -= pad;
224 bounds.fRight += pad;
225 bounds.fLeft += x;
226 bounds.fRight += x;
227 bounds.fTop += y;
228 bounds.fBottom += y;
230 GatherPixelRefDevice::drawRect(draw, bounds, paint);
232 void drawPosText(const SkDraw& draw,
233 const void* text,
234 size_t len,
235 const SkScalar pos[],
236 int scalars_per_pos,
237 const SkPoint& offset,
238 const SkPaint& paint) override {
239 SkBitmap bitmap;
240 if (!GetBitmapFromPaint(paint, &bitmap))
241 return;
243 if (len == 0)
244 return;
246 // Similar to SkDraw asserts.
247 SkASSERT(scalars_per_pos == 1 || scalars_per_pos == 2);
249 SkPoint min_point = SkPoint::Make(offset.x() + pos[0],
250 offset.y() + (2 == scalars_per_pos ? pos[1] : 0));
251 SkPoint max_point = min_point;
253 for (size_t i = 0; i < len; ++i) {
254 SkScalar x = offset.x() + pos[i * scalars_per_pos];
255 SkScalar y = offset.y() + (2 == scalars_per_pos ? pos[i * scalars_per_pos + 1] : 0);
257 min_point.set(std::min(x, min_point.x()), std::min(y, min_point.y()));
258 max_point.set(std::max(x, max_point.x()), std::max(y, max_point.y()));
261 SkRect bounds = SkRect::MakeLTRB(
262 min_point.x(), min_point.y(), max_point.x(), max_point.y());
264 // Math is borrowed from SkBBoxRecord
265 SkPaint::FontMetrics metrics;
266 paint.getFontMetrics(&metrics);
268 bounds.fTop += metrics.fTop;
269 bounds.fBottom += metrics.fBottom;
271 SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
272 bounds.fLeft += pad;
273 bounds.fRight -= pad;
275 GatherPixelRefDevice::drawRect(draw, bounds, paint);
277 void drawTextOnPath(const SkDraw& draw,
278 const void* text,
279 size_t len,
280 const SkPath& path,
281 const SkMatrix* matrix,
282 const SkPaint& paint) override {
283 SkBitmap bitmap;
284 if (!GetBitmapFromPaint(paint, &bitmap))
285 return;
287 // Math is borrowed from SkBBoxRecord
288 SkRect bounds = path.getBounds();
289 SkPaint::FontMetrics metrics;
290 paint.getFontMetrics(&metrics);
292 SkScalar pad = metrics.fTop;
293 bounds.fLeft += pad;
294 bounds.fRight -= pad;
295 bounds.fTop += pad;
296 bounds.fBottom -= pad;
298 GatherPixelRefDevice::drawRect(draw, bounds, paint);
300 void drawVertices(const SkDraw& draw,
301 SkCanvas::VertexMode,
302 int vertex_count,
303 const SkPoint verts[],
304 const SkPoint texs[],
305 const SkColor colors[],
306 SkXfermode* xmode,
307 const uint16_t indices[],
308 int index_count,
309 const SkPaint& paint) override {
310 GatherPixelRefDevice::drawPoints(
311 draw, SkCanvas::kPolygon_PointMode, vertex_count, verts, paint);
313 void drawDevice(const SkDraw&,
314 SkBaseDevice*,
315 int x,
316 int y,
317 const SkPaint&) override {}
319 protected:
320 bool onReadPixels(const SkImageInfo& info,
321 void* pixels,
322 size_t rowBytes,
323 int x,
324 int y) override {
325 return false;
328 bool onWritePixels(const SkImageInfo& info,
329 const void* pixels,
330 size_t rowBytes,
331 int x,
332 int y) override {
333 return false;
336 private:
337 DiscardablePixelRefSet* pixel_ref_set_;
339 void AddBitmap(const SkBitmap& bm,
340 const SkRect& rect,
341 const SkMatrix& matrix,
342 SkFilterQuality filter_quality) {
343 SkRect canvas_rect = SkRect::MakeWH(width(), height());
344 SkRect paint_rect = SkRect::MakeEmpty();
345 if (paint_rect.intersect(rect, canvas_rect)) {
346 pixel_ref_set_->Add(bm.pixelRef(), paint_rect, matrix,
347 filter_quality);
351 bool GetBitmapFromPaint(const SkPaint& paint, SkBitmap* bm) {
352 SkShader* shader = paint.getShader();
353 if (shader) {
354 // Check whether the shader is a gradient in order to prevent generation
355 // of bitmaps from gradient shaders, which implement asABitmap.
356 if (SkShader::kNone_GradientType == shader->asAGradient(NULL))
357 return shader->asABitmap(bm, NULL, NULL);
359 return false;
363 } // namespace
365 void PixelRefUtils::GatherDiscardablePixelRefs(
366 SkPicture* picture,
367 std::vector<PositionPixelRef>* pixel_refs) {
368 pixel_refs->clear();
369 DiscardablePixelRefSet pixel_ref_set(pixel_refs);
371 SkRect picture_bounds = picture->cullRect();
372 SkIRect picture_ibounds = picture_bounds.roundOut();
373 SkBitmap empty_bitmap;
374 empty_bitmap.setInfo(SkImageInfo::MakeUnknown(picture_ibounds.width(),
375 picture_ibounds.height()));
377 GatherPixelRefDevice device(empty_bitmap, &pixel_ref_set);
378 SkNoSaveLayerCanvas canvas(&device);
380 // Draw the picture pinned against our top/left corner.
381 canvas.translate(-picture_bounds.left(), -picture_bounds.top());
382 canvas.drawPicture(picture);
385 } // namespace skia