1 /* 2 * Copyright (C) 2007 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 /** 20 * Container for a dynamically typed data value. Primarily used with 21 * {@link android.content.res.Resources} for holding resource values. 22 */ 23 public class TypedValue { 24 /** The value contains no data. */ 25 public static final int TYPE_NULL = 0x00; 26 27 /** The <var>data</var> field holds a resource identifier. */ 28 public static final int TYPE_REFERENCE = 0x01; 29 /** The <var>data</var> field holds an attribute resource 30 * identifier (referencing an attribute in the current theme 31 * style, not a resource entry). */ 32 public static final int TYPE_ATTRIBUTE = 0x02; 33 /** The <var>string</var> field holds string data. In addition, if 34 * <var>data</var> is non-zero then it is the string block 35 * index of the string and <var>assetCookie</var> is the set of 36 * assets the string came from. */ 37 public static final int TYPE_STRING = 0x03; 38 /** The <var>data</var> field holds an IEEE 754 floating point number. */ 39 public static final int TYPE_FLOAT = 0x04; 40 /** The <var>data</var> field holds a complex number encoding a 41 * dimension value. */ 42 public static final int TYPE_DIMENSION = 0x05; 43 /** The <var>data</var> field holds a complex number encoding a fraction 44 * of a container. */ 45 public static final int TYPE_FRACTION = 0x06; 46 47 /** Identifies the start of plain integer values. Any type value 48 * from this to {@link #TYPE_LAST_INT} means the 49 * <var>data</var> field holds a generic integer value. */ 50 public static final int TYPE_FIRST_INT = 0x10; 51 52 /** The <var>data</var> field holds a number that was 53 * originally specified in decimal. */ 54 public static final int TYPE_INT_DEC = 0x10; 55 /** The <var>data</var> field holds a number that was 56 * originally specified in hexadecimal (0xn). */ 57 public static final int TYPE_INT_HEX = 0x11; 58 /** The <var>data</var> field holds 0 or 1 that was originally 59 * specified as "false" or "true". */ 60 public static final int TYPE_INT_BOOLEAN = 0x12; 61 62 /** Identifies the start of integer values that were specified as 63 * color constants (starting with '#'). */ 64 public static final int TYPE_FIRST_COLOR_INT = 0x1c; 65 66 /** The <var>data</var> field holds a color that was originally 67 * specified as #aarrggbb. */ 68 public static final int TYPE_INT_COLOR_ARGB8 = 0x1c; 69 /** The <var>data</var> field holds a color that was originally 70 * specified as #rrggbb. */ 71 public static final int TYPE_INT_COLOR_RGB8 = 0x1d; 72 /** The <var>data</var> field holds a color that was originally 73 * specified as #argb. */ 74 public static final int TYPE_INT_COLOR_ARGB4 = 0x1e; 75 /** The <var>data</var> field holds a color that was originally 76 * specified as #rgb. */ 77 public static final int TYPE_INT_COLOR_RGB4 = 0x1f; 78 79 /** Identifies the end of integer values that were specified as color 80 * constants. */ 81 public static final int TYPE_LAST_COLOR_INT = 0x1f; 82 83 /** Identifies the end of plain integer values. */ 84 public static final int TYPE_LAST_INT = 0x1f; 85 86 /* ------------------------------------------------------------ */ 87 88 /** Complex data: bit location of unit information. */ 89 public static final int COMPLEX_UNIT_SHIFT = 0; 90 /** Complex data: mask to extract unit information (after shifting by 91 * {@link #COMPLEX_UNIT_SHIFT}). This gives us 16 possible types, as 92 * defined below. */ 93 public static final int COMPLEX_UNIT_MASK = 0xf; 94 95 /** {@link #TYPE_DIMENSION} complex unit: Value is raw pixels. */ 96 public static final int COMPLEX_UNIT_PX = 0; 97 /** {@link #TYPE_DIMENSION} complex unit: Value is Device Independent 98 * Pixels. */ 99 public static final int COMPLEX_UNIT_DIP = 1; 100 /** {@link #TYPE_DIMENSION} complex unit: Value is a scaled pixel. */ 101 public static final int COMPLEX_UNIT_SP = 2; 102 /** {@link #TYPE_DIMENSION} complex unit: Value is in points. */ 103 public static final int COMPLEX_UNIT_PT = 3; 104 /** {@link #TYPE_DIMENSION} complex unit: Value is in inches. */ 105 public static final int COMPLEX_UNIT_IN = 4; 106 /** {@link #TYPE_DIMENSION} complex unit: Value is in millimeters. */ 107 public static final int COMPLEX_UNIT_MM = 5; 108 109 /** {@link #TYPE_FRACTION} complex unit: A basic fraction of the overall 110 * size. */ 111 public static final int COMPLEX_UNIT_FRACTION = 0; 112 /** {@link #TYPE_FRACTION} complex unit: A fraction of the parent size. */ 113 public static final int COMPLEX_UNIT_FRACTION_PARENT = 1; 114 115 /** Complex data: where the radix information is, telling where the decimal 116 * place appears in the mantissa. */ 117 public static final int COMPLEX_RADIX_SHIFT = 4; 118 /** Complex data: mask to extract radix information (after shifting by 119 * {@link #COMPLEX_RADIX_SHIFT}). This give us 4 possible fixed point 120 * representations as defined below. */ 121 public static final int COMPLEX_RADIX_MASK = 0x3; 122 123 /** Complex data: the mantissa is an integral number -- i.e., 0xnnnnnn.0 */ 124 public static final int COMPLEX_RADIX_23p0 = 0; 125 /** Complex data: the mantissa magnitude is 16 bits -- i.e, 0xnnnn.nn */ 126 public static final int COMPLEX_RADIX_16p7 = 1; 127 /** Complex data: the mantissa magnitude is 8 bits -- i.e, 0xnn.nnnn */ 128 public static final int COMPLEX_RADIX_8p15 = 2; 129 /** Complex data: the mantissa magnitude is 0 bits -- i.e, 0x0.nnnnnn */ 130 public static final int COMPLEX_RADIX_0p23 = 3; 131 132 /** Complex data: bit location of mantissa information. */ 133 public static final int COMPLEX_MANTISSA_SHIFT = 8; 134 /** Complex data: mask to extract mantissa information (after shifting by 135 * {@link #COMPLEX_MANTISSA_SHIFT}). This gives us 23 bits of precision; 136 * the top bit is the sign. */ 137 public static final int COMPLEX_MANTISSA_MASK = 0xffffff; 138 139 /* ------------------------------------------------------------ */ 140 141 /** 142 * {@link #TYPE_NULL} data indicating the value was not specified. 143 */ 144 public static final int DATA_NULL_UNDEFINED = 0; 145 /** 146 * {@link #TYPE_NULL} data indicating the value was explicitly set to null. 147 */ 148 public static final int DATA_NULL_EMPTY = 1; 149 150 /* ------------------------------------------------------------ */ 151 152 /** 153 * If {@link #density} is equal to this value, then the density should be 154 * treated as the system's default density value: {@link DisplayMetrics#DENSITY_DEFAULT}. 155 */ 156 public static final int DENSITY_DEFAULT = 0; 157 158 /** 159 * If {@link #density} is equal to this value, then there is no density 160 * associated with the resource and it should not be scaled. 161 */ 162 public static final int DENSITY_NONE = 0xffff; 163 164 /* ------------------------------------------------------------ */ 165 166 /** The type held by this value, as defined by the constants here. 167 * This tells you how to interpret the other fields in the object. */ 168 public int type; 169 170 /** If the value holds a string, this is it. */ 171 public CharSequence string; 172 173 /** Basic data in the value, interpreted according to {@link #type} */ 174 public int data; 175 176 /** Additional information about where the value came from; only 177 * set for strings. */ 178 public int assetCookie; 179 180 /** If Value came from a resource, this holds the corresponding resource id. */ 181 public int resourceId; 182 183 /** If Value came from a resource, these are the configurations for which 184 * its contents can change. */ 185 public int changingConfigurations = -1; 186 187 /** 188 * If the Value came from a resource, this holds the corresponding pixel density. 189 * */ 190 public int density; 191 192 /* ------------------------------------------------------------ */ 193 194 /** Return the data for this value as a float. Only use for values 195 * whose type is {@link #TYPE_FLOAT}. */ getFloat()196 public final float getFloat() { 197 return Float.intBitsToFloat(data); 198 } 199 200 private static final float MANTISSA_MULT = 201 1.0f / (1<<TypedValue.COMPLEX_MANTISSA_SHIFT); 202 private static final float[] RADIX_MULTS = new float[] { 203 1.0f*MANTISSA_MULT, 1.0f/(1<<7)*MANTISSA_MULT, 204 1.0f/(1<<15)*MANTISSA_MULT, 1.0f/(1<<23)*MANTISSA_MULT 205 }; 206 207 /** 208 * Retrieve the base value from a complex data integer. This uses the 209 * {@link #COMPLEX_MANTISSA_MASK} and {@link #COMPLEX_RADIX_MASK} fields of 210 * the data to compute a floating point representation of the number they 211 * describe. The units are ignored. 212 * 213 * @param complex A complex data value. 214 * 215 * @return A floating point value corresponding to the complex data. 216 */ complexToFloat(int complex)217 public static float complexToFloat(int complex) 218 { 219 return (complex&(TypedValue.COMPLEX_MANTISSA_MASK 220 <<TypedValue.COMPLEX_MANTISSA_SHIFT)) 221 * RADIX_MULTS[(complex>>TypedValue.COMPLEX_RADIX_SHIFT) 222 & TypedValue.COMPLEX_RADIX_MASK]; 223 } 224 225 /** 226 * Converts a complex data value holding a dimension to its final floating 227 * point value. The given <var>data</var> must be structured as a 228 * {@link #TYPE_DIMENSION}. 229 * 230 * @param data A complex data value holding a unit, magnitude, and 231 * mantissa. 232 * @param metrics Current display metrics to use in the conversion -- 233 * supplies display density and scaling information. 234 * 235 * @return The complex floating point value multiplied by the appropriate 236 * metrics depending on its unit. 237 */ complexToDimension(int data, DisplayMetrics metrics)238 public static float complexToDimension(int data, DisplayMetrics metrics) 239 { 240 return applyDimension( 241 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK, 242 complexToFloat(data), 243 metrics); 244 } 245 246 /** 247 * Converts a complex data value holding a dimension to its final value 248 * as an integer pixel offset. This is the same as 249 * {@link #complexToDimension}, except the raw floating point value is 250 * truncated to an integer (pixel) value. 251 * The given <var>data</var> must be structured as a 252 * {@link #TYPE_DIMENSION}. 253 * 254 * @param data A complex data value holding a unit, magnitude, and 255 * mantissa. 256 * @param metrics Current display metrics to use in the conversion -- 257 * supplies display density and scaling information. 258 * 259 * @return The number of pixels specified by the data and its desired 260 * multiplier and units. 261 */ complexToDimensionPixelOffset(int data, DisplayMetrics metrics)262 public static int complexToDimensionPixelOffset(int data, 263 DisplayMetrics metrics) 264 { 265 return (int)applyDimension( 266 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK, 267 complexToFloat(data), 268 metrics); 269 } 270 271 /** 272 * Converts a complex data value holding a dimension to its final value 273 * as an integer pixel size. This is the same as 274 * {@link #complexToDimension}, except the raw floating point value is 275 * converted to an integer (pixel) value for use as a size. A size 276 * conversion involves rounding the base value, and ensuring that a 277 * non-zero base value is at least one pixel in size. 278 * The given <var>data</var> must be structured as a 279 * {@link #TYPE_DIMENSION}. 280 * 281 * @param data A complex data value holding a unit, magnitude, and 282 * mantissa. 283 * @param metrics Current display metrics to use in the conversion -- 284 * supplies display density and scaling information. 285 * 286 * @return The number of pixels specified by the data and its desired 287 * multiplier and units. 288 */ complexToDimensionPixelSize(int data, DisplayMetrics metrics)289 public static int complexToDimensionPixelSize(int data, 290 DisplayMetrics metrics) 291 { 292 final float value = complexToFloat(data); 293 final float f = applyDimension( 294 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK, 295 value, 296 metrics); 297 final int res = (int)(f+0.5f); 298 if (res != 0) return res; 299 if (value == 0) return 0; 300 if (value > 0) return 1; 301 return -1; 302 } 303 304 /** 305 * @hide Was accidentally exposed in API level 1 for debugging purposes. 306 * Kept for compatibility just in case although the debugging code has been removed. 307 */ 308 @Deprecated complexToDimensionNoisy(int data, DisplayMetrics metrics)309 public static float complexToDimensionNoisy(int data, DisplayMetrics metrics) 310 { 311 return complexToDimension(data, metrics); 312 } 313 314 /** 315 * Return the complex unit type for this value. For example, a dimen type 316 * with value 12sp will return {@link #COMPLEX_UNIT_SP}. Only use for values 317 * whose type is {@link #TYPE_DIMENSION}. 318 * 319 * @return The complex unit type. 320 */ getComplexUnit()321 public int getComplexUnit() 322 { 323 return COMPLEX_UNIT_MASK & (data>>TypedValue.COMPLEX_UNIT_SHIFT); 324 } 325 326 /** 327 * Converts an unpacked complex data value holding a dimension to its final floating 328 * point value. The two parameters <var>unit</var> and <var>value</var> 329 * are as in {@link #TYPE_DIMENSION}. 330 * 331 * @param unit The unit to convert from. 332 * @param value The value to apply the unit to. 333 * @param metrics Current display metrics to use in the conversion -- 334 * supplies display density and scaling information. 335 * 336 * @return The complex floating point value multiplied by the appropriate 337 * metrics depending on its unit. 338 */ applyDimension(int unit, float value, DisplayMetrics metrics)339 public static float applyDimension(int unit, float value, 340 DisplayMetrics metrics) 341 { 342 switch (unit) { 343 case COMPLEX_UNIT_PX: 344 return value; 345 case COMPLEX_UNIT_DIP: 346 return value * metrics.density; 347 case COMPLEX_UNIT_SP: 348 return value * metrics.scaledDensity; 349 case COMPLEX_UNIT_PT: 350 return value * metrics.xdpi * (1.0f/72); 351 case COMPLEX_UNIT_IN: 352 return value * metrics.xdpi; 353 case COMPLEX_UNIT_MM: 354 return value * metrics.xdpi * (1.0f/25.4f); 355 } 356 return 0; 357 } 358 359 /** 360 * Return the data for this value as a dimension. Only use for values 361 * whose type is {@link #TYPE_DIMENSION}. 362 * 363 * @param metrics Current display metrics to use in the conversion -- 364 * supplies display density and scaling information. 365 * 366 * @return The complex floating point value multiplied by the appropriate 367 * metrics depending on its unit. 368 */ getDimension(DisplayMetrics metrics)369 public float getDimension(DisplayMetrics metrics) 370 { 371 return complexToDimension(data, metrics); 372 } 373 374 /** 375 * Converts a complex data value holding a fraction to its final floating 376 * point value. The given <var>data</var> must be structured as a 377 * {@link #TYPE_FRACTION}. 378 * 379 * @param data A complex data value holding a unit, magnitude, and 380 * mantissa. 381 * @param base The base value of this fraction. In other words, a 382 * standard fraction is multiplied by this value. 383 * @param pbase The parent base value of this fraction. In other 384 * words, a parent fraction (nn%p) is multiplied by this 385 * value. 386 * 387 * @return The complex floating point value multiplied by the appropriate 388 * base value depending on its unit. 389 */ complexToFraction(int data, float base, float pbase)390 public static float complexToFraction(int data, float base, float pbase) 391 { 392 switch ((data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK) { 393 case COMPLEX_UNIT_FRACTION: 394 return complexToFloat(data) * base; 395 case COMPLEX_UNIT_FRACTION_PARENT: 396 return complexToFloat(data) * pbase; 397 } 398 return 0; 399 } 400 401 /** 402 * Return the data for this value as a fraction. Only use for values whose 403 * type is {@link #TYPE_FRACTION}. 404 * 405 * @param base The base value of this fraction. In other words, a 406 * standard fraction is multiplied by this value. 407 * @param pbase The parent base value of this fraction. In other 408 * words, a parent fraction (nn%p) is multiplied by this 409 * value. 410 * 411 * @return The complex floating point value multiplied by the appropriate 412 * base value depending on its unit. 413 */ getFraction(float base, float pbase)414 public float getFraction(float base, float pbase) 415 { 416 return complexToFraction(data, base, pbase); 417 } 418 419 /** 420 * Regardless of the actual type of the value, try to convert it to a 421 * string value. For example, a color type will be converted to a 422 * string of the form #aarrggbb. 423 * 424 * @return CharSequence The coerced string value. If the value is 425 * null or the type is not known, null is returned. 426 */ coerceToString()427 public final CharSequence coerceToString() 428 { 429 int t = type; 430 if (t == TYPE_STRING) { 431 return string; 432 } 433 return coerceToString(t, data); 434 } 435 436 private static final String[] DIMENSION_UNIT_STRS = new String[] { 437 "px", "dip", "sp", "pt", "in", "mm" 438 }; 439 private static final String[] FRACTION_UNIT_STRS = new String[] { 440 "%", "%p" 441 }; 442 443 /** 444 * Perform type conversion as per {@link #coerceToString()} on an 445 * explicitly supplied type and data. 446 * 447 * @param type The data type identifier. 448 * @param data The data value. 449 * 450 * @return String The coerced string value. If the value is 451 * null or the type is not known, null is returned. 452 */ coerceToString(int type, int data)453 public static final String coerceToString(int type, int data) 454 { 455 switch (type) { 456 case TYPE_NULL: 457 return null; 458 case TYPE_REFERENCE: 459 return "@" + data; 460 case TYPE_ATTRIBUTE: 461 return "?" + data; 462 case TYPE_FLOAT: 463 return Float.toString(Float.intBitsToFloat(data)); 464 case TYPE_DIMENSION: 465 return Float.toString(complexToFloat(data)) + DIMENSION_UNIT_STRS[ 466 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK]; 467 case TYPE_FRACTION: 468 return Float.toString(complexToFloat(data)*100) + FRACTION_UNIT_STRS[ 469 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK]; 470 case TYPE_INT_HEX: 471 return "0x" + Integer.toHexString(data); 472 case TYPE_INT_BOOLEAN: 473 return data != 0 ? "true" : "false"; 474 } 475 476 if (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT) { 477 return "#" + Integer.toHexString(data); 478 } else if (type >= TYPE_FIRST_INT && type <= TYPE_LAST_INT) { 479 return Integer.toString(data); 480 } 481 482 return null; 483 } 484 setTo(TypedValue other)485 public void setTo(TypedValue other) 486 { 487 type = other.type; 488 string = other.string; 489 data = other.data; 490 assetCookie = other.assetCookie; 491 resourceId = other.resourceId; 492 density = other.density; 493 } 494 toString()495 public String toString() 496 { 497 StringBuilder sb = new StringBuilder(); 498 sb.append("TypedValue{t=0x").append(Integer.toHexString(type)); 499 sb.append("/d=0x").append(Integer.toHexString(data)); 500 if (type == TYPE_STRING) { 501 sb.append(" \"").append(string != null ? string : "<null>").append("\""); 502 } 503 if (assetCookie != 0) { 504 sb.append(" a=").append(assetCookie); 505 } 506 if (resourceId != 0) { 507 sb.append(" r=0x").append(Integer.toHexString(resourceId)); 508 } 509 sb.append("}"); 510 return sb.toString(); 511 } 512 }; 513 514