| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CC_PAINT_PAINT_CANVAS_H_ |
| #define CC_PAINT_PAINT_CANVAS_H_ |
| |
| #include "base/compiler_specific.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/ref_counted.h" |
| #include "build/build_config.h" |
| #include "cc/paint/node_id.h" |
| #include "cc/paint/paint_export.h" |
| #include "cc/paint/paint_image.h" |
| #include "cc/paint/refcounted_buffer.h" |
| #include "cc/paint/skottie_color_map.h" |
| #include "cc/paint/skottie_frame_data.h" |
| #include "cc/paint/skottie_text_property_value.h" |
| #include "third_party/skia/include/core/SkCanvas.h" |
| |
| class SkTextBlob; |
| |
| namespace printing { |
| class MetafileSkia; |
| } // namespace printing |
| |
| namespace paint_preview { |
| class PaintPreviewTracker; |
| } // namespace paint_preview |
| |
| namespace cc { |
| class SkottieWrapper; |
| class PaintFlags; |
| class PaintRecord; |
| |
| enum class UsePaintCache { kDisabled = 0, kEnabled }; |
| |
| // PaintCanvas is the cc/paint wrapper of SkCanvas. It has a more restricted |
| // interface than SkCanvas (trimmed back to only what Chrome uses). Its reason |
| // for existence is so that it can do custom serialization logic into a |
| // PaintOpBuffer which (unlike SkPicture) is mutable, handles image replacement, |
| // and can be serialized in custom ways (such as using the transfer cache). |
| // |
| // PaintCanvas is usually implemented by either: |
| // (1) SkiaPaintCanvas, which is backed by an SkCanvas, usually for rasterizing. |
| // (2) RecordPaintCanvas, which records paint commands into a PaintOpBuffer. |
| // |
| // SkiaPaintCanvas allows callers to go from PaintCanvas to SkCanvas (or |
| // PaintRecord to SkPicture), but this is a one way trip. There is no way to go |
| // from SkCanvas to PaintCanvas or from SkPicture back into PaintRecord. |
| class CC_PAINT_EXPORT PaintCanvas { |
| public: |
| PaintCanvas() = default; |
| PaintCanvas(const PaintCanvas&) = delete; |
| virtual ~PaintCanvas() = default; |
| |
| PaintCanvas& operator=(const PaintCanvas&) = delete; |
| |
| // TODO(enne): this only appears to mostly be used to determine if this is |
| // recording or not, so could be simplified or removed. |
| virtual SkImageInfo imageInfo() const = 0; |
| |
| virtual void* accessTopLayerPixels(SkImageInfo* info, |
| size_t* rowBytes, |
| SkIPoint* origin = nullptr) = 0; |
| |
| // TODO(enne): It would be nice to get rid of flush() entirely, as it |
| // doesn't really make sense for recording. However, this gets used by |
| // PaintCanvasVideoRenderer which takes a PaintCanvas to paint both |
| // software and hardware video. This is super entangled with ImageBuffer |
| // and canvas/video painting in Blink where the same paths are used for |
| // both recording and gpu work. |
| virtual void flush() = 0; |
| |
| virtual int save() = 0; |
| virtual int saveLayer(const PaintFlags& flags) = 0; |
| virtual int saveLayer(const SkRect& bounds, const PaintFlags& flags) = 0; |
| virtual int saveLayerAlphaf(float alpha) = 0; |
| virtual int saveLayerAlphaf(const SkRect& bounds, float alpha) = 0; |
| |
| virtual void restore() = 0; |
| virtual int getSaveCount() const = 0; |
| virtual void restoreToCount(int save_count) = 0; |
| virtual void translate(SkScalar dx, SkScalar dy) = 0; |
| virtual void scale(SkScalar sx, SkScalar sy) = 0; |
| void scale(SkScalar s) { scale(s, s); } |
| virtual void rotate(SkScalar degrees) = 0; |
| virtual void concat(const SkM44& matrix) = 0; |
| virtual void setMatrix(const SkM44& matrix) = 0; |
| |
| virtual void clipRect(const SkRect& rect, |
| SkClipOp op, |
| bool do_anti_alias) = 0; |
| void clipRect(const SkRect& rect, SkClipOp op) { clipRect(rect, op, false); } |
| void clipRect(const SkRect& rect, bool do_anti_alias) { |
| clipRect(rect, SkClipOp::kIntersect, do_anti_alias); |
| } |
| void clipRect(const SkRect& rect) { |
| clipRect(rect, SkClipOp::kIntersect, false); |
| } |
| |
| virtual void clipRRect(const SkRRect& rrect, |
| SkClipOp op, |
| bool do_anti_alias) = 0; |
| void clipRRect(const SkRRect& rrect, bool do_anti_alias) { |
| clipRRect(rrect, SkClipOp::kIntersect, do_anti_alias); |
| } |
| void clipRRect(const SkRRect& rrect, SkClipOp op) { |
| clipRRect(rrect, op, false); |
| } |
| void clipRRect(const SkRRect& rrect) { |
| clipRRect(rrect, SkClipOp::kIntersect, false); |
| } |
| |
| virtual void clipPath(const SkPath& path, |
| SkClipOp op, |
| bool do_anti_alias, |
| UsePaintCache) = 0; |
| void clipPath(const SkPath& path, SkClipOp op, bool do_anti_alias) { |
| clipPath(path, op, do_anti_alias, UsePaintCache::kEnabled); |
| } |
| void clipPath(const SkPath& path, SkClipOp op) { |
| clipPath(path, op, /*do_anti_alias=*/false, UsePaintCache::kEnabled); |
| } |
| void clipPath(const SkPath& path, bool do_anti_alias) { |
| clipPath(path, SkClipOp::kIntersect, do_anti_alias, |
| UsePaintCache::kEnabled); |
| } |
| |
| virtual bool getLocalClipBounds(SkRect* bounds) const = 0; |
| virtual bool getDeviceClipBounds(SkIRect* bounds) const = 0; |
| virtual void drawColor(SkColor4f color, SkBlendMode mode) = 0; |
| void drawColor(SkColor4f color) { drawColor(color, SkBlendMode::kSrcOver); } |
| |
| // TODO(enne): This is a synonym for drawColor with kSrc. Remove it. |
| virtual void clear(SkColor4f color) = 0; |
| |
| virtual void drawLine(SkScalar x0, |
| SkScalar y0, |
| SkScalar x1, |
| SkScalar y1, |
| const PaintFlags& flags) = 0; |
| virtual void drawRect(const SkRect& rect, const PaintFlags& flags) = 0; |
| virtual void drawIRect(const SkIRect& rect, const PaintFlags& flags) = 0; |
| virtual void drawOval(const SkRect& oval, const PaintFlags& flags) = 0; |
| virtual void drawRRect(const SkRRect& rrect, const PaintFlags& flags) = 0; |
| virtual void drawDRRect(const SkRRect& outer, |
| const SkRRect& inner, |
| const PaintFlags& flags) = 0; |
| virtual void drawRoundRect(const SkRect& rect, |
| SkScalar rx, |
| SkScalar ry, |
| const PaintFlags& flags) = 0; |
| virtual void drawPath(const SkPath& path, |
| const PaintFlags& flags, |
| UsePaintCache) = 0; |
| void drawPath(const SkPath& path, const PaintFlags& flags) { |
| drawPath(path, flags, UsePaintCache::kEnabled); |
| } |
| virtual void drawImage(const PaintImage& image, |
| SkScalar left, |
| SkScalar top, |
| const SkSamplingOptions&, |
| const PaintFlags* flags) = 0; |
| void drawImage(const PaintImage& image, SkScalar left, SkScalar top) { |
| drawImage(image, left, top, SkSamplingOptions(), nullptr); |
| } |
| |
| virtual void drawImageRect(const PaintImage& image, |
| const SkRect& src, |
| const SkRect& dst, |
| const SkSamplingOptions&, |
| const PaintFlags* flags, |
| SkCanvas::SrcRectConstraint constraint) = 0; |
| void drawImageRect(const PaintImage& image, |
| const SkRect& src, |
| const SkRect& dst, |
| SkCanvas::SrcRectConstraint constraint) { |
| drawImageRect(image, src, dst, SkSamplingOptions(), nullptr, constraint); |
| } |
| |
| virtual void drawVertices(scoped_refptr<RefCountedBuffer<SkPoint>> vertices, |
| scoped_refptr<RefCountedBuffer<SkPoint>> uvs, |
| scoped_refptr<RefCountedBuffer<uint16_t>> indices, |
| const PaintFlags& flags) = 0; |
| |
| // Draws the frame of the |skottie| animation specified by the normalized time |
| // t [0->first frame..1->last frame] at the destination bounds given by |dst| |
| // onto the canvas. |images| is a map from asset id to the corresponding image |
| // to use when rendering this frame; it may be empty if this animation frame |
| // does not contain any images in it. |
| virtual void drawSkottie(scoped_refptr<SkottieWrapper> skottie, |
| const SkRect& dst, |
| float t, |
| SkottieFrameDataMap images, |
| const SkottieColorMap& color_map, |
| SkottieTextPropertyValueMap text_map) = 0; |
| |
| virtual void drawTextBlob(sk_sp<SkTextBlob> blob, |
| SkScalar x, |
| SkScalar y, |
| const PaintFlags& flags) = 0; |
| |
| virtual void drawTextBlob(sk_sp<SkTextBlob> blob, |
| SkScalar x, |
| SkScalar y, |
| NodeId node_id, |
| const PaintFlags& flags) = 0; |
| |
| // Unlike SkCanvas::drawPicture, this only plays back the PaintRecord and does |
| // not add an additional clip. This is closer to SkPicture::playback. |
| virtual void drawPicture(PaintRecord record) = 0; |
| |
| virtual SkM44 getLocalToDevice() const = 0; |
| |
| virtual bool NeedsFlush() const = 0; |
| |
| // Used for printing |
| enum class AnnotationType { |
| kUrl, |
| kNameDestination, |
| kLinkToDestination, |
| }; |
| virtual void Annotate(AnnotationType type, |
| const SkRect& rect, |
| sk_sp<SkData> data) = 0; |
| printing::MetafileSkia* GetPrintingMetafile() const { return metafile_; } |
| void SetPrintingMetafile(printing::MetafileSkia* metafile) { |
| metafile_ = metafile; |
| } |
| paint_preview::PaintPreviewTracker* GetPaintPreviewTracker() const { |
| return tracker_; |
| } |
| void SetPaintPreviewTracker(paint_preview::PaintPreviewTracker* tracker) { |
| tracker_ = tracker; |
| } |
| |
| // Subclasses can override to handle custom data. |
| virtual void recordCustomData(uint32_t id) {} |
| |
| // Used for marked content in PDF files. |
| virtual void setNodeId(int) = 0; |
| |
| private: |
| raw_ptr<printing::MetafileSkia> metafile_ = nullptr; |
| raw_ptr<paint_preview::PaintPreviewTracker, DanglingUntriaged> tracker_ = |
| nullptr; |
| }; |
| |
| class CC_PAINT_EXPORT PaintCanvasAutoRestore { |
| public: |
| PaintCanvasAutoRestore(PaintCanvas* canvas, bool save) : canvas_(canvas) { |
| if (canvas_) { |
| save_count_ = canvas_->getSaveCount(); |
| if (save) { |
| canvas_->save(); |
| } |
| } |
| } |
| |
| ~PaintCanvasAutoRestore() { |
| if (canvas_) { |
| canvas_->restoreToCount(save_count_); |
| } |
| } |
| |
| void restore() { |
| if (canvas_) { |
| canvas_->restoreToCount(save_count_); |
| canvas_ = nullptr; |
| } |
| } |
| |
| private: |
| raw_ptr<PaintCanvas> canvas_ = nullptr; |
| int save_count_ = 0; |
| }; |
| |
| } // namespace cc |
| |
| #endif // CC_PAINT_PAINT_CANVAS_H_ |