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 
     22 #include <utils/Log.h>
     23 
     24 #include "Vertex.h"
     25 
     26 namespace android {
     27 namespace uirenderer {
     28 
     29 #define RECT_STRING "%7.2f %7.2f %7.2f %7.2f"
     30 #define RECT_ARGS(r) \
     31     (r).left, (r).top, (r).right, (r).bottom
     32 
     33 ///////////////////////////////////////////////////////////////////////////////
     34 // Structs
     35 ///////////////////////////////////////////////////////////////////////////////
     36 
     37 class Rect {
     38 public:
     39     float left;
     40     float top;
     41     float right;
     42     float bottom;
     43 
     44     // Used by Region
     45     typedef float value_type;
     46 
     47     // we don't provide copy-ctor and operator= on purpose
     48     // because we want the compiler generated versions
     49 
     50     inline Rect():
     51             left(0),
     52             top(0),
     53             right(0),
     54             bottom(0) {
     55     }
     56 
     57     inline Rect(float left, float top, float right, float bottom):
     58             left(left),
     59             top(top),
     60             right(right),
     61             bottom(bottom) {
     62     }
     63 
     64     inline Rect(float width, float height):
     65             left(0.0f),
     66             top(0.0f),
     67             right(width),
     68             bottom(height) {
     69     }
     70 
     71     friend int operator==(const Rect& a, const Rect& b) {
     72         return !memcmp(&a, &b, sizeof(a));
     73     }
     74 
     75     friend int operator!=(const Rect& a, const Rect& b) {
     76         return memcmp(&a, &b, sizeof(a));
     77     }
     78 
     79     inline void clear() {
     80         left = top = right = bottom = 0.0f;
     81     }
     82 
     83     inline bool isEmpty() const {
     84         // this is written in such way this it'll handle NANs to return
     85         // true (empty)
     86         return !((left < right) && (top < bottom));
     87     }
     88 
     89     inline void setEmpty() {
     90         left = top = right = bottom = 0.0f;
     91     }
     92 
     93     inline void set(float left, float top, float right, float bottom) {
     94         this->left = left;
     95         this->right = right;
     96         this->top = top;
     97         this->bottom = bottom;
     98     }
     99 
    100     inline void set(const Rect& r) {
    101         set(r.left, r.top, r.right, r.bottom);
    102     }
    103 
    104     inline float getWidth() const {
    105         return right - left;
    106     }
    107 
    108     inline float getHeight() const {
    109         return bottom - top;
    110     }
    111 
    112     bool intersects(float l, float t, float r, float b) const {
    113         return !intersectWith(l, t, r, b).isEmpty();
    114     }
    115 
    116     bool intersects(const Rect& r) const {
    117         return intersects(r.left, r.top, r.right, r.bottom);
    118     }
    119 
    120     bool intersect(float l, float t, float r, float b) {
    121         Rect tmp(l, t, r, b);
    122         intersectWith(tmp);
    123         if (!tmp.isEmpty()) {
    124             set(tmp);
    125             return true;
    126         }
    127         return false;
    128     }
    129 
    130     bool intersect(const Rect& r) {
    131         return intersect(r.left, r.top, r.right, r.bottom);
    132     }
    133 
    134     inline bool contains(float l, float t, float r, float b) const {
    135         return l >= left && t >= top && r <= right && b <= bottom;
    136     }
    137 
    138     inline bool contains(const Rect& r) const {
    139         return contains(r.left, r.top, r.right, r.bottom);
    140     }
    141 
    142     bool unionWith(const Rect& r) {
    143         if (r.left < r.right && r.top < r.bottom) {
    144             if (left < right && top < bottom) {
    145                 if (left > r.left) left = r.left;
    146                 if (top > r.top) top = r.top;
    147                 if (right < r.right) right = r.right;
    148                 if (bottom < r.bottom) bottom = r.bottom;
    149                 return true;
    150             } else {
    151                 left = r.left;
    152                 top = r.top;
    153                 right = r.right;
    154                 bottom = r.bottom;
    155                 return true;
    156             }
    157         }
    158         return false;
    159     }
    160 
    161     void translate(float dx, float dy) {
    162         left += dx;
    163         right += dx;
    164         top += dy;
    165         bottom += dy;
    166     }
    167 
    168     void outset(float delta) {
    169         left -= delta;
    170         top -= delta;
    171         right += delta;
    172         bottom += delta;
    173     }
    174 
    175     /**
    176      * Similar to snapToPixelBoundaries, but estimates bounds conservatively to handle GL rounding
    177      * errors.
    178      *
    179      * This function should be used whenever estimating the damage rect of geometry already mapped
    180      * into layer space.
    181      */
    182     void snapGeometryToPixelBoundaries(bool snapOut) {
    183         if (snapOut) {
    184             /* For AA geometry with a ramp perimeter, don't snap by rounding - AA geometry will have
    185              * a 0.5 pixel perimeter not accounted for in its bounds. Instead, snap by
    186              * conservatively rounding out the bounds with floor/ceil.
    187              *
    188              * In order to avoid changing integer bounds with floor/ceil due to rounding errors
    189              * inset the bounds first by the fudge factor. Very small fraction-of-a-pixel errors
    190              * from this inset will only incur similarly small errors in output, due to transparency
    191              * in extreme outside of the geometry.
    192              */
    193             left = floorf(left + Vertex::gGeometryFudgeFactor);
    194             top = floorf(top + Vertex::gGeometryFudgeFactor);
    195             right = ceilf(right - Vertex::gGeometryFudgeFactor);
    196             bottom = ceilf(bottom - Vertex::gGeometryFudgeFactor);
    197         } else {
    198             /* For other geometry, we do the regular rounding in order to snap, but also outset the
    199              * bounds by a fudge factor. This ensures that ambiguous geometry (e.g. a non-AA Rect
    200              * with top left at (0.5, 0.5)) will err on the side of a larger damage rect.
    201              */
    202             left = floorf(left + 0.5f - Vertex::gGeometryFudgeFactor);
    203             top = floorf(top + 0.5f - Vertex::gGeometryFudgeFactor);
    204             right = floorf(right + 0.5f + Vertex::gGeometryFudgeFactor);
    205             bottom = floorf(bottom + 0.5f + Vertex::gGeometryFudgeFactor);
    206         }
    207     }
    208 
    209     void snapToPixelBoundaries() {
    210         left = floorf(left + 0.5f);
    211         top = floorf(top + 0.5f);
    212         right = floorf(right + 0.5f);
    213         bottom = floorf(bottom + 0.5f);
    214     }
    215 
    216     void dump() const {
    217         ALOGD("Rect[l=%f t=%f r=%f b=%f]", left, top, right, bottom);
    218     }
    219 
    220 private:
    221     void intersectWith(Rect& tmp) const {
    222         tmp.left = fmaxf(left, tmp.left);
    223         tmp.top = fmaxf(top, tmp.top);
    224         tmp.right = fminf(right, tmp.right);
    225         tmp.bottom = fminf(bottom, tmp.bottom);
    226     }
    227 
    228     Rect intersectWith(float l, float t, float r, float b) const {
    229         Rect tmp;
    230         tmp.left = fmaxf(left, l);
    231         tmp.top = fmaxf(top, t);
    232         tmp.right = fminf(right, r);
    233         tmp.bottom = fminf(bottom, b);
    234         return tmp;
    235     }
    236 
    237 }; // class Rect
    238 
    239 }; // namespace uirenderer
    240 }; // namespace android
    241 
    242 #endif // ANDROID_HWUI_RECT_H
    243