1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef OUTLINE_H
17#define OUTLINE_H
18
19#include <SkPath.h>
20
21#include "Rect.h"
22#include "utils/MathUtils.h"
23
24namespace android {
25namespace uirenderer {
26
27class Outline {
28public:
29    enum class Type {
30        None = 0,
31        Empty = 1,
32        ConvexPath = 2,
33        RoundRect = 3
34    };
35
36    Outline()
37            : mShouldClip(false)
38            , mType(Type::None)
39            , mRadius(0)
40            , mAlpha(0.0f) {}
41
42    void setRoundRect(int left, int top, int right, int bottom, float radius, float alpha) {
43        mAlpha = alpha;
44        if (mType == Type::RoundRect
45                && left == mBounds.left
46                && right == mBounds.right
47                && top == mBounds.top
48                && bottom == mBounds.bottom
49                && radius == mRadius) {
50            // nothing to change, don't do any work
51            return;
52        }
53
54        mType = Type::RoundRect;
55        mBounds.set(left, top, right, bottom);
56        mRadius = radius;
57
58        // update mPath to reflect new outline
59        mPath.reset();
60        if (MathUtils::isPositive(radius)) {
61            mPath.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom),
62                    radius, radius);
63        } else {
64            mPath.addRect(left, top, right, bottom);
65        }
66    }
67
68    void setConvexPath(const SkPath* outline, float alpha) {
69        if (!outline) {
70            setEmpty();
71            return;
72        }
73        mType = Type::ConvexPath;
74        mPath = *outline;
75        mBounds.set(outline->getBounds());
76        mAlpha = alpha;
77    }
78
79    void setEmpty() {
80        mType = Type::Empty;
81        mPath.reset();
82        mAlpha = 0.0f;
83    }
84
85    void setNone() {
86        mType = Type::None;
87        mPath.reset();
88        mAlpha = 0.0f;
89    }
90
91    bool isEmpty() const {
92        return mType == Type::Empty;
93    }
94
95    float getAlpha() const {
96        return mAlpha;
97    }
98
99    void setShouldClip(bool clip) {
100        mShouldClip = clip;
101    }
102
103    bool getShouldClip() const {
104        return mShouldClip;
105    }
106
107    bool willClip() const {
108        // only round rect outlines can be used for clipping
109        return mShouldClip && (mType == Type::RoundRect);
110    }
111
112    bool willRoundRectClip() const {
113        // only round rect outlines can be used for clipping
114        return willClip() && MathUtils::isPositive(mRadius);
115    }
116
117    bool getAsRoundRect(Rect* outRect, float* outRadius) const {
118        if (mType == Type::RoundRect) {
119            outRect->set(mBounds);
120            *outRadius = mRadius;
121            return true;
122        }
123        return false;
124    }
125
126    const SkPath* getPath() const {
127        if (mType == Type::None || mType == Type::Empty) return nullptr;
128
129        return &mPath;
130    }
131
132    Type getType() const {
133        return mType;
134    }
135
136    const Rect& getBounds() const {
137        return mBounds;
138    }
139
140    float getRadius() const {
141        return mRadius;
142    }
143
144private:
145    bool mShouldClip;
146    Type mType;
147    Rect mBounds;
148    float mRadius;
149    float mAlpha;
150    SkPath mPath;
151};
152
153} /* namespace uirenderer */
154} /* namespace android */
155
156#endif /* OUTLINE_H */
157