diff options
author | Xavier Ducrohet <xav@android.com> | 2011-06-09 19:14:06 -0700 |
---|---|---|
committer | Xavier Ducrohet <xav@android.com> | 2011-06-16 18:26:25 -0700 |
commit | ea5f0d0543a2ea78ecb0aa3d080098942ba3a4df (patch) | |
tree | 29029f0d4b315b537ba876369efb629750a19c0d | |
parent | d6465e10c27140647e02be8160d900d6e7e78441 (diff) | |
download | frameworks_base-ea5f0d0543a2ea78ecb0aa3d080098942ba3a4df.zip frameworks_base-ea5f0d0543a2ea78ecb0aa3d080098942ba3a4df.tar.gz frameworks_base-ea5f0d0543a2ea78ecb0aa3d080098942ba3a4df.tar.bz2 |
Bring in more layout lib changes from hc-mr1.
fe051bb2 : Change the way the layoutlib instantiate its XmlPullParser.
A lot of the init code was duplicated so I made a ParserFactory class.
Also created an extension of the KXmlPullParser to override toString().
This allows easier debugging when dealing with multiple parsers (which
is always the case).
Also added some (disabled) debugging printf to deal with parser stack
as it can be tricky figuring out which parsers are in the stack at
which point.
8969147c : Fix case where the int[] attrs doesn't directly match a styleable.
In the case of the FastScroller the int[] is a custom mix of attr
instead of a int[] that exists as R.styleable.foo.
This makes our reflection based mechanism used to find the styleable
fail, so instead we search for each attribute separately (like
we probably should have done from the beginning).
0c264b35: Fix various cases of getDimension to report error if unit is missing.
if getDimention###() is called for a string that has no unit,
then an error is output through LayoutLog, but the rendering keeps
going by using dp as a default.
0beb7eea: Make (Bridge)TypedArray.getInteger() call out to getInt()
Only getInt() resolved attribute flags/enum and I'm not sure why
there's two to begin with.
Change-Id: I015111263d2a2bee76834978ae71eef79defdae3
12 files changed, 322 insertions, 192 deletions
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 904f7a3..8c93c31 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -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; @@ -201,6 +201,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); } @@ -208,7 +211,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()); + } } /** @@ -341,9 +347,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); @@ -682,25 +686,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()); - - // 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(); + false, true, null); - String name = styleAttribute.getValue(); + // 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); - // get the value from the style, or its parent styles. - ResourceValue resValue = mRenderResources.findItemInStyle(style, name); + if (resValue != null) { + // resolve it to make sure there are no references left. + ta.bridgeSetValue(i, attrName, mRenderResources.resolveResValue(resValue)); - // resolve it to make sure there are no references left. - ta.bridgeSetValue(index, name, mRenderResources.resolveResValue(resValue)); + resValue = mRenderResources.resolveResValue(resValue); + } + } } ta.sealArray(); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java index edfe83e..df30c0d 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java @@ -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); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java index d0b90fb..1756496 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java @@ -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 diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java index b1fbf08..260cdc8 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java @@ -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*/); } /** diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java index 70dbaa4..1016b32 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java @@ -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() diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java index 060e6ee..df701d5 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java @@ -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)); } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java index 5507ef9..abd1aaf 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java @@ -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); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java index d7401d9..5f5ebc4 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java @@ -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. diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java new file mode 100644 index 0000000..a235ec3 --- /dev/null +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java @@ -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; + } + } +} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java index f29a9d0..9332105c 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java @@ -820,7 +820,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); @@ -850,7 +851,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 mTitleBarSize = (int)typedValue.getDimension(metrics); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java index e5efa4e..6dcb693 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java @@ -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; + } } diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java index 70d5446..96436fe 100644 --- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java +++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java @@ -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()); |