am d1abd94f: am 04ce8111: Bring in more layout lib changes from hc-mr1.

* commit 'd1abd94f57c0162186c57aea98790e8fa281e0a2':
  Bring in more layout lib changes from hc-mr1.
This commit is contained in:
Xavier Ducrohet
2011-06-16 13:55:30 -07:00
committed by Android Git Automerger
14 changed files with 328 additions and 196 deletions

View File

@ -25,11 +25,11 @@ import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.StyleResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
import com.android.layoutlib.bridge.impl.ParserFactory;
import com.android.layoutlib.bridge.impl.Stack;
import com.android.resources.ResourceType;
import com.android.util.Pair;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@ -206,6 +206,9 @@ public final class BridgeContext extends Activity {
* @param parser the parser to add.
*/
public void pushParser(BridgeXmlBlockParser parser) {
if (ParserFactory.LOG_PARSER) {
System.out.println("PUSH " + parser.getParser().toString());
}
mParserStack.push(parser);
}
@ -213,7 +216,10 @@ public final class BridgeContext extends Activity {
* Removes the parser at the top of the stack
*/
public void popParser() {
mParserStack.pop();
BridgeXmlBlockParser parser = mParserStack.pop();
if (ParserFactory.LOG_PARSER) {
System.out.println("POPD " + parser.getParser().toString());
}
}
/**
@ -346,9 +352,7 @@ public final class BridgeContext extends Activity {
// we need to create a pull parser around the layout XML file, and then
// give that to our XmlBlockParser
try {
KXmlParser parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileInputStream(xml), "UTF-8"); //$NON-NLS-1$);
XmlPullParser parser = ParserFactory.create(xml);
// set the resource ref to have correct view cookies
mBridgeInflater.setResourceReference(resource);
@ -687,25 +691,25 @@ public final class BridgeContext extends Activity {
*/
private BridgeTypedArray createStyleBasedTypedArray(StyleResourceValue style, int[] attrs)
throws Resources.NotFoundException {
AtomicBoolean frameworkAttributes = new AtomicBoolean();
AtomicReference<String> attrName = new AtomicReference<String>();
TreeMap<Integer, String> styleNameMap = searchAttrs(attrs, frameworkAttributes, attrName);
BridgeTypedArray ta = ((BridgeResources) mSystemResources).newTypeArray(attrs.length,
style.isFramework(), frameworkAttributes.get(), attrName.get());
false, true, null);
// loop through all the values in the style map, and init the TypedArray with
// the style we got from the dynamic id
for (Entry<Integer, String> styleAttribute : styleNameMap.entrySet()) {
int index = styleAttribute.getKey().intValue();
// for each attribute, get its name so that we can search it in the style
for (int i = 0 ; i < attrs.length ; i++) {
Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attrs[i]);
if (resolvedResource != null) {
String attrName = resolvedResource.getSecond();
// look for the value in the given style
ResourceValue resValue = mRenderResources.findItemInStyle(style, attrName);
String name = styleAttribute.getValue();
if (resValue != null) {
// resolve it to make sure there are no references left.
ta.bridgeSetValue(i, attrName, mRenderResources.resolveResValue(resValue));
// get the value from the style, or its parent styles.
ResourceValue resValue = mRenderResources.findItemInStyle(style, name);
// resolve it to make sure there are no references left.
ta.bridgeSetValue(index, name, mRenderResources.resolveResValue(resValue));
resValue = mRenderResources.resolveResValue(resValue);
}
}
}
ta.sealArray();

View File

@ -22,10 +22,10 @@ import com.android.ide.common.rendering.api.MergeCookie;
import com.android.ide.common.rendering.api.ResourceReference;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.ParserFactory;
import com.android.resources.ResourceType;
import com.android.util.Pair;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import android.content.Context;
@ -36,7 +36,6 @@ import android.view.View;
import android.view.ViewGroup;
import java.io.File;
import java.io.FileInputStream;
/**
* Custom implementation of {@link LayoutInflater} to handle custom views.
@ -175,9 +174,7 @@ public final class BridgeInflater extends LayoutInflater {
File f = new File(value.getValue());
if (f.isFile()) {
try {
KXmlParser parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$
XmlPullParser parser = ParserFactory.create(f);
BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
parser, bridgeContext, false);

View File

@ -21,12 +21,12 @@ import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
import com.android.layoutlib.bridge.impl.ParserFactory;
import com.android.layoutlib.bridge.impl.ResourceHelper;
import com.android.ninepatch.NinePatch;
import com.android.resources.ResourceType;
import com.android.util.Pair;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@ -131,14 +131,16 @@ public final class BridgeResources extends Resources {
platformStyleable, styleableName);
}
private ResourceValue getResourceValue(int id, boolean[] platformResFlag_out) {
private Pair<String, ResourceValue> getResourceValue(int id, boolean[] platformResFlag_out) {
// first get the String related to this id in the framework
Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
if (resourceInfo != null) {
platformResFlag_out[0] = true;
return mContext.getRenderResources().getFrameworkResource(
resourceInfo.getFirst(), resourceInfo.getSecond());
String attributeName = resourceInfo.getSecond();
return Pair.of(attributeName, mContext.getRenderResources().getFrameworkResource(
resourceInfo.getFirst(), attributeName));
}
// didn't find a match in the framework? look in the project.
@ -147,8 +149,10 @@ public final class BridgeResources extends Resources {
if (resourceInfo != null) {
platformResFlag_out[0] = false;
return mContext.getRenderResources().getProjectResource(
resourceInfo.getFirst(), resourceInfo.getSecond());
String attributeName = resourceInfo.getSecond();
return Pair.of(attributeName, mContext.getRenderResources().getProjectResource(
resourceInfo.getFirst(), attributeName));
}
}
@ -157,10 +161,10 @@ public final class BridgeResources extends Resources {
@Override
public Drawable getDrawable(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
return ResourceHelper.getDrawable(value, mContext);
return ResourceHelper.getDrawable(value.getSecond(), mContext);
}
// id was not found or not resolved. Throw a NotFoundException.
@ -172,11 +176,11 @@ public final class BridgeResources extends Resources {
@Override
public int getColor(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
try {
return ResourceHelper.getColor(value.getValue());
return ResourceHelper.getColor(value.getSecond().getValue());
} catch (NumberFormatException e) {
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e,
null /*data*/);
@ -193,10 +197,11 @@ public final class BridgeResources extends Resources {
@Override
public ColorStateList getColorStateList(int id) throws NotFoundException {
ResourceValue resValue = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> resValue = getResourceValue(id, mPlatformResourceFlag);
if (resValue != null) {
ColorStateList stateList = ResourceHelper.getColorStateList(resValue, mContext);
ColorStateList stateList = ResourceHelper.getColorStateList(resValue.getSecond(),
mContext);
if (stateList != null) {
return stateList;
}
@ -211,10 +216,10 @@ public final class BridgeResources extends Resources {
@Override
public CharSequence getText(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
return value.getValue();
return value.getSecond().getValue();
}
// id was not found or not resolved. Throw a NotFoundException.
@ -226,9 +231,10 @@ public final class BridgeResources extends Resources {
@Override
public XmlResourceParser getLayout(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
if (v != null) {
ResourceValue value = v.getSecond();
XmlPullParser parser = null;
try {
@ -243,9 +249,7 @@ public final class BridgeResources extends Resources {
if (xml.isFile()) {
// we need to create a pull parser around the layout XML file, and then
// give that to our XmlBlockParser
parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileInputStream(xml), "UTF-8"); //$NON-NLS-1$);
parser = ParserFactory.create(xml);
}
}
@ -271,9 +275,10 @@ public final class BridgeResources extends Resources {
@Override
public XmlResourceParser getAnimation(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> v = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
if (v != null) {
ResourceValue value = v.getSecond();
XmlPullParser parser = null;
try {
@ -281,9 +286,7 @@ public final class BridgeResources extends Resources {
if (xml.isFile()) {
// we need to create a pull parser around the layout XML file, and then
// give that to our XmlBlockParser
parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileInputStream(xml), "UTF-8"); //$NON-NLS-1$);
parser = ParserFactory.create(xml);
return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
}
@ -317,10 +320,10 @@ public final class BridgeResources extends Resources {
@Override
public float getDimension(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
String v = value.getValue();
String v = value.getSecond().getValue();
if (v != null) {
if (v.equals(BridgeConstants.MATCH_PARENT) ||
@ -330,7 +333,8 @@ public final class BridgeResources extends Resources {
return LayoutParams.WRAP_CONTENT;
}
if (ResourceHelper.stringToFloat(v, mTmpValue) &&
if (ResourceHelper.parseFloatAttribute(
value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
mTmpValue.type == TypedValue.TYPE_DIMENSION) {
return mTmpValue.getDimension(mMetrics);
}
@ -346,13 +350,14 @@ public final class BridgeResources extends Resources {
@Override
public int getDimensionPixelOffset(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
String v = value.getValue();
String v = value.getSecond().getValue();
if (v != null) {
if (ResourceHelper.stringToFloat(v, mTmpValue) &&
if (ResourceHelper.parseFloatAttribute(
value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
mTmpValue.type == TypedValue.TYPE_DIMENSION) {
return TypedValue.complexToDimensionPixelOffset(mTmpValue.data, mMetrics);
}
@ -368,13 +373,14 @@ public final class BridgeResources extends Resources {
@Override
public int getDimensionPixelSize(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
String v = value.getValue();
String v = value.getSecond().getValue();
if (v != null) {
if (ResourceHelper.stringToFloat(v, mTmpValue) &&
if (ResourceHelper.parseFloatAttribute(
value.getFirst(), v, mTmpValue, true /*requireUnit*/) &&
mTmpValue.type == TypedValue.TYPE_DIMENSION) {
return TypedValue.complexToDimensionPixelSize(mTmpValue.data, mMetrics);
}
@ -390,10 +396,10 @@ public final class BridgeResources extends Resources {
@Override
public int getInteger(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null && value.getValue() != null) {
String v = value.getValue();
if (value != null && value.getSecond().getValue() != null) {
String v = value.getSecond().getValue();
int radix = 10;
if (v.startsWith("0x")) {
v = v.substring(2);
@ -445,10 +451,10 @@ public final class BridgeResources extends Resources {
@Override
public String getString(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null && value.getValue() != null) {
return value.getValue();
if (value != null && value.getSecond().getValue() != null) {
return value.getSecond().getValue();
}
// id was not found or not resolved. Throw a NotFoundException.
@ -461,13 +467,14 @@ public final class BridgeResources extends Resources {
@Override
public void getValue(int id, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
String v = value.getValue();
String v = value.getSecond().getValue();
if (v != null) {
if (ResourceHelper.stringToFloat(v, outValue)) {
if (ResourceHelper.parseFloatAttribute(value.getFirst(), v, outValue,
false /*requireUnit*/)) {
return;
}
@ -490,19 +497,17 @@ public final class BridgeResources extends Resources {
@Override
public XmlResourceParser getXml(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
String v = value.getValue();
String v = value.getSecond().getValue();
if (v != null) {
// check this is a file
File f = new File(value.getValue());
File f = new File(v);
if (f.isFile()) {
try {
KXmlParser parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$);
XmlPullParser parser = ParserFactory.create(f);
return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
} catch (XmlPullParserException e) {
@ -535,9 +540,7 @@ public final class BridgeResources extends Resources {
File f = new File(file);
try {
KXmlParser parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$);
XmlPullParser parser = ParserFactory.create(f);
return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
} catch (XmlPullParserException e) {
@ -554,10 +557,10 @@ public final class BridgeResources extends Resources {
@Override
public InputStream openRawResource(int id) throws NotFoundException {
ResourceValue value = getResourceValue(id, mPlatformResourceFlag);
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
String path = value.getValue();
String path = value.getSecond().getValue();
if (path != null) {
// check this is a file

View File

@ -24,10 +24,10 @@ import com.android.ide.common.rendering.api.StyleResourceValue;
import com.android.internal.util.XmlUtils;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
import com.android.layoutlib.bridge.impl.ParserFactory;
import com.android.layoutlib.bridge.impl.ResourceHelper;
import com.android.resources.ResourceType;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@ -41,7 +41,6 @@ import android.view.LayoutInflater_Delegate;
import android.view.ViewGroup.LayoutParams;
import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.Map;
@ -211,7 +210,7 @@ public final class BridgeTypedArray extends TypedArray {
Map<String, Integer> map = null;
if (mPlatformStyleable) {
map = Bridge.getEnumValues(mNames[index]);
} else {
} else if (mStyleableName != null) {
// get the styleable matching the resolved name
RenderResources res = mContext.getRenderResources();
ResourceValue styleable = res.getProjectResource(ResourceType.DECLARE_STYLEABLE,
@ -331,9 +330,7 @@ public final class BridgeTypedArray extends TypedArray {
File f = new File(value);
if (f.isFile()) {
try {
KXmlParser parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$);
XmlPullParser parser = ParserFactory.create(f);
BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
parser, mContext, resValue.isFramework());
@ -377,26 +374,7 @@ public final class BridgeTypedArray extends TypedArray {
*/
@Override
public int getInteger(int index, int defValue) {
if (mResourceData[index] == null) {
return defValue;
}
String s = mResourceData[index].getValue();
if (s != null) {
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
"\"%s\" in attribute \"%2$s\" cannont be converted to an integer.",
s, mNames[index]), null /*data*/);
// The default value is returned below.
}
}
return defValue;
return getInt(index, defValue);
}
/**
@ -434,7 +412,7 @@ public final class BridgeTypedArray extends TypedArray {
return defValue;
}
if (ResourceHelper.stringToFloat(s, mValue)) {
if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true /*requireUnit*/)) {
return mValue.getDimension(mBridgeResources.mMetrics);
}
@ -561,7 +539,7 @@ public final class BridgeTypedArray extends TypedArray {
throw new RuntimeException();
}
if (ResourceHelper.stringToFloat(s, mValue)) {
if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true /*requireUnit*/)) {
float f = mValue.getDimension(mBridgeResources.mMetrics);
final int res = (int)(f+0.5f);
@ -599,14 +577,15 @@ public final class BridgeTypedArray extends TypedArray {
return defValue;
}
if (ResourceHelper.stringToFloat(value, mValue)) {
if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue,
false /*requireUnit*/)) {
return mValue.getFraction(base, pbase);
}
// looks like we were unable to resolve the fraction value
Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
String.format(
"\"%1$s\" in attribute \"%2$s\" cannont be converted to a fraction.",
"\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.",
value, mNames[index]), null /*data*/);
return defValue;
@ -803,7 +782,8 @@ public final class BridgeTypedArray extends TypedArray {
String s = mResourceData[index].getValue();
return ResourceHelper.stringToFloat(s, outValue);
return ResourceHelper.parseFloatAttribute(mNames[index], s, outValue,
false /*requireUnit*/);
}
/**

View File

@ -18,6 +18,7 @@ package com.android.layoutlib.bridge.android;
import com.android.ide.common.rendering.api.ILayoutPullParser;
import com.android.layoutlib.bridge.impl.ParserFactory;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@ -54,6 +55,10 @@ public class BridgeXmlBlockParser implements XmlResourceParser {
* @param platformFile Indicates whether the the file is a platform file or not.
*/
public BridgeXmlBlockParser(XmlPullParser parser, BridgeContext context, boolean platformFile) {
if (ParserFactory.LOG_PARSER) {
System.out.println("CRTE " + parser.toString());
}
mParser = parser;
mContext = context;
mPlatformFile = platformFile;
@ -65,6 +70,10 @@ public class BridgeXmlBlockParser implements XmlResourceParser {
}
}
public XmlPullParser getParser() {
return mParser;
}
public boolean isPlatformFile() {
return mPlatformFile;
}
@ -247,18 +256,63 @@ public class BridgeXmlBlockParser implements XmlResourceParser {
public int next() throws XmlPullParserException, IOException {
if (!mStarted) {
mStarted = true;
if (ParserFactory.LOG_PARSER) {
System.out.println("STRT " + mParser.toString());
}
return START_DOCUMENT;
}
int ev = mParser.next();
if (ParserFactory.LOG_PARSER) {
System.out.println("NEXT " + mParser.toString() + " " +
eventTypeToString(mEventType) + " -> " + eventTypeToString(ev));
}
if (ev == END_TAG && mParser.getDepth() == 1) {
// done with parser remove it from the context stack.
ensurePopped();
if (ParserFactory.LOG_PARSER) {
System.out.println("");
}
}
mEventType = ev;
return ev;
}
public static String eventTypeToString(int eventType) {
switch (eventType) {
case START_DOCUMENT:
return "START_DOC";
case END_DOCUMENT:
return "END_DOC";
case START_TAG:
return "START_TAG";
case END_TAG:
return "END_TAG";
case TEXT:
return "TEXT";
case CDSECT:
return "CDSECT";
case ENTITY_REF:
return "ENTITY_REF";
case IGNORABLE_WHITESPACE:
return "IGNORABLE_WHITESPACE";
case PROCESSING_INSTRUCTION:
return "PROCESSING_INSTRUCTION";
case COMMENT:
return "COMMENT";
case DOCDECL:
return "DOCDECL";
}
return "????";
}
public void require(int type, String namespace, String name)
throws XmlPullParserException {
if (type != getEventType()

View File

@ -22,11 +22,11 @@ import com.android.ide.common.rendering.api.StyleResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import com.android.layoutlib.bridge.impl.ParserFactory;
import com.android.layoutlib.bridge.impl.ResourceHelper;
import com.android.resources.Density;
import com.android.resources.ResourceType;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@ -60,7 +60,7 @@ abstract class CustomBar extends LinearLayout {
protected abstract TextView getStyleableTextView();
protected CustomBar(Context context, Density density, String layoutPath)
protected CustomBar(Context context, Density density, String layoutPath, String name)
throws XmlPullParserException {
super(context);
setOrientation(LinearLayout.HORIZONTAL);
@ -69,11 +69,8 @@ abstract class CustomBar extends LinearLayout {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
KXmlParser parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(
getClass().getResourceAsStream(layoutPath),
"UTF8"); //$NON-NLS-1$
XmlPullParser parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath),
name);
BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
parser, (BridgeContext) context, false /*platformFile*/);
@ -230,7 +227,8 @@ abstract class CustomBar extends LinearLayout {
if (textSize != null) {
TypedValue out = new TypedValue();
if (ResourceHelper.stringToFloat(textSize.getValue(), out)) {
if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out,
true /*requireUnit*/)) {
textView.setTextSize(
out.getDimension(bridgeContext.getResources().mMetrics));
}

View File

@ -29,7 +29,7 @@ public class FakeActionBar extends CustomBar {
public FakeActionBar(Context context, Density density, String label, String icon)
throws XmlPullParserException {
super(context, density, "/bars/action_bar.xml");
super(context, density, "/bars/action_bar.xml", "action_bar.xml");
// Cannot access the inside items through id because no R.id values have been
// created for them.

View File

@ -30,7 +30,7 @@ import android.widget.TextView;
public class PhoneSystemBar extends CustomBar {
public PhoneSystemBar(Context context, Density density) throws XmlPullParserException {
super(context, density, "/bars/phone_system_bar.xml");
super(context, density, "/bars/phone_system_bar.xml", "phone_system_bar.xml");
setGravity(mGravity | Gravity.RIGHT);
setBackgroundColor(0xFF000000);

View File

@ -29,7 +29,7 @@ import android.widget.TextView;
public class TabletSystemBar extends CustomBar {
public TabletSystemBar(Context context, Density density) throws XmlPullParserException {
super(context, density, "/bars/tablet_system_bar.xml");
super(context, density, "/bars/tablet_system_bar.xml", "tablet_system_bar.xml");
setBackgroundColor(0xFF000000);

View File

@ -29,7 +29,7 @@ public class TitleBar extends CustomBar {
public TitleBar(Context context, Density density, String label)
throws XmlPullParserException {
super(context, density, "/bars/title_bar.xml");
super(context, density, "/bars/title_bar.xml", "title_bar.xml");
// Cannot access the inside items through id because no R.id values have been
// created for them.

View File

@ -0,0 +1,77 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.layoutlib.bridge.impl;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
/**
* A factory for {@link XmlPullParser}.
*
*/
public class ParserFactory {
private final static String ENCODING = "UTF-8"; //$NON-NLS-1$
public final static boolean LOG_PARSER = false;
public static XmlPullParser create(File f)
throws XmlPullParserException, FileNotFoundException {
KXmlParser parser = instantiateParser(f.getName());
parser.setInput(new FileInputStream(f), ENCODING);
return parser;
}
public static XmlPullParser create(InputStream stream, String name)
throws XmlPullParserException {
KXmlParser parser = instantiateParser(name);
parser.setInput(stream, ENCODING);
return parser;
}
private static KXmlParser instantiateParser(String name) throws XmlPullParserException {
KXmlParser parser;
if (name != null) {
parser = new CustomParser(name);
} else {
parser = new KXmlParser();
}
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
return parser;
}
private static class CustomParser extends KXmlParser {
private final String mName;
CustomParser(String name) {
super();
mName = name;
}
@Override
public String toString() {
return mName;
}
}
}

View File

@ -984,7 +984,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
"status_bar_height");
if (value != null) {
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
value.getValue(), true /*requireUnit*/);
if (typedValue != null) {
// compute the pixel value based on the display metrics
mStatusBarSize = (int)typedValue.getDimension(metrics);
@ -1016,7 +1017,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
if (value != null) {
// get the numerical value, if available
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(),
true /*requireUnit*/);
if (typedValue != null) {
// compute the pixel value based on the display metrics
mActionBarSize = (int)typedValue.getDimension(metrics);
@ -1040,7 +1042,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
if (value != null) {
// get the numerical value, if available
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
TypedValue typedValue = ResourceHelper.getValue("windowTitleSize",
value.getValue(), true /*requireUnit*/);
if (typedValue != null) {
// compute the pixel value based on the display metrics
mTitleBarSize = (int)typedValue.getDimension(metrics);
@ -1062,7 +1065,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
"status_bar_height");
if (value != null) {
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
TypedValue typedValue = ResourceHelper.getValue("status_bar_height",
value.getValue(), true /*requireUnit*/);
if (typedValue != null) {
// compute the pixel value based on the display metrics
mSystemBarSize = (int)typedValue.getDimension(metrics);

View File

@ -27,7 +27,6 @@ import com.android.ninepatch.NinePatch;
import com.android.ninepatch.NinePatchChunk;
import com.android.resources.Density;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@ -121,9 +120,7 @@ public final class ResourceHelper {
try {
// let the framework inflate the ColorStateList from the XML file, by
// providing an XmlPullParser
KXmlParser parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$);
XmlPullParser parser = ParserFactory.create(f);
BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
parser, context, resValue.isFramework());
@ -203,9 +200,7 @@ public final class ResourceHelper {
if (f.isFile()) {
try {
// let the framework inflate the Drawable from the XML file.
KXmlParser parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileInputStream(f), "UTF-8"); //$NON-NLS-1$);
XmlPullParser parser = ParserFactory.create(f);
BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
parser, context, value.isFramework());
@ -341,11 +336,11 @@ public final class ResourceHelper {
};
/**
* Returns the raw value from the given string.
* Returns the raw value from the given attribute float-type value string.
* This object is only valid until the next call on to {@link ResourceHelper}.
*/
public static TypedValue getValue(String s) {
if (stringToFloat(s, mValue)) {
public static TypedValue getValue(String attribute, String value, boolean requireUnit) {
if (parseFloatAttribute(attribute, value, mValue, requireUnit)) {
return mValue;
}
@ -353,22 +348,27 @@ public final class ResourceHelper {
}
/**
* Convert the string into a {@link TypedValue}.
* @param s
* @param outValue
* Parse a float attribute and return the parsed value into a given TypedValue.
* @param attribute the name of the attribute. Can be null if <var>requireUnit</var> is false.
* @param value the string value of the attribute
* @param outValue the TypedValue to receive the parsed value
* @param requireUnit whether the value is expected to contain a unit.
* @return true if success.
*/
public static boolean stringToFloat(String s, TypedValue outValue) {
public static boolean parseFloatAttribute(String attribute, String value,
TypedValue outValue, boolean requireUnit) {
assert requireUnit == false || attribute != null;
// remove the space before and after
s = s.trim();
int len = s.length();
value = value.trim();
int len = value.length();
if (len <= 0) {
return false;
}
// check that there's no non ascii characters.
char[] buf = s.toCharArray();
char[] buf = value.toCharArray();
for (int i = 0 ; i < len ; i++) {
if (buf[i] > 255) {
return false;
@ -381,7 +381,7 @@ public final class ResourceHelper {
}
// now look for the string that is after the float...
Matcher m = sFloatPattern.matcher(s);
Matcher m = sFloatPattern.matcher(value);
if (m.matches()) {
String f_str = m.group(1);
String end = m.group(2);
@ -397,45 +397,7 @@ public final class ResourceHelper {
if (end.length() > 0 && end.charAt(0) != ' ') {
// Might be a unit...
if (parseUnit(end, outValue, sFloatOut)) {
f *= sFloatOut[0];
boolean neg = f < 0;
if (neg) {
f = -f;
}
long bits = (long)(f*(1<<23)+.5f);
int radix;
int shift;
if ((bits&0x7fffff) == 0) {
// Always use 23p0 if there is no fraction, just to make
// things easier to read.
radix = TypedValue.COMPLEX_RADIX_23p0;
shift = 23;
} else if ((bits&0xffffffffff800000L) == 0) {
// Magnitude is zero -- can fit in 0 bits of precision.
radix = TypedValue.COMPLEX_RADIX_0p23;
shift = 0;
} else if ((bits&0xffffffff80000000L) == 0) {
// Magnitude can fit in 8 bits of precision.
radix = TypedValue.COMPLEX_RADIX_8p15;
shift = 8;
} else if ((bits&0xffffff8000000000L) == 0) {
// Magnitude can fit in 16 bits of precision.
radix = TypedValue.COMPLEX_RADIX_16p7;
shift = 16;
} else {
// Magnitude needs entire range, so no fractional part.
radix = TypedValue.COMPLEX_RADIX_23p0;
shift = 23;
}
int mantissa = (int)(
(bits>>shift) & TypedValue.COMPLEX_MANTISSA_MASK);
if (neg) {
mantissa = (-mantissa) & TypedValue.COMPLEX_MANTISSA_MASK;
}
outValue.data |=
(radix<<TypedValue.COMPLEX_RADIX_SHIFT)
| (mantissa<<TypedValue.COMPLEX_MANTISSA_SHIFT);
computeTypedValue(outValue, f, sFloatOut[0]);
return true;
}
return false;
@ -446,8 +408,20 @@ public final class ResourceHelper {
if (end.length() == 0) {
if (outValue != null) {
outValue.type = TypedValue.TYPE_FLOAT;
outValue.data = Float.floatToIntBits(f);
if (requireUnit == false) {
outValue.type = TypedValue.TYPE_FLOAT;
outValue.data = Float.floatToIntBits(f);
} else {
// no unit when required? Use dp and out an error.
applyUnit(sUnitNames[1], outValue, sFloatOut);
computeTypedValue(outValue, f, sFloatOut[0]);
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
String.format(
"Dimension \"%1$s\" in attribute \"%2$s\" is missing unit!",
value, attribute),
null);
}
return true;
}
}
@ -456,20 +430,64 @@ public final class ResourceHelper {
return false;
}
private static void computeTypedValue(TypedValue outValue, float value, float scale) {
value *= scale;
boolean neg = value < 0;
if (neg) {
value = -value;
}
long bits = (long)(value*(1<<23)+.5f);
int radix;
int shift;
if ((bits&0x7fffff) == 0) {
// Always use 23p0 if there is no fraction, just to make
// things easier to read.
radix = TypedValue.COMPLEX_RADIX_23p0;
shift = 23;
} else if ((bits&0xffffffffff800000L) == 0) {
// Magnitude is zero -- can fit in 0 bits of precision.
radix = TypedValue.COMPLEX_RADIX_0p23;
shift = 0;
} else if ((bits&0xffffffff80000000L) == 0) {
// Magnitude can fit in 8 bits of precision.
radix = TypedValue.COMPLEX_RADIX_8p15;
shift = 8;
} else if ((bits&0xffffff8000000000L) == 0) {
// Magnitude can fit in 16 bits of precision.
radix = TypedValue.COMPLEX_RADIX_16p7;
shift = 16;
} else {
// Magnitude needs entire range, so no fractional part.
radix = TypedValue.COMPLEX_RADIX_23p0;
shift = 23;
}
int mantissa = (int)(
(bits>>shift) & TypedValue.COMPLEX_MANTISSA_MASK);
if (neg) {
mantissa = (-mantissa) & TypedValue.COMPLEX_MANTISSA_MASK;
}
outValue.data |=
(radix<<TypedValue.COMPLEX_RADIX_SHIFT)
| (mantissa<<TypedValue.COMPLEX_MANTISSA_SHIFT);
}
private static boolean parseUnit(String str, TypedValue outValue, float[] outScale) {
str = str.trim();
for (UnitEntry unit : sUnitNames) {
if (unit.name.equals(str)) {
outValue.type = unit.type;
outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT;
outScale[0] = unit.scale;
applyUnit(unit, outValue, outScale);
return true;
}
}
return false;
}
private static void applyUnit(UnitEntry unit, TypedValue outValue, float[] outScale) {
outValue.type = unit.type;
outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT;
outScale[0] = unit.scale;
}
}

View File

@ -16,14 +16,11 @@
package com.android.layoutlib.bridge.android;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import com.android.layoutlib.bridge.impl.ParserFactory;
import org.kxml2.io.KXmlParser;
import org.w3c.dom.Node;
import org.xmlpull.v1.XmlPullParser;
import java.io.InputStream;
import junit.framework.TestCase;
public class BridgeXmlBlockParserTest extends TestCase {
@ -39,12 +36,12 @@ public class BridgeXmlBlockParserTest extends TestCase {
}
public void testXmlBlockParser() throws Exception {
XmlPullParser parser = new KXmlParser();
parser = new BridgeXmlBlockParser(parser, null, false /* platformResourceFlag */);
InputStream input = this.getClass().getClassLoader().getResourceAsStream(
"com/android/layoutlib/testdata/layout1.xml");
parser.setInput(input, "UTF-8"); //$NON-NLS-1$
XmlPullParser parser = ParserFactory.create(
getClass().getResourceAsStream("com/android/layoutlib/testdata/layout1.xml"),
"layout1.xml");
parser = new BridgeXmlBlockParser(parser, null, false /* platformResourceFlag */);
assertEquals(XmlPullParser.START_DOCUMENT, parser.next());