• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 package com.android.server.wm.traces.common
18 
19 /**
20  * Wrapper for FloatRectProto (frameworks/native/services/surfaceflinger/layerproto/layers.proto)
21  *
22  * This class is used by flicker and Winscope
23  */
24 data class RectF(
25     val left: Float = 0f,
26     val top: Float = 0f,
27     val right: Float = 0f,
28     val bottom: Float = 0f
29 ) {
30     val height: Float get() = bottom - top
31     val width: Float get() = right - left
32 
33     /**
34      * Returns true if the rectangle is empty (left >= right or top >= bottom)
35      */
36     val isEmpty: Boolean
37         get() = width <= 0f || height <= 0f
38     val isNotEmpty: Boolean
39         get() = !isEmpty
40 
41     /**
42      * Returns a [Rect] version fo this rectangle.
43      *
44      * All fractional parts are rounded to 0
45      */
toRectnull46     fun toRect(): Rect {
47         return Rect(left.toInt(), top.toInt(), right.toInt(), bottom.toInt())
48     }
49 
50     /**
51      * Returns true iff the specified rectangle r is inside or equal to this
52      * rectangle. An empty rectangle never contains another rectangle.
53      *
54      * @param r The rectangle being tested for containment.
55      * @return true iff the specified rectangle r is inside or equal to this
56      *              rectangle
57      */
containsnull58     operator fun contains(r: RectF): Boolean {
59         // check for empty first
60         return this.left < this.right && this.top < this.bottom && // now check for containment
61                 left <= r.left && top <= r.top && right >= r.right && bottom >= r.bottom
62     }
63 
64     /**
65      * Returns a [RectF] where the dimensions don't exceed those of [crop]
66      *
67      * @param crop The crop that should be applied to this layer
68      */
cropnull69     fun crop(crop: RectF): RectF {
70         val newLeft = maxOf(left, crop.left)
71         val newTop = maxOf(top, crop.top)
72         val newRight = minOf(right, crop.right)
73         val newBottom = minOf(bottom, crop.bottom)
74         return RectF(newLeft, newTop, newRight, newBottom)
75     }
76 
77     /**
78      * If the rectangle specified by left,top,right,bottom intersects this
79      * rectangle, return true and set this rectangle to that intersection,
80      * otherwise return false and do not change this rectangle. No check is
81      * performed to see if either rectangle is empty. Note: To just test for
82      * intersection, use intersects()
83      *
84      * @param left The left side of the rectangle being intersected with this
85      * rectangle
86      * @param top The top of the rectangle being intersected with this rectangle
87      * @param right The right side of the rectangle being intersected with this
88      * rectangle.
89      * @param bottom The bottom of the rectangle being intersected with this
90      * rectangle.
91      * @return A rectangle with the intersection coordinates
92      */
intersectionnull93     fun intersection(left: Float, top: Float, right: Float, bottom: Float): RectF {
94         if (this.left < right && left < this.right && this.top <= bottom && top <= this.bottom) {
95             var intersectionLeft = this.left
96             var intersectionTop = this.top
97             var intersectionRight = this.right
98             var intersectionBottom = this.bottom
99 
100             if (this.left < left) {
101                 intersectionLeft = left
102             }
103             if (this.top < top) {
104                 intersectionTop = top
105             }
106             if (this.right > right) {
107                 intersectionRight = right
108             }
109             if (this.bottom > bottom) {
110                 intersectionBottom = bottom
111             }
112             return RectF(intersectionLeft, intersectionTop, intersectionRight, intersectionBottom)
113         }
114         return EMPTY
115     }
116 
117     /**
118      * If the specified rectangle intersects this rectangle, return true and set
119      * this rectangle to that intersection, otherwise return false and do not
120      * change this rectangle. No check is performed to see if either rectangle
121      * is empty. To just test for intersection, use intersects()
122      *
123      * @param r The rectangle being intersected with this rectangle.
124      * @return A rectangle with the intersection coordinates
125      */
intersectionnull126     fun intersection(r: RectF): RectF = intersection(r.left, r.top, r.right, r.bottom)
127 
128     fun prettyPrint(): String =
129         if (isEmpty) {
130             "[empty]"
131         } else {
132             val left = FloatFormatter.format(left)
133             val top = FloatFormatter.format(top)
134             val right = FloatFormatter.format(right)
135             val bottom = FloatFormatter.format(bottom)
136             "($left, $top) - ($right, $bottom)"
137         }
138 
toStringnull139     override fun toString(): String = prettyPrint()
140 
141     override fun equals(other: Any?): Boolean {
142         if (this === other) return true
143         if (other !is RectF) return false
144 
145         if (left != other.left) return false
146         if (top != other.top) return false
147         if (right != other.right) return false
148         if (bottom != other.bottom) return false
149 
150         return true
151     }
152 
hashCodenull153     override fun hashCode(): Int {
154         var result = left.hashCode()
155         result = 31 * result + top.hashCode()
156         result = 31 * result + right.hashCode()
157         result = 31 * result + bottom.hashCode()
158         return result
159     }
160 
161     companion object {
162         val EMPTY: RectF = RectF()
163     }
164 }
165