blob: 62df5647cdaa251b0b27dc009e95f9829bb35bc3 [file] [log] [blame]
Igor Murashkinb3a78b22014-04-17 14:01:13 -07001/*
2 * Copyright (C) 2013 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
17package android.util;
18
Jeff Sharkey5b836f22014-08-27 14:46:32 -070019import static com.android.internal.util.Preconditions.checkNotNull;
20
Igor Murashkinb3a78b22014-04-17 14:01:13 -070021/**
22 * Immutable class for describing width and height dimensions in pixels.
23 */
Jeff Sharkey5ef33982014-09-04 18:13:39 -070024public final class Size {
Igor Murashkinb3a78b22014-04-17 14:01:13 -070025 /**
26 * Create a new immutable Size instance.
27 *
28 * @param width The width of the size, in pixels
29 * @param height The height of the size, in pixels
30 */
31 public Size(int width, int height) {
32 mWidth = width;
33 mHeight = height;
34 }
35
36 /**
37 * Get the width of the size (in pixels).
38 * @return width
39 */
40 public int getWidth() {
41 return mWidth;
42 }
43
44 /**
45 * Get the height of the size (in pixels).
46 * @return height
47 */
48 public int getHeight() {
49 return mHeight;
50 }
51
52 /**
53 * Check if this size is equal to another size.
54 * <p>
55 * Two sizes are equal if and only if both their widths and heights are
56 * equal.
57 * </p>
58 * <p>
59 * A size object is never equal to any other type of object.
60 * </p>
61 *
62 * @return {@code true} if the objects were equal, {@code false} otherwise
63 */
64 @Override
65 public boolean equals(final Object obj) {
66 if (obj == null) {
67 return false;
68 }
69 if (this == obj) {
70 return true;
71 }
72 if (obj instanceof Size) {
73 Size other = (Size) obj;
74 return mWidth == other.mWidth && mHeight == other.mHeight;
75 }
76 return false;
77 }
78
79 /**
80 * Return the size represented as a string with the format {@code "WxH"}
81 *
82 * @return string representation of the size
83 */
84 @Override
85 public String toString() {
86 return mWidth + "x" + mHeight;
87 }
88
Lajos Molnarb1a236b2014-07-11 00:54:50 -070089 private static NumberFormatException invalidSize(String s) {
90 throw new NumberFormatException("Invalid Size: \"" + s + "\"");
91 }
92
93 /**
94 * Parses the specified string as a size value.
95 * <p>
96 * The ASCII characters {@code \}{@code u002a} ('*') and
97 * {@code \}{@code u0078} ('x') are recognized as separators between
98 * the width and height.</p>
99 * <p>
100 * For any {@code Size s}: {@code Size.parseSize(s.toString()).equals(s)}.
101 * However, the method also handles sizes expressed in the
102 * following forms:</p>
103 * <p>
104 * "<i>width</i>{@code x}<i>height</i>" or
105 * "<i>width</i>{@code *}<i>height</i>" {@code => new Size(width, height)},
106 * where <i>width</i> and <i>height</i> are string integers potentially
107 * containing a sign, such as "-10", "+7" or "5".</p>
108 *
109 * <pre>{@code
110 * Size.parseSize("3*+6").equals(new Size(3, 6)) == true
111 * Size.parseSize("-3x-6").equals(new Size(-3, -6)) == true
112 * Size.parseSize("4 by 3") => throws NumberFormatException
113 * }</pre>
114 *
115 * @param string the string representation of a size value.
116 * @return the size value represented by {@code string}.
117 *
118 * @throws NumberFormatException if {@code string} cannot be parsed
119 * as a size value.
120 * @throws NullPointerException if {@code string} was {@code null}
121 */
122 public static Size parseSize(String string)
123 throws NumberFormatException {
124 checkNotNull(string, "string must not be null");
125
126 int sep_ix = string.indexOf('*');
127 if (sep_ix < 0) {
128 sep_ix = string.indexOf('x');
129 }
130 if (sep_ix < 0) {
131 throw invalidSize(string);
132 }
133 try {
134 return new Size(Integer.parseInt(string.substring(0, sep_ix)),
135 Integer.parseInt(string.substring(sep_ix + 1)));
136 } catch (NumberFormatException e) {
137 throw invalidSize(string);
138 }
139 }
140
Igor Murashkinb3a78b22014-04-17 14:01:13 -0700141 /**
142 * {@inheritDoc}
143 */
144 @Override
145 public int hashCode() {
146 // assuming most sizes are <2^16, doing a rotate will give us perfect hashing
147 return mHeight ^ ((mWidth << (Integer.SIZE / 2)) | (mWidth >>> (Integer.SIZE / 2)));
148 }
149
150 private final int mWidth;
151 private final int mHeight;
Jeff Sharkey5b836f22014-08-27 14:46:32 -0700152}