1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2008 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License. 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage com.android.layoutlib.bridge.impl; 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 195f1bf496948fb6383ae17e5467a26a00489d7564Deepanshu Guptaimport com.android.SdkConstants; 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.DensityBasedResourceValue; 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.LayoutLog; 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.RenderResources; 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.ResourceValue; 24fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Guptaimport com.android.internal.util.XmlUtils; 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.Bridge; 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.android.BridgeContext; 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser; 28cd6e47e4455cec8daa4570ac8073d93bd567d139Deepanshu Guptaimport com.android.layoutlib.bridge.android.RenderParamsFlags; 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ninepatch.NinePatch; 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ninepatch.NinePatchChunk; 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.resources.Density; 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.xmlpull.v1.XmlPullParser; 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport org.xmlpull.v1.XmlPullParserException; 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 36476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.NonNull; 37566b303365078fac9a454f1595add19e02631db3Diego Perezimport android.annotation.Nullable; 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.res.ColorStateList; 39566b303365078fac9a454f1595add19e02631db3Diego Perezimport android.content.res.ComplexColor; 40566b303365078fac9a454f1595add19e02631db3Diego Perezimport android.content.res.ComplexColor_Accessor; 41789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perezimport android.content.res.FontResourcesParser; 42566b303365078fac9a454f1595add19e02631db3Diego Perezimport android.content.res.GradientColor; 434a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Guptaimport android.content.res.Resources.Theme; 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Bitmap; 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Bitmap_Delegate; 46d88c717b4e124e435e54bf1542774aa100773c3eDiego Perezimport android.graphics.Color; 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.NinePatch_Delegate; 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Rect; 49789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perezimport android.graphics.Typeface; 50789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perezimport android.graphics.Typeface_Accessor; 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.drawable.BitmapDrawable; 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.drawable.ColorDrawable; 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.drawable.Drawable; 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.drawable.NinePatchDrawable; 55789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perezimport android.text.FontConfig; 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.util.TypedValue; 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.File; 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.FileInputStream; 60566b303365078fac9a454f1595add19e02631db3Diego Perezimport java.io.FileNotFoundException; 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.IOException; 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.InputStream; 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.net.MalformedURLException; 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.regex.Matcher; 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.regex.Pattern; 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/** 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Helper class to provide various conversion method used in handling android resources. 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic final class ResourceHelper { 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final static Pattern sFloatPattern = Pattern.compile("(-?[0-9]+(?:\\.[0-9]+)?)(.*)"); 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final static float[] sFloatOut = new float[1]; 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final static TypedValue mValue = new TypedValue(); 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns the color value represented by the given string value 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param value the color value 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @return the color as an int 811a12b805698c7cba9c2daa78c76c055afbdfa9fcDeepanshu Gupta * @throws NumberFormatException if the conversion failed. 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static int getColor(String value) { 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value != null) { 85fb175664469f1eb1bc598f54a7f86ff008e88b0eDiego Perez value = value.trim(); 861a12b805698c7cba9c2daa78c76c055afbdfa9fcDeepanshu Gupta if (!value.startsWith("#")) { 875f1bf496948fb6383ae17e5467a26a00489d7564Deepanshu Gupta if (value.startsWith(SdkConstants.PREFIX_THEME_REF)) { 885f1bf496948fb6383ae17e5467a26a00489d7564Deepanshu Gupta throw new NumberFormatException(String.format( 895f1bf496948fb6383ae17e5467a26a00489d7564Deepanshu Gupta "Attribute '%s' not found. Are you using the right theme?", value)); 905f1bf496948fb6383ae17e5467a26a00489d7564Deepanshu Gupta } 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new NumberFormatException( 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String.format("Color value '%s' must start with #", value)); 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value = value.substring(1); 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // make sure it's not longer than 32bit 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.length() > 8) { 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new NumberFormatException(String.format( 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Color value '%s' is too long. Format is either" + 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "#AARRGGBB, #RRGGBB, #RGB, or #ARGB", 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value)); 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value.length() == 3) { // RGB format 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char[] color = new char[8]; 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski color[0] = color[1] = 'F'; 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski color[2] = color[3] = value.charAt(0); 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski color[4] = color[5] = value.charAt(1); 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski color[6] = color[7] = value.charAt(2); 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value = new String(color); 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (value.length() == 4) { // ARGB format 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char[] color = new char[8]; 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski color[0] = color[1] = value.charAt(0); 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski color[2] = color[3] = value.charAt(1); 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski color[4] = color[5] = value.charAt(2); 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski color[6] = color[7] = value.charAt(3); 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value = new String(color); 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (value.length() == 6) { 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value = "FF" + value; 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // this is a RRGGBB or AARRGGBB value 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Integer.parseInt will fail to parse strings like "ff191919", so we use 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // a Long, but cast the result back into an int, since we know that we're only 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // dealing with 32 bit values. 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return (int)Long.parseLong(value, 16); 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new NumberFormatException(); 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 134566b303365078fac9a454f1595add19e02631db3Diego Perez /** 135566b303365078fac9a454f1595add19e02631db3Diego Perez * Returns a {@link ComplexColor} from the given {@link ResourceValue} 136566b303365078fac9a454f1595add19e02631db3Diego Perez * 137566b303365078fac9a454f1595add19e02631db3Diego Perez * @param resValue the value containing a color value or a file path to a complex color 138566b303365078fac9a454f1595add19e02631db3Diego Perez * definition 139566b303365078fac9a454f1595add19e02631db3Diego Perez * @param context the current context 140566b303365078fac9a454f1595add19e02631db3Diego Perez * @param theme the theme to use when resolving the complex color 141566b303365078fac9a454f1595add19e02631db3Diego Perez * @param allowGradients when false, only {@link ColorStateList} will be returned. If a {@link 142566b303365078fac9a454f1595add19e02631db3Diego Perez * GradientColor} is found, null will be returned. 143566b303365078fac9a454f1595add19e02631db3Diego Perez */ 144566b303365078fac9a454f1595add19e02631db3Diego Perez @Nullable 145566b303365078fac9a454f1595add19e02631db3Diego Perez private static ComplexColor getInternalComplexColor(@NonNull ResourceValue resValue, 146566b303365078fac9a454f1595add19e02631db3Diego Perez @NonNull BridgeContext context, @Nullable Theme theme, boolean allowGradients) { 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String value = resValue.getValue(); 148566b303365078fac9a454f1595add19e02631db3Diego Perez if (value == null || RenderResources.REFERENCE_NULL.equals(value)) { 149566b303365078fac9a454f1595add19e02631db3Diego Perez return null; 150566b303365078fac9a454f1595add19e02631db3Diego Perez } 151566b303365078fac9a454f1595add19e02631db3Diego Perez 152cd6e47e4455cec8daa4570ac8073d93bd567d139Deepanshu Gupta XmlPullParser parser = null; 153566b303365078fac9a454f1595add19e02631db3Diego Perez // first check if the value is a file (xml most likely) 154cd6e47e4455cec8daa4570ac8073d93bd567d139Deepanshu Gupta Boolean psiParserSupport = context.getLayoutlibCallback().getFlag( 155cd6e47e4455cec8daa4570ac8073d93bd567d139Deepanshu Gupta RenderParamsFlags.FLAG_KEY_XML_FILE_PARSER_SUPPORT); 156cd6e47e4455cec8daa4570ac8073d93bd567d139Deepanshu Gupta if (psiParserSupport != null && psiParserSupport) { 157cd6e47e4455cec8daa4570ac8073d93bd567d139Deepanshu Gupta parser = context.getLayoutlibCallback().getXmlFileParser(value); 158cd6e47e4455cec8daa4570ac8073d93bd567d139Deepanshu Gupta } 159566b303365078fac9a454f1595add19e02631db3Diego Perez if (parser == null) { 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski File f = new File(value); 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (f.isFile()) { 162566b303365078fac9a454f1595add19e02631db3Diego Perez // let the framework inflate the color from the XML file, by 163566b303365078fac9a454f1595add19e02631db3Diego Perez // providing an XmlPullParser 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try { 165566b303365078fac9a454f1595add19e02631db3Diego Perez parser = ParserFactory.create(f); 166566b303365078fac9a454f1595add19e02631db3Diego Perez } catch (XmlPullParserException | FileNotFoundException e) { 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Failed to parse file " + value, e, null /*data*/); 169282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 170566b303365078fac9a454f1595add19e02631db3Diego Perez } 171566b303365078fac9a454f1595add19e02631db3Diego Perez } 172566b303365078fac9a454f1595add19e02631db3Diego Perez 173566b303365078fac9a454f1595add19e02631db3Diego Perez if (parser != null) { 174566b303365078fac9a454f1595add19e02631db3Diego Perez try { 175566b303365078fac9a454f1595add19e02631db3Diego Perez BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 176566b303365078fac9a454f1595add19e02631db3Diego Perez parser, context, resValue.isFramework()); 177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try { 178566b303365078fac9a454f1595add19e02631db3Diego Perez // Advance the parser to the first element so we can detect if it's a 179566b303365078fac9a454f1595add19e02631db3Diego Perez // color list or a gradient color 180566b303365078fac9a454f1595add19e02631db3Diego Perez int type; 181566b303365078fac9a454f1595add19e02631db3Diego Perez //noinspection StatementWithEmptyBody 182566b303365078fac9a454f1595add19e02631db3Diego Perez while ((type = blockParser.next()) != XmlPullParser.START_TAG 183566b303365078fac9a454f1595add19e02631db3Diego Perez && type != XmlPullParser.END_DOCUMENT) { 184566b303365078fac9a454f1595add19e02631db3Diego Perez // Seek parser to start tag. 185566b303365078fac9a454f1595add19e02631db3Diego Perez } 186566b303365078fac9a454f1595add19e02631db3Diego Perez 187566b303365078fac9a454f1595add19e02631db3Diego Perez if (type != XmlPullParser.START_TAG) { 188d88c717b4e124e435e54bf1542774aa100773c3eDiego Perez assert false : "No start tag found"; 189d88c717b4e124e435e54bf1542774aa100773c3eDiego Perez return null; 190566b303365078fac9a454f1595add19e02631db3Diego Perez } 191566b303365078fac9a454f1595add19e02631db3Diego Perez 192566b303365078fac9a454f1595add19e02631db3Diego Perez final String name = blockParser.getName(); 193566b303365078fac9a454f1595add19e02631db3Diego Perez if (allowGradients && "gradient".equals(name)) { 194566b303365078fac9a454f1595add19e02631db3Diego Perez return ComplexColor_Accessor.createGradientColorFromXmlInner( 195566b303365078fac9a454f1595add19e02631db3Diego Perez context.getResources(), 196566b303365078fac9a454f1595add19e02631db3Diego Perez blockParser, blockParser, 197566b303365078fac9a454f1595add19e02631db3Diego Perez theme); 198566b303365078fac9a454f1595add19e02631db3Diego Perez } else if ("selector".equals(name)) { 199566b303365078fac9a454f1595add19e02631db3Diego Perez return ComplexColor_Accessor.createColorStateListFromXmlInner( 200566b303365078fac9a454f1595add19e02631db3Diego Perez context.getResources(), 201566b303365078fac9a454f1595add19e02631db3Diego Perez blockParser, blockParser, 202566b303365078fac9a454f1595add19e02631db3Diego Perez theme); 203566b303365078fac9a454f1595add19e02631db3Diego Perez } 204566b303365078fac9a454f1595add19e02631db3Diego Perez } finally { 205566b303365078fac9a454f1595add19e02631db3Diego Perez blockParser.ensurePopped(); 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 207566b303365078fac9a454f1595add19e02631db3Diego Perez } catch (XmlPullParserException e) { 208566b303365078fac9a454f1595add19e02631db3Diego Perez Bridge.getLog().error(LayoutLog.TAG_BROKEN, 209566b303365078fac9a454f1595add19e02631db3Diego Perez "Failed to configure parser for " + value, e, null /*data*/); 210566b303365078fac9a454f1595add19e02631db3Diego Perez // we'll return null below. 211566b303365078fac9a454f1595add19e02631db3Diego Perez } catch (Exception e) { 212566b303365078fac9a454f1595add19e02631db3Diego Perez // this is an error and not warning since the file existence is 213566b303365078fac9a454f1595add19e02631db3Diego Perez // checked before attempting to parse it. 214566b303365078fac9a454f1595add19e02631db3Diego Perez Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, 215566b303365078fac9a454f1595add19e02631db3Diego Perez "Failed to parse file " + value, e, null /*data*/); 216566b303365078fac9a454f1595add19e02631db3Diego Perez 217566b303365078fac9a454f1595add19e02631db3Diego Perez return null; 218566b303365078fac9a454f1595add19e02631db3Diego Perez } 219566b303365078fac9a454f1595add19e02631db3Diego Perez } else { 220566b303365078fac9a454f1595add19e02631db3Diego Perez // try to load the color state list from an int 221566b303365078fac9a454f1595add19e02631db3Diego Perez try { 222566b303365078fac9a454f1595add19e02631db3Diego Perez int color = getColor(value); 223566b303365078fac9a454f1595add19e02631db3Diego Perez return ColorStateList.valueOf(color); 224566b303365078fac9a454f1595add19e02631db3Diego Perez } catch (NumberFormatException e) { 225566b303365078fac9a454f1595add19e02631db3Diego Perez Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, 226566b303365078fac9a454f1595add19e02631db3Diego Perez "Failed to convert " + value + " into a ColorStateList", e, 227566b303365078fac9a454f1595add19e02631db3Diego Perez null /*data*/); 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 235566b303365078fac9a454f1595add19e02631db3Diego Perez * Returns a {@link ColorStateList} from the given {@link ResourceValue} 236566b303365078fac9a454f1595add19e02631db3Diego Perez * 237566b303365078fac9a454f1595add19e02631db3Diego Perez * @param resValue the value containing a color value or a file path to a complex color 238566b303365078fac9a454f1595add19e02631db3Diego Perez * definition 239566b303365078fac9a454f1595add19e02631db3Diego Perez * @param context the current context 240566b303365078fac9a454f1595add19e02631db3Diego Perez */ 241566b303365078fac9a454f1595add19e02631db3Diego Perez @Nullable 242566b303365078fac9a454f1595add19e02631db3Diego Perez public static ColorStateList getColorStateList(@NonNull ResourceValue resValue, 243566b303365078fac9a454f1595add19e02631db3Diego Perez @NonNull BridgeContext context) { 244566b303365078fac9a454f1595add19e02631db3Diego Perez return (ColorStateList) getInternalComplexColor(resValue, context, context.getTheme(), 245566b303365078fac9a454f1595add19e02631db3Diego Perez false); 246566b303365078fac9a454f1595add19e02631db3Diego Perez } 247566b303365078fac9a454f1595add19e02631db3Diego Perez 248566b303365078fac9a454f1595add19e02631db3Diego Perez /** 249566b303365078fac9a454f1595add19e02631db3Diego Perez * Returns a {@link ComplexColor} from the given {@link ResourceValue} 250566b303365078fac9a454f1595add19e02631db3Diego Perez * 251566b303365078fac9a454f1595add19e02631db3Diego Perez * @param resValue the value containing a color value or a file path to a complex color 252566b303365078fac9a454f1595add19e02631db3Diego Perez * definition 253566b303365078fac9a454f1595add19e02631db3Diego Perez * @param context the current context 254566b303365078fac9a454f1595add19e02631db3Diego Perez */ 255566b303365078fac9a454f1595add19e02631db3Diego Perez @Nullable 256566b303365078fac9a454f1595add19e02631db3Diego Perez public static ComplexColor getComplexColor(@NonNull ResourceValue resValue, 257566b303365078fac9a454f1595add19e02631db3Diego Perez @NonNull BridgeContext context) { 258566b303365078fac9a454f1595add19e02631db3Diego Perez return getInternalComplexColor(resValue, context, context.getTheme(), true); 259566b303365078fac9a454f1595add19e02631db3Diego Perez } 260566b303365078fac9a454f1595add19e02631db3Diego Perez 261566b303365078fac9a454f1595add19e02631db3Diego Perez /** 262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns a drawable from the given value. 263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable, 264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * or an hexadecimal color 265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param context the current context 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static Drawable getDrawable(ResourceValue value, BridgeContext context) { 2684a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta return getDrawable(value, context, null); 2694a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta } 2704a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta 2714a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta /** 2724a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta * Returns a drawable from the given value. 2734a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable, 2744a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta * or an hexadecimal color 2754a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta * @param context the current context 2764a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta * @param theme the theme to be used to inflate the drawable. 2774a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta */ 2784a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta public static Drawable getDrawable(ResourceValue value, BridgeContext context, Theme theme) { 27914bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta if (value == null) { 28014bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta return null; 28114bf0cef7eeed572a67c29a328581afac4decc20Deepanshu Gupta } 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String stringValue = value.getValue(); 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (RenderResources.REFERENCE_NULL.equals(stringValue)) { 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String lowerCaseValue = stringValue.toLowerCase(); 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Density density = Density.MEDIUM; 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value instanceof DensityBasedResourceValue) { 291bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez density = ((DensityBasedResourceValue) value).getResourceDensity(); 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (lowerCaseValue.endsWith(NinePatch.EXTENSION_9PATCH)) { 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski File file = new File(stringValue); 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (file.isFile()) { 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try { 298bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez return getNinePatchDrawable(new FileInputStream(file), density, 299bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez value.isFramework(), stringValue, context); 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } catch (IOException e) { 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // failed to read the file, we'll return null below. 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Failed lot load " + file.getAbsolutePath(), e, null /*data*/); 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 308bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez } else if (lowerCaseValue.endsWith(".xml") || stringValue.startsWith("@aapt:_aapt/")) { 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // create a block parser for the file 310bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez try { 311bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez XmlPullParser parser = context.getLayoutlibCallback().getParser(value); 312bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez if (parser == null) { 313bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez File drawableFile = new File(stringValue); 314bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez if (drawableFile.isFile()) { 315bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez parser = ParserFactory.create(drawableFile); 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 318bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez 319bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez BridgeXmlBlockParser blockParser = 320bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez new BridgeXmlBlockParser(parser, context, value.isFramework()); 321bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez try { 322bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez return Drawable.createFromXml(context.getResources(), blockParser, theme); 323bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez } finally { 324bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez blockParser.ensurePopped(); 325bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez } 326bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez } catch (Exception e) { 327bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez // this is an error and not warning since the file existence is checked before 328bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez // attempting to parse it. 329bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez Bridge.getLog().error(null, "Failed to parse file " + stringValue, e, 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski null /*data*/); 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski File bmpFile = new File(stringValue); 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bmpFile.isFile()) { 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try { 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bitmap bitmap = Bridge.getCachedBitmap(stringValue, 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value.isFramework() ? null : context.getProjectKey()); 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bitmap == null) { 342bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez bitmap = 343bc9d2a13f0bbeae4ebf04da5a0b0d2f7814b40e4Diego Perez Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/, density); 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.setCachedBitmap(stringValue, bitmap, 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value.isFramework() ? null : context.getProjectKey()); 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return new BitmapDrawable(context.getResources(), bitmap); 349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } catch (IOException e) { 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we'll return null below 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Failed lot load " + bmpFile.getAbsolutePath(), e, null /*data*/); 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // attempt to get a color from the value 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try { 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int color = getColor(stringValue); 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return new ColorDrawable(color); 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } catch (NumberFormatException e) { 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // we'll return null below. 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Failed to convert " + stringValue + " into a drawable", e, 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski null /*data*/); 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 371789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez /** 372789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez * Returns a {@link Typeface} given a font name. The font name, can be a system font family 373789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez * (like sans-serif) or a full path if the font is to be loaded from resources. 374789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez */ 375789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez public static Typeface getFont(String fontName, BridgeContext context, Theme theme, boolean 376789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez isFramework) { 377789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez if (fontName == null) { 378789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez return null; 379789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 380789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez 381789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez if (Typeface_Accessor.isSystemFont(fontName)) { 382789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez // Shortcut for the case where we are asking for a system font name. Those are not 383789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez // loaded using external resources. 384789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez return null; 385789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 386789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez 387789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez // Check if this is an asset that we've already loaded dynamically 388789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez Typeface typeface = Typeface.findFromCache(context.getAssets(), fontName); 389789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez if (typeface != null) { 390789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez return typeface; 391789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 392789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez 393789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez String lowerCaseValue = fontName.toLowerCase(); 394789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez if (lowerCaseValue.endsWith(".xml")) { 395789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez // create a block parser for the file 396789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez Boolean psiParserSupport = context.getLayoutlibCallback().getFlag( 397789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez RenderParamsFlags.FLAG_KEY_XML_FILE_PARSER_SUPPORT); 398789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez XmlPullParser parser = null; 399789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez if (psiParserSupport != null && psiParserSupport) { 400789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez parser = context.getLayoutlibCallback().getXmlFileParser(fontName); 401789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 402789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez else { 403789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez File f = new File(fontName); 404789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez if (f.isFile()) { 405789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez try { 406789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez parser = ParserFactory.create(f); 407789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } catch (XmlPullParserException | FileNotFoundException e) { 408789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez // this is an error and not warning since the file existence is checked before 409789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez // attempting to parse it. 410789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez Bridge.getLog().error(null, "Failed to parse file " + fontName, 411789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez e, null /*data*/); 412789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 413789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 414789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 415789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez 416789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez if (parser != null) { 417789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 418789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez parser, context, isFramework); 419789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez try { 420ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka FontResourcesParser.FamilyResourceEntry entry = 421ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka FontResourcesParser.parse(blockParser, context.getResources()); 422ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka typeface = Typeface.createFromResources(entry, context.getAssets(), 423789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez fontName); 424789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } catch (XmlPullParserException | IOException e) { 425789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez Bridge.getLog().error(null, "Failed to parse file " + fontName, 426789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez e, null /*data*/); 427789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } finally { 428789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez blockParser.ensurePopped(); 429789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 430789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } else { 431789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez Bridge.getLog().error(LayoutLog.TAG_BROKEN, 432789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez String.format("File %s does not exist (or is not a file)", fontName), 433789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez null /*data*/); 434789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 435789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } else { 436789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez typeface = Typeface.createFromResources(context.getAssets(), fontName, 0); 437789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 438789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez 439789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez return typeface; 440789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 441789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez 442789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez /** 443789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez * Returns a {@link Typeface} given a font name. The font name, can be a system font family 444789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez * (like sans-serif) or a full path if the font is to be loaded from resources. 445789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez */ 446789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez public static Typeface getFont(ResourceValue value, BridgeContext context, Theme theme) { 447789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez if (value == null) { 448789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez return null; 449789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 450789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez 451789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez return getFont(value.getValue(), context, theme, value.isFramework()); 452789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez } 453789c4b4b14880621f05e7750f594b24bc93fcff9Diego Perez 454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static Drawable getNinePatchDrawable(InputStream inputStream, Density density, 455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski boolean isFramework, String cacheKey, BridgeContext context) throws IOException { 456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // see if we still have both the chunk and the bitmap in the caches 457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NinePatchChunk chunk = Bridge.getCached9Patch(cacheKey, 458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski isFramework ? null : context.getProjectKey()); 459282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bitmap bitmap = Bridge.getCachedBitmap(cacheKey, 460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski isFramework ? null : context.getProjectKey()); 461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // if either chunk or bitmap is null, then we reload the 9-patch file. 463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (chunk == null || bitmap == null) { 464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try { 465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NinePatch ninePatch = NinePatch.load(inputStream, true /*is9Patch*/, 466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski false /* convert */); 467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (ninePatch != null) { 468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (chunk == null) { 469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski chunk = ninePatch.getChunk(); 470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.setCached9Patch(cacheKey, chunk, 472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski isFramework ? null : context.getProjectKey()); 473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (bitmap == null) { 476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(), 477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski false /*isMutable*/, 478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski density); 479282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.setCachedBitmap(cacheKey, bitmap, 481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski isFramework ? null : context.getProjectKey()); 482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } catch (MalformedURLException e) { 485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // URL is wrong, we'll return null below 486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (chunk != null && bitmap != null) { 490282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int[] padding = chunk.getPadding(); 491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Rect paddingRect = new Rect(padding[0], padding[1], padding[2], padding[3]); 492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return new NinePatchDrawable(context.getResources(), bitmap, 494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski NinePatch_Delegate.serialize(chunk), 495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski paddingRect, null); 496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 501fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta /** 502fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta * Looks for an attribute in the current theme. 503fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta * 504fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta * @param resources the render resources 505fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta * @param name the name of the attribute 506fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta * @param defaultValue the default value. 507fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta * @param isFrameworkAttr if the attribute is in android namespace 508fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta * @return the value of the attribute or the default one if not found. 509fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta */ 510fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta public static boolean getBooleanThemeValue(@NonNull RenderResources resources, String name, 511fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta boolean isFrameworkAttr, boolean defaultValue) { 512fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta ResourceValue value = resources.findItemInTheme(name, isFrameworkAttr); 513fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta value = resources.resolveResValue(value); 514fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta if (value == null) { 515fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta return defaultValue; 516fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta } 517fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue); 518fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta } 519fc8f4aad7395eca11f6d9b82eb266b1f4ee5041bDeepanshu Gupta 520282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // ------- TypedValue stuff 521282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // This is taken from //device/libs/utils/ResourceTypes.cpp 522282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 523282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static final class UnitEntry { 524282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String name; 525282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int type; 526282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int unit; 527282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski float scale; 528282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 529282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski UnitEntry(String name, int type, int unit, float scale) { 530282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski this.name = name; 531282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski this.type = type; 532282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski this.unit = unit; 533282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski this.scale = scale; 534282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 535282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 536282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 537282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final static UnitEntry[] sUnitNames = new UnitEntry[] { 538282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski new UnitEntry("px", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_PX, 1.0f), 539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski new UnitEntry("dip", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_DIP, 1.0f), 540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski new UnitEntry("dp", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_DIP, 1.0f), 541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski new UnitEntry("sp", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_SP, 1.0f), 542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski new UnitEntry("pt", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_PT, 1.0f), 543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski new UnitEntry("in", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_IN, 1.0f), 544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski new UnitEntry("mm", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_MM, 1.0f), 545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski new UnitEntry("%", TypedValue.TYPE_FRACTION, TypedValue.COMPLEX_UNIT_FRACTION, 1.0f/100), 546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski new UnitEntry("%p", TypedValue.TYPE_FRACTION, TypedValue.COMPLEX_UNIT_FRACTION_PARENT, 1.0f/100), 547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski }; 548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 549282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns the raw value from the given attribute float-type value string. 551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This object is only valid until the next call on to {@link ResourceHelper}. 552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static TypedValue getValue(String attribute, String value, boolean requireUnit) { 554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (parseFloatAttribute(attribute, value, mValue, requireUnit)) { 555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mValue; 556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return null; 559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 560282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Parse a float attribute and return the parsed value into a given TypedValue. 563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param attribute the name of the attribute. Can be null if <var>requireUnit</var> is false. 564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param value the string value of the attribute 565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param outValue the TypedValue to receive the parsed value 566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param requireUnit whether the value is expected to contain a unit. 567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @return true if success. 568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 569171804201dd556f8ce7ee7618661a5c8ee71507aDeepanshu Gupta public static boolean parseFloatAttribute(String attribute, @NonNull String value, 570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TypedValue outValue, boolean requireUnit) { 5711a12b805698c7cba9c2daa78c76c055afbdfa9fcDeepanshu Gupta assert !requireUnit || attribute != null; 572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // remove the space before and after 574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value = value.trim(); 575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int len = value.length(); 576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (len <= 0) { 578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // check that there's no non ascii characters. 582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski char[] buf = value.toCharArray(); 583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 0 ; i < len ; i++) { 584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (buf[i] > 255) { 585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // check the first character 590458f2a7bbbcc45d12b575fe9f3b2f8e1a20f9b1cDeepanshu Gupta if ((buf[0] < '0' || buf[0] > '9') && buf[0] != '.' && buf[0] != '-' && buf[0] != '+') { 591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // now look for the string that is after the float... 595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Matcher m = sFloatPattern.matcher(value); 596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (m.matches()) { 597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String f_str = m.group(1); 598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String end = m.group(2); 599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski float f; 601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try { 602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski f = Float.parseFloat(f_str); 603282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } catch (NumberFormatException e) { 604282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // this shouldn't happen with the regexp above. 605282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 606282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 607282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 608282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (end.length() > 0 && end.charAt(0) != ' ') { 609282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Might be a unit... 610282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (parseUnit(end, outValue, sFloatOut)) { 611282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski computeTypedValue(outValue, f, sFloatOut[0]); 612282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 613282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 614282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 615282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 616282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 617282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // make sure it's only spaces at the end. 618282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski end = end.trim(); 619282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 620282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (end.length() == 0) { 621282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (outValue != null) { 6221a12b805698c7cba9c2daa78c76c055afbdfa9fcDeepanshu Gupta if (!requireUnit) { 623282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue.type = TypedValue.TYPE_FLOAT; 624282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue.data = Float.floatToIntBits(f); 625282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 626282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // no unit when required? Use dp and out an error. 627282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski applyUnit(sUnitNames[1], outValue, sFloatOut); 628282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski computeTypedValue(outValue, f, sFloatOut[0]); 629282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 630282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, 631282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String.format( 632282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski "Dimension \"%1$s\" in attribute \"%2$s\" is missing unit!", 633282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value, attribute), 634282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski null); 635282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 636282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 637282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 638282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 639282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 640282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 641282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 642282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 643282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 644282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static void computeTypedValue(TypedValue outValue, float value, float scale) { 645282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value *= scale; 646282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski boolean neg = value < 0; 647282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (neg) { 648282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski value = -value; 649282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 650282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski long bits = (long)(value*(1<<23)+.5f); 651282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int radix; 652282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int shift; 653282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if ((bits&0x7fffff) == 0) { 654282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Always use 23p0 if there is no fraction, just to make 655282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // things easier to read. 656282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski radix = TypedValue.COMPLEX_RADIX_23p0; 657282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski shift = 23; 658282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if ((bits&0xffffffffff800000L) == 0) { 659282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Magnitude is zero -- can fit in 0 bits of precision. 660282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski radix = TypedValue.COMPLEX_RADIX_0p23; 661282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski shift = 0; 662282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if ((bits&0xffffffff80000000L) == 0) { 663282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Magnitude can fit in 8 bits of precision. 664282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski radix = TypedValue.COMPLEX_RADIX_8p15; 665282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski shift = 8; 666282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if ((bits&0xffffff8000000000L) == 0) { 667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Magnitude can fit in 16 bits of precision. 668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski radix = TypedValue.COMPLEX_RADIX_16p7; 669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski shift = 16; 670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Magnitude needs entire range, so no fractional part. 672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski radix = TypedValue.COMPLEX_RADIX_23p0; 673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski shift = 23; 674282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 675282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int mantissa = (int)( 676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (bits>>shift) & TypedValue.COMPLEX_MANTISSA_MASK); 677282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (neg) { 678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mantissa = (-mantissa) & TypedValue.COMPLEX_MANTISSA_MASK; 679282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 680282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue.data |= 681282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski (radix<<TypedValue.COMPLEX_RADIX_SHIFT) 682282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski | (mantissa<<TypedValue.COMPLEX_MANTISSA_SHIFT); 683282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 685282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static boolean parseUnit(String str, TypedValue outValue, float[] outScale) { 686282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski str = str.trim(); 687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (UnitEntry unit : sUnitNames) { 689282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (unit.name.equals(str)) { 690282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski applyUnit(unit, outValue, outScale); 691282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 692282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 693282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 694282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 695282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 696282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static void applyUnit(UnitEntry unit, TypedValue outValue, float[] outScale) { 699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue.type = unit.type; 7001a12b805698c7cba9c2daa78c76c055afbdfa9fcDeepanshu Gupta // COMPLEX_UNIT_SHIFT is 0 and hence intelliJ complains about it. Suppress the warning. 7011a12b805698c7cba9c2daa78c76c055afbdfa9fcDeepanshu Gupta //noinspection PointlessBitwiseExpression 702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT; 703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski outScale[0] = unit.scale; 704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 707