Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2010 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 
     17 #ifndef ANDROID_HWUI_RECT_H
     18 #define ANDROID_HWUI_RECT_H
     19 
     20 #include <cmath>
     21 #include <algorithm>
     22 #include <SkRect.h>
     23 
     24 #include <utils/Log.h>
     25 
     26 #include "Vertex.h"
     27 
     28 namespace android {
     29 namespace uirenderer {
     30 
     31 #define RECT_STRING "%5.2f %5.2f %5.2f %5.2f"
     32 #define RECT_ARGS(r) \
     33     (r).left, (r).top, (r).right, (r).bottom
     34 #define SK_RECT_ARGS(r) \
     35     (r).left(), (r).top(), (r).right(), (r).bottom()
     36 
     37 ///////////////////////////////////////////////////////////////////////////////
     38 // Structs
     39 ///////////////////////////////////////////////////////////////////////////////
     40 
     41 class Rect {
     42 public:
     43     float left;
     44     float top;
     45     float right;
     46     float bottom;
     47 
     48     // Used by Region
     49     typedef float value_type;
     50 
     51     // we don't provide copy-ctor and operator= on purpose
     52     // because we want the compiler generated versions
     53 
     54     inline Rect():
     55             left(0),
     56             top(0),
     57             right(0),
     58             bottom(0) {
     59     }
     60 
     61     inline Rect(float left, float top, float right, float bottom):
     62             left(left),
     63             top(top),
     64             right(right),
     65             bottom(bottom) {
     66     }
     67 
     68     inline Rect(float width, float height):
     69             left(0.0f),
     70             top(0.0f),
     71             right(width),
     72             bottom(height) {
     73     }
     74 
     75     inline Rect(const SkRect& rect):
     76             left(rect.fLeft),
     77             top(rect.fTop),
     78             right(rect.fRight),
     79             bottom(rect.fBottom) {
     80     }
     81 
     82     friend int operator==(const Rect& a, const Rect& b) {
     83         return !memcmp(&a, &b, sizeof(a));
     84     }
     85 
     86     friend int operator!=(const Rect& a, const Rect& b) {
     87         return memcmp(&a, &b, sizeof(a));
     88     }
     89 
     90     inline void clear() {
     91         left = top = right = bottom = 0.0f;
     92     }
     93 
     94     inline bool isEmpty() const {
     95         // this is written in such way this it'll handle NANs to return
     96         // true (empty)
     97         return !((left < right) && (top < bottom));
     98     }
     99 
    100     inline void setEmpty() {
    101         left = top = right = bottom = 0.0f;
    102     }
    103 
    104     inline void set(float left, float top, float right, float bottom) {
    105         this->left = left;
    106         this->right = right;
    107         this->top = top;
    108         this->bottom = bottom;
    109     }
    110 
    111     inline void set(const Rect& r) {
    112         set(r.left, r.top, r.right, r.bottom);
    113     }
    114 
    115     inline void set(const SkIRect& r) {
    116         set(r.left(), r.top(), r.right(), r.bottom());
    117     }
    118 
    119     inline float getWidth() const {
    120         return right - left;
    121     }
    122 
    123     inline float getHeight() const {
    124         return bottom - top;
    125     }
    126 
    127     bool intersects(float l, float t, float r, float b) const {
    128         return !intersectWith(l, t, r, b).isEmpty();
    129     }
    130 
    131     bool intersects(const Rect& r) const {
    132         return intersects(r.left, r.top, r.right, r.bottom);
    133     }
    134 
    135     bool intersect(float l, float t, float r, float b) {
    136         Rect tmp(l, t, r, b);
    137         intersectWith(tmp);
    138         if (!tmp.isEmpty()) {
    139             set(tmp);
    140             return true;
    141         }
    142         return false;
    143     }
    144 
    145     bool intersect(const Rect& r) {
    146         return intersect(r.left, r.top, r.right, r.bottom);
    147     }
    148 
    149     inline bool contains(float l, float t, float r, float b) const {
    150         return l >= left && t >= top && r <= right && b <= bottom;
    151     }
    152 
    153     inline bool contains(const Rect& r) const {
    154         return contains(r.left, r.top, r.right, r.bottom);
    155     }
    156 
    157     bool unionWith(const Rect& r) {
    158         if (r.left < r.right && r.top < r.bottom) {
    159             if (left < right && top < bottom) {
    160                 if (left > r.left) left = r.left;
    161                 if (top > r.top) top = r.top;
    162                 if (right < r.right) right = r.right;
    163                 if (bottom < r.bottom) bottom = r.bottom;
    164                 return true;
    165             } else {
    166                 left = r.left;
    167                 top = r.top;
    168                 right = r.right;
    169                 bottom = r.bottom;
    170                 return true;
    171             }
    172         }
    173         return false;
    174     }
    175 
    176     void translate(float dx, float dy) {
    177         left += dx;
    178         right += dx;
    179         top += dy;
    180         bottom += dy;
    181     }
    182 
    183     void inset(float delta) {
    184         outset(-delta);
    185     }
    186 
    187     void outset(float delta) {
    188         left -= delta;
    189         top -= delta;
    190         right += delta;
    191         bottom += delta;
    192     }
    193 
    194     void outset(float xdelta, float ydelta) {
    195         left -= xdelta;
    196         top -= ydelta;
    197         right += xdelta;
    198         bottom += ydelta;
    199     }
    200 
    201     /**
    202      * Similar to snapToPixelBoundaries, but estimates bounds conservatively to handle GL rounding
    203      * errors.
    204      *
    205      * This function should be used whenever estimating the damage rect of geometry already mapped
    206      * into layer space.
    207      */
    208     void snapGeometryToPixelBoundaries(bool snapOut) {
    209         if (snapOut) {
    210             /* For AA geometry with a ramp perimeter, don't snap by rounding - AA geometry will have
    211              * a 0.5 pixel perimeter not accounted for in its bounds. Instead, snap by
    212              * conservatively rounding out the bounds with floor/ceil.
    213              *
    214              * In order to avoid changing integer bounds with floor/ceil due to rounding errors
    215              * inset the bounds first by the fudge factor. Very small fraction-of-a-pixel errors
    216              * from this inset will only incur similarly small errors in output, due to transparency
    217              * in extreme outside of the geometry.
    218              */
    219             left = floorf(left + Vertex::GeometryFudgeFactor());
    220             top = floorf(top + Vertex::GeometryFudgeFactor());
    221             right = ceilf(right - Vertex::GeometryFudgeFactor());
    222             bottom = ceilf(bottom - Vertex::GeometryFudgeFactor());
    223         } else {
    224             /* For other geometry, we do the regular rounding in order to snap, but also outset the
    225              * bounds by a fudge factor. This ensures that ambiguous geometry (e.g. a non-AA Rect
    226              * with top left at (0.5, 0.5)) will err on the side of a larger damage rect.
    227              */
    228             left = floorf(left + 0.5f - Vertex::GeometryFudgeFactor());
    229             top = floorf(top + 0.5f - Vertex::GeometryFudgeFactor());
    230             right = floorf(right + 0.5f + Vertex::GeometryFudgeFactor());
    231             bottom = floorf(bottom + 0.5f + Vertex::GeometryFudgeFactor());
    232         }
    233     }
    234 
    235     void snapToPixelBoundaries() {
    236         left = floorf(left + 0.5f);
    237         top = floorf(top + 0.5f);
    238         right = floorf(right + 0.5f);
    239         bottom = floorf(bottom + 0.5f);
    240     }
    241 
    242     void roundOut() {
    243         left = floorf(left);
    244         top = floorf(top);
    245         right = ceilf(right);
    246         bottom = ceilf(bottom);
    247     }
    248 
    249     void expandToCoverVertex(float x, float y) {
    250         left = std::min(left, x);
    251         top = std::min(top, y);
    252         right = std::max(right, x);
    253         bottom = std::max(bottom, y);
    254     }
    255 
    256     void expandToCoverRect(float otherLeft, float otherTop, float otherRight, float otherBottom) {
    257         left = std::min(left, otherLeft);
    258         top = std::min(top, otherTop);
    259         right = std::max(right, otherRight);
    260         bottom = std::max(bottom, otherBottom);
    261     }
    262 
    263     SkRect toSkRect() const {
    264         return SkRect::MakeLTRB(left, top, right, bottom);
    265     }
    266 
    267     SkIRect toSkIRect() const {
    268         return SkIRect::MakeLTRB(left, top, right, bottom);
    269     }
    270 
    271     void dump(const char* label = nullptr) const {
    272         ALOGD("%s[l=%f t=%f r=%f b=%f]", label ? label : "Rect", left, top, right, bottom);
    273     }
    274 
    275 private:
    276     void intersectWith(Rect& tmp) const {
    277         tmp.left = std::max(left, tmp.left);
    278         tmp.top = std::max(top, tmp.top);
    279         tmp.right = std::min(right, tmp.right);
    280         tmp.bottom = std::min(bottom, tmp.bottom);
    281     }
    282 
    283     Rect intersectWith(float l, float t, float r, float b) const {
    284         Rect tmp;
    285         tmp.left = std::max(left, l);
    286         tmp.top = std::max(top, t);
    287         tmp.right = std::min(right, r);
    288         tmp.bottom = std::min(bottom, b);
    289         return tmp;
    290     }
    291 
    292 }; // class Rect
    293 
    294 }; // namespace uirenderer
    295 }; // namespace android
    296 
    297 #endif // ANDROID_HWUI_RECT_H
    298