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