• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkPathEffectBase_DEFINED
9 #define SkPathEffectBase_DEFINED
10 
11 #include "include/core/SkPath.h"
12 #include "include/core/SkPathEffect.h"
13 #include "include/core/SkPoint.h"
14 #include "include/core/SkRect.h"
15 
16 class SkPath;
17 class SkStrokeRec;
18 
19 class SkPathEffectBase : public SkPathEffect {
20 public:
SkPathEffectBase()21     SkPathEffectBase() {}
22 
23     /** \class PointData
24 
25         PointData aggregates all the information needed to draw the point
26         primitives returned by an 'asPoints' call.
27     */
28     class PointData {
29     public:
PointData()30         PointData()
31             : fFlags(0)
32             , fPoints(nullptr)
33             , fNumPoints(0) {
34             fSize.set(SK_Scalar1, SK_Scalar1);
35             // 'asPoints' needs to initialize/fill-in 'fClipRect' if it sets
36             // the kUseClip flag
37         }
~PointData()38         ~PointData() {
39             delete [] fPoints;
40         }
41 
42         // TODO: consider using passed-in flags to limit the work asPoints does.
43         // For example, a kNoPath flag could indicate don't bother generating
44         // stamped solutions.
45 
46         // Currently none of these flags are supported.
47         enum PointFlags {
48             kCircles_PointFlag            = 0x01,   // draw points as circles (instead of rects)
49             kUsePath_PointFlag            = 0x02,   // draw points as stamps of the returned path
50             kUseClip_PointFlag            = 0x04,   // apply 'fClipRect' before drawing the points
51         };
52 
53         uint32_t           fFlags;      // flags that impact the drawing of the points
54         SkPoint*           fPoints;     // the center point of each generated point
55         int                fNumPoints;  // number of points in fPoints
56         SkVector           fSize;       // the size to draw the points
57         SkRect             fClipRect;   // clip required to draw the points (if kUseClip is set)
58         SkPath             fPath;       // 'stamp' to be used at each point (if kUsePath is set)
59 
60         SkPath             fFirst;      // If not empty, contains geometry for first point
61         SkPath             fLast;       // If not empty, contains geometry for last point
62     };
63 
64     /**
65      *  Does applying this path effect to 'src' yield a set of points? If so,
66      *  optionally return the points in 'results'.
67      */
68     bool asPoints(PointData* results, const SkPath& src,
69                           const SkStrokeRec&, const SkMatrix&,
70                           const SkRect* cullR) const;
71 
72     /**
73      *  If the PathEffect can be represented as a dash pattern, asADash will return kDash_DashType
74      *  and None otherwise. If a non NULL info is passed in, the various DashInfo will be filled
75      *  in if the PathEffect can be a dash pattern. If passed in info has an fCount equal or
76      *  greater to that of the effect, it will memcpy the values of the dash intervals into the
77      *  info. Thus the general approach will be call asADash once with default info to get DashType
78      *  and fCount. If effect can be represented as a dash pattern, allocate space for the intervals
79      *  in info, then call asADash again with the same info and the intervals will get copied in.
80      */
81 
getFlattenableType()82     SkFlattenable::Type getFlattenableType() const override {
83         return kSkPathEffect_Type;
84     }
85 
86     static sk_sp<SkPathEffect> Deserialize(const void* data, size_t size,
87                                           const SkDeserialProcs* procs = nullptr) {
88         return sk_sp<SkPathEffect>(static_cast<SkPathEffect*>(
89                                   SkFlattenable::Deserialize(
90                                   kSkPathEffect_Type, data, size, procs).release()));
91     }
92 
93     /**
94      * Filter the input path.
95      *
96      * The CTM parameter is provided for path effects that can use the information.
97      * The output of path effects must always be in the original (input) coordinate system,
98      * regardless of whether the path effect uses the CTM or not.
99      */
100     virtual bool onFilterPath(SkPath*, const SkPath&, SkStrokeRec*, const SkRect*,
101                               const SkMatrix& /* ctm */) const = 0;
102 
103     /** Path effects *requiring* a valid CTM should override to return true. */
onNeedsCTM()104     virtual bool onNeedsCTM() const { return false; }
105 
onAsPoints(PointData *,const SkPath &,const SkStrokeRec &,const SkMatrix &,const SkRect *)106     virtual bool onAsPoints(PointData*, const SkPath&, const SkStrokeRec&, const SkMatrix&,
107                             const SkRect*) const {
108         return false;
109     }
onAsADash(DashInfo *)110     virtual DashType onAsADash(DashInfo*) const {
111         return kNone_DashType;
112     }
113 
114 
115     // Compute a conservative bounds for its effect, given the bounds of the path. 'bounds' is
116     // both the input and output; if false is returned, fast bounds could not be calculated and
117     // 'bounds' is undefined.
118     //
119     // If 'bounds' is null, performs a dry-run determining if bounds could be computed.
120     virtual bool computeFastBounds(SkRect* bounds) const = 0;
121 
122     static void RegisterFlattenables();
123 
124 private:
125     using INHERITED = SkPathEffect;
126 };
127 
128 ////////////////////////////////////////////////////////////////////////////////////////////////
129 
as_PEB(SkPathEffect * effect)130 static inline SkPathEffectBase* as_PEB(SkPathEffect* effect) {
131     return static_cast<SkPathEffectBase*>(effect);
132 }
133 
as_PEB(const SkPathEffect * effect)134 static inline const SkPathEffectBase* as_PEB(const SkPathEffect* effect) {
135     return static_cast<const SkPathEffectBase*>(effect);
136 }
137 
as_PEB(const sk_sp<SkPathEffect> & effect)138 static inline const SkPathEffectBase* as_PEB(const sk_sp<SkPathEffect>& effect) {
139     return static_cast<SkPathEffectBase*>(effect.get());
140 }
141 
as_PEB_sp(sk_sp<SkPathEffect> effect)142 static inline sk_sp<SkPathEffectBase> as_PEB_sp(sk_sp<SkPathEffect> effect) {
143     return sk_sp<SkPathEffectBase>(static_cast<SkPathEffectBase*>(effect.release()));
144 }
145 
146 #endif
147