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

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

Issue 2768143002: Back PaintRecord with PaintOpBuffer instead of SkPicture (Closed)
Patch Set: Remove unneeded expectation 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,
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::writePixels(const SkImageInfo& info,
56 const void* pixels,
57 size_t row_bytes,
58 int x,
59 int y) {
60 NOTREACHED();
61 return false;
62 }
63
64 int RecordPaintCanvas::save() {
65 buffer_->push<SaveOp>();
66 return canvas_.save();
67 }
68
69 int RecordPaintCanvas::saveLayer(const SkRect* bounds,
70 const PaintFlags* flags) {
71 if (flags) {
72 if (flags->IsSimpleOpacity()) {
73 // TODO(enne): maybe more callers should know this and call
74 // saveLayerAlpha instead of needing to check here.
75 uint8_t alpha = SkColorGetA(flags->getColor());
76 return saveLayerAlpha(bounds, alpha);
77 }
78
79 // TODO(enne): it appears that image filters affect matrices and color
80 // matrices affect transparent flags on SkCanvas layers, but it's not clear
81 // whether those are actually needed and we could just skip ToSkPaint here.
82 buffer_->push<SaveLayerOp>(bounds, flags);
83 const SkPaint& paint = ToSkPaint(*flags);
84 return canvas_.saveLayer(bounds, &paint);
85 }
86 buffer_->push<SaveLayerOp>(bounds, flags);
87 return canvas_.saveLayer(bounds, nullptr);
88 }
89
90 int RecordPaintCanvas::saveLayerAlpha(const SkRect* bounds, uint8_t alpha) {
91 buffer_->push<SaveLayerAlphaOp>(bounds, alpha);
92 return canvas_.saveLayerAlpha(bounds, alpha);
93 }
94
95 void RecordPaintCanvas::restore() {
96 buffer_->push<RestoreOp>();
97 canvas_.restore();
98 }
99
100 int RecordPaintCanvas::getSaveCount() const {
101 return canvas_.getSaveCount();
102 }
103
104 void RecordPaintCanvas::restoreToCount(int save_count) {
105 DCHECK_GE(save_count, 1);
106 int diff = canvas_.getSaveCount() - save_count;
107 DCHECK_GE(diff, 0);
108 for (int i = 0; i < diff; ++i)
109 restore();
110 }
111
112 void RecordPaintCanvas::translate(SkScalar dx, SkScalar dy) {
113 buffer_->push<TranslateOp>(dx, dy);
114 canvas_.translate(dx, dy);
115 }
116
117 void RecordPaintCanvas::scale(SkScalar sx, SkScalar sy) {
118 buffer_->push<ScaleOp>(sx, sy);
119 canvas_.scale(sx, sy);
120 }
121
122 void RecordPaintCanvas::rotate(SkScalar degrees) {
123 buffer_->push<RotateOp>(degrees);
124 canvas_.rotate(degrees);
125 }
126
127 void RecordPaintCanvas::concat(const SkMatrix& matrix) {
128 buffer_->push<ConcatOp>(matrix);
129 canvas_.concat(matrix);
130 }
131
132 void RecordPaintCanvas::setMatrix(const SkMatrix& matrix) {
133 buffer_->push<SetMatrixOp>(matrix);
134 canvas_.setMatrix(matrix);
135 }
136
137 void RecordPaintCanvas::clipRect(const SkRect& rect,
138 SkClipOp op,
139 bool antialias) {
140 buffer_->push<ClipRectOp>(rect, op, antialias);
141 canvas_.clipRect(rect, op, antialias);
142 }
143
144 void RecordPaintCanvas::clipRRect(const SkRRect& rrect,
145 SkClipOp op,
146 bool antialias) {
147 // TODO(enne): does this happen? Should the caller know this?
148 if (rrect.isRect()) {
149 clipRect(rrect.getBounds(), op, antialias);
150 return;
151 }
152 buffer_->push<ClipRRectOp>(rrect, op, antialias);
153 canvas_.clipRRect(rrect, op, antialias);
154 }
155
156 void RecordPaintCanvas::clipPath(const SkPath& path,
157 SkClipOp op,
158 bool antialias) {
159 if (!path.isInverseFillType() && canvas_.getTotalMatrix().rectStaysRect()) {
160 // TODO(enne): do these cases happen? should the caller know that this isn't
161 // a path?
162 SkRect rect;
163 if (path.isRect(&rect)) {
164 clipRect(rect, op, antialias);
165 return;
166 }
167 SkRRect rrect;
168 if (path.isOval(&rect)) {
169 rrect.setOval(rect);
170 clipRRect(rrect, op, antialias);
171 return;
172 }
173 if (path.isRRect(&rrect)) {
174 clipRRect(rrect, op, antialias);
175 return;
176 }
177 }
178
179 buffer_->push<ClipPathOp>(path, op, antialias);
180 canvas_.clipPath(path, op, antialias);
181 return;
182 }
183
184 bool RecordPaintCanvas::quickReject(const SkRect& rect) const {
185 return canvas_.quickReject(rect);
186 }
187
188 bool RecordPaintCanvas::quickReject(const SkPath& path) const {
189 return canvas_.quickReject(path);
190 }
191
192 SkRect RecordPaintCanvas::getLocalClipBounds() const {
193 return canvas_.getLocalClipBounds();
194 }
195
196 bool RecordPaintCanvas::getLocalClipBounds(SkRect* bounds) const {
197 return canvas_.getLocalClipBounds(bounds);
198 }
199
200 SkIRect RecordPaintCanvas::getDeviceClipBounds() const {
201 return canvas_.getDeviceClipBounds();
202 }
203
204 bool RecordPaintCanvas::getDeviceClipBounds(SkIRect* bounds) const {
205 return canvas_.getDeviceClipBounds(bounds);
206 }
207
208 void RecordPaintCanvas::drawColor(SkColor color, SkBlendMode mode) {
209 buffer_->push<DrawColorOp>(color, mode);
210 }
211
212 void RecordPaintCanvas::clear(SkColor color) {
213 buffer_->push<DrawColorOp>(color, SkBlendMode::kSrc);
214 }
215
216 void RecordPaintCanvas::drawLine(SkScalar x0,
217 SkScalar y0,
218 SkScalar x1,
219 SkScalar y1,
220 const PaintFlags& flags) {
221 buffer_->push<DrawLineOp>(x0, y0, x1, y1, flags);
222 }
223
224 void RecordPaintCanvas::drawRect(const SkRect& rect, const PaintFlags& flags) {
225 buffer_->push<DrawRectOp>(rect, flags);
226 }
227
228 void RecordPaintCanvas::drawIRect(const SkIRect& rect,
229 const PaintFlags& flags) {
230 buffer_->push<DrawIRectOp>(rect, flags);
231 }
232
233 void RecordPaintCanvas::drawOval(const SkRect& oval, const PaintFlags& flags) {
234 buffer_->push<DrawOvalOp>(oval, flags);
235 }
236
237 void RecordPaintCanvas::drawRRect(const SkRRect& rrect,
238 const PaintFlags& flags) {
239 buffer_->push<DrawRRectOp>(rrect, flags);
240 }
241
242 void RecordPaintCanvas::drawDRRect(const SkRRect& outer,
243 const SkRRect& inner,
244 const PaintFlags& flags) {
245 if (outer.isEmpty())
246 return;
247 if (inner.isEmpty()) {
248 drawRRect(outer, flags);
249 return;
250 }
251 buffer_->push<DrawDRRectOp>(outer, inner, flags);
252 }
253
254 void RecordPaintCanvas::drawCircle(SkScalar cx,
255 SkScalar cy,
256 SkScalar radius,
257 const PaintFlags& flags) {
258 buffer_->push<DrawCircleOp>(cx, cy, radius, flags);
259 }
260
261 void RecordPaintCanvas::drawArc(const SkRect& oval,
262 SkScalar start_angle,
263 SkScalar sweep_angle,
264 bool use_center,
265 const PaintFlags& flags) {
266 buffer_->push<DrawArcOp>(oval, start_angle, sweep_angle, use_center, flags);
267 }
268
269 void RecordPaintCanvas::drawRoundRect(const SkRect& rect,
270 SkScalar rx,
271 SkScalar ry,
272 const PaintFlags& flags) {
273 // TODO(enne): move this into base class?
274 if (rx > 0 && ry > 0) {
275 SkRRect rrect;
276 rrect.setRectXY(rect, rx, ry);
277 drawRRect(rrect, flags);
278 } else {
279 drawRect(rect, flags);
280 }
281 }
282
283 void RecordPaintCanvas::drawPath(const SkPath& path, const PaintFlags& flags) {
284 buffer_->push<DrawPathOp>(path, flags);
285 }
286
287 void RecordPaintCanvas::drawImage(sk_sp<const SkImage> image,
288 SkScalar left,
289 SkScalar top,
290 const PaintFlags* flags) {
291 buffer_->push<DrawImageOp>(image, left, top, flags);
292 }
293
294 void RecordPaintCanvas::drawImageRect(sk_sp<const SkImage> image,
295 const SkRect& src,
296 const SkRect& dst,
297 const PaintFlags* flags,
298 SrcRectConstraint constraint) {
299 buffer_->push<DrawImageRectOp>(image, src, dst, flags, constraint);
300 }
301
302 void RecordPaintCanvas::drawBitmap(const SkBitmap& bitmap,
303 SkScalar left,
304 SkScalar top,
305 const PaintFlags* flags) {
306 // TODO(enne): Move into base class?
307 if (bitmap.drawsNothing())
308 return;
309 drawImage(SkImage::MakeFromBitmap(bitmap), left, top, flags);
310 }
311
312 void RecordPaintCanvas::drawText(const void* text,
313 size_t byte_length,
314 SkScalar x,
315 SkScalar y,
316 const PaintFlags& flags) {
317 buffer_->push_with_data<DrawTextOp>(text, byte_length, x, y, flags);
318 }
319
320 void RecordPaintCanvas::drawPosText(const void* text,
321 size_t byte_length,
322 const SkPoint pos[],
323 const PaintFlags& flags) {
324 size_t count = ToSkPaint(flags).countText(text, byte_length);
325 buffer_->push_with_data_array<DrawPosTextOp>(text, byte_length, pos, count,
326 flags);
327 }
328
329 void RecordPaintCanvas::drawTextBlob(sk_sp<SkTextBlob> blob,
330 SkScalar x,
331 SkScalar y,
332 const PaintFlags& flags) {
333 buffer_->push<DrawTextBlobOp>(blob, x, y, flags);
334 }
335
336 void RecordPaintCanvas::drawDisplayItemList(
337 scoped_refptr<DisplayItemList> list) {
338 buffer_->push<DrawDisplayItemListOp>(list);
339 }
340
341 void RecordPaintCanvas::drawPicture(sk_sp<const PaintRecord> record) {
342 // TODO(enne): If this is small, maybe flatten it?
343 buffer_->push<DrawRecordOp>(record);
344 }
345
346 bool RecordPaintCanvas::isClipEmpty() const {
347 return canvas_.isClipEmpty();
348 }
349
350 bool RecordPaintCanvas::isClipRect() const {
351 return canvas_.isClipRect();
352 }
353
354 const SkMatrix& RecordPaintCanvas::getTotalMatrix() const {
355 return canvas_.getTotalMatrix();
356 }
357
358 void RecordPaintCanvas::temporary_internal_describeTopLayer(
359 SkMatrix* matrix,
360 SkIRect* clip_bounds) {
361 return canvas_.temporary_internal_describeTopLayer(matrix, clip_bounds);
362 }
363
364 bool RecordPaintCanvas::ToPixmap(SkPixmap* output) {
365 // TODO(enne): It'd be nice to make this NOTREACHED() or remove this from
366 // RecordPaintCanvas, but this is used by GraphicsContextCanvas for knowing
367 // whether or not it can raster directly into pixels with Cg.
368 return false;
369 }
370
371 void RecordPaintCanvas::Annotate(AnnotationType type,
372 const SkRect& rect,
373 sk_sp<SkData> data) {
374 buffer_->push<AnnotateOp>(type, rect, data);
375 }
376
377 void RecordPaintCanvas::PlaybackPaintRecord(sk_sp<const PaintRecord> record) {
378 drawPicture(record);
379 }
380
381 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698