• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.annotation.FloatRange;
21 import android.annotation.IntDef;
22 import android.annotation.IntRange;
23 import android.content.pm.ActivityInfo.Config;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 
28 /**
29  * Container for a dynamically typed data value.  Primarily used with
30  * {@link android.content.res.Resources} for holding resource values.
31  */
32 public class TypedValue {
33     /** The value contains no data. */
34     public static final int TYPE_NULL = 0x00;
35 
36     /** The <var>data</var> field holds a resource identifier. */
37     public static final int TYPE_REFERENCE = 0x01;
38     /** The <var>data</var> field holds an attribute resource
39      *  identifier (referencing an attribute in the current theme
40      *  style, not a resource entry). */
41     public static final int TYPE_ATTRIBUTE = 0x02;
42     /** The <var>string</var> field holds string data.  In addition, if
43      *  <var>data</var> is non-zero then it is the string block
44      *  index of the string and <var>assetCookie</var> is the set of
45      *  assets the string came from. */
46     public static final int TYPE_STRING = 0x03;
47     /** The <var>data</var> field holds an IEEE 754 floating point number. */
48     public static final int TYPE_FLOAT = 0x04;
49     /** The <var>data</var> field holds a complex number encoding a
50      *  dimension value. */
51     public static final int TYPE_DIMENSION = 0x05;
52     /** The <var>data</var> field holds a complex number encoding a fraction
53      *  of a container. */
54     public static final int TYPE_FRACTION = 0x06;
55 
56     /** Identifies the start of plain integer values.  Any type value
57      *  from this to {@link #TYPE_LAST_INT} means the
58      *  <var>data</var> field holds a generic integer value. */
59     public static final int TYPE_FIRST_INT = 0x10;
60 
61     /** The <var>data</var> field holds a number that was
62      *  originally specified in decimal. */
63     public static final int TYPE_INT_DEC = 0x10;
64     /** The <var>data</var> field holds a number that was
65      *  originally specified in hexadecimal (0xn). */
66     public static final int TYPE_INT_HEX = 0x11;
67     /** The <var>data</var> field holds 0 or 1 that was originally
68      *  specified as "false" or "true". */
69     public static final int TYPE_INT_BOOLEAN = 0x12;
70 
71     /** Identifies the start of integer values that were specified as
72      *  color constants (starting with '#'). */
73     public static final int TYPE_FIRST_COLOR_INT = 0x1c;
74 
75     /** The <var>data</var> field holds a color that was originally
76      *  specified as #aarrggbb. */
77     public static final int TYPE_INT_COLOR_ARGB8 = 0x1c;
78     /** The <var>data</var> field holds a color that was originally
79      *  specified as #rrggbb. */
80     public static final int TYPE_INT_COLOR_RGB8 = 0x1d;
81     /** The <var>data</var> field holds a color that was originally
82      *  specified as #argb. */
83     public static final int TYPE_INT_COLOR_ARGB4 = 0x1e;
84     /** The <var>data</var> field holds a color that was originally
85      *  specified as #rgb. */
86     public static final int TYPE_INT_COLOR_RGB4 = 0x1f;
87 
88     /** Identifies the end of integer values that were specified as color
89      *  constants. */
90     public static final int TYPE_LAST_COLOR_INT = 0x1f;
91 
92     /** Identifies the end of plain integer values. */
93     public static final int TYPE_LAST_INT = 0x1f;
94 
95     /* ------------------------------------------------------------ */
96 
97     /** Complex data: bit location of unit information. */
98     public static final int COMPLEX_UNIT_SHIFT = 0;
99     /** Complex data: mask to extract unit information (after shifting by
100      *  {@link #COMPLEX_UNIT_SHIFT}). This gives us 16 possible types, as
101      *  defined below. */
102     public static final int COMPLEX_UNIT_MASK = 0xf;
103 
104     /** @hide **/
105     @IntDef(prefix = "COMPLEX_UNIT_", value = {
106             COMPLEX_UNIT_PX,
107             COMPLEX_UNIT_DIP,
108             COMPLEX_UNIT_SP,
109             COMPLEX_UNIT_PT,
110             COMPLEX_UNIT_IN,
111             COMPLEX_UNIT_MM,
112     })
113     @Retention(RetentionPolicy.SOURCE)
114     public @interface ComplexDimensionUnit {}
115 
116     /** {@link #TYPE_DIMENSION} complex unit: Value is raw pixels. */
117     public static final int COMPLEX_UNIT_PX = 0;
118     /** {@link #TYPE_DIMENSION} complex unit: Value is Device Independent
119      *  Pixels. */
120     public static final int COMPLEX_UNIT_DIP = 1;
121     /** {@link #TYPE_DIMENSION} complex unit: Value is a scaled pixel. */
122     public static final int COMPLEX_UNIT_SP = 2;
123     /** {@link #TYPE_DIMENSION} complex unit: Value is in points. */
124     public static final int COMPLEX_UNIT_PT = 3;
125     /** {@link #TYPE_DIMENSION} complex unit: Value is in inches. */
126     public static final int COMPLEX_UNIT_IN = 4;
127     /** {@link #TYPE_DIMENSION} complex unit: Value is in millimeters. */
128     public static final int COMPLEX_UNIT_MM = 5;
129 
130     /** {@link #TYPE_FRACTION} complex unit: A basic fraction of the overall
131      *  size. */
132     public static final int COMPLEX_UNIT_FRACTION = 0;
133     /** {@link #TYPE_FRACTION} complex unit: A fraction of the parent size. */
134     public static final int COMPLEX_UNIT_FRACTION_PARENT = 1;
135 
136     /** Complex data: where the radix information is, telling where the decimal
137      *  place appears in the mantissa. */
138     public static final int COMPLEX_RADIX_SHIFT = 4;
139     /** Complex data: mask to extract radix information (after shifting by
140      * {@link #COMPLEX_RADIX_SHIFT}). This give us 4 possible fixed point
141      * representations as defined below. */
142     public static final int COMPLEX_RADIX_MASK = 0x3;
143 
144     /** Complex data: the mantissa is an integral number -- i.e., 0xnnnnnn.0 */
145     public static final int COMPLEX_RADIX_23p0 = 0;
146     /** Complex data: the mantissa magnitude is 16 bits -- i.e, 0xnnnn.nn */
147     public static final int COMPLEX_RADIX_16p7 = 1;
148     /** Complex data: the mantissa magnitude is 8 bits -- i.e, 0xnn.nnnn */
149     public static final int COMPLEX_RADIX_8p15 = 2;
150     /** Complex data: the mantissa magnitude is 0 bits -- i.e, 0x0.nnnnnn */
151     public static final int COMPLEX_RADIX_0p23 = 3;
152 
153     /** Complex data: bit location of mantissa information. */
154     public static final int COMPLEX_MANTISSA_SHIFT = 8;
155     /** Complex data: mask to extract mantissa information (after shifting by
156      *  {@link #COMPLEX_MANTISSA_SHIFT}). This gives us 23 bits of precision;
157      *  the top bit is the sign. */
158     public static final int COMPLEX_MANTISSA_MASK = 0xffffff;
159 
160     /* ------------------------------------------------------------ */
161 
162     /**
163      * {@link #TYPE_NULL} data indicating the value was not specified.
164      */
165     public static final int DATA_NULL_UNDEFINED = 0;
166     /**
167      * {@link #TYPE_NULL} data indicating the value was explicitly set to null.
168      */
169     public static final int DATA_NULL_EMPTY = 1;
170 
171     /* ------------------------------------------------------------ */
172 
173     /**
174      * If {@link #density} is equal to this value, then the density should be
175      * treated as the system's default density value: {@link DisplayMetrics#DENSITY_DEFAULT}.
176      */
177     public static final int DENSITY_DEFAULT = 0;
178 
179     /**
180      * If {@link #density} is equal to this value, then there is no density
181      * associated with the resource and it should not be scaled.
182      */
183     public static final int DENSITY_NONE = 0xffff;
184 
185     /* ------------------------------------------------------------ */
186 
187     /** The type held by this value, as defined by the constants here.
188      *  This tells you how to interpret the other fields in the object. */
189     public int type;
190 
191     /** If the value holds a string, this is it. */
192     public CharSequence string;
193 
194     /** Basic data in the value, interpreted according to {@link #type} */
195     public int data;
196 
197     /** Additional information about where the value came from; only
198      *  set for strings. */
199     public int assetCookie;
200 
201     /** If Value came from a resource, this holds the corresponding resource id. */
202     @AnyRes
203     public int resourceId;
204 
205     /**
206      * If the value came from a resource, these are the configurations for
207      * which its contents can change.
208      *
209      * <p>For example, if a resource has a value defined for the -land resource qualifier,
210      * this field will have the {@link android.content.pm.ActivityInfo#CONFIG_ORIENTATION} bit set.
211      * </p>
212      *
213      * @see android.content.pm.ActivityInfo#CONFIG_MCC
214      * @see android.content.pm.ActivityInfo#CONFIG_MNC
215      * @see android.content.pm.ActivityInfo#CONFIG_LOCALE
216      * @see android.content.pm.ActivityInfo#CONFIG_TOUCHSCREEN
217      * @see android.content.pm.ActivityInfo#CONFIG_KEYBOARD
218      * @see android.content.pm.ActivityInfo#CONFIG_KEYBOARD_HIDDEN
219      * @see android.content.pm.ActivityInfo#CONFIG_NAVIGATION
220      * @see android.content.pm.ActivityInfo#CONFIG_ORIENTATION
221      * @see android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
222      * @see android.content.pm.ActivityInfo#CONFIG_UI_MODE
223      * @see android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
224      * @see android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
225      * @see android.content.pm.ActivityInfo#CONFIG_DENSITY
226      * @see android.content.pm.ActivityInfo#CONFIG_LAYOUT_DIRECTION
227      * @see android.content.pm.ActivityInfo#CONFIG_COLOR_MODE
228      *
229      */
230     public @Config int changingConfigurations = -1;
231 
232     /**
233      * If the Value came from a resource, this holds the corresponding pixel density.
234      * */
235     public int density;
236 
237     /**
238      * If the Value came from a style resource or a layout resource (set in an XML layout), this
239      * holds the corresponding style or layout resource id against which the attribute was resolved.
240      */
241     public int sourceResourceId;
242 
243     /* ------------------------------------------------------------ */
244 
245     /** Return the data for this value as a float.  Only use for values
246      *  whose type is {@link #TYPE_FLOAT}. */
getFloat()247     public final float getFloat() {
248         return Float.intBitsToFloat(data);
249     }
250 
251     private static final float MANTISSA_MULT =
252         1.0f / (1<<TypedValue.COMPLEX_MANTISSA_SHIFT);
253     private static final float[] RADIX_MULTS = new float[] {
254         1.0f*MANTISSA_MULT, 1.0f/(1<<7)*MANTISSA_MULT,
255         1.0f/(1<<15)*MANTISSA_MULT, 1.0f/(1<<23)*MANTISSA_MULT
256     };
257 
258     /**
259      * Determine if a value is a color.
260      *
261      * This works by comparing {@link #type} to {@link #TYPE_FIRST_COLOR_INT}
262      * and {@link #TYPE_LAST_COLOR_INT}.
263      *
264      * @return true if this value is a color
265      */
isColorType()266     public boolean isColorType() {
267         return (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT);
268     }
269 
270     /**
271      * Retrieve the base value from a complex data integer.  This uses the
272      * {@link #COMPLEX_MANTISSA_MASK} and {@link #COMPLEX_RADIX_MASK} fields of
273      * the data to compute a floating point representation of the number they
274      * describe.  The units are ignored.
275      *
276      * @param complex A complex data value.
277      *
278      * @return A floating point value corresponding to the complex data.
279      */
complexToFloat(int complex)280     public static float complexToFloat(int complex)
281     {
282         return (complex&(TypedValue.COMPLEX_MANTISSA_MASK
283                    <<TypedValue.COMPLEX_MANTISSA_SHIFT))
284             * RADIX_MULTS[(complex>>TypedValue.COMPLEX_RADIX_SHIFT)
285                             & TypedValue.COMPLEX_RADIX_MASK];
286     }
287 
288     /**
289      * Converts a complex data value holding a dimension to its final floating
290      * point value. The given <var>data</var> must be structured as a
291      * {@link #TYPE_DIMENSION}.
292      *
293      * @param data A complex data value holding a unit, magnitude, and
294      *             mantissa.
295      * @param metrics Current display metrics to use in the conversion --
296      *                supplies display density and scaling information.
297      *
298      * @return The complex floating point value multiplied by the appropriate
299      * metrics depending on its unit.
300      */
complexToDimension(int data, DisplayMetrics metrics)301     public static float complexToDimension(int data, DisplayMetrics metrics)
302     {
303         return applyDimension(
304             (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
305             complexToFloat(data),
306             metrics);
307     }
308 
309     /**
310      * Converts a complex data value holding a dimension to its final value
311      * as an integer pixel offset.  This is the same as
312      * {@link #complexToDimension}, except the raw floating point value is
313      * truncated to an integer (pixel) value.
314      * The given <var>data</var> must be structured as a
315      * {@link #TYPE_DIMENSION}.
316      *
317      * @param data A complex data value holding a unit, magnitude, and
318      *             mantissa.
319      * @param metrics Current display metrics to use in the conversion --
320      *                supplies display density and scaling information.
321      *
322      * @return The number of pixels specified by the data and its desired
323      * multiplier and units.
324      */
complexToDimensionPixelOffset(int data, DisplayMetrics metrics)325     public static int complexToDimensionPixelOffset(int data,
326             DisplayMetrics metrics)
327     {
328         return (int)applyDimension(
329                 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
330                 complexToFloat(data),
331                 metrics);
332     }
333 
334     /**
335      * Converts a complex data value holding a dimension to its final value
336      * as an integer pixel size.  This is the same as
337      * {@link #complexToDimension}, except the raw floating point value is
338      * converted to an integer (pixel) value for use as a size.  A size
339      * conversion involves rounding the base value, and ensuring that a
340      * non-zero base value is at least one pixel in size.
341      * The given <var>data</var> must be structured as a
342      * {@link #TYPE_DIMENSION}.
343      *
344      * @param data A complex data value holding a unit, magnitude, and
345      *             mantissa.
346      * @param metrics Current display metrics to use in the conversion --
347      *                supplies display density and scaling information.
348      *
349      * @return The number of pixels specified by the data and its desired
350      * multiplier and units.
351      */
complexToDimensionPixelSize(int data, DisplayMetrics metrics)352     public static int complexToDimensionPixelSize(int data,
353             DisplayMetrics metrics)
354     {
355         final float value = complexToFloat(data);
356         final float f = applyDimension(
357                 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
358                 value,
359                 metrics);
360         final int res = (int) ((f >= 0) ? (f + 0.5f) : (f - 0.5f));
361         if (res != 0) return res;
362         if (value == 0) return 0;
363         if (value > 0) return 1;
364         return -1;
365     }
366 
367     /**
368      * @hide Was accidentally exposed in API level 1 for debugging purposes.
369      * Kept for compatibility just in case although the debugging code has been removed.
370      */
371     @Deprecated
complexToDimensionNoisy(int data, DisplayMetrics metrics)372     public static float complexToDimensionNoisy(int data, DisplayMetrics metrics)
373     {
374         return complexToDimension(data, metrics);
375     }
376 
377     /**
378      * Return the complex unit type for this value. For example, a dimen type
379      * with value 12sp will return {@link #COMPLEX_UNIT_SP}. Only use for values
380      * whose type is {@link #TYPE_DIMENSION}.
381      *
382      * @return The complex unit type.
383      */
getComplexUnit()384      public int getComplexUnit()
385      {
386          return COMPLEX_UNIT_MASK & (data>>TypedValue.COMPLEX_UNIT_SHIFT);
387      }
388 
389     /**
390      * Converts an unpacked complex data value holding a dimension to its final floating
391      * point value. The two parameters <var>unit</var> and <var>value</var>
392      * are as in {@link #TYPE_DIMENSION}.
393      *
394      * @param unit The unit to convert from.
395      * @param value The value to apply the unit to.
396      * @param metrics Current display metrics to use in the conversion --
397      *                supplies display density and scaling information.
398      *
399      * @return The complex floating point value multiplied by the appropriate
400      * metrics depending on its unit.
401      */
applyDimension(@omplexDimensionUnit int unit, float value, DisplayMetrics metrics)402     public static float applyDimension(@ComplexDimensionUnit int unit, float value,
403                                        DisplayMetrics metrics)
404     {
405         switch (unit) {
406         case COMPLEX_UNIT_PX:
407             return value;
408         case COMPLEX_UNIT_DIP:
409             return value * metrics.density;
410         case COMPLEX_UNIT_SP:
411             return value * metrics.scaledDensity;
412         case COMPLEX_UNIT_PT:
413             return value * metrics.xdpi * (1.0f/72);
414         case COMPLEX_UNIT_IN:
415             return value * metrics.xdpi;
416         case COMPLEX_UNIT_MM:
417             return value * metrics.xdpi * (1.0f/25.4f);
418         }
419         return 0;
420     }
421 
422     /**
423      * Return the data for this value as a dimension.  Only use for values
424      * whose type is {@link #TYPE_DIMENSION}.
425      *
426      * @param metrics Current display metrics to use in the conversion --
427      *                supplies display density and scaling information.
428      *
429      * @return The complex floating point value multiplied by the appropriate
430      * metrics depending on its unit.
431      */
getDimension(DisplayMetrics metrics)432     public float getDimension(DisplayMetrics metrics)
433     {
434         return complexToDimension(data, metrics);
435     }
436 
437     /**
438      * Construct a complex data integer.  This validates the radix and the magnitude of the
439      * mantissa, and sets the {@link TypedValue#COMPLEX_MANTISSA_MASK} and
440      * {@link TypedValue#COMPLEX_RADIX_MASK} components as provided. The units are not set.
441      **
442      * @param mantissa an integer representing the mantissa.
443      * @param radix a radix option, e.g. {@link TypedValue#COMPLEX_RADIX_23p0}.
444      * @return A complex data integer representing the value.
445      * @hide
446      */
createComplex(@ntRangefrom = -0x800000, to = 0x7FFFFF) int mantissa, int radix)447     private static int createComplex(@IntRange(from = -0x800000, to = 0x7FFFFF) int mantissa,
448             int radix) {
449         if (mantissa < -0x800000 || mantissa >= 0x800000) {
450             throw new IllegalArgumentException("Magnitude of mantissa is too large: " + mantissa);
451         }
452         if (radix < TypedValue.COMPLEX_RADIX_23p0 || radix > TypedValue.COMPLEX_RADIX_0p23) {
453             throw new IllegalArgumentException("Invalid radix: " + radix);
454         }
455         return ((mantissa & TypedValue.COMPLEX_MANTISSA_MASK) << TypedValue.COMPLEX_MANTISSA_SHIFT)
456                 | (radix << TypedValue.COMPLEX_RADIX_SHIFT);
457     }
458 
459     /**
460      * Convert a base value to a complex data integer.  This sets the {@link
461      * TypedValue#COMPLEX_MANTISSA_MASK} and {@link TypedValue#COMPLEX_RADIX_MASK} fields of the
462      * data to create a floating point representation of the given value. The units are not set.
463      *
464      * <p>This is the inverse of {@link TypedValue#complexToFloat(int)}.
465      *
466      * @param value An integer value.
467      * @return A complex data integer representing the value.
468      * @hide
469      */
intToComplex(int value)470     public static int intToComplex(int value) {
471         if (value < -0x800000 || value >= 0x800000) {
472             throw new IllegalArgumentException("Magnitude of the value is too large: " + value);
473         }
474         return createComplex(value, TypedValue.COMPLEX_RADIX_23p0);
475     }
476 
477     /**
478      * Convert a base value to a complex data integer.  This sets the {@link
479      * TypedValue#COMPLEX_MANTISSA_MASK} and {@link TypedValue#COMPLEX_RADIX_MASK} fields of the
480      * data to create a floating point representation of the given value. The units are not set.
481      *
482      * <p>This is the inverse of {@link TypedValue#complexToFloat(int)}.
483      *
484      * @param value A floating point value.
485      * @return A complex data integer representing the value.
486      * @hide
487      */
floatToComplex(@loatRangefrom = -0x800000, to = 0x7FFFFF) float value)488     public static int floatToComplex(@FloatRange(from = -0x800000, to = 0x7FFFFF) float value) {
489         // validate that the magnitude fits in this representation
490         if (value < (float) -0x800000 - .5f || value >= (float) 0x800000 - .5f) {
491             throw new IllegalArgumentException("Magnitude of the value is too large: " + value);
492         }
493         try {
494             // If there's no fraction, use integer representation, as that's clearer
495             if (value == (float) (int) value) {
496                 return createComplex((int) value, TypedValue.COMPLEX_RADIX_23p0);
497             }
498             float absValue = Math.abs(value);
499             // If the magnitude is 0, we don't need any magnitude digits
500             if (absValue < 1f) {
501                 return createComplex(Math.round(value * (1 << 23)), TypedValue.COMPLEX_RADIX_0p23);
502             }
503             // If the magnitude is less than 2^8, use 8 magnitude digits
504             if (absValue < (float) (1 << 8)) {
505                 return createComplex(Math.round(value * (1 << 15)), TypedValue.COMPLEX_RADIX_8p15);
506             }
507             // If the magnitude is less than 2^16, use 16 magnitude digits
508             if (absValue < (float) (1 << 16)) {
509                 return createComplex(Math.round(value * (1 << 7)), TypedValue.COMPLEX_RADIX_16p7);
510             }
511             // The magnitude requires all 23 digits
512             return createComplex(Math.round(value), TypedValue.COMPLEX_RADIX_23p0);
513         } catch (IllegalArgumentException ex) {
514             // Wrap exception so as to include the value argument in the message.
515             throw new IllegalArgumentException("Unable to convert value to complex: " + value, ex);
516         }
517     }
518 
519     /**
520      * <p>Creates a complex data integer that stores a dimension value and units.
521      *
522      * <p>The resulting value can be passed to e.g.
523      * {@link TypedValue#complexToDimensionPixelOffset(int, DisplayMetrics)} to calculate the pixel
524      * value for the dimension.
525      *
526      * @param value the value of the dimension
527      * @param units the units of the dimension, e.g. {@link TypedValue#COMPLEX_UNIT_DIP}
528      * @return A complex data integer representing the value and units of the dimension.
529      * @hide
530      */
createComplexDimension( @ntRangefrom = -0x800000, to = 0x7FFFFF) int value, @ComplexDimensionUnit int units)531     public static int createComplexDimension(
532             @IntRange(from = -0x800000, to = 0x7FFFFF) int value,
533             @ComplexDimensionUnit int units) {
534         if (units < TypedValue.COMPLEX_UNIT_PX || units > TypedValue.COMPLEX_UNIT_MM) {
535             throw new IllegalArgumentException("Must be a valid COMPLEX_UNIT_*: " + units);
536         }
537         return intToComplex(value) | units;
538     }
539 
540     /**
541      * <p>Creates a complex data integer that stores a dimension value and units.
542      *
543      * <p>The resulting value can be passed to e.g.
544      * {@link TypedValue#complexToDimensionPixelOffset(int, DisplayMetrics)} to calculate the pixel
545      * value for the dimension.
546      *
547      * @param value the value of the dimension
548      * @param units the units of the dimension, e.g. {@link TypedValue#COMPLEX_UNIT_DIP}
549      * @return A complex data integer representing the value and units of the dimension.
550      * @hide
551      */
createComplexDimension( @loatRangefrom = -0x800000, to = 0x7FFFFF) float value, @ComplexDimensionUnit int units)552     public static int createComplexDimension(
553             @FloatRange(from = -0x800000, to = 0x7FFFFF) float value,
554             @ComplexDimensionUnit int units) {
555         if (units < TypedValue.COMPLEX_UNIT_PX || units > TypedValue.COMPLEX_UNIT_MM) {
556             throw new IllegalArgumentException("Must be a valid COMPLEX_UNIT_*: " + units);
557         }
558         return floatToComplex(value) | units;
559     }
560 
561     /**
562      * Converts a complex data value holding a fraction to its final floating
563      * point value. The given <var>data</var> must be structured as a
564      * {@link #TYPE_FRACTION}.
565      *
566      * @param data A complex data value holding a unit, magnitude, and
567      *             mantissa.
568      * @param base The base value of this fraction.  In other words, a
569      *             standard fraction is multiplied by this value.
570      * @param pbase The parent base value of this fraction.  In other
571      *             words, a parent fraction (nn%p) is multiplied by this
572      *             value.
573      *
574      * @return The complex floating point value multiplied by the appropriate
575      * base value depending on its unit.
576      */
complexToFraction(int data, float base, float pbase)577     public static float complexToFraction(int data, float base, float pbase)
578     {
579         switch ((data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK) {
580         case COMPLEX_UNIT_FRACTION:
581             return complexToFloat(data) * base;
582         case COMPLEX_UNIT_FRACTION_PARENT:
583             return complexToFloat(data) * pbase;
584         }
585         return 0;
586     }
587 
588     /**
589      * Return the data for this value as a fraction.  Only use for values whose
590      * type is {@link #TYPE_FRACTION}.
591      *
592      * @param base The base value of this fraction.  In other words, a
593      *             standard fraction is multiplied by this value.
594      * @param pbase The parent base value of this fraction.  In other
595      *             words, a parent fraction (nn%p) is multiplied by this
596      *             value.
597      *
598      * @return The complex floating point value multiplied by the appropriate
599      * base value depending on its unit.
600      */
getFraction(float base, float pbase)601     public float getFraction(float base, float pbase)
602     {
603         return complexToFraction(data, base, pbase);
604     }
605 
606     /**
607      * Regardless of the actual type of the value, try to convert it to a
608      * string value.  For example, a color type will be converted to a
609      * string of the form #aarrggbb.
610      *
611      * @return CharSequence The coerced string value.  If the value is
612      *         null or the type is not known, null is returned.
613      */
coerceToString()614     public final CharSequence coerceToString()
615     {
616         int t = type;
617         if (t == TYPE_STRING) {
618             return string;
619         }
620         return coerceToString(t, data);
621     }
622 
623     private static final String[] DIMENSION_UNIT_STRS = new String[] {
624         "px", "dip", "sp", "pt", "in", "mm"
625     };
626     private static final String[] FRACTION_UNIT_STRS = new String[] {
627         "%", "%p"
628     };
629 
630     /**
631      * Perform type conversion as per {@link #coerceToString()} on an
632      * explicitly supplied type and data.
633      *
634      * @param type The data type identifier.
635      * @param data The data value.
636      *
637      * @return String The coerced string value.  If the value is
638      *         null or the type is not known, null is returned.
639      */
coerceToString(int type, int data)640     public static final String coerceToString(int type, int data)
641     {
642         switch (type) {
643         case TYPE_NULL:
644             return null;
645         case TYPE_REFERENCE:
646             return "@" + data;
647         case TYPE_ATTRIBUTE:
648             return "?" + data;
649         case TYPE_FLOAT:
650             return Float.toString(Float.intBitsToFloat(data));
651         case TYPE_DIMENSION:
652             return Float.toString(complexToFloat(data)) + DIMENSION_UNIT_STRS[
653                 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK];
654         case TYPE_FRACTION:
655             return Float.toString(complexToFloat(data)*100) + FRACTION_UNIT_STRS[
656                 (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK];
657         case TYPE_INT_HEX:
658             return "0x" + Integer.toHexString(data);
659         case TYPE_INT_BOOLEAN:
660             return data != 0 ? "true" : "false";
661         }
662 
663         if (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT) {
664             return "#" + Integer.toHexString(data);
665         } else if (type >= TYPE_FIRST_INT && type <= TYPE_LAST_INT) {
666             return Integer.toString(data);
667         }
668 
669         return null;
670     }
671 
setTo(TypedValue other)672     public void setTo(TypedValue other)
673     {
674         type = other.type;
675         string = other.string;
676         data = other.data;
677         assetCookie = other.assetCookie;
678         resourceId = other.resourceId;
679         density = other.density;
680     }
681 
toString()682     public String toString()
683     {
684         StringBuilder sb = new StringBuilder();
685         sb.append("TypedValue{t=0x").append(Integer.toHexString(type));
686         sb.append("/d=0x").append(Integer.toHexString(data));
687         if (type == TYPE_STRING) {
688             sb.append(" \"").append(string != null ? string : "<null>").append("\"");
689         }
690         if (assetCookie != 0) {
691             sb.append(" a=").append(assetCookie);
692         }
693         if (resourceId != 0) {
694             sb.append(" r=0x").append(Integer.toHexString(resourceId));
695         }
696         sb.append("}");
697         return sb.toString();
698     }
699 };
700 
701