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_FLAGS_H_
6 #define CC_PAINT_PAINT_FLAGS_H_
7 
8 #include "base/compiler_specific.h"
9 #include "cc/paint/paint_export.h"
10 #include "cc/paint/paint_shader.h"
11 #include "third_party/skia/include/core/SkCanvas.h"
12 #include "third_party/skia/include/core/SkColorFilter.h"
13 #include "third_party/skia/include/core/SkDrawLooper.h"
14 #include "third_party/skia/include/core/SkImageFilter.h"
15 #include "third_party/skia/include/core/SkMaskFilter.h"
16 #include "third_party/skia/include/core/SkPaint.h"
17 #include "third_party/skia/include/core/SkPathEffect.h"
18 #include "third_party/skia/include/core/SkShader.h"
19 
20 namespace cc {
21 class PaintFilter;
22 
23 class CC_PAINT_EXPORT PaintFlags {
24  public:
25   PaintFlags();
26   PaintFlags(const PaintFlags& flags);
27   PaintFlags(PaintFlags&& other);
28   ~PaintFlags();
29 
30   PaintFlags& operator=(const PaintFlags& other);
31   PaintFlags& operator=(PaintFlags&& other);
32 
33   enum Style {
34     kFill_Style = SkPaint::kFill_Style,
35     kStroke_Style = SkPaint::kStroke_Style,
36   };
37   bool nothingToDraw() const;
getStyle()38   ALWAYS_INLINE Style getStyle() const {
39     return static_cast<Style>(bitfields_.style_);
40   }
setStyle(Style style)41   ALWAYS_INLINE void setStyle(Style style) { bitfields_.style_ = style; }
getColor()42   ALWAYS_INLINE SkColor getColor() const { return color_; }
setColor(SkColor color)43   ALWAYS_INLINE void setColor(SkColor color) { color_ = color; }
getAlpha()44   ALWAYS_INLINE uint8_t getAlpha() const { return SkColorGetA(color_); }
setAlpha(uint8_t a)45   ALWAYS_INLINE void setAlpha(uint8_t a) {
46     color_ = SkColorSetARGB(a, SkColorGetR(color_), SkColorGetG(color_),
47                             SkColorGetB(color_));
48   }
setBlendMode(SkBlendMode mode)49   ALWAYS_INLINE void setBlendMode(SkBlendMode mode) {
50     blend_mode_ = static_cast<uint32_t>(mode);
51   }
getBlendMode()52   ALWAYS_INLINE SkBlendMode getBlendMode() const {
53     return static_cast<SkBlendMode>(blend_mode_);
54   }
isAntiAlias()55   ALWAYS_INLINE bool isAntiAlias() const { return bitfields_.antialias_; }
setAntiAlias(bool aa)56   ALWAYS_INLINE void setAntiAlias(bool aa) { bitfields_.antialias_ = aa; }
isDither()57   ALWAYS_INLINE bool isDither() const { return bitfields_.dither_; }
setDither(bool dither)58   ALWAYS_INLINE void setDither(bool dither) { bitfields_.dither_ = dither; }
setFilterQuality(SkFilterQuality quality)59   ALWAYS_INLINE void setFilterQuality(SkFilterQuality quality) {
60     bitfields_.filter_quality_ = quality;
61   }
getFilterQuality()62   ALWAYS_INLINE SkFilterQuality getFilterQuality() const {
63     return static_cast<SkFilterQuality>(bitfields_.filter_quality_);
64   }
useDarkModeForImage()65   ALWAYS_INLINE bool useDarkModeForImage() const {
66     return bitfields_.use_dark_mode_for_image_;
67   }
setUseDarkModeForImage(bool use_dark_mode_for_image)68   ALWAYS_INLINE void setUseDarkModeForImage(bool use_dark_mode_for_image) {
69     bitfields_.use_dark_mode_for_image_ = use_dark_mode_for_image;
70   }
getStrokeWidth()71   ALWAYS_INLINE SkScalar getStrokeWidth() const { return width_; }
setStrokeWidth(SkScalar width)72   ALWAYS_INLINE void setStrokeWidth(SkScalar width) { width_ = width; }
getStrokeMiter()73   ALWAYS_INLINE SkScalar getStrokeMiter() const { return miter_limit_; }
setStrokeMiter(SkScalar miter)74   ALWAYS_INLINE void setStrokeMiter(SkScalar miter) { miter_limit_ = miter; }
75   enum Cap {
76     kButt_Cap = SkPaint::kButt_Cap,    //!< begin/end contours with no extension
77     kRound_Cap = SkPaint::kRound_Cap,  //!< begin/end contours with a
78                                        //! semi-circle extension
79     kSquare_Cap = SkPaint::kSquare_Cap,  //!< begin/end contours with a half
80                                          //! square extension
81     kLast_Cap = kSquare_Cap,
82     kDefault_Cap = kButt_Cap
83   };
getStrokeCap()84   ALWAYS_INLINE Cap getStrokeCap() const {
85     return static_cast<Cap>(bitfields_.cap_type_);
86   }
setStrokeCap(Cap cap)87   ALWAYS_INLINE void setStrokeCap(Cap cap) { bitfields_.cap_type_ = cap; }
88   enum Join {
89     kMiter_Join = SkPaint::kMiter_Join,
90     kRound_Join = SkPaint::kRound_Join,
91     kBevel_Join = SkPaint::kBevel_Join,
92     kLast_Join = kBevel_Join,
93     kDefault_Join = kMiter_Join
94   };
getStrokeJoin()95   ALWAYS_INLINE Join getStrokeJoin() const {
96     return static_cast<Join>(bitfields_.join_type_);
97   }
setStrokeJoin(Join join)98   ALWAYS_INLINE void setStrokeJoin(Join join) { bitfields_.join_type_ = join; }
99 
getColorFilter()100   ALWAYS_INLINE const sk_sp<SkColorFilter>& getColorFilter() const {
101     return color_filter_;
102   }
setColorFilter(sk_sp<SkColorFilter> filter)103   ALWAYS_INLINE void setColorFilter(sk_sp<SkColorFilter> filter) {
104     color_filter_ = std::move(filter);
105   }
getMaskFilter()106   ALWAYS_INLINE const sk_sp<SkMaskFilter>& getMaskFilter() const {
107     return mask_filter_;
108   }
setMaskFilter(sk_sp<SkMaskFilter> mask)109   ALWAYS_INLINE void setMaskFilter(sk_sp<SkMaskFilter> mask) {
110     mask_filter_ = std::move(mask);
111   }
112 
getShader()113   ALWAYS_INLINE const PaintShader* getShader() const { return shader_.get(); }
114 
115   // Returns true if the shader has been set on the flags.
HasShader()116   ALWAYS_INLINE bool HasShader() const { return !!shader_; }
117 
118   // Returns whether the shader is opaque. Note that it is only valid to call
119   // this function if HasShader() returns true.
ShaderIsOpaque()120   ALWAYS_INLINE bool ShaderIsOpaque() const { return shader_->IsOpaque(); }
121 
setShader(sk_sp<PaintShader> shader)122   ALWAYS_INLINE void setShader(sk_sp<PaintShader> shader) {
123     shader_ = std::move(shader);
124   }
125 
getPathEffect()126   ALWAYS_INLINE const sk_sp<SkPathEffect>& getPathEffect() const {
127     return path_effect_;
128   }
setPathEffect(sk_sp<SkPathEffect> effect)129   ALWAYS_INLINE void setPathEffect(sk_sp<SkPathEffect> effect) {
130     path_effect_ = std::move(effect);
131   }
132   bool getFillPath(const SkPath& src,
133                    SkPath* dst,
134                    const SkRect* cull_rect = nullptr,
135                    SkScalar res_scale = 1) const;
136 
getImageFilter()137   ALWAYS_INLINE const sk_sp<PaintFilter>& getImageFilter() const {
138     return image_filter_;
139   }
140   void setImageFilter(sk_sp<PaintFilter> filter);
141 
getLooper()142   ALWAYS_INLINE const sk_sp<SkDrawLooper>& getLooper() const {
143     return draw_looper_;
144   }
setLooper(sk_sp<SkDrawLooper> looper)145   ALWAYS_INLINE void setLooper(sk_sp<SkDrawLooper> looper) {
146     draw_looper_ = std::move(looper);
147   }
148 
149   // Returns true if this just represents an opacity blend when used as
150   // saveLayer flags, thus the saveLayer can be converted to a saveLayerAlpha.
151   bool IsSimpleOpacity() const;
152 
153   // Returns true if this (of a drawOp) allows the sequence
154   // saveLayerAlpha/drawOp/restore to be folded into a single drawOp by baking
155   // the alpha in the saveLayerAlpha into the flags of the drawOp.
156   bool SupportsFoldingAlpha() const;
157 
158   // SkPaint does not support loopers, so callers of SkToPaint need
159   // to check for loopers manually (see getLooper()).
160   SkPaint ToSkPaint() const;
161 
162   template <typename Proc>
DrawToSk(SkCanvas * canvas,Proc proc)163   void DrawToSk(SkCanvas* canvas, Proc proc) const {
164     SkPaint paint = ToSkPaint();
165     if (const sk_sp<SkDrawLooper>& looper = getLooper())
166       looper->apply(canvas, paint, proc);
167     else
168       proc(canvas, paint);
169   }
170 
171   bool IsValid() const;
172   bool operator==(const PaintFlags& other) const;
173   bool operator!=(const PaintFlags& other) const { return !(*this == other); }
174 
175   bool HasDiscardableImages() const;
176 
177   size_t GetSerializedSize() const;
178 
179  private:
180   friend class PaintOpReader;
181   friend class PaintOpWriter;
182 
183   sk_sp<SkPathEffect> path_effect_;
184   sk_sp<PaintShader> shader_;
185   sk_sp<SkMaskFilter> mask_filter_;
186   sk_sp<SkColorFilter> color_filter_;
187   sk_sp<SkDrawLooper> draw_looper_;
188   sk_sp<PaintFilter> image_filter_;
189 
190   // Match(ish) SkPaint defaults.  SkPaintDefaults is not public, so this
191   // just uses these values and ignores any SkUserConfig overrides.
192   SkColor color_ = SK_ColorBLACK;
193   float width_ = 0.f;
194   float miter_limit_ = 4.f;
195   uint32_t blend_mode_ = static_cast<uint32_t>(SkBlendMode::kSrcOver);
196 
197   struct PaintFlagsBitfields {
198     uint32_t antialias_ : 1;
199     uint32_t dither_ : 1;
200     uint32_t cap_type_ : 2;
201     uint32_t join_type_ : 2;
202     uint32_t style_ : 2;
203     uint32_t filter_quality_ : 2;
204     // Specifies whether the compositor should use a dark mode filter when
205     // rasterizing image on the draw op with this PaintFlags.
206     uint32_t use_dark_mode_for_image_ : 1;
207   };
208 
209   union {
210     PaintFlagsBitfields bitfields_;
211     uint32_t bitfields_uint_;
212   };
213 };
214 
215 }  // namespace cc
216 
217 #endif  // CC_PAINT_PAINT_FLAGS_H_
218