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