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 * Gives a conservative value for the outset that should applied to a 103 * geometries bounds to account for any inflation due to applying this 104 * strokeRec to the geometry. 105 */ 106 SkScalar getInflationRadius() const; 107 108 /** 109 * Equivalent to: 110 * SkStrokeRec rec(paint, style); 111 * rec.getInflationRadius(); 112 * This does not account for other effects on the paint (i.e. path 113 * effect). 114 */ 115 static SkScalar GetInflationRadius(const SkPaint&, SkPaint::Style); 116 117 /** 118 * Compare if two SkStrokeRecs have an equal effect on a path. 119 * Equal SkStrokeRecs produce equal paths. Equality of produced 120 * paths does not take the ResScale parameter into account. 121 */ hasEqualEffect(const SkStrokeRec & other)122 bool hasEqualEffect(const SkStrokeRec& other) const { 123 if (!this->needToApply()) { 124 return this->getStyle() == other.getStyle(); 125 } 126 return fWidth == other.fWidth && 127 fMiterLimit == other.fMiterLimit && 128 fCap == other.fCap && 129 fJoin == other.fJoin && 130 fStrokeAndFill == other.fStrokeAndFill; 131 } 132 133 private: 134 void init(const SkPaint&, SkPaint::Style, SkScalar resScale); 135 136 SkScalar fResScale; 137 SkScalar fWidth; 138 SkScalar fMiterLimit; 139 // The following three members are packed together into a single u32. 140 // This is to avoid unnecessary padding and ensure binary equality for 141 // hashing (because the padded areas might contain garbage values). 142 // 143 // fCap and fJoin are larger than needed to avoid having to initialize 144 // any pad values 145 uint32_t fCap : 16; // SkPaint::Cap 146 uint32_t fJoin : 15; // SkPaint::Join 147 uint32_t fStrokeAndFill : 1; // bool 148 }; 149 SK_END_REQUIRE_DENSE 150 151 #endif 152