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 #ifndef CC_PAINT_PAINT_CANVAS_H_
6 #define CC_PAINT_PAINT_CANVAS_H_
7 
8 #include "base/compiler_specific.h"
9 #include "base/memory/ref_counted.h"
10 #include "build/build_config.h"
11 #include "cc/paint/node_id.h"
12 #include "cc/paint/paint_export.h"
13 #include "cc/paint/paint_image.h"
14 #include "third_party/skia/include/core/SkCanvas.h"
15 #include "third_party/skia/include/core/SkTextBlob.h"
16 
17 namespace printing {
18 class MetafileSkia;
19 }  // namespace printing
20 
21 namespace paint_preview {
22 class PaintPreviewTracker;
23 }  // namespace paint_preview
24 
25 namespace cc {
26 class SkottieWrapper;
27 class PaintFlags;
28 class PaintOpBuffer;
29 
30 using PaintRecord = PaintOpBuffer;
31 
32 // PaintCanvas is the cc/paint wrapper of SkCanvas.  It has a more restricted
33 // interface than SkCanvas (trimmed back to only what Chrome uses).  Its reason
34 // for existence is so that it can do custom serialization logic into a
35 // PaintOpBuffer which (unlike SkPicture) is mutable, handles image replacement,
36 // and can be serialized in custom ways (such as using the transfer cache).
37 //
38 // PaintCanvas is usually implemented by either:
39 // (1) SkiaPaintCanvas, which is backed by an SkCanvas, usually for rasterizing.
40 // (2) RecordPaintCanvas, which records paint commands into a PaintOpBuffer.
41 //
42 // SkiaPaintCanvas allows callers to go from PaintCanvas to SkCanvas (or
43 // PaintRecord to SkPicture), but this is a one way trip.  There is no way to go
44 // from SkCanvas to PaintCanvas or from SkPicture back into PaintRecord.
45 class CC_PAINT_EXPORT PaintCanvas {
46  public:
47   PaintCanvas() = default;
48   PaintCanvas(const PaintCanvas&) = delete;
49   virtual ~PaintCanvas() = default;
50 
51   PaintCanvas& operator=(const PaintCanvas&) = delete;
52 
53   // TODO(enne): this only appears to mostly be used to determine if this is
54   // recording or not, so could be simplified or removed.
55   virtual SkImageInfo imageInfo() const = 0;
56 
57   virtual void* accessTopLayerPixels(SkImageInfo* info,
58                                      size_t* rowBytes,
59                                      SkIPoint* origin = nullptr) = 0;
60 
61   // TODO(enne): It would be nice to get rid of flush() entirely, as it
62   // doesn't really make sense for recording.  However, this gets used by
63   // PaintCanvasVideoRenderer which takes a PaintCanvas to paint both
64   // software and hardware video.  This is super entangled with ImageBuffer
65   // and canvas/video painting in Blink where the same paths are used for
66   // both recording and gpu work.
67   virtual void flush() = 0;
68 
69   virtual int save() = 0;
70   virtual int saveLayer(const SkRect* bounds, const PaintFlags* flags) = 0;
71   virtual int saveLayerAlpha(const SkRect* bounds, uint8_t alpha) = 0;
72 
73   virtual void restore() = 0;
74   virtual int getSaveCount() const = 0;
75   virtual void restoreToCount(int save_count) = 0;
76   virtual void translate(SkScalar dx, SkScalar dy) = 0;
77   virtual void scale(SkScalar sx, SkScalar sy) = 0;
78   virtual void rotate(SkScalar degrees) = 0;
79   virtual void concat(const SkMatrix& matrix) = 0;
80   virtual void setMatrix(const SkMatrix& matrix) = 0;
81 
82   virtual void clipRect(const SkRect& rect,
83                         SkClipOp op,
84                         bool do_anti_alias) = 0;
clipRect(const SkRect & rect,SkClipOp op)85   void clipRect(const SkRect& rect, SkClipOp op) { clipRect(rect, op, false); }
clipRect(const SkRect & rect,bool do_anti_alias)86   void clipRect(const SkRect& rect, bool do_anti_alias) {
87     clipRect(rect, SkClipOp::kIntersect, do_anti_alias);
88   }
clipRect(const SkRect & rect)89   void clipRect(const SkRect& rect) {
90     clipRect(rect, SkClipOp::kIntersect, false);
91   }
92 
93   virtual void clipRRect(const SkRRect& rrect,
94                          SkClipOp op,
95                          bool do_anti_alias) = 0;
clipRRect(const SkRRect & rrect,bool do_anti_alias)96   void clipRRect(const SkRRect& rrect, bool do_anti_alias) {
97     clipRRect(rrect, SkClipOp::kIntersect, do_anti_alias);
98   }
clipRRect(const SkRRect & rrect,SkClipOp op)99   void clipRRect(const SkRRect& rrect, SkClipOp op) {
100     clipRRect(rrect, op, false);
101   }
clipRRect(const SkRRect & rrect)102   void clipRRect(const SkRRect& rrect) {
103     clipRRect(rrect, SkClipOp::kIntersect, false);
104   }
105 
106   virtual void clipPath(const SkPath& path,
107                         SkClipOp op,
108                         bool do_anti_alias) = 0;
clipPath(const SkPath & path,SkClipOp op)109   void clipPath(const SkPath& path, SkClipOp op) { clipPath(path, op, false); }
clipPath(const SkPath & path,bool do_anti_alias)110   void clipPath(const SkPath& path, bool do_anti_alias) {
111     clipPath(path, SkClipOp::kIntersect, do_anti_alias);
112   }
113 
114   virtual SkRect getLocalClipBounds() const = 0;
115   virtual bool getLocalClipBounds(SkRect* bounds) const = 0;
116   virtual SkIRect getDeviceClipBounds() const = 0;
117   virtual bool getDeviceClipBounds(SkIRect* bounds) const = 0;
118   virtual void drawColor(SkColor color, SkBlendMode mode) = 0;
drawColor(SkColor color)119   void drawColor(SkColor color) { drawColor(color, SkBlendMode::kSrcOver); }
120 
121   // TODO(enne): This is a synonym for drawColor with kSrc.  Remove it.
122   virtual void clear(SkColor color) = 0;
123 
124   virtual void drawLine(SkScalar x0,
125                         SkScalar y0,
126                         SkScalar x1,
127                         SkScalar y1,
128                         const PaintFlags& flags) = 0;
129   virtual void drawRect(const SkRect& rect, const PaintFlags& flags) = 0;
130   virtual void drawIRect(const SkIRect& rect, const PaintFlags& flags) = 0;
131   virtual void drawOval(const SkRect& oval, const PaintFlags& flags) = 0;
132   virtual void drawRRect(const SkRRect& rrect, const PaintFlags& flags) = 0;
133   virtual void drawDRRect(const SkRRect& outer,
134                           const SkRRect& inner,
135                           const PaintFlags& flags) = 0;
136   virtual void drawRoundRect(const SkRect& rect,
137                              SkScalar rx,
138                              SkScalar ry,
139                              const PaintFlags& flags) = 0;
140   virtual void drawPath(const SkPath& path, const PaintFlags& flags) = 0;
141   virtual void drawImage(const PaintImage& image,
142                          SkScalar left,
143                          SkScalar top,
144                          const PaintFlags* flags) = 0;
drawImage(const PaintImage & image,SkScalar left,SkScalar top)145   void drawImage(const PaintImage& image, SkScalar left, SkScalar top) {
146     drawImage(image, left, top, nullptr);
147   }
148 
149   virtual void drawImageRect(const PaintImage& image,
150                              const SkRect& src,
151                              const SkRect& dst,
152                              const PaintFlags* flags,
153                              SkCanvas::SrcRectConstraint constraint) = 0;
154 
155   // Draws the frame of the |skottie| animation specified by the normalized time
156   // t [0->first frame..1->last frame] at the destination bounds given by |dst|
157   // onto the canvas.
158   virtual void drawSkottie(scoped_refptr<SkottieWrapper> skottie,
159                            const SkRect& dst,
160                            float t) = 0;
161 
162   virtual void drawTextBlob(sk_sp<SkTextBlob> blob,
163                             SkScalar x,
164                             SkScalar y,
165                             const PaintFlags& flags) = 0;
166 
167   virtual void drawTextBlob(sk_sp<SkTextBlob> blob,
168                             SkScalar x,
169                             SkScalar y,
170                             NodeId node_id,
171                             const PaintFlags& flags) = 0;
172 
173   // Unlike SkCanvas::drawPicture, this only plays back the PaintRecord and does
174   // not add an additional clip.  This is closer to SkPicture::playback.
175   virtual void drawPicture(sk_sp<const PaintRecord> record) = 0;
176 
177   virtual bool isClipEmpty() const = 0;
178   virtual SkMatrix getTotalMatrix() const = 0;
179 
180   // Used for printing
181   enum class AnnotationType {
182     URL,
183     NAMED_DESTINATION,
184     LINK_TO_DESTINATION,
185   };
186   virtual void Annotate(AnnotationType type,
187                         const SkRect& rect,
188                         sk_sp<SkData> data) = 0;
GetPrintingMetafile()189   printing::MetafileSkia* GetPrintingMetafile() const { return metafile_; }
SetPrintingMetafile(printing::MetafileSkia * metafile)190   void SetPrintingMetafile(printing::MetafileSkia* metafile) {
191     metafile_ = metafile;
192   }
GetPaintPreviewTracker()193   paint_preview::PaintPreviewTracker* GetPaintPreviewTracker() const {
194     return tracker_;
195   }
SetPaintPreviewTracker(paint_preview::PaintPreviewTracker * tracker)196   void SetPaintPreviewTracker(paint_preview::PaintPreviewTracker* tracker) {
197     tracker_ = tracker;
198   }
199 
200   // Subclasses can override to handle custom data.
recordCustomData(uint32_t id)201   virtual void recordCustomData(uint32_t id) {}
202 
203   // Used for marked content in PDF files.
204   virtual void setNodeId(int) = 0;
205 
206  private:
207   printing::MetafileSkia* metafile_ = nullptr;
208   paint_preview::PaintPreviewTracker* tracker_ = nullptr;
209 };
210 
211 class CC_PAINT_EXPORT PaintCanvasAutoRestore {
212  public:
PaintCanvasAutoRestore(PaintCanvas * canvas,bool save)213   PaintCanvasAutoRestore(PaintCanvas* canvas, bool save) : canvas_(canvas) {
214     if (canvas_) {
215       save_count_ = canvas_->getSaveCount();
216       if (save) {
217         canvas_->save();
218       }
219     }
220   }
221 
~PaintCanvasAutoRestore()222   ~PaintCanvasAutoRestore() {
223     if (canvas_) {
224       canvas_->restoreToCount(save_count_);
225     }
226   }
227 
restore()228   void restore() {
229     if (canvas_) {
230       canvas_->restoreToCount(save_count_);
231       canvas_ = nullptr;
232     }
233   }
234 
235  private:
236   PaintCanvas* canvas_ = nullptr;
237   int save_count_ = 0;
238 };
239 
240 }  // namespace cc
241 
242 #endif  // CC_PAINT_PAINT_CANVAS_H_
243