// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CC_PAINT_PAINT_SHADER_H_ #define CC_PAINT_PAINT_SHADER_H_ #include #include #include "base/optional.h" #include "base/stl_util.h" #include "cc/paint/image_analysis_state.h" #include "cc/paint/paint_export.h" #include "cc/paint/paint_image.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkScalar.h" #include "third_party/skia/include/core/SkShader.h" #include "ui/gfx/geometry/size_f.h" namespace cc { class ImageProvider; class PaintOpBuffer; using PaintRecord = PaintOpBuffer; class CC_PAINT_EXPORT PaintShader : public SkRefCnt { public: enum class Type : uint8_t { kColor, kLinearGradient, kRadialGradient, kTwoPointConicalGradient, kSweepGradient, kImage, kPaintRecord, kShaderCount }; // Scaling behavior dictates how a PaintRecord shader will behave. Use // RasterAtScale to create a picture shader. Use FixedScale to create an image // shader that is backed by the paint record. enum class ScalingBehavior : uint8_t { kRasterAtScale, kFixedScale }; static sk_sp MakeColor(SkColor color); static sk_sp MakeLinearGradient( const SkPoint* points, const SkColor* colors, const SkScalar* pos, int count, SkShader::TileMode mode, uint32_t flags = 0, const SkMatrix* local_matrix = nullptr, SkColor fallback_color = SK_ColorTRANSPARENT); static sk_sp MakeRadialGradient( const SkPoint& center, SkScalar radius, const SkColor colors[], const SkScalar pos[], int color_count, SkShader::TileMode mode, uint32_t flags = 0, const SkMatrix* local_matrix = nullptr, SkColor fallback_color = SK_ColorTRANSPARENT); static sk_sp MakeTwoPointConicalGradient( const SkPoint& start, SkScalar start_radius, const SkPoint& end, SkScalar end_radius, const SkColor colors[], const SkScalar pos[], int color_count, SkShader::TileMode mode, uint32_t flags = 0, const SkMatrix* local_matrix = nullptr, SkColor fallback_color = SK_ColorTRANSPARENT); static sk_sp MakeSweepGradient( SkScalar cx, SkScalar cy, const SkColor colors[], const SkScalar pos[], int color_count, SkShader::TileMode mode, SkScalar start_degrees, SkScalar end_degrees, uint32_t flags = 0, const SkMatrix* local_matrix = nullptr, SkColor fallback_color = SK_ColorTRANSPARENT); static sk_sp MakeImage(const PaintImage& image, SkShader::TileMode tx, SkShader::TileMode ty, const SkMatrix* local_matrix); static sk_sp MakePaintRecord( sk_sp record, const SkRect& tile, SkShader::TileMode tx, SkShader::TileMode ty, const SkMatrix* local_matrix, ScalingBehavior scaling_behavior = ScalingBehavior::kRasterAtScale); static size_t GetSerializedSize(const PaintShader* shader); ~PaintShader() override; void set_has_animated_images(bool has_animated_images) { image_analysis_state_ = has_animated_images ? ImageAnalysisState::kAnimatedImages : ImageAnalysisState::kNoAnimatedImages; } ImageAnalysisState image_analysis_state() const { return image_analysis_state_; } bool has_discardable_images() const; SkMatrix GetLocalMatrix() const { return local_matrix_ ? *local_matrix_ : SkMatrix::I(); } Type shader_type() const { return shader_type_; } const PaintImage& paint_image() const { DCHECK_EQ(Type::kImage, shader_type_); return image_; } const gfx::SizeF* tile_scale() const { return base::OptionalOrNullptr(tile_scale_); } const sk_sp& paint_record() const { return record_; } bool GetRasterizationTileRect(const SkMatrix& ctm, SkRect* tile_rect) const; SkShader::TileMode tx() const { return tx_; } SkShader::TileMode ty() const { return ty_; } SkRect tile() const { return tile_; } bool IsOpaque() const; // Returns true if the shader looks like it is valid (ie the members required // for this shader type all look reasonable. Returns false otherwise. Note // that this is a best effort function since truly validating whether the // shader is correct is hard. bool IsValid() const; bool operator==(const PaintShader& other) const; bool operator!=(const PaintShader& other) const { return !(*this == other); } private: friend class PaintFlags; friend class PaintOpReader; friend class PaintOpSerializationTestUtils; friend class PaintOpWriter; friend class ScopedRasterFlags; FRIEND_TEST_ALL_PREFIXES(PaintShaderTest, DecodePaintRecord); FRIEND_TEST_ALL_PREFIXES(PaintOpBufferTest, PaintRecordShaderSerialization); explicit PaintShader(Type type); sk_sp GetSkShader() const; void CreateSkShader(ImageProvider* image_provider = nullptr); sk_sp CreateDecodedPaintRecord( const SkMatrix& ctm, ImageProvider* image_provider) const; void SetColorsAndPositions(const SkColor* colors, const SkScalar* positions, int count); void SetMatrixAndTiling(const SkMatrix* matrix, SkShader::TileMode tx, SkShader::TileMode ty); void SetFlagsAndFallback(uint32_t flags, SkColor fallback_color); Type shader_type_ = Type::kShaderCount; uint32_t flags_ = 0; SkScalar end_radius_ = 0; SkScalar start_radius_ = 0; SkShader::TileMode tx_ = SkShader::kClamp_TileMode; SkShader::TileMode ty_ = SkShader::kClamp_TileMode; SkColor fallback_color_ = SK_ColorTRANSPARENT; ScalingBehavior scaling_behavior_ = ScalingBehavior::kRasterAtScale; base::Optional local_matrix_; SkPoint center_ = SkPoint::Make(0, 0); SkRect tile_ = SkRect::MakeEmpty(); SkPoint start_point_ = SkPoint::Make(0, 0); SkPoint end_point_ = SkPoint::Make(0, 0); SkScalar start_degrees_ = 0; SkScalar end_degrees_ = 0; PaintImage image_; sk_sp record_; // For decoded PaintRecord shaders, specifies the scale at which the record // will be rasterized. base::Optional tile_scale_; std::vector colors_; std::vector positions_; // The |cached_shader_| can be derived/creates from other inputs present in // the PaintShader but we always construct it at creation time to ensure that // accesses to it are thread-safe. sk_sp cached_shader_; ImageAnalysisState image_analysis_state_ = ImageAnalysisState::kNoAnalysis; DISALLOW_COPY_AND_ASSIGN(PaintShader); }; } // namespace cc #endif // CC_PAINT_PAINT_SHADER_H_