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