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 "include/core/SkPaint.h" 12 #include "include/private/SkMacros.h" 13 14 class SkPath; 15 16 SK_BEGIN_REQUIRE_DENSE 17 class SK_API SkStrokeRec { 18 public: 19 enum InitStyle { 20 kHairline_InitStyle, 21 kFill_InitStyle 22 }; 23 SkStrokeRec(InitStyle style); 24 SkStrokeRec(const SkPaint&, SkPaint::Style, SkScalar resScale = 1); 25 explicit SkStrokeRec(const SkPaint&, SkScalar resScale = 1); 26 27 enum Style { 28 kHairline_Style, 29 kFill_Style, 30 kStroke_Style, 31 kStrokeAndFill_Style 32 }; 33 34 static constexpr int kStyleCount = kStrokeAndFill_Style + 1; 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 static SkScalar GetInflationRadius(SkPaint::Join, SkScalar miterLimit, SkPaint::Cap, 118 SkScalar strokeWidth); 119 120 /** 121 * Compare if two SkStrokeRecs have an equal effect on a path. 122 * Equal SkStrokeRecs produce equal paths. Equality of produced 123 * paths does not take the ResScale parameter into account. 124 */ hasEqualEffect(const SkStrokeRec & other)125 bool hasEqualEffect(const SkStrokeRec& other) const { 126 if (!this->needToApply()) { 127 return this->getStyle() == other.getStyle(); 128 } 129 return fWidth == other.fWidth && 130 (fJoin != SkPaint::kMiter_Join || fMiterLimit == other.fMiterLimit) && 131 fCap == other.fCap && 132 fJoin == other.fJoin && 133 fStrokeAndFill == other.fStrokeAndFill; 134 } 135 136 private: 137 void init(const SkPaint&, SkPaint::Style, SkScalar resScale); 138 139 SkScalar fResScale; 140 SkScalar fWidth; 141 SkScalar fMiterLimit; 142 // The following three members are packed together into a single u32. 143 // This is to avoid unnecessary padding and ensure binary equality for 144 // hashing (because the padded areas might contain garbage values). 145 // 146 // fCap and fJoin are larger than needed to avoid having to initialize 147 // any pad values 148 uint32_t fCap : 16; // SkPaint::Cap 149 uint32_t fJoin : 15; // SkPaint::Join 150 uint32_t fStrokeAndFill : 1; // bool 151 }; 152 SK_END_REQUIRE_DENSE 153 154 #endif 155