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