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