| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 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" | 
| Chris Craik | b60d3e7 | 2015-06-25 17:15:16 -0700 | [diff] [blame] | 22 | #include "utils/MathUtils.h" | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 23 |  | 
|  | 24 | namespace android { | 
|  | 25 | namespace uirenderer { | 
|  | 26 |  | 
|  | 27 | class Outline { | 
|  | 28 | public: | 
| Leon Scroggins III | a49beaa | 2020-01-30 15:34:13 -0500 | [diff] [blame] | 29 | enum class Type { None = 0, Empty = 1, Path = 2, RoundRect = 3 }; | 
| John Reck | e248bd1 | 2015-08-05 13:53:53 -0700 | [diff] [blame] | 30 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 31 | Outline() : mShouldClip(false), mType(Type::None), mRadius(0), mAlpha(0.0f) {} | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 32 |  | 
| Chris Craik | 77b5cad | 2014-07-30 18:23:07 -0700 | [diff] [blame] | 33 | void setRoundRect(int left, int top, int right, int bottom, float radius, float alpha) { | 
| Chris Craik | 40de9f2 | 2015-07-29 12:51:41 -0700 | [diff] [blame] | 34 | mAlpha = alpha; | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 35 | if (mType == Type::RoundRect && left == mBounds.left && right == mBounds.right && | 
|  | 36 | top == mBounds.top && bottom == mBounds.bottom && radius == mRadius) { | 
| Chris Craik | 40de9f2 | 2015-07-29 12:51:41 -0700 | [diff] [blame] | 37 | // nothing to change, don't do any work | 
|  | 38 | return; | 
|  | 39 | } | 
|  | 40 |  | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 41 | mType = Type::RoundRect; | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 42 | mBounds.set(left, top, right, bottom); | 
|  | 43 | mRadius = radius; | 
| Chris Craik | 40de9f2 | 2015-07-29 12:51:41 -0700 | [diff] [blame] | 44 |  | 
| Stan Iliev | f563833 | 2017-12-08 11:32:12 -0500 | [diff] [blame] | 45 | // Reuse memory if previous outline was the same shape (rect or round rect). | 
| John Reck | e170fb6 | 2018-05-07 08:12:07 -0700 | [diff] [blame] | 46 | if (mPath.countVerbs() > 10) { | 
| Stan Iliev | f563833 | 2017-12-08 11:32:12 -0500 | [diff] [blame] | 47 | mPath.reset(); | 
|  | 48 | } else { | 
|  | 49 | mPath.rewind(); | 
|  | 50 | } | 
|  | 51 |  | 
| Chris Craik | 40de9f2 | 2015-07-29 12:51:41 -0700 | [diff] [blame] | 52 | // update mPath to reflect new outline | 
| Chris Craik | 40de9f2 | 2015-07-29 12:51:41 -0700 | [diff] [blame] | 53 | if (MathUtils::isPositive(radius)) { | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 54 | mPath.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), radius, radius); | 
| Chris Craik | 40de9f2 | 2015-07-29 12:51:41 -0700 | [diff] [blame] | 55 | } else { | 
|  | 56 | mPath.addRect(left, top, right, bottom); | 
|  | 57 | } | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 58 | } | 
|  | 59 |  | 
| Leon Scroggins III | a49beaa | 2020-01-30 15:34:13 -0500 | [diff] [blame] | 60 | void setPath(const SkPath* outline, float alpha) { | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 61 | if (!outline) { | 
|  | 62 | setEmpty(); | 
|  | 63 | return; | 
|  | 64 | } | 
| Leon Scroggins III | a49beaa | 2020-01-30 15:34:13 -0500 | [diff] [blame] | 65 | mType = Type::Path; | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 66 | mPath = *outline; | 
|  | 67 | mBounds.set(outline->getBounds()); | 
| Chris Craik | 77b5cad | 2014-07-30 18:23:07 -0700 | [diff] [blame] | 68 | mAlpha = alpha; | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 69 | } | 
|  | 70 |  | 
| Chris Craik | 0645128 | 2014-07-21 10:25:54 -0700 | [diff] [blame] | 71 | void setEmpty() { | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 72 | mType = Type::Empty; | 
| Chris Craik | 0645128 | 2014-07-21 10:25:54 -0700 | [diff] [blame] | 73 | mPath.reset(); | 
| Chris Craik | 77b5cad | 2014-07-30 18:23:07 -0700 | [diff] [blame] | 74 | mAlpha = 0.0f; | 
| Chris Craik | 6131732 | 2014-05-21 13:03:52 -0700 | [diff] [blame] | 75 | } | 
|  | 76 |  | 
| Chris Craik | 0645128 | 2014-07-21 10:25:54 -0700 | [diff] [blame] | 77 | void setNone() { | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 78 | mType = Type::None; | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 79 | mPath.reset(); | 
| Chris Craik | 77b5cad | 2014-07-30 18:23:07 -0700 | [diff] [blame] | 80 | mAlpha = 0.0f; | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 81 | } | 
|  | 82 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 83 | bool isEmpty() const { return mType == Type::Empty; } | 
| Chris Craik | 0645128 | 2014-07-21 10:25:54 -0700 | [diff] [blame] | 84 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 85 | float getAlpha() const { return mAlpha; } | 
| Chris Craik | 77b5cad | 2014-07-30 18:23:07 -0700 | [diff] [blame] | 86 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 87 | void setShouldClip(bool clip) { mShouldClip = clip; } | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 88 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 89 | bool getShouldClip() const { return mShouldClip; } | 
| Chris Craik | deeda3d | 2014-05-05 19:09:33 -0700 | [diff] [blame] | 90 |  | 
| Chet Haase | 33c1ea7 | 2021-09-27 20:56:08 +0000 | [diff] [blame] | 91 | bool willClip() const { return mShouldClip; } | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 92 |  | 
| Chet Haase | 33c1ea7 | 2021-09-27 20:56:08 +0000 | [diff] [blame] | 93 | bool willComplexClip() const { | 
|  | 94 | return mShouldClip && (mType != Type::RoundRect || MathUtils::isPositive(mRadius)); | 
| Chris Craik | b60d3e7 | 2015-06-25 17:15:16 -0700 | [diff] [blame] | 95 | } | 
|  | 96 |  | 
| Chris Craik | deeda3d | 2014-05-05 19:09:33 -0700 | [diff] [blame] | 97 | bool getAsRoundRect(Rect* outRect, float* outRadius) const { | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 98 | if (mType == Type::RoundRect) { | 
| Chris Craik | deeda3d | 2014-05-05 19:09:33 -0700 | [diff] [blame] | 99 | outRect->set(mBounds); | 
|  | 100 | *outRadius = mRadius; | 
|  | 101 | return true; | 
|  | 102 | } | 
|  | 103 | return false; | 
|  | 104 | } | 
|  | 105 |  | 
| John Reck | d0a0b2a | 2014-03-20 16:28:56 -0700 | [diff] [blame] | 106 | const SkPath* getPath() const { | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 107 | if (mType == Type::None || mType == Type::Empty) return nullptr; | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 108 |  | 
|  | 109 | return &mPath; | 
|  | 110 | } | 
|  | 111 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 112 | Type getType() const { return mType; } | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 113 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 114 | const Rect& getBounds() const { return mBounds; } | 
| John Reck | e248bd1 | 2015-08-05 13:53:53 -0700 | [diff] [blame] | 115 |  | 
| John Reck | 1bcacfd | 2017-11-03 10:12:19 -0700 | [diff] [blame] | 116 | float getRadius() const { return mRadius; } | 
| John Reck | e248bd1 | 2015-08-05 13:53:53 -0700 | [diff] [blame] | 117 |  | 
|  | 118 | private: | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 119 | bool mShouldClip; | 
| Chris Craik | b9ce116d | 2015-08-20 15:14:06 -0700 | [diff] [blame] | 120 | Type mType; | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 121 | Rect mBounds; | 
|  | 122 | float mRadius; | 
| Chris Craik | 77b5cad | 2014-07-30 18:23:07 -0700 | [diff] [blame] | 123 | float mAlpha; | 
| Chris Craik | b49f446 | 2014-03-20 12:44:20 -0700 | [diff] [blame] | 124 | SkPath mPath; | 
|  | 125 | }; | 
|  | 126 |  | 
|  | 127 | } /* namespace uirenderer */ | 
|  | 128 | } /* namespace android */ | 
|  | 129 |  | 
|  | 130 | #endif /* OUTLINE_H */ |