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