Home | History | Annotate | Download | only in util
      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.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  */
     26 public 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