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