• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Google Inc.
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 GrStrokeInfo_DEFINED
9 #define GrStrokeInfo_DEFINED
10 
11 #include "SkPathEffect.h"
12 #include "SkStrokeRec.h"
13 #include "SkTemplates.h"
14 
15 class GrUniqueKey;
16 
17 /*
18  * GrStrokeInfo encapsulates all the pertinent infomation regarding the stroke. The SkStrokeRec
19  * which holds information on fill style, width, miter, cap, and join. It also holds information
20  * about the dash like intervals, count, and phase.
21  */
22 class GrStrokeInfo : public SkStrokeRec {
23 public:
FillInfo()24     static const GrStrokeInfo& FillInfo() {
25         static const GrStrokeInfo gFill(kFill_InitStyle);
26         return gFill;
27     }
28 
GrStrokeInfo(SkStrokeRec::InitStyle style)29     GrStrokeInfo(SkStrokeRec::InitStyle style)
30         : INHERITED(style)
31         , fDashType(SkPathEffect::kNone_DashType) {
32     }
33 
34     GrStrokeInfo(const GrStrokeInfo& src, bool includeDash = true)
INHERITED(src)35         : INHERITED(src) {
36         if (includeDash && src.isDashed()) {
37             fDashType = src.fDashType;
38             fDashPhase = src.fDashPhase;
39             fIntervals.reset(src.getDashCount());
40             memcpy(fIntervals.get(), src.fIntervals.get(), fIntervals.count() * sizeof(SkScalar));
41         } else {
42             fDashType = SkPathEffect::kNone_DashType;
43         }
44     }
45 
GrStrokeInfo(const SkPaint & paint,SkPaint::Style styleOverride)46     GrStrokeInfo(const SkPaint& paint, SkPaint::Style styleOverride)
47         : INHERITED(paint, styleOverride)
48         , fDashType(SkPathEffect::kNone_DashType) {
49         this->init(paint);
50     }
51 
GrStrokeInfo(const SkPaint & paint)52     explicit GrStrokeInfo(const SkPaint& paint)
53         : INHERITED(paint)
54         , fDashType(SkPathEffect::kNone_DashType) {
55         this->init(paint);
56     }
57 
58     GrStrokeInfo& operator=(const GrStrokeInfo& other) {
59         if (other.isDashed()) {
60             fDashType = other.fDashType;
61             fDashPhase = other.fDashPhase;
62             fIntervals.reset(other.getDashCount());
63             memcpy(fIntervals.get(), other.fIntervals.get(), fIntervals.count() * sizeof(SkScalar));
64         } else {
65             this->removeDash();
66         }
67         this->INHERITED::operator=(other);
68         return *this;
69     }
70 
hasEqualEffect(const GrStrokeInfo & other)71     bool hasEqualEffect(const GrStrokeInfo& other) const {
72         if (this->isDashed() != other.isDashed()) {
73             return false;
74         }
75         if (this->isDashed()) {
76             if (fDashPhase != other.fDashPhase ||
77                 fIntervals.count() != other.fIntervals.count() ||
78                 memcmp(fIntervals.get(), other.fIntervals.get(),
79                        fIntervals.count() * sizeof(SkScalar)) != 0) {
80                 return false;
81             }
82         }
83         return this->INHERITED::hasEqualEffect(other);
84     }
85 
86     /*
87      * This functions takes in a patheffect and updates the dashing information if the path effect
88      * is a Dash type. Returns true if the path effect is a dashed effect and we are stroking,
89      * otherwise it returns false.
90      */
setDashInfo(const SkPathEffect * pe)91     bool setDashInfo(const SkPathEffect* pe) {
92         if (pe && !this->isFillStyle()) {
93             SkPathEffect::DashInfo dashInfo;
94             fDashType = pe->asADash(&dashInfo);
95             if (SkPathEffect::kDash_DashType == fDashType) {
96                 fIntervals.reset(dashInfo.fCount);
97                 dashInfo.fIntervals = fIntervals.get();
98                 pe->asADash(&dashInfo);
99                 fDashPhase = dashInfo.fPhase;
100                 return true;
101             }
102         }
103         return false;
104     }
105 
106     /*
107      * Like the above, but sets with an explicit SkPathEffect::DashInfo
108      */
setDashInfo(const SkPathEffect::DashInfo & info)109     bool setDashInfo(const SkPathEffect::DashInfo& info) {
110         if (!this->isFillStyle()) {
111             fDashType = SkPathEffect::kDash_DashType;
112             fDashPhase = info.fPhase;
113             fIntervals.reset(info.fCount);
114             for (int i = 0; i < fIntervals.count(); i++) {
115                 fIntervals[i] = info.fIntervals[i];
116             }
117             return true;
118         }
119         return false;
120     }
121 
isDashed()122     bool isDashed() const {
123         return (!this->isFillStyle() && SkPathEffect::kDash_DashType == fDashType);
124     }
125 
getDashCount()126     int32_t getDashCount() const {
127         SkASSERT(this->isDashed());
128         return fIntervals.count();
129     }
130 
getDashPhase()131     SkScalar getDashPhase() const {
132         SkASSERT(this->isDashed());
133         return fDashPhase;
134     }
135 
getDashIntervals()136     const SkScalar* getDashIntervals() const {
137         SkASSERT(this->isDashed());
138         return fIntervals.get();
139     }
140 
removeDash()141     void removeDash() {
142         fDashType = SkPathEffect::kNone_DashType;
143     }
144 
145     /** Applies the dash to a path, if the stroke info has dashing.
146      * @return true if the dashing was applied (dst and dstStrokeInfo will be modified).
147      *         false if the stroke info did not have dashing. The dst and dstStrokeInfo
148      *               will be unmodified. The stroking in the SkStrokeRec might still
149      *               be applicable.
150      */
151     bool applyDashToPath(SkPath* dst, GrStrokeInfo* dstStrokeInfo, const SkPath& src) const;
152 
153     /**
154      * Computes the length of the data that will be written by asUniqueKeyFragment() function.
155      */
computeUniqueKeyFragmentData32Cnt()156     int computeUniqueKeyFragmentData32Cnt() const {
157         const int kSkScalarData32Cnt = sizeof(SkScalar) / sizeof(uint32_t);
158         // SkStrokeRec data: 32 bits for style+join+cap and 2 scalars for miter and width.
159         int strokeKeyData32Cnt = 1 + 2 * kSkScalarData32Cnt;
160 
161         if (this->isDashed()) {
162             // One scalar for dash phase and one for each dash value.
163             strokeKeyData32Cnt += (1 + this->getDashCount()) * kSkScalarData32Cnt;
164         }
165         return strokeKeyData32Cnt;
166     }
167 
168     /**
169      * Writes the object contents as uint32_t data, to be used with GrUniqueKey.
170      * Note: the data written does not encode the length, so care must be taken to ensure
171      * that the full unique key data is encoded properly. For example, GrStrokeInfo
172      * fragment can be placed last in the sequence, at fixed index.
173      */
174     void asUniqueKeyFragment(uint32_t*) const;
175 
176 private:
177     // Prevent accidental usage, should use GrStrokeInfo::hasEqualEffect.
178     bool hasEqualEffect(const SkStrokeRec& other) const;
179 
init(const SkPaint & paint)180     void init(const SkPaint& paint) {
181         const SkPathEffect* pe = paint.getPathEffect();
182         this->setDashInfo(pe);
183     }
184 
185     SkPathEffect::DashType fDashType;
186     SkScalar               fDashPhase;
187     SkAutoSTArray<2, SkScalar> fIntervals;
188     typedef SkStrokeRec INHERITED;
189 };
190 
191 #endif
192