1 /* 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 17 package android.util; 18 19 import static com.android.internal.util.Preconditions.checkNotNull; 20 21 /** 22 * Immutable class for describing width and height dimensions in pixels. 23 */ 24 public final class Size { 25 /** 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 */ Size(int width, int height)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 */ getWidth()40 public int getWidth() { 41 return mWidth; 42 } 43 44 /** 45 * Get the height of the size (in pixels). 46 * @return height 47 */ getHeight()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 equals(final Object obj)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 toString()85 public String toString() { 86 return mWidth + "x" + mHeight; 87 } 88 invalidSize(String s)89 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 */ parseSize(String string)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 141 /** 142 * {@inheritDoc} 143 */ 144 @Override hashCode()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; 152 } 153