• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package android.util;
18 
19 import static com.android.internal.util.Preconditions.checkArgumentFinite;
20 import static com.android.internal.util.Preconditions.checkNotNull;
21 
22 import android.annotation.NonNull;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 /**
27  * Immutable class for describing width and height dimensions in some arbitrary
28  * unit.
29  * <p>
30  * Width and height are finite values stored as a floating point representation.
31  * </p>
32  */
33 @android.ravenwood.annotation.RavenwoodKeepWholeClass
34 public final class SizeF implements Parcelable {
35     /**
36      * Create a new immutable SizeF instance.
37      *
38      * <p>Both the {@code width} and the {@code height} must be a finite number.
39      * In particular, {@code NaN} and positive/negative infinity are illegal values.</p>
40      *
41      * @param width The width of the size
42      * @param height The height of the size
43      *
44      * @throws IllegalArgumentException
45      *             if either {@code width} or {@code height} was not finite.
46      */
SizeF(final float width, final float height)47     public SizeF(final float width, final float height) {
48         mWidth = checkArgumentFinite(width, "width");
49         mHeight = checkArgumentFinite(height, "height");
50     }
51 
52     /**
53      * Get the width of the size (as an arbitrary unit).
54      * @return width
55      */
getWidth()56     public float getWidth() {
57         return mWidth;
58     }
59 
60     /**
61      * Get the height of the size (as an arbitrary unit).
62      * @return height
63      */
getHeight()64     public float getHeight() {
65         return mHeight;
66     }
67 
68     /**
69      * Check if this size is equal to another size.
70      *
71      * <p>Two sizes are equal if and only if both their widths and heights are the same.</p>
72      *
73      * <p>For this purpose, the width/height float values are considered to be the same if and only
74      * if the method {@link Float#floatToIntBits(float)} returns the identical {@code int} value
75      * when applied to each.</p>
76      *
77      * @return {@code true} if the objects were equal, {@code false} otherwise
78      */
79     @Override
equals(final Object obj)80     public boolean equals(final Object obj) {
81         if (obj == null) {
82             return false;
83         }
84         if (this == obj) {
85             return true;
86         }
87         if (obj instanceof SizeF) {
88             final SizeF other = (SizeF) obj;
89             return mWidth == other.mWidth && mHeight == other.mHeight;
90         }
91         return false;
92     }
93 
94     /**
95      * Return the size represented as a string with the format {@code "WxH"}
96      *
97      * @return string representation of the size
98      */
99     @Override
toString()100     public String toString() {
101         return mWidth + "x" + mHeight;
102     }
103 
invalidSizeF(String s)104     private static NumberFormatException invalidSizeF(String s) {
105         throw new NumberFormatException("Invalid SizeF: \"" + s + "\"");
106     }
107 
108     /**
109      * Parses the specified string as a size value.
110      * <p>
111      * The ASCII characters {@code \}{@code u002a} ('*') and
112      * {@code \}{@code u0078} ('x') are recognized as separators between
113      * the width and height.</p>
114      * <p>
115      * For any {@code SizeF s}: {@code SizeF.parseSizeF(s.toString()).equals(s)}.
116      * However, the method also handles sizes expressed in the
117      * following forms:</p>
118      * <p>
119      * "<i>width</i>{@code x}<i>height</i>" or
120      * "<i>width</i>{@code *}<i>height</i>" {@code => new SizeF(width, height)},
121      * where <i>width</i> and <i>height</i> are string floats potentially
122      * containing a sign, such as "-10.3", "+7" or "5.2", but not containing
123      * an {@code 'x'} (such as a float in hexadecimal string format).</p>
124      *
125      * <pre>{@code
126      * SizeF.parseSizeF("3.2*+6").equals(new SizeF(3.2f, 6.0f)) == true
127      * SizeF.parseSizeF("-3x-6").equals(new SizeF(-3.0f, -6.0f)) == true
128      * SizeF.parseSizeF("4 by 3") => throws NumberFormatException
129      * }</pre>
130      *
131      * @param string the string representation of a size value.
132      * @return the size value represented by {@code string}.
133      *
134      * @throws NumberFormatException if {@code string} cannot be parsed
135      * as a size value.
136      * @throws NullPointerException if {@code string} was {@code null}
137      */
parseSizeF(String string)138     public static SizeF parseSizeF(String string)
139             throws NumberFormatException {
140         checkNotNull(string, "string must not be null");
141 
142         int sep_ix = string.indexOf('*');
143         if (sep_ix < 0) {
144             sep_ix = string.indexOf('x');
145         }
146         if (sep_ix < 0) {
147             throw invalidSizeF(string);
148         }
149         try {
150             return new SizeF(Float.parseFloat(string.substring(0, sep_ix)),
151                     Float.parseFloat(string.substring(sep_ix + 1)));
152         } catch (NumberFormatException e) {
153             throw invalidSizeF(string);
154         } catch (IllegalArgumentException e) {
155             throw invalidSizeF(string);
156         }
157     }
158 
159     /**
160      * {@inheritDoc}
161      */
162     @Override
hashCode()163     public int hashCode() {
164         return Float.floatToIntBits(mWidth) ^ Float.floatToIntBits(mHeight);
165     }
166 
167     private final float mWidth;
168     private final float mHeight;
169 
170     /**
171      * Parcelable interface methods
172      */
173     @Override
describeContents()174     public int describeContents() {
175         return 0;
176     }
177 
178     /**
179      * Write this size to the specified parcel. To restore a size from a parcel, use the
180      * {@link #CREATOR}.
181      * @param out The parcel to write the point's coordinates into
182      */
183     @Override
writeToParcel(@onNull Parcel out, int flags)184     public void writeToParcel(@NonNull Parcel out, int flags) {
185         out.writeFloat(mWidth);
186         out.writeFloat(mHeight);
187     }
188 
189     public static final @NonNull Creator<SizeF> CREATOR = new Creator<SizeF>() {
190         /**
191          * Return a new size from the data in the specified parcel.
192          */
193         @Override
194         public @NonNull SizeF createFromParcel(@NonNull Parcel in) {
195             float width = in.readFloat();
196             float height = in.readFloat();
197             return new SizeF(width, height);
198         }
199 
200         /**
201          * Return an array of sizes of the specified size.
202          */
203         @Override
204         public @NonNull SizeF[] newArray(int size) {
205             return new SizeF[size];
206         }
207     };
208 }
209