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