TypedValue.java revision 9f357ae9f038b97e4426bf3707ca94624cdf5d75
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
19/**
20 * Container for a dynamically typed data value.  Primarily used with
21 * {@link android.content.res.Resources} for holding resource values.
22 */
23public 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}. */
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     */
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     */
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     */
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     */
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
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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
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
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