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