Home | History | Annotate | Download | only in hwui
      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 { None = 0, Empty = 1, ConvexPath = 2, RoundRect = 3 };
     30 
     31     Outline() : mShouldClip(false), mType(Type::None), mRadius(0), mAlpha(0.0f) {}
     32 
     33     void setRoundRect(int left, int top, int right, int bottom, float radius, float alpha) {
     34         mAlpha = alpha;
     35         if (mType == Type::RoundRect && left == mBounds.left && right == mBounds.right &&
     36             top == mBounds.top && bottom == mBounds.bottom && radius == mRadius) {
     37             // nothing to change, don't do any work
     38             return;
     39         }
     40 
     41         mType = Type::RoundRect;
     42         mBounds.set(left, top, right, bottom);
     43         mRadius = radius;
     44 
     45 
     46         // Reuse memory if previous outline was the same shape (rect or round rect).
     47         if ( mPath.countVerbs() > 10) {
     48             mPath.reset();
     49         } else {
     50             mPath.rewind();
     51         }
     52 
     53         // update mPath to reflect new outline
     54         if (MathUtils::isPositive(radius)) {
     55             mPath.addRoundRect(SkRect::MakeLTRB(left, top, right, bottom), radius, radius);
     56         } else {
     57             mPath.addRect(left, top, right, bottom);
     58         }
     59     }
     60 
     61     void setConvexPath(const SkPath* outline, float alpha) {
     62         if (!outline) {
     63             setEmpty();
     64             return;
     65         }
     66         mType = Type::ConvexPath;
     67         mPath = *outline;
     68         mBounds.set(outline->getBounds());
     69         mAlpha = alpha;
     70     }
     71 
     72     void setEmpty() {
     73         mType = Type::Empty;
     74         mPath.reset();
     75         mAlpha = 0.0f;
     76     }
     77 
     78     void setNone() {
     79         mType = Type::None;
     80         mPath.reset();
     81         mAlpha = 0.0f;
     82     }
     83 
     84     bool isEmpty() const { return mType == Type::Empty; }
     85 
     86     float getAlpha() const { return mAlpha; }
     87 
     88     void setShouldClip(bool clip) { mShouldClip = clip; }
     89 
     90     bool getShouldClip() const { return mShouldClip; }
     91 
     92     bool willClip() const {
     93         // only round rect outlines can be used for clipping
     94         return mShouldClip && (mType == Type::RoundRect);
     95     }
     96 
     97     bool willRoundRectClip() const {
     98         // only round rect outlines can be used for clipping
     99         return willClip() && MathUtils::isPositive(mRadius);
    100     }
    101 
    102     bool getAsRoundRect(Rect* outRect, float* outRadius) const {
    103         if (mType == Type::RoundRect) {
    104             outRect->set(mBounds);
    105             *outRadius = mRadius;
    106             return true;
    107         }
    108         return false;
    109     }
    110 
    111     const SkPath* getPath() const {
    112         if (mType == Type::None || mType == Type::Empty) return nullptr;
    113 
    114         return &mPath;
    115     }
    116 
    117     Type getType() const { return mType; }
    118 
    119     const Rect& getBounds() const { return mBounds; }
    120 
    121     float getRadius() const { return mRadius; }
    122 
    123 private:
    124     bool mShouldClip;
    125     Type mType;
    126     Rect mBounds;
    127     float mRadius;
    128     float mAlpha;
    129     SkPath mPath;
    130 };
    131 
    132 } /* namespace uirenderer */
    133 } /* namespace android */
    134 
    135 #endif /* OUTLINE_H */
    136