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