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     public @Config int changingConfigurations = -1;
192 
193     /**
194      * If the Value came from a resource, this holds the corresponding pixel density.
195      * */
196     public int density;
197 
198     /* ------------------------------------------------------------ */
199 
200     /** Return the data for this value as a float.  Only use for values
201      *  whose type is {@link #TYPE_FLOAT}. */
getFloat()202     public final float getFloat() {
203         return Float.intBitsToFloat(data);
204     }
205 
206     private static final float MANTISSA_MULT =
207         1.0f / (1<<TypedValue.COMPLEX_MANTISSA_SHIFT);
208     private static final float[] RADIX_MULTS = new float[] {
209         1.0f*MANTISSA_MULT, 1.0f/(1<<7)*MANTISSA_MULT,
210         1.0f/(1<<15)*MANTISSA_MULT, 1.0f/(1<<23)*MANTISSA_MULT
211     };
212 
213     /**
214      * Retrieve the base value from a complex data integer.  This uses the
215      * {@link #COMPLEX_MANTISSA_MASK} and {@link #COMPLEX_RADIX_MASK} fields of
216      * the data to compute a floating point representation of the number they
217      * describe.  The units are ignored.
218      *
219      * @param complex A complex data value.
220      *
221      * @return A floating point value corresponding to the complex data.
222      */
complexToFloat(int complex)223     public static float complexToFloat(int complex)
224     {
225         return (complex&(TypedValue.COMPLEX_MANTISSA_MASK
226                    <<TypedValue.COMPLEX_MANTISSA_SHIFT))
227             * RADIX_MULTS[(complex>>TypedValue.COMPLEX_RADIX_SHIFT)
228                             & TypedValue.COMPLEX_RADIX_MASK];
229     }
230 
231     /**
232      * Converts a complex data value holding a dimension to its final floating
233      * point value. The given <var>data</var> must be structured as a
234      * {@link #TYPE_DIMENSION}.
235      *
236      * @param data A complex data value holding a unit, magnitude, and
237      *             mantissa.
238      * @param metrics Current display metrics to use in the conversion --
239      *                supplies display density and scaling information.
240      *
241      * @return The complex floating point value multiplied by the appropriate
242      * metrics depending on its unit.
243      */
complexToDimension(int data, DisplayMetrics metrics)244     public static float complexToDimension(int data, DisplayMetrics metrics)
245     {
246         return applyDimension(
247             (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
248             complexToFloat(data),
249             metrics);
250     }
251 
252     /**
253      * Converts a complex data value holding a dimension to its final value
254      * as an integer pixel offset.  This is the same as
255      * {@link #complexToDimension}, except the raw floating point value is
256      * truncated to an integer (pixel) value.
257      * The given <var>data</var> must be structured as a
258      * {@link #TYPE_DIMENSION}.
259      *
260      * @param data A complex data value holding a unit, magnitude, and
261      *             mantissa.
262      * @param metrics Current display metrics to use in the conversion --
263      *                supplies display density and scaling information.
264      *
265      * @return The number of pixels specified by the data and its desired
266      * multiplier and units.
267      */
complexToDimensionPixelOffset(int data, DisplayMetrics metrics)268     public static int complexToDimensionPixelOffset(int data,
269             DisplayMetrics metrics)
270     {
271         return (int)applyDimension(
272                 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
273                 complexToFloat(data),
274                 metrics);
275     }
276 
277     /**
278      * Converts a complex data value holding a dimension to its final value
279      * as an integer pixel size.  This is the same as
280      * {@link #complexToDimension}, except the raw floating point value is
281      * converted to an integer (pixel) value for use as a size.  A size
282      * conversion involves rounding the base value, and ensuring that a
283      * non-zero base value is at least one pixel in size.
284      * The given <var>data</var> must be structured as a
285      * {@link #TYPE_DIMENSION}.
286      *
287      * @param data A complex data value holding a unit, magnitude, and
288      *             mantissa.
289      * @param metrics Current display metrics to use in the conversion --
290      *                supplies display density and scaling information.
291      *
292      * @return The number of pixels specified by the data and its desired
293      * multiplier and units.
294      */
complexToDimensionPixelSize(int data, DisplayMetrics metrics)295     public static int complexToDimensionPixelSize(int data,
296             DisplayMetrics metrics)
297     {
298         final float value = complexToFloat(data);
299         final float f = applyDimension(
300                 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
301                 value,
302                 metrics);
303         final int res = (int)(f+0.5f);
304         if (res != 0) return res;
305         if (value == 0) return 0;
306         if (value > 0) return 1;
307         return -1;
308     }
309 
310     /**
311      * @hide Was accidentally exposed in API level 1 for debugging purposes.
312      * Kept for compatibility just in case although the debugging code has been removed.
313      */
314     @Deprecated
complexToDimensionNoisy(int data, DisplayMetrics metrics)315     public static float complexToDimensionNoisy(int data, DisplayMetrics metrics)
316     {
317         return complexToDimension(data, metrics);
318     }
319 
320     /**
321      * Return the complex unit type for this value. For example, a dimen type
322      * with value 12sp will return {@link #COMPLEX_UNIT_SP}. Only use for values
323      * whose type is {@link #TYPE_DIMENSION}.
324      *
325      * @return The complex unit type.
326      */
getComplexUnit()327      public int getComplexUnit()
328      {
329          return COMPLEX_UNIT_MASK & (data>>TypedValue.COMPLEX_UNIT_SHIFT);
330      }
331 
332     /**
333      * Converts an unpacked complex data value holding a dimension to its final floating
334      * point value. The two parameters <var>unit</var> and <var>value</var>
335      * are as in {@link #TYPE_DIMENSION}.
336      *
337      * @param unit The unit to convert from.
338      * @param value The value to apply the unit to.
339      * @param metrics Current display metrics to use in the conversion --
340      *                supplies display density and scaling information.
341      *
342      * @return The complex floating point value multiplied by the appropriate
343      * metrics depending on its unit.
344      */
applyDimension(int unit, float value, DisplayMetrics metrics)345     public static float applyDimension(int unit, float value,
346                                        DisplayMetrics metrics)
347     {
348         switch (unit) {
349         case COMPLEX_UNIT_PX:
350             return value;
351         case COMPLEX_UNIT_DIP:
352             return value * metrics.density;
353         case COMPLEX_UNIT_SP:
354             return value * metrics.scaledDensity;
355         case COMPLEX_UNIT_PT:
356             return value * metrics.xdpi * (1.0f/72);
357         case COMPLEX_UNIT_IN:
358             return value * metrics.xdpi;
359         case COMPLEX_UNIT_MM:
360             return value * metrics.xdpi * (1.0f/25.4f);
361         }
362         return 0;
363     }
364 
365     /**
366      * Return the data for this value as a dimension.  Only use for values
367      * whose type is {@link #TYPE_DIMENSION}.
368      *
369      * @param metrics Current display metrics to use in the conversion --
370      *                supplies display density and scaling information.
371      *
372      * @return The complex floating point value multiplied by the appropriate
373      * metrics depending on its unit.
374      */
getDimension(DisplayMetrics metrics)375     public float getDimension(DisplayMetrics metrics)
376     {
377         return complexToDimension(data, metrics);
378     }
379 
380     /**
381      * Converts a complex data value holding a fraction to its final floating
382      * point value. The given <var>data</var> must be structured as a
383      * {@link #TYPE_FRACTION}.
384      *
385      * @param data A complex data value holding a unit, magnitude, and
386      *             mantissa.
387      * @param base The base value of this fraction.  In other words, a
388      *             standard fraction is multiplied by this value.
389      * @param pbase The parent base value of this fraction.  In other
390      *             words, a parent fraction (nn%p) is multiplied by this
391      *             value.
392      *
393      * @return The complex floating point value multiplied by the appropriate
394      * base value depending on its unit.
395      */
complexToFraction(int data, float base, float pbase)396     public static float complexToFraction(int data, float base, float pbase)
397     {
398         switch ((data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK) {
399         case COMPLEX_UNIT_FRACTION:
400             return complexToFloat(data) * base;
401         case COMPLEX_UNIT_FRACTION_PARENT:
402             return complexToFloat(data) * pbase;
403         }
404         return 0;
405     }
406 
407     /**
408      * Return the data for this value as a fraction.  Only use for values whose
409      * type is {@link #TYPE_FRACTION}.
410      *
411      * @param base The base value of this fraction.  In other words, a
412      *             standard fraction is multiplied by this value.
413      * @param pbase The parent base value of this fraction.  In other
414      *             words, a parent fraction (nn%p) is multiplied by this
415      *             value.
416      *
417      * @return The complex floating point value multiplied by the appropriate
418      * base value depending on its unit.
419      */
getFraction(float base, float pbase)420     public float getFraction(float base, float pbase)
421     {
422         return complexToFraction(data, base, pbase);
423     }
424 
425     /**
426      * Regardless of the actual type of the value, try to convert it to a
427      * string value.  For example, a color type will be converted to a
428      * string of the form #aarrggbb.
429      *
430      * @return CharSequence The coerced string value.  If the value is
431      *         null or the type is not known, null is returned.
432      */
coerceToString()433     public final CharSequence coerceToString()
434     {
435         int t = type;
436         if (t == TYPE_STRING) {
437             return string;
438         }
439         return coerceToString(t, data);
440     }
441 
442     private static final String[] DIMENSION_UNIT_STRS = new String[] {
443         "px", "dip", "sp", "pt", "in", "mm"
444     };
445     private static final String[] FRACTION_UNIT_STRS = new String[] {
446         "%", "%p"
447     };
448 
449     /**
450      * Perform type conversion as per {@link #coerceToString()} on an
451      * explicitly supplied type and data.
452      *
453      * @param type The data type identifier.
454      * @param data The data value.
455      *
456      * @return String The coerced string value.  If the value is
457      *         null or the type is not known, null is returned.
458      */
coerceToString(int type, int data)459     public static final String coerceToString(int type, int data)
460     {
461         switch (type) {
462         case TYPE_NULL:
463             return null;
464         case TYPE_REFERENCE:
465             return "@" + data;
466         case TYPE_ATTRIBUTE:
467             return "?" + data;
468         case TYPE_FLOAT:
469             return Float.toString(Float.intBitsToFloat(data));
470         case TYPE_DIMENSION:
471             return Float.toString(complexToFloat(data)) + DIMENSION_UNIT_STRS[
472                 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK];
473         case TYPE_FRACTION:
474             return Float.toString(complexToFloat(data)*100) + FRACTION_UNIT_STRS[
475                 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK];
476         case TYPE_INT_HEX:
477             return "0x" + Integer.toHexString(data);
478         case TYPE_INT_BOOLEAN:
479             return data != 0 ? "true" : "false";
480         }
481 
482         if (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT) {
483             return "#" + Integer.toHexString(data);
484         } else if (type >= TYPE_FIRST_INT && type <= TYPE_LAST_INT) {
485             return Integer.toString(data);
486         }
487 
488         return null;
489     }
490 
setTo(TypedValue other)491     public void setTo(TypedValue other)
492     {
493         type = other.type;
494         string = other.string;
495         data = other.data;
496         assetCookie = other.assetCookie;
497         resourceId = other.resourceId;
498         density = other.density;
499     }
500 
toString()501     public String toString()
502     {
503         StringBuilder sb = new StringBuilder();
504         sb.append("TypedValue{t=0x").append(Integer.toHexString(type));
505         sb.append("/d=0x").append(Integer.toHexString(data));
506         if (type == TYPE_STRING) {
507             sb.append(" \"").append(string != null ? string : "<null>").append("\"");
508         }
509         if (assetCookie != 0) {
510             sb.append(" a=").append(assetCookie);
511         }
512         if (resourceId != 0) {
513             sb.append(" r=0x").append(Integer.toHexString(resourceId));
514         }
515         sb.append("}");
516         return sb.toString();
517     }
518 };
519 
520