#ifndef CC_PAINT_PAINT_OP_H_
#define CC_PAINT_PAINT_OP_H_
#include <stdint.h>
#include <array>
#include <cmath>
#include <iosfwd>
#include <limits>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/debug/alias.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "cc/base/math_util.h"
#include "cc/paint/element_id.h"
#include "cc/paint/node_id.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_export.h"
#include "cc/paint/paint_filter.h"
#include "cc/paint/paint_flags.h"
#include "cc/paint/paint_record.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_resource_metadata.h"
#include "cc/paint/skottie_text_property_value.h"
#include "cc/paint/skottie_wrapper.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPathTypes.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkScalar.h"
#include "ui/gfx/display_color_spaces.h"
#include "ui/gfx/geometry/rect.h"
class SkImage;
class SkTextBlob;
namespace sktext::gpu {
class Slug;
}
namespace cc {
class DisplayItemList;
class PaintOpWriter;
class PaintOpReader;
class CC_PAINT_EXPORT ThreadsafePath : public SkPath {
public:
explicit ThreadsafePath(const SkPath& path) : SkPath(path) {
updateBoundsCache();
getGenerationID();
}
ThreadsafePath() {
updateBoundsCache();
getGenerationID();
}
};
#define HAS_SERIALIZATION_FUNCTIONS() \
void Serialize(PaintOpWriter& writer, const PaintFlags* flags_to_serialize, \
const SkM44& current_ctm, const SkM44& original_ctm) const; \
static PaintOp* Deserialize(PaintOpReader& reader, void* output)
enum class PaintOpType : uint8_t {
kAnnotate,
kClipPath,
kClipRect,
kClipRRect,
kConcat,
kCustomData,
kDrawArc,
kDrawArcLite,
kDrawColor,
kDrawDRRect,
kDrawImage,
kDrawImageRect,
kDrawIRect,
kDrawLine,
kDrawLineLite,
kDrawOval,
kDrawPath,
kDrawRecord,
kDrawRect,
kDrawRRect,
kDrawScrollingContents,
kDrawSkottie,
kDrawSlug,
kDrawTextBlob,
kDrawVertices,
kNoop,
kRestore,
kRotate,
kSave,
kSaveLayer,
kSaveLayerAlpha,
kSaveLayerFilters,
kScale,
kSetMatrix,
kSetNodeId,
kTranslate,
kLastPaintOpType = kTranslate,
};
CC_PAINT_EXPORT std::string PaintOpTypeToString(PaintOpType type);
CC_PAINT_EXPORT std::ostream& operator<<(std::ostream&, PaintOpType);
class CC_PAINT_EXPORT PaintOp {
public:
PaintOp(const PaintOp&) = delete;
PaintOp& operator=(const PaintOp&) = delete;
void DestroyThis();
uint8_t type;
using SerializeOptions = PaintOpBuffer::SerializeOptions;
using DeserializeOptions = PaintOpBuffer::DeserializeOptions;
PaintOpType GetType() const { return static_cast<PaintOpType>(type); }
void Raster(SkCanvas* canvas, const PlaybackParams& params) const;
bool IsDrawOp() const { return g_is_draw_op[type]; }
bool IsPaintOpWithFlags() const { return g_has_paint_flags[type]; }
uint16_t AlignedSize() const { return g_type_to_aligned_size[type]; }
bool EqualsForTesting(const PaintOp& other) const;
enum class SerializedImageType : uint8_t {
kNoImage,
kImageData,
kTransferCacheEntry,
kMailbox,
kLastType = kMailbox
};
size_t Serialize(void* memory,
size_t size,
const SerializeOptions& options,
const PaintFlags* flags_to_serialize,
const SkM44& current_ctm,
const SkM44& original_ctm) const;
static PaintOp* Deserialize(const volatile void* input,
size_t input_size,
void* output,
size_t output_size,
size_t* read_bytes,
const DeserializeOptions& options);
static PaintOp* DeserializeIntoPaintOpBuffer(
const volatile void* input,
size_t input_size,
PaintOpBuffer* buffer,
size_t* read_bytes,
const DeserializeOptions& options);
static bool GetBounds(const PaintOp& op, SkRect* rect);
static gfx::Rect ComputePaintRect(const PaintOp& op,
const SkRect& clip_rect,
const SkMatrix& ctm);
static bool QuickRejectDraw(const PaintOp& op, const SkCanvas* canvas);
static bool OpHasDiscardableImages(const PaintOp& op);
static bool OpHasDrawTextOps(const PaintOp& op);
static size_t OpAdditionalOpCount(const PaintOp& op);
static bool TypeHasFlags(PaintOpType type);
static bool IsValidDrawColorSkBlendMode(SkBlendMode mode) {
return static_cast<uint32_t>(mode) <=
static_cast<uint32_t>(SkBlendMode::kLastCoeffMode);
}
static bool IsValidPaintFlagsSkBlendMode(SkBlendMode mode) {
return static_cast<uint32_t>(mode) <=
static_cast<uint32_t>(SkBlendMode::kLastMode);
}
static constexpr size_t kNumOpTypes =
static_cast<size_t>(PaintOpType::kLastPaintOpType) + 1;
static constexpr bool kIsDrawOp = false;
static constexpr bool kHasPaintFlags = false;
protected:
explicit PaintOp(PaintOpType type) : type(static_cast<uint8_t>(type)) {}
~PaintOp() = default;
int CountSlowPaths() const { return 0; }
int CountSlowPathsFromFlags() const { return 0; }
bool HasNonAAPaint() const { return false; }
bool HasDrawTextOps() const { return false; }
bool HasSaveLayerOps() const { return false; }
bool HasSaveLayerAlphaOps() const { return false; }
bool HasEffectsPreventingLCDTextForSaveLayerAlpha() const { return false; }
bool HasDiscardableImages(gfx::ContentColorUsage* content_color_usage) const {
return false;
}
bool HasDiscardableImagesFromFlags(
gfx::ContentColorUsage* content_color_usage) const {
return false;
}
size_t AdditionalBytesUsed() const { return 0; }
size_t AdditionalOpCount() const { return 0; }
static bool IsValidSkClipOp(SkClipOp op) {
return static_cast<uint32_t>(op) <=
static_cast<uint32_t>(SkClipOp::kMax_EnumValue);
}
static bool IsValidPath(const SkPath& path) { return path.isValid(); }
static bool IsUnsetRect(const SkRect& rect) {
return rect.fLeft == SK_ScalarInfinity;
}
static bool IsValidOrUnsetRect(const SkRect& rect) {
return IsUnsetRect(rect) || rect.isFinite();
}
static const std::array<bool, kNumOpTypes> g_is_draw_op;
static const std::array<bool, kNumOpTypes> g_has_paint_flags;
static const std::array<uint16_t, kNumOpTypes> g_type_to_aligned_size;
static const SkRect kUnsetRect;
};
class CC_PAINT_EXPORT PaintOpWithFlags : public PaintOp {
public:
static constexpr bool kHasPaintFlags = true;
int CountSlowPathsFromFlags() const { return flags.getPathEffect() ? 1 : 0; }
bool HasDiscardableImagesFromFlags(
gfx::ContentColorUsage* content_color_usage) const;
void RasterWithFlags(SkCanvas* canvas,
const PaintFlags* flags,
const PlaybackParams& params) const;
PaintFlags flags;
protected:
PaintOpWithFlags(PaintOpType type, const PaintFlags& flags)
: PaintOp(type), flags(flags) {}
explicit PaintOpWithFlags(PaintOpType type) : PaintOp(type) {}
~PaintOpWithFlags() = default;
bool HasNonAAPaint() const { return !flags.isAntiAlias(); }
};
#define INTERNAL_PAINTOP_BASE_TYPE(type, super) \
class type : public super { \
public: \
using super::CountSlowPaths; \
using super::CountSlowPathsFromFlags; \
using super::HasNonAAPaint; \
using super::HasDrawTextOps; \
using super::HasSaveLayerOps; \
using super::HasSaveLayerAlphaOps; \
using super::HasEffectsPreventingLCDTextForSaveLayerAlpha; \
using super::HasDiscardableImages; \
using super::HasDiscardableImagesFromFlags; \
using super::AdditionalBytesUsed; \
using super::AdditionalOpCount; \
\
protected: \
using super::super; \
}
INTERNAL_PAINTOP_BASE_TYPE(PaintOpBaseInternal, PaintOp);
INTERNAL_PAINTOP_BASE_TYPE(PaintOpWithFlagsBaseInternal, PaintOpWithFlags);
#undef INTERNAL_PAINTOP_BASE_TYPE
class CC_PAINT_EXPORT AnnotateOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kAnnotate;
AnnotateOp(PaintCanvas::AnnotationType annotation_type,
const SkRect& rect,
sk_sp<SkData> data);
~AnnotateOp();
static void Raster(const AnnotateOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return rect.isFinite(); }
bool EqualsForTesting(const AnnotateOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
PaintCanvas::AnnotationType annotation_type;
SkRect rect;
sk_sp<SkData> data;
private:
AnnotateOp();
};
class CC_PAINT_EXPORT ClipPathOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kClipPath;
ClipPathOp(SkPath path,
SkClipOp op,
bool antialias,
UsePaintCache use_paint_cache = UsePaintCache::kEnabled)
: PaintOpBaseInternal(kType),
path(path),
op(op),
antialias(antialias),
use_cache(use_paint_cache) {}
static void Raster(const ClipPathOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return IsValidSkClipOp(op) && IsValidPath(path); }
bool EqualsForTesting(const ClipPathOp& other) const;
int CountSlowPaths() const;
bool HasNonAAPaint() const { return !antialias; }
HAS_SERIALIZATION_FUNCTIONS();
ThreadsafePath path;
SkClipOp op;
bool antialias;
UsePaintCache use_cache = UsePaintCache::kDisabled;
private:
ClipPathOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT ClipRectOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kClipRect;
ClipRectOp(const SkRect& rect, SkClipOp op, bool antialias)
: PaintOpBaseInternal(kType), rect(rect), op(op), antialias(antialias) {}
static void Raster(const ClipRectOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return IsValidSkClipOp(op) && rect.isFinite(); }
bool EqualsForTesting(const ClipRectOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkRect rect;
SkClipOp op;
bool antialias;
private:
ClipRectOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT ClipRRectOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kClipRRect;
ClipRRectOp(const SkRRect& rrect, SkClipOp op, bool antialias)
: PaintOpBaseInternal(kType),
rrect(rrect),
op(op),
antialias(antialias) {}
static void Raster(const ClipRRectOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return IsValidSkClipOp(op) && rrect.isValid(); }
bool EqualsForTesting(const ClipRRectOp& other) const;
bool HasNonAAPaint() const { return !antialias; }
HAS_SERIALIZATION_FUNCTIONS();
SkRRect rrect;
SkClipOp op;
bool antialias;
private:
ClipRRectOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT ConcatOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kConcat;
explicit ConcatOp(const SkM44& matrix)
: PaintOpBaseInternal(kType), matrix(matrix) {}
static void Raster(const ConcatOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return true; }
bool EqualsForTesting(const ConcatOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkM44 matrix;
private:
ConcatOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT CustomDataOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kCustomData;
explicit CustomDataOp(uint32_t id) : PaintOpBaseInternal(kType), id(id) {}
static void Raster(const CustomDataOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return true; }
bool EqualsForTesting(const CustomDataOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
uint32_t id;
private:
CustomDataOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawColorOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawColor;
static constexpr bool kIsDrawOp = true;
DrawColorOp(SkColor4f color, SkBlendMode mode)
: PaintOpBaseInternal(kType), color(color), mode(mode) {}
static void Raster(const DrawColorOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return IsValidDrawColorSkBlendMode(mode); }
bool EqualsForTesting(const DrawColorOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkColor4f color;
SkBlendMode mode;
private:
DrawColorOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawDRRectOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawDRRect;
static constexpr bool kIsDrawOp = true;
DrawDRRectOp(const SkRRect& outer,
const SkRRect& inner,
const PaintFlags& flags)
: PaintOpWithFlagsBaseInternal(kType, flags),
outer(outer),
inner(inner) {}
static void RasterWithFlags(const DrawDRRectOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const {
return flags.IsValid() && outer.isValid() && inner.isValid();
}
bool EqualsForTesting(const DrawDRRectOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkRRect outer;
SkRRect inner;
private:
DrawDRRectOp() : PaintOpWithFlagsBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawImageOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawImage;
static constexpr bool kIsDrawOp = true;
DrawImageOp(const PaintImage& image, SkScalar left, SkScalar top);
DrawImageOp(const PaintImage& image,
SkScalar left,
SkScalar top,
const SkSamplingOptions&,
const PaintFlags* flags);
~DrawImageOp();
static void RasterWithFlags(const DrawImageOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const {
return flags.IsValid() && std::isfinite(scale_adjustment.width()) &&
std::isfinite(scale_adjustment.height());
}
bool EqualsForTesting(const DrawImageOp& other) const;
bool HasDiscardableImages(gfx::ContentColorUsage* content_color_usage) const;
PaintFlags::FilterQuality GetImageQuality() const;
bool HasNonAAPaint() const { return false; }
HAS_SERIALIZATION_FUNCTIONS();
PaintImage image;
SkScalar left;
SkScalar top;
SkSamplingOptions sampling;
private:
DrawImageOp();
SkSize scale_adjustment = SkSize::Make(1.f, 1.f);
};
class CC_PAINT_EXPORT DrawImageRectOp final
: public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawImageRect;
static constexpr bool kIsDrawOp = true;
DrawImageRectOp(const PaintImage& image,
const SkRect& src,
const SkRect& dst,
SkCanvas::SrcRectConstraint constraint);
DrawImageRectOp(const PaintImage& image,
const SkRect& src,
const SkRect& dst,
const SkSamplingOptions&,
const PaintFlags* flags,
SkCanvas::SrcRectConstraint constraint);
~DrawImageRectOp();
static void RasterWithFlags(const DrawImageRectOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const {
return flags.IsValid() && src.isFinite() && dst.isFinite() &&
std::isfinite(scale_adjustment.width()) &&
std::isfinite(scale_adjustment.height());
}
bool EqualsForTesting(const DrawImageRectOp& other) const;
bool HasDiscardableImages(gfx::ContentColorUsage* content_color_usage) const;
PaintFlags::FilterQuality GetImageQuality() const;
HAS_SERIALIZATION_FUNCTIONS();
PaintImage image;
SkRect src;
SkRect dst;
SkSamplingOptions sampling;
SkCanvas::SrcRectConstraint constraint;
private:
DrawImageRectOp();
SkSize scale_adjustment = SkSize::Make(1.f, 1.f);
};
class CC_PAINT_EXPORT DrawIRectOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawIRect;
static constexpr bool kIsDrawOp = true;
DrawIRectOp(const SkIRect& rect, const PaintFlags& flags)
: PaintOpWithFlagsBaseInternal(kType, flags), rect(rect) {}
static void RasterWithFlags(const DrawIRectOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return flags.IsValid(); }
bool EqualsForTesting(const DrawIRectOp& other) const;
bool HasNonAAPaint() const { return false; }
HAS_SERIALIZATION_FUNCTIONS();
SkIRect rect;
private:
DrawIRectOp() : PaintOpWithFlagsBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawLineOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawLine;
static constexpr bool kIsDrawOp = true;
DrawLineOp(SkScalar x0,
SkScalar y0,
SkScalar x1,
SkScalar y1,
const PaintFlags& flags,
bool draw_as_path = false)
: PaintOpWithFlagsBaseInternal(kType, flags),
x0(x0),
y0(y0),
x1(x1),
y1(y1),
draw_as_path(draw_as_path) {}
static void RasterWithFlags(const DrawLineOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return flags.IsValid(); }
bool EqualsForTesting(const DrawLineOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
int CountSlowPaths() const;
SkScalar x0;
SkScalar y0;
SkScalar x1;
SkScalar y1;
bool draw_as_path;
private:
DrawLineOp() : PaintOpWithFlagsBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawLineLiteOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawLineLite;
static constexpr bool kIsDrawOp = true;
DrawLineLiteOp(SkScalar x0,
SkScalar y0,
SkScalar x1,
SkScalar y1,
const CorePaintFlags& core_paint_flags)
: PaintOpBaseInternal(kType),
x0(x0),
y0(y0),
x1(x1),
y1(y1),
core_paint_flags(core_paint_flags) {}
static void Raster(const DrawLineLiteOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return core_paint_flags.IsValid(); }
bool EqualsForTesting(const DrawLineLiteOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
int CountSlowPaths() const { return 0; }
SkScalar x0;
SkScalar y0;
SkScalar x1;
SkScalar y1;
CorePaintFlags core_paint_flags;
private:
DrawLineLiteOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawArcLiteOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawArcLite;
static constexpr bool kIsDrawOp = true;
DrawArcLiteOp(const SkRect& oval,
SkScalar start_angle_degrees,
SkScalar sweep_angle_degrees,
const CorePaintFlags& core_paint_flags)
: PaintOpBaseInternal(kType),
oval(oval),
start_angle_degrees(start_angle_degrees),
sweep_angle_degrees(sweep_angle_degrees),
core_paint_flags(core_paint_flags) {}
static void Raster(const DrawArcLiteOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const {
return core_paint_flags.IsValid() && oval.isFinite() &&
std::isfinite(start_angle_degrees) &&
std::isfinite(sweep_angle_degrees);
}
bool EqualsForTesting(const DrawArcLiteOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkRect oval;
SkScalar start_angle_degrees;
SkScalar sweep_angle_degrees;
CorePaintFlags core_paint_flags;
private:
DrawArcLiteOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawArcOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawArc;
static constexpr bool kIsDrawOp = true;
DrawArcOp(const SkRect& oval,
SkScalar start_angle_degrees,
SkScalar sweep_angle_degrees,
const PaintFlags& flags)
: PaintOpWithFlagsBaseInternal(kType, flags),
oval(oval),
start_angle_degrees(start_angle_degrees),
sweep_angle_degrees(sweep_angle_degrees) {}
static void RasterWithFlags(const DrawArcOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
void RasterWithFlagsImpl(const PaintFlags* flags, SkCanvas* canvas) const;
bool IsValid() const {
return flags.IsValid() && oval.isFinite() &&
std::isfinite(start_angle_degrees) &&
std::isfinite(sweep_angle_degrees);
}
bool EqualsForTesting(const DrawArcOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkRect oval;
SkScalar start_angle_degrees;
SkScalar sweep_angle_degrees;
private:
DrawArcOp() : PaintOpWithFlagsBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawOvalOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawOval;
static constexpr bool kIsDrawOp = true;
DrawOvalOp(const SkRect& oval, const PaintFlags& flags)
: PaintOpWithFlagsBaseInternal(kType, flags), oval(oval) {}
static void RasterWithFlags(const DrawOvalOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return flags.IsValid() && oval.isFinite(); }
bool EqualsForTesting(const DrawOvalOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkRect oval;
private:
DrawOvalOp() : PaintOpWithFlagsBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawPathOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawPath;
static constexpr bool kIsDrawOp = true;
DrawPathOp(const SkPath& path,
const PaintFlags& flags,
UsePaintCache use_paint_cache = UsePaintCache::kEnabled)
: PaintOpWithFlagsBaseInternal(kType, flags),
path(path),
sk_path_fill_type(path.getFillType()),
use_cache(use_paint_cache) {}
static void RasterWithFlags(const DrawPathOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return flags.IsValid() && IsValidPath(path); }
bool EqualsForTesting(const DrawPathOp& other) const;
int CountSlowPaths() const;
HAS_SERIALIZATION_FUNCTIONS();
ThreadsafePath path;
SkPathFillType sk_path_fill_type;
UsePaintCache use_cache = UsePaintCache::kDisabled;
private:
DrawPathOp() : PaintOpWithFlagsBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawRecordOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawRecord;
static constexpr bool kIsDrawOp = true;
explicit DrawRecordOp(PaintRecord record, bool local_ctm = true);
~DrawRecordOp();
static void Raster(const DrawRecordOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return true; }
bool EqualsForTesting(const DrawRecordOp& other) const;
size_t AdditionalBytesUsed() const;
size_t AdditionalOpCount() const;
bool HasDiscardableImages(gfx::ContentColorUsage* content_color_usage) const;
int CountSlowPaths() const;
bool HasNonAAPaint() const;
bool HasDrawTextOps() const;
bool HasSaveLayerOps() const;
bool HasSaveLayerAlphaOps() const;
bool HasEffectsPreventingLCDTextForSaveLayerAlpha() const;
HAS_SERIALIZATION_FUNCTIONS();
PaintRecord record;
bool local_ctm = true;
};
class CC_PAINT_EXPORT DrawRectOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawRect;
static constexpr bool kIsDrawOp = true;
DrawRectOp(const SkRect& rect, const PaintFlags& flags)
: PaintOpWithFlagsBaseInternal(kType, flags), rect(rect) {}
static void RasterWithFlags(const DrawRectOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return flags.IsValid() && rect.isFinite(); }
bool EqualsForTesting(const DrawRectOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkRect rect;
private:
DrawRectOp() : PaintOpWithFlagsBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawRRectOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawRRect;
static constexpr bool kIsDrawOp = true;
DrawRRectOp(const SkRRect& rrect, const PaintFlags& flags)
: PaintOpWithFlagsBaseInternal(kType, flags), rrect(rrect) {}
static void RasterWithFlags(const DrawRRectOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return flags.IsValid() && rrect.isValid(); }
bool EqualsForTesting(const DrawRRectOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkRRect rrect;
private:
DrawRRectOp() : PaintOpWithFlagsBaseInternal(kType) {}
};
class CC_PAINT_EXPORT DrawScrollingContentsOp final
: public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawScrollingContents;
static constexpr bool kIsDrawOp = true;
DrawScrollingContentsOp(ElementId scroll_element_id,
scoped_refptr<DisplayItemList> display_item_list);
~DrawScrollingContentsOp();
static void Raster(const DrawScrollingContentsOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return scroll_element_id && display_item_list; }
bool EqualsForTesting(const DrawScrollingContentsOp& other) const;
size_t AdditionalBytesUsed() const;
size_t AdditionalOpCount() const;
bool HasDiscardableImages(gfx::ContentColorUsage* content_color_usage) const;
int CountSlowPaths() const;
bool HasNonAAPaint() const;
bool HasDrawTextOps() const;
bool HasSaveLayerOps() const;
bool HasSaveLayerAlphaOps() const;
bool HasEffectsPreventingLCDTextForSaveLayerAlpha() const;
HAS_SERIALIZATION_FUNCTIONS();
ElementId scroll_element_id;
scoped_refptr<DisplayItemList> display_item_list;
};
class CC_PAINT_EXPORT DrawVerticesOp final
: public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawVertices;
static constexpr bool kIsDrawOp = true;
DrawVerticesOp(scoped_refptr<RefCountedBuffer<SkPoint>> vertices,
scoped_refptr<RefCountedBuffer<SkPoint>> uvs,
scoped_refptr<RefCountedBuffer<uint16_t>> indices,
const PaintFlags&);
~DrawVerticesOp();
static void RasterWithFlags(const DrawVerticesOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const {
return flags.IsValid() && vertices && uvs && indices &&
vertices->data().size() > 0 &&
vertices->data().size() == uvs->data().size() &&
indices->data().size() > 0 && (indices->data().size() % 3) == 0;
}
bool EqualsForTesting(const DrawVerticesOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
scoped_refptr<RefCountedBuffer<SkPoint>> vertices;
scoped_refptr<RefCountedBuffer<SkPoint>> uvs;
scoped_refptr<RefCountedBuffer<uint16_t>> indices;
private:
DrawVerticesOp();
};
class CC_PAINT_EXPORT DrawSkottieOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawSkottie;
static constexpr bool kIsDrawOp = true;
DrawSkottieOp(scoped_refptr<SkottieWrapper> skottie,
SkRect dst,
float t,
SkottieFrameDataMap images,
const SkottieColorMap& color_map,
SkottieTextPropertyValueMap text_map);
~DrawSkottieOp();
static void Raster(const DrawSkottieOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const {
return skottie && skottie->is_valid() && !dst.isEmpty() && t >= 0 &&
t <= 1.f;
}
bool EqualsForTesting(const DrawSkottieOp& other) const;
bool HasDiscardableImages(gfx::ContentColorUsage* content_color_usage) const;
HAS_SERIALIZATION_FUNCTIONS();
scoped_refptr<SkottieWrapper> skottie;
SkRect dst;
float t;
SkottieFrameDataMap images;
SkottieColorMap color_map;
SkottieTextPropertyValueMap text_map;
private:
SkottieWrapper::FrameDataFetchResult GetImageAssetForRaster(
SkCanvas* canvas,
const PlaybackParams& params,
SkottieResourceIdHash asset_id,
float t_frame,
sk_sp<SkImage>& image_out,
SkSamplingOptions& sampling_out) const;
DrawSkottieOp();
};
class CC_PAINT_EXPORT DrawSlugOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawSlug;
static constexpr bool kIsDrawOp = true;
DrawSlugOp(sk_sp<sktext::gpu::Slug> slug, const PaintFlags& flags);
~DrawSlugOp();
static void SerializeSlugs(
const sk_sp<sktext::gpu::Slug>& slug,
const std::vector<sk_sp<sktext::gpu::Slug>>& extra_slugs,
PaintOpWriter& writer,
const PaintFlags* flags_to_serialize,
const SkM44& current_ctm);
static void RasterWithFlags(const DrawSlugOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return flags.IsValid(); }
bool HasDrawTextOps() const { return true; }
bool EqualsForTesting(const DrawSlugOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
sk_sp<sktext::gpu::Slug> slug;
std::vector<sk_sp<sktext::gpu::Slug>> extra_slugs;
private:
DrawSlugOp();
};
class CC_PAINT_EXPORT DrawTextBlobOp final
: public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kDrawTextBlob;
static constexpr bool kIsDrawOp = true;
DrawTextBlobOp(sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y,
const PaintFlags& flags);
DrawTextBlobOp(sk_sp<SkTextBlob> blob,
SkScalar x,
SkScalar y,
NodeId node_id,
const PaintFlags& flags);
~DrawTextBlobOp();
static void RasterWithFlags(const DrawTextBlobOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return flags.IsValid(); }
bool HasDrawTextOps() const { return true; }
bool EqualsForTesting(const DrawTextBlobOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
sk_sp<SkTextBlob> blob;
mutable sk_sp<sktext::gpu::Slug> slug;
mutable std::vector<sk_sp<sktext::gpu::Slug>> extra_slugs;
SkScalar x;
SkScalar y;
NodeId node_id = kInvalidNodeId;
private:
DrawTextBlobOp();
};
class CC_PAINT_EXPORT NoopOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kNoop;
NoopOp() : PaintOpBaseInternal(kType) {}
static void Raster(const NoopOp* op,
SkCanvas* canvas,
const PlaybackParams& params) {}
bool IsValid() const { return true; }
bool EqualsForTesting(const NoopOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
};
class CC_PAINT_EXPORT RestoreOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kRestore;
RestoreOp() : PaintOpBaseInternal(kType) {}
static void Raster(const RestoreOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return true; }
bool EqualsForTesting(const RestoreOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
};
class CC_PAINT_EXPORT RotateOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kRotate;
explicit RotateOp(SkScalar degrees)
: PaintOpBaseInternal(kType), degrees(degrees) {}
static void Raster(const RotateOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return true; }
bool EqualsForTesting(const RotateOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkScalar degrees;
private:
RotateOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT SaveOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kSave;
SaveOp() : PaintOpBaseInternal(kType) {}
static void Raster(const SaveOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return true; }
bool EqualsForTesting(const SaveOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
};
class CC_PAINT_EXPORT SaveLayerOp final : public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kSaveLayer;
explicit SaveLayerOp(const PaintFlags& flags)
: PaintOpWithFlagsBaseInternal(kType, flags), bounds(kUnsetRect) {}
SaveLayerOp(const SkRect& bounds, const PaintFlags& flags)
: PaintOpWithFlagsBaseInternal(kType, flags), bounds(bounds) {}
static void RasterWithFlags(const SaveLayerOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return flags.IsValid() && IsValidOrUnsetRect(bounds); }
bool EqualsForTesting(const SaveLayerOp& other) const;
bool HasNonAAPaint() const { return false; }
bool HasEffectsPreventingLCDTextForSaveLayerAlpha() const { return true; }
bool HasSaveLayerOps() const { return true; }
HAS_SERIALIZATION_FUNCTIONS();
SkRect bounds;
private:
SaveLayerOp() : PaintOpWithFlagsBaseInternal(kType) {}
};
class CC_PAINT_EXPORT SaveLayerAlphaOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kSaveLayerAlpha;
template <class F>
requires(std::is_same_v<F, float>)
explicit SaveLayerAlphaOp(F alpha)
: PaintOpBaseInternal(kType), bounds(kUnsetRect), alpha(alpha) {}
template <class F>
requires(std::is_same_v<F, float>)
SaveLayerAlphaOp(const SkRect& bounds, F alpha)
: PaintOpBaseInternal(kType), bounds(bounds), alpha(alpha) {}
static void Raster(const SaveLayerAlphaOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return IsValidOrUnsetRect(bounds); }
bool EqualsForTesting(const SaveLayerAlphaOp& other) const;
bool HasSaveLayerOps() const { return true; }
bool HasSaveLayerAlphaOps() const { return true; }
HAS_SERIALIZATION_FUNCTIONS();
SkRect bounds;
float alpha;
private:
SaveLayerAlphaOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT SaveLayerFiltersOp final
: public PaintOpWithFlagsBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kSaveLayerFilters;
static constexpr int kMaxFiltersPerLayer = SkCanvas::kMaxFiltersPerLayer;
explicit SaveLayerFiltersOp(base::span<const sk_sp<PaintFilter>> filters,
const PaintFlags& flags);
~SaveLayerFiltersOp();
static void RasterWithFlags(const SaveLayerFiltersOp* op,
const PaintFlags* flags,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const {
return flags.IsValid() && (!flags.getImageFilter() || filters.empty()) &&
filters.size() <= kMaxFiltersPerLayer;
}
bool EqualsForTesting(const SaveLayerFiltersOp& other) const;
bool HasSaveLayerOps() const { return true; }
HAS_SERIALIZATION_FUNCTIONS();
std::vector<sk_sp<PaintFilter>> filters;
private:
SaveLayerFiltersOp();
};
class CC_PAINT_EXPORT ScaleOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kScale;
ScaleOp(SkScalar sx, SkScalar sy)
: PaintOpBaseInternal(kType), sx(sx), sy(sy) {}
static void Raster(const ScaleOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return true; }
bool EqualsForTesting(const ScaleOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkScalar sx;
SkScalar sy;
private:
ScaleOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT SetMatrixOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kSetMatrix;
explicit SetMatrixOp(const SkM44& matrix)
: PaintOpBaseInternal(kType), matrix(matrix) {}
static void Raster(const SetMatrixOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return true; }
bool EqualsForTesting(const SetMatrixOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkM44 matrix;
private:
SetMatrixOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT SetNodeIdOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kSetNodeId;
explicit SetNodeIdOp(int node_id)
: PaintOpBaseInternal(kType), node_id(node_id) {}
static void Raster(const SetNodeIdOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return true; }
bool EqualsForTesting(const SetNodeIdOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
int node_id;
private:
SetNodeIdOp() : PaintOpBaseInternal(kType) {}
};
class CC_PAINT_EXPORT TranslateOp final : public PaintOpBaseInternal {
public:
static constexpr PaintOpType kType = PaintOpType::kTranslate;
TranslateOp(SkScalar dx, SkScalar dy)
: PaintOpBaseInternal(kType), dx(dx), dy(dy) {}
static void Raster(const TranslateOp* op,
SkCanvas* canvas,
const PlaybackParams& params);
bool IsValid() const { return true; }
bool EqualsForTesting(const TranslateOp& other) const;
HAS_SERIALIZATION_FUNCTIONS();
SkScalar dx;
SkScalar dy;
private:
TranslateOp() : PaintOpBaseInternal(kType) {}
};
#undef HAS_SERIALIZATION_FUNCTIONS
using LargestPaintOp =
typename std::conditional<(sizeof(DrawImageRectOp) > sizeof(DrawDRRectOp)),
DrawImageRectOp,
DrawDRRectOp>::type;
inline constexpr size_t kLargestPaintOpAlignedSize =
PaintOpBuffer::ComputeOpAlignedSize<LargestPaintOp>();
void PrintTo(const PaintOp& rect, std::ostream* os);
CC_PAINT_EXPORT bool AreLiteOpsEnabled();
}
#endif