1 /* 2 * Copyright 2012 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 SkStrokeRec_DEFINED 9 #define SkStrokeRec_DEFINED 10 11 #include "SkPaint.h" 12 13 class SkPath; 14 15 SK_BEGIN_REQUIRE_DENSE 16 class SkStrokeRec { 17 public: 18 enum InitStyle { 19 kHairline_InitStyle, 20 kFill_InitStyle 21 }; 22 SkStrokeRec(InitStyle style); 23 SkStrokeRec(const SkPaint&, SkPaint::Style, SkScalar resScale = 1); 24 explicit SkStrokeRec(const SkPaint&, SkScalar resScale = 1); 25 26 enum Style { 27 kHairline_Style, 28 kFill_Style, 29 kStroke_Style, 30 kStrokeAndFill_Style 31 }; 32 enum { 33 kStyleCount = kStrokeAndFill_Style + 1 34 }; 35 36 Style getStyle() const; getWidth()37 SkScalar getWidth() const { return fWidth; } getMiter()38 SkScalar getMiter() const { return fMiterLimit; } getCap()39 SkPaint::Cap getCap() const { return (SkPaint::Cap)fCap; } getJoin()40 SkPaint::Join getJoin() const { return (SkPaint::Join)fJoin; } 41 isHairlineStyle()42 bool isHairlineStyle() const { 43 return kHairline_Style == this->getStyle(); 44 } 45 isFillStyle()46 bool isFillStyle() const { 47 return kFill_Style == this->getStyle(); 48 } 49 50 void setFillStyle(); 51 void setHairlineStyle(); 52 /** 53 * Specify the strokewidth, and optionally if you want stroke + fill. 54 * Note, if width==0, then this request is taken to mean: 55 * strokeAndFill==true -> new style will be Fill 56 * strokeAndFill==false -> new style will be Hairline 57 */ 58 void setStrokeStyle(SkScalar width, bool strokeAndFill = false); 59 setStrokeParams(SkPaint::Cap cap,SkPaint::Join join,SkScalar miterLimit)60 void setStrokeParams(SkPaint::Cap cap, SkPaint::Join join, SkScalar miterLimit) { 61 fCap = cap; 62 fJoin = join; 63 fMiterLimit = miterLimit; 64 } 65 getResScale()66 SkScalar getResScale() const { 67 return fResScale; 68 } 69 setResScale(SkScalar rs)70 void setResScale(SkScalar rs) { 71 SkASSERT(rs > 0 && SkScalarIsFinite(rs)); 72 fResScale = rs; 73 } 74 75 /** 76 * Returns true if this specifes any thick stroking, i.e. applyToPath() 77 * will return true. 78 */ needToApply()79 bool needToApply() const { 80 Style style = this->getStyle(); 81 return (kStroke_Style == style) || (kStrokeAndFill_Style == style); 82 } 83 84 /** 85 * Apply these stroke parameters to the src path, returning the result 86 * in dst. 87 * 88 * If there was no change (i.e. style == hairline or fill) this returns 89 * false and dst is unchanged. Otherwise returns true and the result is 90 * stored in dst. 91 * 92 * src and dst may be the same path. 93 */ 94 bool applyToPath(SkPath* dst, const SkPath& src) const; 95 96 /** 97 * Apply these stroke parameters to a paint. 98 */ 99 void applyToPaint(SkPaint* paint) const; 100 101 /** 102 * Compare if two SkStrokeRecs have an equal effect on a path. 103 * Equal SkStrokeRecs produce equal paths. Equality of produced 104 * paths does not take the ResScale parameter into account. 105 */ hasEqualEffect(const SkStrokeRec & other)106 bool hasEqualEffect(const SkStrokeRec& other) const { 107 if (!this->needToApply()) { 108 return this->getStyle() == other.getStyle(); 109 } 110 return fWidth == other.fWidth && 111 fMiterLimit == other.fMiterLimit && 112 fCap == other.fCap && 113 fJoin == other.fJoin && 114 fStrokeAndFill == other.fStrokeAndFill; 115 } 116 117 private: 118 void init(const SkPaint&, SkPaint::Style, SkScalar resScale); 119 120 SkScalar fResScale; 121 SkScalar fWidth; 122 SkScalar fMiterLimit; 123 // The following three members are packed together into a single u32. 124 // This is to avoid unnecessary padding and ensure binary equality for 125 // hashing (because the padded areas might contain garbage values). 126 // 127 // fCap and fJoin are larger than needed to avoid having to initialize 128 // any pad values 129 uint32_t fCap : 16; // SkPaint::Cap 130 uint32_t fJoin : 15; // SkPaint::Join 131 uint32_t fStrokeAndFill : 1; // bool 132 }; 133 SK_END_REQUIRE_DENSE 134 135 #endif 136