19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetpackage com.android.layoutlib.bridge.impl; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1919a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.DensityBasedResourceValue; 20918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohetimport com.android.ide.common.rendering.api.LayoutLog; 21bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport com.android.ide.common.rendering.api.RenderResources; 2219a021038f2f4683dddef651543d7298f5bd7218Xavier Ducrohetimport com.android.ide.common.rendering.api.ResourceValue; 23c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 24c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeContext; 25c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohetimport com.android.layoutlib.bridge.android.BridgeXmlBlockParser; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.ninepatch.NinePatch; 272d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport com.android.ninepatch.NinePatchChunk; 2816584225125acba18b74920b902c798dfead0328Xavier Ducrohetimport com.android.resources.Density; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParser; 31bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport org.xmlpull.v1.XmlPullParserException; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohetimport android.content.res.ColorStateList; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap; 355de11a18e9151e6bc9b3e81cf31fc43dc63dffbfXavier Ducrohetimport android.graphics.Bitmap_Delegate; 362d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport android.graphics.NinePatch_Delegate; 372d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport android.graphics.Rect; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.BitmapDrawable; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.ColorDrawable; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.drawable.Drawable; 412d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohetimport android.graphics.drawable.NinePatchDrawable; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.TypedValue; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File; 4513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohetimport java.io.FileInputStream; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException; 4713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohetimport java.io.InputStream; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.net.MalformedURLException; 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Matcher; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Pattern; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 5390c6b7e639921e264ac65699439578bcbdbf583aXavier Ducrohet * Helper class to provide various conversion method used in handling android resources. 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic final class ResourceHelper { 5656a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static Pattern sFloatPattern = Pattern.compile("(-?[0-9]+(?:\\.[0-9]+)?)(.*)"); 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static float[] sFloatOut = new float[1]; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static TypedValue mValue = new TypedValue(); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the color value represented by the given string value 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value the color value 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the color as an int 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @throw NumberFormatException if the conversion failed. 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 68c2e9651bf386a1f7bf7fc706cf5424950570470cXavier Ducrohet public static int getColor(String value) { 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value != null) { 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.startsWith("#") == false) { 7156222cfbe9973c518f7e8c9113c614de80b5a4b2Xavier Ducrohet throw new NumberFormatException( 7256222cfbe9973c518f7e8c9113c614de80b5a4b2Xavier Ducrohet String.format("Color value '%s' must start with #", value)); 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = value.substring(1); 7656a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure it's not longer than 32bit 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.length() > 8) { 7956222cfbe9973c518f7e8c9113c614de80b5a4b2Xavier Ducrohet throw new NumberFormatException(String.format( 8056222cfbe9973c518f7e8c9113c614de80b5a4b2Xavier Ducrohet "Color value '%s' is too long. Format is either" + 8156222cfbe9973c518f7e8c9113c614de80b5a4b2Xavier Ducrohet "#AARRGGBB, #RRGGBB, #RGB, or #ARGB", 8256222cfbe9973c518f7e8c9113c614de80b5a4b2Xavier Ducrohet value)); 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8456a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value.length() == 3) { // RGB format 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] color = new char[8]; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project color[0] = color[1] = 'F'; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project color[2] = color[3] = value.charAt(0); 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project color[4] = color[5] = value.charAt(1); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project color[6] = color[7] = value.charAt(2); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = new String(color); 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (value.length() == 4) { // ARGB format 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char[] color = new char[8]; 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project color[0] = color[1] = value.charAt(0); 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project color[2] = color[3] = value.charAt(1); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project color[4] = color[5] = value.charAt(2); 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project color[6] = color[7] = value.charAt(3); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = new String(color); 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (value.length() == 6) { 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = "FF" + value; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this is a RRGGBB or AARRGGBB value 10456a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Integer.parseInt will fail to parse strings like "ff191919", so we use 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // a Long, but cast the result back into an int, since we know that we're only 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // dealing with 32 bit values. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (int)Long.parseLong(value, 16); 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new NumberFormatException(); 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 114bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet public static ColorStateList getColorStateList(ResourceValue resValue, BridgeContext context) { 115bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet String value = resValue.getValue(); 1162fae858db55fc6984ef923a6226b9408c37c72cbXavier Ducrohet if (value != null && RenderResources.REFERENCE_NULL.equals(value) == false) { 117bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // first check if the value is a file (xml most likely) 118bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet File f = new File(value); 119bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (f.isFile()) { 120bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet try { 121bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // let the framework inflate the ColorStateList from the XML file, by 122bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // providing an XmlPullParser 12304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet XmlPullParser parser = ParserFactory.create(f); 124bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 12502d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 12602d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet parser, context, resValue.isFramework()); 12702d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet try { 12802d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet return ColorStateList.createFromXml(context.getResources(), blockParser); 12902d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet } finally { 13002d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet blockParser.ensurePopped(); 13102d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet } 132bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (XmlPullParserException e) { 133bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet Bridge.getLog().error(LayoutLog.TAG_BROKEN, 134bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet "Failed to configure parser for " + value, e, null /*data*/); 135bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // we'll return null below. 136bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (Exception e) { 137bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // this is an error and not warning since the file existence is 138bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // checked before attempting to parse it. 139bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, 140bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet "Failed to parse file " + value, e, null /*data*/); 141bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 142bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return null; 143bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 144bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } else { 145bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet // try to load the color state list from an int 146bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet try { 147bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet int color = ResourceHelper.getColor(value); 148bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return ColorStateList.valueOf(color); 149bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } catch (NumberFormatException e) { 150bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, 151bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet "Failed to convert " + value + " into a ColorStateList", e, 152bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet null /*data*/); 153bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return null; 154bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 155bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 156bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 157bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 158bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return null; 159bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 160bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns a drawable from the given value. 16356a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable, 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or an hexadecimal color 165bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet * @param context the current context 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 167bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet public static Drawable getDrawable(ResourceValue value, BridgeContext context) { 16856a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet String stringValue = value.getValue(); 169bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet if (RenderResources.REFERENCE_NULL.equals(stringValue)) { 170bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet return null; 171bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet } 17256a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 17356a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet String lowerCaseValue = stringValue.toLowerCase(); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet Density density = Density.MEDIUM; 17613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (value instanceof DensityBasedResourceValue) { 17713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet density = 17813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet ((DensityBasedResourceValue)value).getResourceDensity(); 17913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 18013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 18113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lowerCaseValue.endsWith(NinePatch.EXTENSION_9PATCH)) { 18356a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet File file = new File(stringValue); 18456a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet if (file.isFile()) { 18513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet try { 18613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet return getNinePatchDrawable( 18713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet new FileInputStream(file), density, value.isFramework(), 18813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet stringValue, context); 18913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } catch (IOException e) { 19013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet // failed to read the file, we'll return null below. 19113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, 19213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet "Failed lot load " + file.getAbsolutePath(), e, null /*data*/); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19556a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (lowerCaseValue.endsWith(".xml")) { 19890c6b7e639921e264ac65699439578bcbdbf583aXavier Ducrohet // create a block parser for the file 19956a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet File f = new File(stringValue); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (f.isFile()) { 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // let the framework inflate the Drawable from the XML file. 20304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet XmlPullParser parser = ParserFactory.create(f); 20456a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 20502d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser( 20602d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet parser, context, value.isFramework()); 20702d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet try { 20802d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet return Drawable.createFromXml(context.getResources(), blockParser); 20902d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet } finally { 21002d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet blockParser.ensurePopped(); 21102d2b5a4031c80bfe1012ce2f4f7b3695762abd9Xavier Ducrohet } 2126c740cf71e5ce5ba7c8493c545c3a57c57ac7024Xavier Ducrohet } catch (Exception e) { 2136c740cf71e5ce5ba7c8493c545c3a57c57ac7024Xavier Ducrohet // this is an error and not warning since the file existence is checked before 2146c740cf71e5ce5ba7c8493c545c3a57c57ac7024Xavier Ducrohet // attempting to parse it. 215b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet Bridge.getLog().error(null, "Failed to parse file " + stringValue, 216b353495192ba1acce94b8ab8aeeffe3c9a3bcfacXavier Ducrohet e, null /*data*/); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2186c740cf71e5ce5ba7c8493c545c3a57c57ac7024Xavier Ducrohet } else { 219918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohet Bridge.getLog().error(LayoutLog.TAG_BROKEN, 22051a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet String.format("File %s does not exist (or is not a file)", stringValue), 22151a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet null /*data*/); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 22656a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet File bmpFile = new File(stringValue); 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bmpFile.isFile()) { 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 22956a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet Bitmap bitmap = Bridge.getCachedBitmap(stringValue, 230bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet value.isFramework() ? null : context.getProjectKey()); 23156a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bitmap == null) { 2332d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/, 2342d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet density); 2352d56b273ef6e2984a4e8914fb67772b173d0a154Xavier Ducrohet Bridge.setCachedBitmap(stringValue, bitmap, 236bbbb8326020368958a3f1d248878329e9d6b10c0Xavier Ducrohet value.isFramework() ? null : context.getProjectKey()); 23756a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet } 23856a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 23956a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet return new BitmapDrawable(context.getResources(), bitmap); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (IOException e) { 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we'll return null below 242918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohet Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, 24351a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet "Failed lot load " + bmpFile.getAbsolutePath(), e, null /*data*/); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // attempt to get a color from the value 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 24856a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet int color = getColor(stringValue); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new ColorDrawable(color); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we'll return null below. 252918aaa5717fce6081557c82ce1c439b6922737d5Xavier Ducrohet Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, 25351a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet "Failed to convert " + stringValue + " into a drawable", e, 25451a7e5447de94791c464cda5cc6ebbf616d73c80Xavier Ducrohet null /*data*/); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25856a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet private static Drawable getNinePatchDrawable(InputStream inputStream, Density density, 26313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet boolean isFramework, String cacheKey, BridgeContext context) throws IOException { 26413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet // see if we still have both the chunk and the bitmap in the caches 26513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet NinePatchChunk chunk = Bridge.getCached9Patch(cacheKey, 26613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet isFramework ? null : context.getProjectKey()); 26713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet Bitmap bitmap = Bridge.getCachedBitmap(cacheKey, 26813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet isFramework ? null : context.getProjectKey()); 26913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 27013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet // if either chunk or bitmap is null, then we reload the 9-patch file. 27113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (chunk == null || bitmap == null) { 27213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet try { 27313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet NinePatch ninePatch = NinePatch.load(inputStream, true /*is9Patch*/, 27413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet false /* convert */); 27513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (ninePatch != null) { 27613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (chunk == null) { 27713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet chunk = ninePatch.getChunk(); 27813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 27913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet Bridge.setCached9Patch(cacheKey, chunk, 28013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet isFramework ? null : context.getProjectKey()); 28113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 28213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 28313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (bitmap == null) { 28413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(), 28513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet false /*isMutable*/, 28613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet density); 28713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 28813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet Bridge.setCachedBitmap(cacheKey, bitmap, 28913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet isFramework ? null : context.getProjectKey()); 29013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 29113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 29213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } catch (MalformedURLException e) { 29313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet // URL is wrong, we'll return null below 29413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 29513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 29613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 29713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (chunk != null && bitmap != null) { 29813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet int[] padding = chunk.getPadding(); 29913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet Rect paddingRect = new Rect(padding[0], padding[1], padding[2], padding[3]); 30013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 30113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet return new NinePatchDrawable(context.getResources(), bitmap, 30213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet NinePatch_Delegate.serialize(chunk), 30313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet paddingRect, null); 30413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 30513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 30613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet return null; 30713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 30856a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ------- TypedValue stuff 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is taken from //device/libs/utils/ResourceTypes.cpp 31156a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final class UnitEntry { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String name; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int type; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int unit; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float scale; 31756a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project UnitEntry(String name, int type, int unit, float scale) { 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.name = name; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.type = type; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.unit = unit; 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.scale = scale; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final static UnitEntry[] sUnitNames = new UnitEntry[] { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new UnitEntry("px", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_PX, 1.0f), 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new UnitEntry("dip", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_DIP, 1.0f), 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new UnitEntry("dp", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_DIP, 1.0f), 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new UnitEntry("sp", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_SP, 1.0f), 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new UnitEntry("pt", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_PT, 1.0f), 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new UnitEntry("in", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_IN, 1.0f), 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new UnitEntry("mm", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_MM, 1.0f), 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new UnitEntry("%", TypedValue.TYPE_FRACTION, TypedValue.COMPLEX_UNIT_FRACTION, 1.0f/100), 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new UnitEntry("%p", TypedValue.TYPE_FRACTION, TypedValue.COMPLEX_UNIT_FRACTION_PARENT, 1.0f/100), 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 33756a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 33904ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet * Returns the raw value from the given attribute float-type value string. 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This object is only valid until the next call on to {@link ResourceHelper}. 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 34204ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet public static TypedValue getValue(String attribute, String value, boolean requireUnit) { 34304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet if (parseFloatAttribute(attribute, value, mValue, requireUnit)) { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mValue; 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34656a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34956a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 35104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet * Parse a float attribute and return the parsed value into a given TypedValue. 35204ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet * @param attribute the name of the attribute. Can be null if <var>requireUnit</var> is false. 35304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet * @param value the string value of the attribute 35404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet * @param outValue the TypedValue to receive the parsed value 35504ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet * @param requireUnit whether the value is expected to contain a unit. 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if success. 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 35804ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet public static boolean parseFloatAttribute(String attribute, String value, 35904ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet TypedValue outValue, boolean requireUnit) { 36004ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet assert requireUnit == false || attribute != null; 36104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // remove the space before and after 36304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet value = value.trim(); 36404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet int len = value.length(); 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (len <= 0) { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // check that there's no non ascii characters. 37104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet char[] buf = value.toCharArray(); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0 ; i < len ; i++) { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (buf[i] > 255) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // check the first character 3796f2fb570642189ec2b6068632c25f02391007bb5Xavier Ducrohet if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.' && buf[0] != '-') { 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 38256a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // now look for the string that is after the float... 38404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet Matcher m = sFloatPattern.matcher(value); 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (m.matches()) { 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String f_str = m.group(1); 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String end = m.group(2); 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project float f; 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project f = Float.parseFloat(f_str); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // this shouldn't happen with the regexp above. 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 39656a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end.length() > 0 && end.charAt(0) != ' ') { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Might be a unit... 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (parseUnit(end, outValue, sFloatOut)) { 40004ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet computeTypedValue(outValue, f, sFloatOut[0]); 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 40556a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure it's only spaces at the end. 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end = end.trim(); 40856a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end.length() == 0) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (outValue != null) { 41104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet if (requireUnit == false) { 41204ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet outValue.type = TypedValue.TYPE_FLOAT; 41304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet outValue.data = Float.floatToIntBits(f); 41404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } else { 41504ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet // no unit when required? Use dp and out an error. 41604ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet applyUnit(sUnitNames[1], outValue, sFloatOut); 41704ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet computeTypedValue(outValue, f, sFloatOut[0]); 41804ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet 41904ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE, 42004ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet String.format( 42104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet "Dimension \"%1$s\" in attribute \"%2$s\" is missing unit!", 42204ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet value, attribute), 42304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet null); 42404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 43256a92e3ba0d7da310b4c6e09f54dee10f1f395bbXavier Ducrohet 43304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet private static void computeTypedValue(TypedValue outValue, float value, float scale) { 43404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet value *= scale; 43504ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet boolean neg = value < 0; 43604ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet if (neg) { 43704ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet value = -value; 43804ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } 43904ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet long bits = (long)(value*(1<<23)+.5f); 44004ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet int radix; 44104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet int shift; 44204ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet if ((bits&0x7fffff) == 0) { 44304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet // Always use 23p0 if there is no fraction, just to make 44404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet // things easier to read. 44504ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet radix = TypedValue.COMPLEX_RADIX_23p0; 44604ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet shift = 23; 44704ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } else if ((bits&0xffffffffff800000L) == 0) { 44804ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet // Magnitude is zero -- can fit in 0 bits of precision. 44904ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet radix = TypedValue.COMPLEX_RADIX_0p23; 45004ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet shift = 0; 45104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } else if ((bits&0xffffffff80000000L) == 0) { 45204ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet // Magnitude can fit in 8 bits of precision. 45304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet radix = TypedValue.COMPLEX_RADIX_8p15; 45404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet shift = 8; 45504ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } else if ((bits&0xffffff8000000000L) == 0) { 45604ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet // Magnitude can fit in 16 bits of precision. 45704ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet radix = TypedValue.COMPLEX_RADIX_16p7; 45804ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet shift = 16; 45904ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } else { 46004ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet // Magnitude needs entire range, so no fractional part. 46104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet radix = TypedValue.COMPLEX_RADIX_23p0; 46204ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet shift = 23; 46304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } 46404ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet int mantissa = (int)( 46504ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet (bits>>shift) & TypedValue.COMPLEX_MANTISSA_MASK); 46604ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet if (neg) { 46704ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet mantissa = (-mantissa) & TypedValue.COMPLEX_MANTISSA_MASK; 46804ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } 46904ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet outValue.data |= 47004ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet (radix<<TypedValue.COMPLEX_RADIX_SHIFT) 47104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet | (mantissa<<TypedValue.COMPLEX_MANTISSA_SHIFT); 47204ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } 47304ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static boolean parseUnit(String str, TypedValue outValue, float[] outScale) { 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project str = str.trim(); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (UnitEntry unit : sUnitNames) { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (unit.name.equals(str)) { 47904ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet applyUnit(unit, outValue, outScale); 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 48604ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet 48704ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet private static void applyUnit(UnitEntry unit, TypedValue outValue, float[] outScale) { 48804ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet outValue.type = unit.type; 48904ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT; 49004ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet outScale[0] = unit.scale; 49104ce81113107d2bfa0b8248b13145b4cf24cb943Xavier Ducrohet } 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 49313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 494