1b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik/*
2b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik * Copyright (C) 2014 The Android Open Source Project
3b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik *
4b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik * Licensed under the Apache License, Version 2.0 (the "License");
5b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik * you may not use this file except in compliance with the License.
6b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik * You may obtain a copy of the License at
7b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik *
8b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik *      http://www.apache.org/licenses/LICENSE-2.0
9b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik *
10b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik * Unless required by applicable law or agreed to in writing, software
11b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik * distributed under the License is distributed on an "AS IS" BASIS,
12b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik * See the License for the specific language governing permissions and
14b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik * limitations under the License.
15b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik */
16b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#ifndef OUTLINE_H
17b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#define OUTLINE_H
18b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
19b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#include <SkPath.h>
20b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
21b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#include "Rect.h"
22b60d3e7856f74c72898b2cba553db0d2e2d1365dChris Craik#include "utils/MathUtils.h"
23b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
24b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craiknamespace android {
25b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craiknamespace uirenderer {
26b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
27b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craikclass Outline {
28b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craikpublic:
29e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    enum class Type {
30e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        None = 0,
31e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        Empty = 1,
32e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        ConvexPath = 2,
33e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        RoundRect = 3
34e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    };
35e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck
36b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    Outline()
37b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            : mShouldClip(false)
38b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik            , mType(Type::None)
3977b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik            , mRadius(0)
4077b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik            , mAlpha(0.0f) {}
41b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
4277b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik    void setRoundRect(int left, int top, int right, int bottom, float radius, float alpha) {
4340de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik        mAlpha = alpha;
44b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        if (mType == Type::RoundRect
4540de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik                && left == mBounds.left
4640de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik                && right == mBounds.right
4740de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik                && top == mBounds.top
4840de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik                && bottom == mBounds.bottom
4940de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik                && radius == mRadius) {
5040de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik            // nothing to change, don't do any work
5140de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik            return;
5240de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik        }
5340de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik
54b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        mType = Type::RoundRect;
55b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        mBounds.set(left, top, right, bottom);
56b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        mRadius = radius;
5740de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik
5840de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik        // update mPath to reflect new outline
59b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        mPath.reset();
6040de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik        if (MathUtils::isPositive(radius)) {
6140de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik            mPath.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom),
6240de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik                    radius, radius);
6340de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik        } else {
6440de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik            mPath.addRect(left, top, right, bottom);
6540de9f28f48f80674ae64b7f165b56281e8b9038Chris Craik        }
66b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
67b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
6877b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik    void setConvexPath(const SkPath* outline, float alpha) {
69b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        if (!outline) {
70b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            setEmpty();
71b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik            return;
72b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        }
73b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        mType = Type::ConvexPath;
74b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        mPath = *outline;
75b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        mBounds.set(outline->getBounds());
7677b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik        mAlpha = alpha;
77b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
78b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
790645128b80621edee70f8cab4afb208fe0c26becChris Craik    void setEmpty() {
80b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        mType = Type::Empty;
810645128b80621edee70f8cab4afb208fe0c26becChris Craik        mPath.reset();
8277b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik        mAlpha = 0.0f;
8361317325b7b4b4ffafd9400ab5966e8d7c67df2eChris Craik    }
8461317325b7b4b4ffafd9400ab5966e8d7c67df2eChris Craik
850645128b80621edee70f8cab4afb208fe0c26becChris Craik    void setNone() {
86b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        mType = Type::None;
87b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        mPath.reset();
8877b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik        mAlpha = 0.0f;
89b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
90b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
910645128b80621edee70f8cab4afb208fe0c26becChris Craik    bool isEmpty() const {
92b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        return mType == Type::Empty;
930645128b80621edee70f8cab4afb208fe0c26becChris Craik    }
940645128b80621edee70f8cab4afb208fe0c26becChris Craik
9577b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik    float getAlpha() const {
9677b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik        return mAlpha;
9777b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik    }
9877b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik
99b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    void setShouldClip(bool clip) {
100b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        mShouldClip = clip;
101b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
102b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
103deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    bool getShouldClip() const {
104deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        return mShouldClip;
105deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    }
106deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
107b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    bool willClip() const {
108b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        // only round rect outlines can be used for clipping
109b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        return mShouldClip && (mType == Type::RoundRect);
110b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
111b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
112b60d3e7856f74c72898b2cba553db0d2e2d1365dChris Craik    bool willRoundRectClip() const {
113b60d3e7856f74c72898b2cba553db0d2e2d1365dChris Craik        // only round rect outlines can be used for clipping
114b60d3e7856f74c72898b2cba553db0d2e2d1365dChris Craik        return willClip() && MathUtils::isPositive(mRadius);
115b60d3e7856f74c72898b2cba553db0d2e2d1365dChris Craik    }
116b60d3e7856f74c72898b2cba553db0d2e2d1365dChris Craik
117deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    bool getAsRoundRect(Rect* outRect, float* outRadius) const {
118b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        if (mType == Type::RoundRect) {
119deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik            outRect->set(mBounds);
120deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik            *outRadius = mRadius;
121deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik            return true;
122deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        }
123deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik        return false;
124deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik    }
125deeda3d337aed1eee218b89a7aba5992ced371f0Chris Craik
126d0a0b2a3140bfb1819a116413ce9d81886697a07John Reck    const SkPath* getPath() const {
127b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik        if (mType == Type::None || mType == Type::Empty) return nullptr;
128b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
129b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik        return &mPath;
130b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    }
131b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
132e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    Type getType() const {
133e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        return mType;
134e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    }
135b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
136e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    const Rect& getBounds() const {
137e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        return mBounds;
138e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    }
139e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck
140e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    float getRadius() const {
141e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck        return mRadius;
142e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck    }
143e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reck
144e248bd1b2c3fcf8088429507e73b31f45ee2544bJohn Reckprivate:
145b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    bool mShouldClip;
146b9ce116dac378b4cf4490f265dcbd5704a1dd43cChris Craik    Type mType;
147b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    Rect mBounds;
148b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    float mRadius;
14977b5cad3efedd20f2b7cc14d87ccce1b0261960aChris Craik    float mAlpha;
150b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik    SkPath mPath;
151b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik};
152b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
153b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik} /* namespace uirenderer */
154b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik} /* namespace android */
155b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik
156b49f446c98096c4790a11d9b5bc83a4e585278c9Chris Craik#endif /* OUTLINE_H */
157