1bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy/*
2bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * Copyright (C) 2010 The Android Open Source Project
3bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy *
4bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
5bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * you may not use this file except in compliance with the License.
6bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * You may obtain a copy of the License at
7bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy *
8bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
9bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy *
10bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * Unless required by applicable law or agreed to in writing, software
11bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
12bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * See the License for the specific language governing permissions and
14bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy * limitations under the License.
15bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy */
16bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
1791eff22b5d7f8fe551bae01331948858ce932a96Chris Craik#pragma once
185b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
1991eff22b5d7f8fe551bae01331948858ce932a96Chris Craik#include "Vertex.h"
20bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
215cbbce535744b89df5ecea95de21ee3733298260Romain Guy#include <utils/Log.h>
225cbbce535744b89df5ecea95de21ee3733298260Romain Guy
231bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <SkRect.h>
2491eff22b5d7f8fe551bae01331948858ce932a96Chris Craik#include <algorithm>
2591eff22b5d7f8fe551bae01331948858ce932a96Chris Craik#include <cmath>
2691eff22b5d7f8fe551bae01331948858ce932a96Chris Craik#include <iomanip>
2791eff22b5d7f8fe551bae01331948858ce932a96Chris Craik#include <ostream>
2832f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik
29bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guynamespace android {
309d5316e3f56d138504565ff311145ac01621dff4Romain Guynamespace uirenderer {
31bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
3262d307c2402777d5e53b4590af5f32f8c55afd81Chris Craik#define RECT_STRING "%5.2f %5.2f %5.2f %5.2f"
331bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define RECT_ARGS(r) (r).left, (r).top, (r).right, (r).bottom
341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define SK_RECT_ARGS(r) (r).left(), (r).top(), (r).right(), (r).bottom()
3528ce94a4ffc7576f40776d212f1ada79fafaa061Chris Craik
36bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy///////////////////////////////////////////////////////////////////////////////
37bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy// Structs
38bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy///////////////////////////////////////////////////////////////////////////////
39bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
4083b186a246e8ffd52b91a17c0019dd8c9c9d21b1Mathias Agopianclass Rect {
4183b186a246e8ffd52b91a17c0019dd8c9c9d21b1Mathias Agopianpublic:
427ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    float left;
437ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    float top;
447ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    float right;
457ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    float bottom;
467ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
475b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    // Used by Region
485b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    typedef float value_type;
495b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
5083b186a246e8ffd52b91a17c0019dd8c9c9d21b1Mathias Agopian    // we don't provide copy-ctor and operator= on purpose
5183b186a246e8ffd52b91a17c0019dd8c9c9d21b1Mathias Agopian    // because we want the compiler generated versions
5283b186a246e8ffd52b91a17c0019dd8c9c9d21b1Mathias Agopian
531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline Rect() : left(0), top(0), right(0), bottom(0) {}
547ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
551bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline Rect(float left, float top, float right, float bottom)
561bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            : left(left), top(top), right(right), bottom(bottom) {}
577ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline Rect(float width, float height) : left(0.0f), top(0.0f), right(width), bottom(height) {}
595b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline Rect(const SkIRect& rect)
611bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            :  // NOLINT, implicit
621bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            left(rect.fLeft)
631bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            , top(rect.fTop)
641bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            , right(rect.fRight)
651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            , bottom(rect.fBottom) {}
6682457c51176855b9be0b441010870093a6feb414Chris Craik
671bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline Rect(const SkRect& rect)
681bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            :  // NOLINT, implicit
691bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            left(rect.fLeft)
701bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            , top(rect.fTop)
711bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            , right(rect.fRight)
721bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            , bottom(rect.fBottom) {}
73af6f7ed8dd4288a41d0a07a1f0f0be7d6d035b33ztenghui
741bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    friend int operator==(const Rect& a, const Rect& b) { return !memcmp(&a, &b, sizeof(a)); }
757ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
761bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    friend int operator!=(const Rect& a, const Rect& b) { return memcmp(&a, &b, sizeof(a)); }
777ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
781bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline void clear() { left = top = right = bottom = 0.0f; }
795b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
805b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    inline bool isEmpty() const {
8183b186a246e8ffd52b91a17c0019dd8c9c9d21b1Mathias Agopian        // this is written in such way this it'll handle NANs to return
8283b186a246e8ffd52b91a17c0019dd8c9c9d21b1Mathias Agopian        // true (empty)
8383b186a246e8ffd52b91a17c0019dd8c9c9d21b1Mathias Agopian        return !((left < right) && (top < bottom));
847ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
857ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
861bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline void setEmpty() { left = top = right = bottom = 0.0f; }
877ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
885b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    inline void set(float left, float top, float right, float bottom) {
897ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        this->left = left;
907ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        this->right = right;
917ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        this->top = top;
927ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy        this->bottom = bottom;
937ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
947ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
951bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline void set(const Rect& r) { set(r.left, r.top, r.right, r.bottom); }
967ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
971bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline void set(const SkIRect& r) { set(r.left(), r.top(), r.right(), r.bottom()); }
98487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline float getWidth() const { return right - left; }
1007ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
1011bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline float getHeight() const { return bottom - top; }
1027ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
10383b186a246e8ffd52b91a17c0019dd8c9c9d21b1Mathias Agopian    bool intersects(float l, float t, float r, float b) const {
104ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik        float tempLeft = std::max(left, l);
105ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik        float tempTop = std::max(top, t);
106ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik        float tempRight = std::min(right, r);
107ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik        float tempBottom = std::min(bottom, b);
108ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik
1091bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        return ((tempLeft < tempRight) && (tempTop < tempBottom));  // !isEmpty
1107ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
1117ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
1121bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    bool intersects(const Rect& r) const { return intersects(r.left, r.top, r.right, r.bottom); }
1137ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
114ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik    /**
115ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik     * This method is named 'doIntersect' instead of 'intersect' so as not to be confused with
116ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik     * SkRect::intersect / android.graphics.Rect#intersect behavior, which do not modify the object
117ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik     * if the intersection of the rects would be empty.
118ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik     */
119ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik    void doIntersect(float l, float t, float r, float b) {
120ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik        left = std::max(left, l);
121ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik        top = std::max(top, t);
122ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik        right = std::min(right, r);
123ac02eb9035a13a3d09c2def9ed63d04225eb2509Chris Craik        bottom = std::min(bottom, b);
1247ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
1257ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
1261bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    void doIntersect(const Rect& r) { doIntersect(r.left, r.top, r.right, r.bottom); }
1277ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy
1282db5e993b626794eb07a0ff354269f9a77da81b3Romain Guy    inline bool contains(float l, float t, float r, float b) const {
129ec31f83bd3af1f900d1ee9116b15f56904c66dcdRomain Guy        return l >= left && t >= top && r <= right && b <= bottom;
130ec31f83bd3af1f900d1ee9116b15f56904c66dcdRomain Guy    }
131ec31f83bd3af1f900d1ee9116b15f56904c66dcdRomain Guy
1321bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    inline bool contains(const Rect& r) const { return contains(r.left, r.top, r.right, r.bottom); }
133ec31f83bd3af1f900d1ee9116b15f56904c66dcdRomain Guy
134079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy    bool unionWith(const Rect& r) {
135079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        if (r.left < r.right && r.top < r.bottom) {
136079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy            if (left < right && top < bottom) {
137079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                if (left > r.left) left = r.left;
138079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                if (top > r.top) top = r.top;
139079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                if (right < r.right) right = r.right;
140079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                if (bottom < r.bottom) bottom = r.bottom;
141079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                return true;
142079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy            } else {
143079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                left = r.left;
144079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                top = r.top;
145079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                right = r.right;
146079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                bottom = r.bottom;
147079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy                return true;
148079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy            }
149079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        }
150079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy        return false;
151079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy    }
152079ba2c85b15e882629b8d188f5fbdb42f7f8eeaRomain Guy
1535b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    void translate(float dx, float dy) {
1545b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        left += dx;
1555b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        right += dx;
1565b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        top += dy;
1575b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy        bottom += dy;
1585b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy    }
1595b3b35296e8b2c8d3f07d32bb645d5414db41a1dRomain Guy
1601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    void inset(float delta) { outset(-delta); }
161e4aa95e3627226bcb0d8cc3e42dca6e4df8f421cChris Craik
162c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    void outset(float delta) {
163c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        left -= delta;
164c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        top -= delta;
165c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        right += delta;
166c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        bottom += delta;
167c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
168c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
16905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    void outset(float xdelta, float ydelta) {
17005f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        left -= xdelta;
17105f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        top -= ydelta;
17205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        right += xdelta;
17305f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik        bottom += ydelta;
17405f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    }
17505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik
1765e49b307eb99269db2db257760508b8efd7bb97dChris Craik    /**
17732f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik     * Similar to snapToPixelBoundaries, but estimates bounds conservatively to handle GL rounding
17832f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik     * errors.
1795e49b307eb99269db2db257760508b8efd7bb97dChris Craik     *
18032f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik     * This function should be used whenever estimating the damage rect of geometry already mapped
18132f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik     * into layer space.
1825e49b307eb99269db2db257760508b8efd7bb97dChris Craik     */
18332f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik    void snapGeometryToPixelBoundaries(bool snapOut) {
18432f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik        if (snapOut) {
18532f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik            /* For AA geometry with a ramp perimeter, don't snap by rounding - AA geometry will have
18632f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             * a 0.5 pixel perimeter not accounted for in its bounds. Instead, snap by
18732f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             * conservatively rounding out the bounds with floor/ceil.
18832f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             *
18932f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             * In order to avoid changing integer bounds with floor/ceil due to rounding errors
19032f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             * inset the bounds first by the fudge factor. Very small fraction-of-a-pixel errors
19132f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             * from this inset will only incur similarly small errors in output, due to transparency
19232f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             * in extreme outside of the geometry.
19332f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             */
194564acf7c9bff822f608cda0d5df0a64a9f9aaefdChris Craik            left = floorf(left + Vertex::GeometryFudgeFactor());
195564acf7c9bff822f608cda0d5df0a64a9f9aaefdChris Craik            top = floorf(top + Vertex::GeometryFudgeFactor());
196564acf7c9bff822f608cda0d5df0a64a9f9aaefdChris Craik            right = ceilf(right - Vertex::GeometryFudgeFactor());
197564acf7c9bff822f608cda0d5df0a64a9f9aaefdChris Craik            bottom = ceilf(bottom - Vertex::GeometryFudgeFactor());
19832f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik        } else {
19932f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik            /* For other geometry, we do the regular rounding in order to snap, but also outset the
20032f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             * bounds by a fudge factor. This ensures that ambiguous geometry (e.g. a non-AA Rect
20132f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             * with top left at (0.5, 0.5)) will err on the side of a larger damage rect.
20232f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik             */
203564acf7c9bff822f608cda0d5df0a64a9f9aaefdChris Craik            left = floorf(left + 0.5f - Vertex::GeometryFudgeFactor());
204564acf7c9bff822f608cda0d5df0a64a9f9aaefdChris Craik            top = floorf(top + 0.5f - Vertex::GeometryFudgeFactor());
205564acf7c9bff822f608cda0d5df0a64a9f9aaefdChris Craik            right = floorf(right + 0.5f + Vertex::GeometryFudgeFactor());
206564acf7c9bff822f608cda0d5df0a64a9f9aaefdChris Craik            bottom = floorf(bottom + 0.5f + Vertex::GeometryFudgeFactor());
20732f05e343c5ffb17f3235942bcda651bd3b9f1d6Chris Craik        }
2085e49b307eb99269db2db257760508b8efd7bb97dChris Craik    }
2095e49b307eb99269db2db257760508b8efd7bb97dChris Craik
210bf434114cbf55b216fdc76fc8d65a75e84c9dab5Romain Guy    void snapToPixelBoundaries() {
211ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy        left = floorf(left + 0.5f);
212ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy        top = floorf(top + 0.5f);
213ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy        right = floorf(right + 0.5f);
214ae88e5e8e9cb6c9539314c4360c5b20f8ec1fefcRomain Guy        bottom = floorf(bottom + 0.5f);
215bf434114cbf55b216fdc76fc8d65a75e84c9dab5Romain Guy    }
216bf434114cbf55b216fdc76fc8d65a75e84c9dab5Romain Guy
217f0a590781b2c3e34132b2011d3956135add73ae0Chris Craik    void roundOut() {
218f0a590781b2c3e34132b2011d3956135add73ae0Chris Craik        left = floorf(left);
219f0a590781b2c3e34132b2011d3956135add73ae0Chris Craik        top = floorf(top);
220f0a590781b2c3e34132b2011d3956135add73ae0Chris Craik        right = ceilf(right);
221f0a590781b2c3e34132b2011d3956135add73ae0Chris Craik        bottom = ceilf(bottom);
222f0a590781b2c3e34132b2011d3956135add73ae0Chris Craik    }
223f0a590781b2c3e34132b2011d3956135add73ae0Chris Craik
22415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik    /*
22515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik     * Similar to unionWith, except this makes the assumption that both rects are non-empty
22615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik     * to avoid both emptiness checks.
22715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik     */
22815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik    void expandToCover(const Rect& other) {
22915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik        left = std::min(left, other.left);
23015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik        top = std::min(top, other.top);
23115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik        right = std::max(right, other.right);
23215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik        bottom = std::max(bottom, other.bottom);
23315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik    }
23415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik
23515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik    void expandToCover(float x, float y) {
236df72b63928cc1492b72ba9a4e99d5e714f93ccc6Chris Craik        left = std::min(left, x);
237df72b63928cc1492b72ba9a4e99d5e714f93ccc6Chris Craik        top = std::min(top, y);
238df72b63928cc1492b72ba9a4e99d5e714f93ccc6Chris Craik        right = std::max(right, x);
239df72b63928cc1492b72ba9a4e99d5e714f93ccc6Chris Craik        bottom = std::max(bottom, y);
240c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik    }
241c93e45cf045f41aea95f856173e4043d988a5a5cChris Craik
2421bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    SkRect toSkRect() const { return SkRect::MakeLTRB(left, top, right, bottom); }
243487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
2441bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    SkIRect toSkIRect() const { return SkIRect::MakeLTRB(left, top, right, bottom); }
245487a92caef2eb90a62e8f8d7a6fe6315f1c1d8d8Rob Tsuk
246e84a208317e0ed388fcdad1e6743c7849acb51b0Chris Craik    void dump(const char* label = nullptr) const {
2478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        ALOGD("%s[l=%.2f t=%.2f r=%.2f b=%.2f]", label ? label : "Rect", left, top, right, bottom);
2487ae7ac48aa2b53453c9805075171ecd5bcafd7deRomain Guy    }
24991eff22b5d7f8fe551bae01331948858ce932a96Chris Craik
25091eff22b5d7f8fe551bae01331948858ce932a96Chris Craik    friend std::ostream& operator<<(std::ostream& os, const Rect& rect) {
25191eff22b5d7f8fe551bae01331948858ce932a96Chris Craik        if (rect.isEmpty()) {
252034a10bf216cdef251928edf72d93668d81515f8Chris Craik            // Print empty, but continue, since empty rects may still have useful coordinate info
253034a10bf216cdef251928edf72d93668d81515f8Chris Craik            os << "(empty)";
25491eff22b5d7f8fe551bae01331948858ce932a96Chris Craik        }
25591eff22b5d7f8fe551bae01331948858ce932a96Chris Craik
25691eff22b5d7f8fe551bae01331948858ce932a96Chris Craik        if (rect.left == 0 && rect.top == 0) {
25791eff22b5d7f8fe551bae01331948858ce932a96Chris Craik            return os << "[" << rect.right << " x " << rect.bottom << "]";
25891eff22b5d7f8fe551bae01331948858ce932a96Chris Craik        }
25991eff22b5d7f8fe551bae01331948858ce932a96Chris Craik
2601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        return os << "[" << rect.left << " " << rect.top << " " << rect.right << " " << rect.bottom
2611bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                  << "]";
26291eff22b5d7f8fe551bae01331948858ce932a96Chris Craik    }
2631bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // class Rect
264bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy
2651bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // namespace uirenderer
2661bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // namespace android
267