• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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