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 24 namespace android { 25 namespace uirenderer { 26 27 class Outline { 28 public: 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 144 private: 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