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