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