Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: skia/ext/lazy_pixel_ref_utils.cc

Issue 111143005: cc: Gather and lock/unlock SkDiscardablePixelRefs instead of skia::LazyPixelRefs. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2013 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.
4
5 #include "skia/ext/lazy_pixel_ref_utils.h"
6
7 #include <algorithm>
8
9 #include "skia/ext/lazy_pixel_ref.h"
10 #include "third_party/skia/include/core/SkBitmapDevice.h"
11 #include "third_party/skia/include/core/SkCanvas.h"
12 #include "third_party/skia/include/core/SkData.h"
13 #include "third_party/skia/include/core/SkDraw.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/src/core/SkRasterClip.h"
19
20 namespace skia {
21
22 namespace {
23
24 // URI label for a lazily decoded SkPixelRef.
25 const char kLabelLazyDecoded[] = "lazy";
26
27 class LazyPixelRefSet {
28 public:
29 LazyPixelRefSet(
30 std::vector<LazyPixelRefUtils::PositionLazyPixelRef>* pixel_refs)
31 : pixel_refs_(pixel_refs) {}
32
33 void Add(SkPixelRef* pixel_ref, const SkRect& rect) {
34 // Only save lazy pixel refs.
35 if (pixel_ref->getURI() &&
36 !strcmp(pixel_ref->getURI(), kLabelLazyDecoded)) {
37 LazyPixelRefUtils::PositionLazyPixelRef position_pixel_ref;
38 position_pixel_ref.lazy_pixel_ref =
39 static_cast<skia::LazyPixelRef*>(pixel_ref);
40 position_pixel_ref.pixel_ref_rect = rect;
41 pixel_refs_->push_back(position_pixel_ref);
42 }
43 }
44
45 private:
46 std::vector<LazyPixelRefUtils::PositionLazyPixelRef>* pixel_refs_;
47 };
48
49 class GatherPixelRefDevice : public SkBitmapDevice {
50 public:
51 GatherPixelRefDevice(const SkBitmap& bm, LazyPixelRefSet* lazy_pixel_ref_set)
52 : SkBitmapDevice(bm), lazy_pixel_ref_set_(lazy_pixel_ref_set) {}
53
54 virtual void clear(SkColor color) SK_OVERRIDE {}
55 virtual void writePixels(const SkBitmap& bitmap,
56 int x,
57 int y,
58 SkCanvas::Config8888 config8888) SK_OVERRIDE {}
59
60 virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
61 SkBitmap bitmap;
62 if (GetBitmapFromPaint(paint, &bitmap)) {
63 SkRect clip_rect = SkRect::Make(draw.fRC->getBounds());
64 AddBitmap(bitmap, clip_rect);
65 }
66 }
67
68 virtual void drawPoints(const SkDraw& draw,
69 SkCanvas::PointMode mode,
70 size_t count,
71 const SkPoint points[],
72 const SkPaint& paint) SK_OVERRIDE {
73 SkBitmap bitmap;
74 if (!GetBitmapFromPaint(paint, &bitmap))
75 return;
76
77 if (count == 0)
78 return;
79
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()));
88 }
89
90 SkRect bounds = SkRect::MakeLTRB(
91 min_point.x(), min_point.y(), max_point.x(), max_point.y());
92
93 GatherPixelRefDevice::drawRect(draw, bounds, paint);
94 }
95 virtual void drawRect(const SkDraw& draw,
96 const SkRect& rect,
97 const SkPaint& paint) SK_OVERRIDE {
98 SkBitmap bitmap;
99 if (GetBitmapFromPaint(paint, &bitmap)) {
100 SkRect mapped_rect;
101 draw.fMatrix->mapRect(&mapped_rect, rect);
102 mapped_rect.intersect(SkRect::Make(draw.fRC->getBounds()));
103 AddBitmap(bitmap, mapped_rect);
104 }
105 }
106 virtual void drawOval(const SkDraw& draw,
107 const SkRect& rect,
108 const SkPaint& paint) SK_OVERRIDE {
109 GatherPixelRefDevice::drawRect(draw, rect, paint);
110 }
111 virtual void drawRRect(const SkDraw& draw,
112 const SkRRect& rect,
113 const SkPaint& paint) SK_OVERRIDE {
114 GatherPixelRefDevice::drawRect(draw, rect.rect(), paint);
115 }
116 virtual void drawPath(const SkDraw& draw,
117 const SkPath& path,
118 const SkPaint& paint,
119 const SkMatrix* pre_path_matrix,
120 bool path_is_mutable) SK_OVERRIDE {
121 SkBitmap bitmap;
122 if (!GetBitmapFromPaint(paint, &bitmap))
123 return;
124
125 SkRect path_bounds = path.getBounds();
126 SkRect final_rect;
127 if (pre_path_matrix != NULL)
128 pre_path_matrix->mapRect(&final_rect, path_bounds);
129 else
130 final_rect = path_bounds;
131
132 GatherPixelRefDevice::drawRect(draw, final_rect, paint);
133 }
134 virtual void drawBitmap(const SkDraw& draw,
135 const SkBitmap& bitmap,
136 const SkMatrix& matrix,
137 const SkPaint& paint) SK_OVERRIDE {
138 SkMatrix total_matrix;
139 total_matrix.setConcat(*draw.fMatrix, matrix);
140
141 SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
142 SkRect mapped_rect;
143 total_matrix.mapRect(&mapped_rect, bitmap_rect);
144 AddBitmap(bitmap, mapped_rect);
145
146 SkBitmap paint_bitmap;
147 if (GetBitmapFromPaint(paint, &paint_bitmap))
148 AddBitmap(paint_bitmap, mapped_rect);
149 }
150 virtual void drawBitmapRect(const SkDraw& draw,
151 const SkBitmap& bitmap,
152 const SkRect* src_or_null,
153 const SkRect& dst,
154 const SkPaint& paint,
155 SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
156 SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
157 SkMatrix matrix;
158 matrix.setRectToRect(bitmap_rect, dst, SkMatrix::kFill_ScaleToFit);
159 GatherPixelRefDevice::drawBitmap(draw, bitmap, matrix, paint);
160 }
161 virtual void drawSprite(const SkDraw& draw,
162 const SkBitmap& bitmap,
163 int x,
164 int y,
165 const SkPaint& paint) SK_OVERRIDE {
166 // Sprites aren't affected by current matrix, so we can't reuse drawRect.
167 SkMatrix matrix;
168 matrix.setTranslate(x, y);
169
170 SkRect bitmap_rect = SkRect::MakeWH(bitmap.width(), bitmap.height());
171 SkRect mapped_rect;
172 matrix.mapRect(&mapped_rect, bitmap_rect);
173
174 AddBitmap(bitmap, mapped_rect);
175 SkBitmap paint_bitmap;
176 if (GetBitmapFromPaint(paint, &paint_bitmap))
177 AddBitmap(paint_bitmap, mapped_rect);
178 }
179 virtual void drawText(const SkDraw& draw,
180 const void* text,
181 size_t len,
182 SkScalar x,
183 SkScalar y,
184 const SkPaint& paint) SK_OVERRIDE {
185 SkBitmap bitmap;
186 if (!GetBitmapFromPaint(paint, &bitmap))
187 return;
188
189 // Math is borrowed from SkBBoxRecord
190 SkRect bounds;
191 paint.measureText(text, len, &bounds);
192 SkPaint::FontMetrics metrics;
193 paint.getFontMetrics(&metrics);
194
195 if (paint.isVerticalText()) {
196 SkScalar h = bounds.fBottom - bounds.fTop;
197 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
198 bounds.fTop -= h / 2;
199 bounds.fBottom -= h / 2;
200 }
201 bounds.fBottom += metrics.fBottom;
202 bounds.fTop += metrics.fTop;
203 } else {
204 SkScalar w = bounds.fRight - bounds.fLeft;
205 if (paint.getTextAlign() == SkPaint::kCenter_Align) {
206 bounds.fLeft -= w / 2;
207 bounds.fRight -= w / 2;
208 } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
209 bounds.fLeft -= w;
210 bounds.fRight -= w;
211 }
212 bounds.fTop = metrics.fTop;
213 bounds.fBottom = metrics.fBottom;
214 }
215
216 SkScalar pad = (metrics.fBottom - metrics.fTop) / 2;
217 bounds.fLeft -= pad;
218 bounds.fRight += pad;
219 bounds.fLeft += x;
220 bounds.fRight += x;
221 bounds.fTop += y;
222 bounds.fBottom += y;
223
224 GatherPixelRefDevice::drawRect(draw, bounds, paint);
225 }
226 virtual void drawPosText(const SkDraw& draw,
227 const void* text,
228 size_t len,
229 const SkScalar pos[],
230 SkScalar const_y,
231 int scalars_per_pos,
232 const SkPaint& paint) SK_OVERRIDE {
233 SkBitmap bitmap;
234 if (!GetBitmapFromPaint(paint, &bitmap))
235 return;
236
237 if (len == 0)
238 return;
239
240 // Similar to SkDraw asserts.
241 SkASSERT(scalars_per_pos == 1 || scalars_per_pos == 2);
242
243 SkPoint min_point;
244 SkPoint max_point;
245 if (scalars_per_pos == 1) {
246 min_point.set(pos[0], const_y);
247 max_point.set(pos[0], const_y);
248 } else if (scalars_per_pos == 2) {
249 min_point.set(pos[0], const_y + pos[1]);
250 max_point.set(pos[0], const_y + pos[1]);
251 }
252
253 for (size_t i = 0; i < len; ++i) {
254 SkScalar x = pos[i * scalars_per_pos];
255 SkScalar y = const_y;
256 if (scalars_per_pos == 2)
257 y += pos[i * scalars_per_pos + 1];
258
259 min_point.set(std::min(x, min_point.x()), std::min(y, min_point.y()));
260 max_point.set(std::max(x, max_point.x()), std::max(y, max_point.y()));
261 }
262
263 SkRect bounds = SkRect::MakeLTRB(
264 min_point.x(), min_point.y(), max_point.x(), max_point.y());
265
266 // Math is borrowed from SkBBoxRecord
267 SkPaint::FontMetrics metrics;
268 paint.getFontMetrics(&metrics);
269
270 bounds.fTop += metrics.fTop;
271 bounds.fBottom += metrics.fBottom;
272
273 SkScalar pad = (metrics.fTop - metrics.fBottom) / 2;
274 bounds.fLeft += pad;
275 bounds.fRight -= pad;
276
277 GatherPixelRefDevice::drawRect(draw, bounds, paint);
278 }
279 virtual void drawTextOnPath(const SkDraw& draw,
280 const void* text,
281 size_t len,
282 const SkPath& path,
283 const SkMatrix* matrix,
284 const SkPaint& paint) SK_OVERRIDE {
285 SkBitmap bitmap;
286 if (!GetBitmapFromPaint(paint, &bitmap))
287 return;
288
289 // Math is borrowed from SkBBoxRecord
290 SkRect bounds = path.getBounds();
291 SkPaint::FontMetrics metrics;
292 paint.getFontMetrics(&metrics);
293
294 SkScalar pad = metrics.fTop;
295 bounds.fLeft += pad;
296 bounds.fRight -= pad;
297 bounds.fTop += pad;
298 bounds.fBottom -= pad;
299
300 GatherPixelRefDevice::drawRect(draw, bounds, paint);
301 }
302 virtual void drawVertices(const SkDraw& draw,
303 SkCanvas::VertexMode,
304 int vertex_count,
305 const SkPoint verts[],
306 const SkPoint texs[],
307 const SkColor colors[],
308 SkXfermode* xmode,
309 const uint16_t indices[],
310 int index_count,
311 const SkPaint& paint) SK_OVERRIDE {
312 GatherPixelRefDevice::drawPoints(
313 draw, SkCanvas::kPolygon_PointMode, vertex_count, verts, paint);
314 }
315 virtual void drawDevice(const SkDraw&,
316 SkBaseDevice*,
317 int x,
318 int y,
319 const SkPaint&) SK_OVERRIDE {}
320
321 protected:
322 virtual bool onReadPixels(const SkBitmap& bitmap,
323 int x,
324 int y,
325 SkCanvas::Config8888 config8888) SK_OVERRIDE {
326 return false;
327 }
328
329 private:
330 LazyPixelRefSet* lazy_pixel_ref_set_;
331
332 void AddBitmap(const SkBitmap& bm, const SkRect& rect) {
333 SkRect canvas_rect = SkRect::MakeWH(width(), height());
334 SkRect paint_rect = SkRect::MakeEmpty();
335 paint_rect.intersect(rect, canvas_rect);
336 lazy_pixel_ref_set_->Add(bm.pixelRef(), paint_rect);
337 }
338
339 bool GetBitmapFromPaint(const SkPaint& paint, SkBitmap* bm) {
340 SkShader* shader = paint.getShader();
341 if (shader) {
342 // Check whether the shader is a gradient in order to prevent generation
343 // of bitmaps from gradient shaders, which implement asABitmap.
344 if (SkShader::kNone_GradientType == shader->asAGradient(NULL))
345 return shader->asABitmap(bm, NULL, NULL);
346 }
347 return false;
348 }
349 };
350
351 class NoSaveLayerCanvas : public SkCanvas {
352 public:
353 NoSaveLayerCanvas(SkBaseDevice* device) : INHERITED(device) {}
354
355 // Turn saveLayer() into save() for speed, should not affect correctness.
356 virtual int saveLayer(const SkRect* bounds,
357 const SkPaint* paint,
358 SaveFlags flags) SK_OVERRIDE {
359
360 // Like SkPictureRecord, we don't want to create layers, but we do need
361 // to respect the save and (possibly) its rect-clip.
362 int count = this->INHERITED::save(flags);
363 if (bounds) {
364 this->INHERITED::clipRectBounds(bounds, flags, NULL);
365 }
366 return count;
367 }
368
369 // Disable aa for speed.
370 virtual bool clipRect(const SkRect& rect, SkRegion::Op op, bool doAA)
371 SK_OVERRIDE {
372 return this->INHERITED::clipRect(rect, op, false);
373 }
374
375 virtual bool clipPath(const SkPath& path, SkRegion::Op op, bool doAA)
376 SK_OVERRIDE {
377 return this->updateClipConservativelyUsingBounds(
378 path.getBounds(), op, path.isInverseFillType());
379 }
380 virtual bool clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA)
381 SK_OVERRIDE {
382 return this->updateClipConservativelyUsingBounds(
383 rrect.getBounds(), op, false);
384 }
385
386 private:
387 typedef SkCanvas INHERITED;
388 };
389
390 } // namespace
391
392 void LazyPixelRefUtils::GatherPixelRefs(
393 SkPicture* picture,
394 std::vector<PositionLazyPixelRef>* lazy_pixel_refs) {
395 lazy_pixel_refs->clear();
396 LazyPixelRefSet pixel_ref_set(lazy_pixel_refs);
397
398 SkBitmap empty_bitmap;
399 empty_bitmap.setConfig(
400 SkBitmap::kNo_Config, picture->width(), picture->height());
401
402 GatherPixelRefDevice device(empty_bitmap, &pixel_ref_set);
403 NoSaveLayerCanvas canvas(&device);
404
405 canvas.clipRect(SkRect::MakeWH(picture->width(), picture->height()),
406 SkRegion::kIntersect_Op,
407 false);
408 canvas.drawPicture(*picture);
409 }
410
411 } // namespace skia
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698