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

Side by Side Diff: cc/paint/record_paint_canvas.cc

Issue 2768143002: Back PaintRecord with PaintOpBuffer instead of SkPicture (Closed)
Patch Set: vmpstr review, fix mac theme issuesa Created 3 years, 8 months 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
OLDNEW
(Empty)
1 // Copyright 2017 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 "cc/paint/record_paint_canvas.h"
6
7 #include "base/memory/ptr_util.h"
8 #include "cc/paint/display_item_list.h"
9 #include "cc/paint/paint_op_buffer.h"
10 #include "cc/paint/paint_record.h"
11 #include "cc/paint/paint_recorder.h"
12 #include "third_party/skia/include/core/SkAnnotation.h"
13 #include "third_party/skia/include/core/SkMetaData.h"
14 #include "third_party/skia/include/utils/SkNWayCanvas.h"
15
16 namespace cc {
17
18 RecordPaintCanvas::RecordPaintCanvas(PaintOpBuffer* buffer,
19 const SkRect& cull_rect)
20 : buffer_(buffer),
21 canvas_(static_cast<int>(std::ceil(cull_rect.right())),
22 static_cast<int>(std::ceil(cull_rect.bottom()))) {
23 DCHECK(buffer_);
24
25 // This is part of the "recording canvases have a size, but why" dance.
26 // By creating a canvas of size (right x bottom) and then clipping it,
27 // It makes getDeviceClipBounds return the original cull rect, which code
28 // in GraphicsContextCanvas on Mac expects. (Just creating an SkNoDrawCanvas
29 // with the cull_rect makes a canvas of size (width x height) instead
30 // which is incorrect. SkRecorder cheats with private resetForNextCanvas.
31 canvas_.clipRect(SkRect::Make(cull_rect.roundOut()), SkClipOp::kIntersect,
enne (OOO) 2017/04/06 23:17:05 Fixed the mac layout test issues with this. If ht
mtklein_C 2017/04/06 23:22:18 Yeah, this actually doesn't seem too crazy. I thi
32 false);
33 }
34
35 RecordPaintCanvas::~RecordPaintCanvas() = default;
36
37 SkMetaData& RecordPaintCanvas::getMetaData() {
38 // This could just be SkMetaData owned by RecordPaintCanvas, but since
39 // SkCanvas already has one, we might as well use it directly.
40 return canvas_.getMetaData();
41 }
42
43 SkImageInfo RecordPaintCanvas::imageInfo() const {
44 return canvas_.imageInfo();
45 }
46
47 void RecordPaintCanvas::flush() {
48 // This is a noop when recording.
49 }
50
51 SkISize RecordPaintCanvas::getBaseLayerSize() const {
52 return canvas_.getBaseLayerSize();
53 }
54
55 bool RecordPaintCanvas::readPixels(const SkImageInfo& dest_info,
56 void* dest_pixels,
57 size_t dest_row_bytes,
58 int src_x,
59 int src_y) {
60 NOTREACHED();
61 return false;
62 }
63
64 bool RecordPaintCanvas::readPixels(SkBitmap* bitmap, int src_x, int src_y) {
65 NOTREACHED();
66 return false;
67 }
68
69 bool RecordPaintCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
70 NOTREACHED();
71 return false;
72 }
73
74 bool RecordPaintCanvas::writePixels(const SkImageInfo& info,
75 const void* pixels,
76 size_t row_bytes,
77 int x,
78 int y) {
79 NOTREACHED();
80 return false;
81 }
82
83 int RecordPaintCanvas::save() {
84 buffer_->push<SaveOp>();
85 return canvas_.save();
86 }
87
88 int RecordPaintCanvas::saveLayer(const SkRect* bounds,
89 const PaintFlags* flags) {
90 if (flags) {
91 if (flags->IsSimpleOpacity()) {
92 // TODO(enne): maybe more callers should know this and call
93 // saveLayerAlpha instead of needing to check here.
94 uint8_t alpha = SkColorGetA(flags->getColor());
95 return saveLayerAlpha(bounds, alpha);
96 }
97
98 // TODO(enne): it appears that image filters affect matrices and color
99 // matrices affect transparent flags on SkCanvas layers, but it's not clear
100 // whether those are actually needed and we could just skip ToSkPaint here.
101 buffer_->push<SaveLayerOp>(bounds, flags);
102 const SkPaint& paint = ToSkPaint(*flags);
103 return canvas_.saveLayer(bounds, &paint);
104 }
105 buffer_->push<SaveLayerOp>(bounds, flags);
106 return canvas_.saveLayer(bounds, nullptr);
107 }
108
109 int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
110 buffer_->push<SaveLayerAlphaOp>(bounds, alpha);
111 return canvas_.saveLayerAlpha(bounds, alpha);
112 }
113
114 void RecordPaintCanvas::restore() {
115 buffer_->push<RestoreOp>();
116 canvas_.restore();
117 }
118
119 int RecordPaintCanvas::getSaveCount() const {
120 return canvas_.getSaveCount();
121 }
122
123 void RecordPaintCanvas::restoreToCount(int save_count) {
124 DCHECK_GE(save_count, 1);
125 int diff = canvas_.getSaveCount() - save_count;
126 DCHECK_GE(diff, 0);
127 for (int i = 0; i < diff; ++i)
128 restore();
129 }
130
131 void RecordPaintCanvas::translate(SkScalar dx, SkScalar dy) {
132 buffer_->push<TranslateOp>(dx, dy);
133 canvas_.translate(dx, dy);
134 }
135
136 void RecordPaintCanvas::scale(SkScalar sx, SkScalar sy) {
137 buffer_->push<ScaleOp>(sx, sy);
138 canvas_.scale(sx, sy);
139 }
140
141 void RecordPaintCanvas::rotate(SkScalar degrees) {
142 buffer_->push<RotateOp>(degrees);
143 canvas_.rotate(degrees);
144 }
145
146 void RecordPaintCanvas::concat(const SkMatrix& matrix) {
147 buffer_->push<ConcatOp>(matrix);
148 canvas_.concat(matrix);
149 }
150
151 void RecordPaintCanvas::setMatrix(const SkMatrix& matrix) {
152 buffer_->push<SetMatrixOp>(matrix);
153 canvas_.setMatrix(matrix);
154 }
155
156 void RecordPaintCanvas::clipRect(const SkRect& rect,
157 SkClipOp op,
158 bool antialias) {
159 buffer_->push<ClipRectOp>(rect, op, antialias);
160 canvas_.clipRect(rect, op, antialias);
161 }
162
163 void RecordPaintCanvas::clipRRect(const SkRRect& rrect,
164 SkClipOp op,
165 bool antialias) {
166 // TODO(enne): does this happen? Should the caller know this?
167 if (rrect.isRect()) {
168 clipRect(rrect.getBounds(), op, antialias);
169 return;
170 }
171 buffer_->push<ClipRRectOp>(rrect, op, antialias);
172 canvas_.clipRRect(rrect, op, antialias);
173 }
174
175 void RecordPaintCanvas::clipPath(const SkPath& path,
176 SkClipOp op,
177 bool antialias) {
178 if (!path.isInverseFillType() && canvas_.getTotalMatrix().rectStaysRect()) {
179 // TODO(enne): do these cases happen? should the caller know that this isn't
180 // a path?
181 SkRect rect;
182 if (path.isRect(&rect)) {
183 clipRect(rect, op, antialias);
184 return;
185 }
186 SkRRect rrect;
187 if (path.isOval(&rect)) {
188 rrect.setOval(rect);
189 clipRRect(rrect, op, antialias);
190 return;
191 }
192 if (path.isRRect(&rrect)) {
193 clipRRect(rrect, op, antialias);
194 return;
195 }
196 }
197
198 buffer_->push<ClipPathOp>(path, op, antialias);
199 canvas_.clipPath(path, op, antialias);
200 return;
201 }
202
203 bool RecordPaintCanvas::quickReject(const SkRect& rect) const {
204 return canvas_.quickReject(rect);
205 }
206
207 bool RecordPaintCanvas::quickReject(const SkPath& path) const {
208 return canvas_.quickReject(path);
209 }
210
211 SkRect RecordPaintCanvas::getLocalClipBounds() const {
212 return canvas_.getLocalClipBounds();
213 }
214
215 bool RecordPaintCanvas::getLocalClipBounds(SkRect* bounds) const {
216 return canvas_.getLocalClipBounds(bounds);
217 }
218
219 SkIRect RecordPaintCanvas::getDeviceClipBounds() const {
220 return canvas_.getDeviceClipBounds();
221 }
222
223 bool RecordPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const {
224 return canvas_.getDeviceClipBounds(bounds);
225 }
226
227 void RecordPaintCanvas::drawColor(SkColor color, SkBlendMode mode) {
228 buffer_->push<DrawColorOp>(color, mode);
229 }
230
231 void RecordPaintCanvas::clear(SkColor color) {
232 buffer_->push<DrawColorOp>(color, SkBlendMode::kSrc);
233 }
234
235 void RecordPaintCanvas::drawLine(SkScalar x0,
236 SkScalar y0,
237 SkScalar x1,
238 SkScalar y1,
239 const PaintFlags& flags) {
240 buffer_->push<DrawLineOp>(x0, y0, x1, y1, flags);
241 }
242
243 void RecordPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) {
244 buffer_->push<DrawRectOp>(rect, flags);
245 }
246
247 void RecordPaintCanvas::drawIRect(const SkIRect& rect,
248 const PaintFlags& flags) {
249 buffer_->push<DrawIRectOp>(rect, flags);
250 }
251
252 void RecordPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) {
253 buffer_->push<DrawOvalOp>(oval, flags);
254 }
255
256 void RecordPaintCanvas::drawRRect(const SkRRect& rrect,
257 const PaintFlags& flags) {
258 buffer_->push<DrawRRectOp>(rrect, flags);
259 }
260
261 void RecordPaintCanvas::drawDRRect(const SkRRect& outer,
262 const SkRRect& inner,
263 const PaintFlags& flags) {
264 if (outer.isEmpty())
265 return;
266 if (inner.isEmpty()) {
267 drawRRect(outer, flags);
268 return;
269 }
270 buffer_->push<DrawDRRectOp>(outer, inner, flags);
271 }
272
273 void RecordPaintCanvas::drawCircle(SkScalar cx,
274 SkScalar cy,
275 SkScalar radius,
276 const PaintFlags& flags) {
277 buffer_->push<DrawCircleOp>(cx, cy, radius, flags);
278 }
279
280 void RecordPaintCanvas::drawArc(const SkRect& oval,
281 SkScalar start_angle,
282 SkScalar sweep_angle,
283 bool use_center,
284 const PaintFlags& flags) {
285 buffer_->push<DrawArcOp>(oval, start_angle, sweep_angle, use_center, flags);
286 }
287
288 void RecordPaintCanvas::drawRoundRect(const SkRect& rect,
289 SkScalar rx,
290 SkScalar ry,
291 const PaintFlags& flags) {
292 // TODO(enne): move this into base class?
293 if (rx > 0 && ry > 0) {
294 SkRRect rrect;
295 rrect.setRectXY(rect, rx, ry);
296 drawRRect(rrect, flags);
297 } else {
298 drawRect(rect, flags);
299 }
300 }
301
302 void RecordPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) {
303 buffer_->push<DrawPathOp>(path, flags);
304 }
305
306 void RecordPaintCanvas::drawImage(sk_sp<const SkImage> image,
307 SkScalar left,
308 SkScalar top,
309 const PaintFlags* flags) {
310 buffer_->push<DrawImageOp>(image, left, top, flags);
311 }
312
313 void RecordPaintCanvas::drawImageRect(sk_sp<const SkImage> image,
314 const SkRect& src,
315 const SkRect& dst,
316 const PaintFlags* flags,
317 SrcRectConstraint constraint) {
318 buffer_->push<DrawImageRectOp>(image, src, dst, flags, constraint);
319 }
320
321 void RecordPaintCanvas::drawBitmap(const SkBitmap& bitmap,
322 SkScalar left,
323 SkScalar top,
324 const PaintFlags* flags) {
325 // TODO(enne): Move into base class?
326 if (bitmap.drawsNothing())
327 return;
328 drawImage(SkImage::MakeFromBitmap(bitmap), left, top, flags);
329 }
330
331 void RecordPaintCanvas::drawText(const void* text,
332 size_t byte_length,
333 SkScalar x,
334 SkScalar y,
335 const PaintFlags& flags) {
336 buffer_->push_with_data<DrawTextOp>(text, byte_length, x, y, flags);
337 }
338
339 void RecordPaintCanvas::drawPosText(const void* text,
340 size_t byte_length,
341 const SkPoint pos[],
342 const PaintFlags& flags) {
343 size_t count = ToSkPaint(flags).countText(text, byte_length);
344 buffer_->push_with_data_array<DrawPosTextOp>(text, byte_length, pos, count,
345 flags);
346 }
347
348 void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
349 SkScalar x,
350 SkScalar y,
351 const PaintFlags& flags) {
352 buffer_->push<DrawTextBlobOp>(blob, x, y, flags);
353 }
354
355 void RecordPaintCanvas::drawDisplayItemList(
356 scoped_refptr<DisplayItemList> list) {
357 buffer_->push<DrawDisplayItemListOp>(list);
358 }
359
360 void RecordPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) {
361 // TODO(enne): If this is small, maybe flatten it?
362 buffer_->push<DrawRecordOp>(record);
363 }
364
365 bool RecordPaintCanvas::isClipEmpty() const {
366 return canvas_.isClipEmpty();
367 }
368
369 bool RecordPaintCanvas::isClipRect() const {
370 return canvas_.isClipRect();
371 }
372
373 const SkMatrix& RecordPaintCanvas::getTotalMatrix() const {
374 return canvas_.getTotalMatrix();
375 }
376
377 void RecordPaintCanvas::temporary_internal_describeTopLayer(
378 SkMatrix* matrix,
379 SkIRect* clip_bounds) {
380 return canvas_.temporary_internal_describeTopLayer(matrix, clip_bounds);
381 }
382
383 bool RecordPaintCanvas::ToPixmap(SkPixmap* output) {
384 // TODO(enne): It'd be nice to make this NOTREACHED() or remove this from
385 // RecordPaintCanvas, but this is used by GraphicsContextCanvas for knowing
386 // whether or not it can raster directly into pixels with Cg.
387 return false;
388 }
389
390 void RecordPaintCanvas::Annotate(AnnotationType type,
391 const SkRect& rect,
392 sk_sp<SkData> data) {
393 buffer_->push<AnnotateOp>(type, rect, data);
394 }
395
396 void RecordPaintCanvas::PlaybackPaintRecord(sk_sp<const PaintRecord> record) {
397 drawPicture(record);
398 }
399
400 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698