aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2017-07-05 07:23:54 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2017-07-05 07:23:54 +0000
commit80ed4728ea443a560baf7677367500d618a98f27 (patch)
tree29ffbb68785b38ea42bfb91da61d845c14f10b82
parent8c18c45e978ef270fba5424534611710b4386f6a (diff)
parentb2dfcdc4a71e44089871a0520109a55abbe16615 (diff)
downloadlayoutlib-80ed4728ea443a560baf7677367500d618a98f27.tar.gz
release-request-96c1d2fa-6213-4670-8f45-7a1668ab4a26-for-git_oc-mr1-release-4153896 snap-temp-L86500000079599461
Change-Id: I3bfc0704cf490250dc582a76cc16e90f15b2d10c
-rw-r--r--bridge/src/android/graphics/BidiRenderer.java85
-rw-r--r--bridge/src/android/graphics/NinePatch_Delegate.java13
-rw-r--r--bridge/src/com/android/layoutlib/bridge/android/support/FragmentTabHostUtil.java52
-rw-r--r--bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java8
-rw-r--r--bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java120
-rw-r--r--bridge/tests/res/testApp/MyApplication/golden/activity.pngbin36035 -> 35669 bytes
-rw-r--r--bridge/tests/res/testApp/MyApplication/golden/allwidgets.pngbin67362 -> 66711 bytes
-rw-r--r--bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.pngbin52448 -> 51410 bytes
-rw-r--r--bridge/tests/res/testApp/MyApplication/golden/font_test.pngbin52171 -> 52715 bytes
-rw-r--r--bridge/tests/src/com/android/layoutlib/bridge/impl/ResourceHelperTest.java51
-rw-r--r--bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java3
11 files changed, 211 insertions, 121 deletions
diff --git a/bridge/src/android/graphics/BidiRenderer.java b/bridge/src/android/graphics/BidiRenderer.java
index f2904b2446..63691c3889 100644
--- a/bridge/src/android/graphics/BidiRenderer.java
+++ b/bridge/src/android/graphics/BidiRenderer.java
@@ -19,8 +19,9 @@ package android.graphics;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.graphics.Paint_Delegate.FontInfo;
-import android.icu.lang.UScript;
import android.icu.lang.UScriptRun;
import android.icu.text.Bidi;
import android.icu.text.BidiRun;
@@ -32,7 +33,6 @@ import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
-import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@@ -45,26 +45,20 @@ public class BidiRenderer {
private static String JAVA_VENDOR = System.getProperty("java.vendor");
private static class ScriptRun {
- int start;
- int limit;
- boolean isRtl;
- int scriptCode;
- Font font;
+ private final int start;
+ private final int limit;
+ private final Font font;
- public ScriptRun(int start, int limit, boolean isRtl) {
+ private ScriptRun(int start, int limit, @NonNull Font font) {
this.start = start;
this.limit = limit;
- this.isRtl = isRtl;
- this.scriptCode = UScript.INVALID_CODE;
+ this.font = font;
}
}
private final Graphics2D mGraphics;
private final Paint_Delegate mPaint;
private char[] mText;
- // This List can contain nulls. A null font implies that the we weren't able to load the font
- // properly. So, if we encounter a situation where we try to use that font, log a warning.
- private List<Font> mFonts;
// Bounds of the text drawn so far.
private RectF mBounds;
private float mBaseline;
@@ -79,14 +73,6 @@ public class BidiRenderer {
mGraphics = graphics;
mPaint = paint;
mText = text;
- mFonts = new ArrayList<Font>(paint.getFonts().size());
- for (FontInfo fontInfo : paint.getFonts()) {
- if (fontInfo == null) {
- mFonts.add(null);
- continue;
- }
- mFonts.add(fontInfo.mFont);
- }
mBounds = new RectF();
}
@@ -98,7 +84,7 @@ public class BidiRenderer {
*
*/
public BidiRenderer setRenderLocation(float x, float y) {
- mBounds = new RectF(x, y, x, y);
+ mBounds.set(x, y, x, y);
mBaseline = y;
return this;
}
@@ -141,7 +127,7 @@ public class BidiRenderer {
int advancesIndex, boolean draw) {
// We break the text into scripts and then select font based on it and then render each of
// the script runs.
- for (ScriptRun run : getScriptRuns(mText, start, limit, isRtl, mFonts)) {
+ for (ScriptRun run : getScriptRuns(mText, start, limit, mPaint.getFonts())) {
int flag = Font.LAYOUT_NO_LIMIT_CONTEXT | Font.LAYOUT_NO_START_CONTEXT;
flag |= isRtl ? Font.LAYOUT_RIGHT_TO_LEFT : Font.LAYOUT_LEFT_TO_RIGHT;
renderScript(run.start, run.limit, run.font, flag, advances, advancesIndex, draw);
@@ -157,7 +143,7 @@ public class BidiRenderer {
*/
private void renderScript(int start, int limit, Font preferredFont, int flag,
float[] advances, int advancesIndex, boolean draw) {
- if (mFonts.size() == 0 || preferredFont == null) {
+ if (mPaint.getFonts().size() == 0 || preferredFont == null) {
return;
}
@@ -179,7 +165,10 @@ public class BidiRenderer {
// The current character cannot be drawn with the preferred font. Cycle through all the
// fonts to check which one can draw it.
int charCount = Character.isHighSurrogate(mText[start]) ? 2 : 1;
- for (Font font : mFonts) {
+ List<FontInfo> fontInfos = mPaint.getFonts();
+ //noinspection ForLoopReplaceableByForEach (avoid iterator allocation)
+ for (int i = 0; i < fontInfos.size(); i++) {
+ Font font = fontInfos.get(i).mFont;
if (font == null) {
logFontWarning();
continue;
@@ -250,60 +239,62 @@ public class BidiRenderer {
// Update the bounds.
Rectangle2D awtBounds = gv.getLogicalBounds();
- RectF bounds = awtRectToAndroidRect(awtBounds, mBounds.right, mBaseline);
// If the width of the bounds is zero, no text had been drawn earlier. Hence, use the
// coordinates from the bounds as an offset.
if (Math.abs(mBounds.right - mBounds.left) == 0) {
- mBounds = bounds;
+ mBounds = awtRectToAndroidRect(awtBounds, mBounds.right, mBaseline, mBounds);
} else {
- mBounds.union(bounds);
+ mBounds.union(awtRectToAndroidRect(awtBounds, mBounds.right, mBaseline, null));
}
}
// --- Static helper methods ---
- private static RectF awtRectToAndroidRect(Rectangle2D awtRec, float offsetX, float offsetY) {
+ private static RectF awtRectToAndroidRect(Rectangle2D awtRec, float offsetX, float offsetY,
+ @Nullable RectF destination) {
float left = (float) awtRec.getX();
float top = (float) awtRec.getY();
float right = (float) (left + awtRec.getWidth());
float bottom = (float) (top + awtRec.getHeight());
- RectF androidRect = new RectF(left, top, right, bottom);
- androidRect.offset(offsetX, offsetY);
- return androidRect;
+ if (destination != null) {
+ destination.set(left, top, right, bottom);
+ } else {
+ destination = new RectF(left, top, right, bottom);
+ }
+ destination.offset(offsetX, offsetY);
+ return destination;
}
- /* package */ static List<ScriptRun> getScriptRuns(char[] text, int start, int limit,
- boolean isRtl, List<Font> fonts) {
- LinkedList<ScriptRun> scriptRuns = new LinkedList<ScriptRun>();
+ private static List<ScriptRun> getScriptRuns(char[] text, int start, int limit, List<FontInfo> fonts) {
+ LinkedList<ScriptRun> scriptRuns = new LinkedList<>();
int count = limit - start;
UScriptRun uScriptRun = new UScriptRun(text, start, count);
while (uScriptRun.next()) {
int scriptStart = uScriptRun.getScriptStart();
int scriptLimit = uScriptRun.getScriptLimit();
- ScriptRun run = new ScriptRun(scriptStart, scriptLimit, isRtl);
- run.scriptCode = uScriptRun.getScriptCode();
- setScriptFont(text, run, fonts);
+ ScriptRun run = new ScriptRun(
+ scriptStart, scriptLimit,
+ getScriptFont(text, scriptStart, scriptLimit, fonts));
scriptRuns.add(run);
}
-
return scriptRuns;
}
// TODO: Replace this method with one which returns the font based on the scriptCode.
- private static void setScriptFont(char[] text, ScriptRun run,
- List<Font> fonts) {
- for (Font font : fonts) {
- if (font == null) {
+ @NonNull
+ private static Font getScriptFont(char[] text, int start, int limit, List<FontInfo> fonts) {
+ for (FontInfo fontInfo : fonts) {
+ if (fontInfo.mFont == null) {
logFontWarning();
continue;
}
- if (font.canDisplayUpTo(text, run.start, run.limit) == -1) {
- run.font = font;
- return;
+ if (fontInfo.mFont.canDisplayUpTo(text, start, limit) == -1) {
+ return fontInfo.mFont;
}
}
- run.font = fonts.get(0);
+
+ return fonts.get(0).mFont;
}
private static int getIcuFlags(int bidiFlag) {
diff --git a/bridge/src/android/graphics/NinePatch_Delegate.java b/bridge/src/android/graphics/NinePatch_Delegate.java
index 1f0eb3bab5..43e5b0f974 100644
--- a/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -19,14 +19,11 @@ package android.graphics;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.impl.GcSnapshot;
import com.android.ninepatch.NinePatchChunk;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.drawable.NinePatchDrawable;
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -50,7 +47,7 @@ public final class NinePatch_Delegate {
// ---- delegate manager ----
private static final DelegateManager<NinePatch_Delegate> sManager =
- new DelegateManager<NinePatch_Delegate>(NinePatch_Delegate.class);
+ new DelegateManager<>(NinePatch_Delegate.class);
// ---- delegate helper data ----
/**
@@ -62,8 +59,7 @@ public final class NinePatch_Delegate {
* Using the cache map allows us to not have to deserialize the byte[] back into a
* {@link NinePatchChunk} every time a rendering is done.
*/
- private final static Map<byte[], SoftReference<NinePatchChunk>> sChunkCache =
- new HashMap<byte[], SoftReference<NinePatchChunk>>();
+ private final static Map<byte[], SoftReference<NinePatchChunk>> sChunkCache = new HashMap<>();
// ---- delegate data ----
private byte[] chunk;
@@ -97,7 +93,7 @@ public final class NinePatch_Delegate {
// get the array and add it to the cache
byte[] array = baos.toByteArray();
- sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk));
+ sChunkCache.put(array, new SoftReference<>(chunk));
return array;
}
@@ -122,7 +118,7 @@ public final class NinePatch_Delegate {
// put back the chunk in the cache
if (chunk != null) {
- sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk));
+ sChunkCache.put(array, new SoftReference<>(chunk));
}
} catch (IOException e) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN,
@@ -151,7 +147,6 @@ public final class NinePatch_Delegate {
/*package*/ static boolean isNinePatchChunk(byte[] chunk) {
NinePatchChunk chunkObject = getChunk(chunk);
return chunkObject != null;
-
}
@LayoutlibDelegate
diff --git a/bridge/src/com/android/layoutlib/bridge/android/support/FragmentTabHostUtil.java b/bridge/src/com/android/layoutlib/bridge/android/support/FragmentTabHostUtil.java
new file mode 100644
index 0000000000..730ac1300e
--- /dev/null
+++ b/bridge/src/com/android/layoutlib/bridge/android/support/FragmentTabHostUtil.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 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.android.support;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
+
+import android.content.Context;
+import android.widget.TabHost;
+
+import static com.android.layoutlib.bridge.util.ReflectionUtils.getCause;
+import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod;
+import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;
+
+/**
+ * Utility class for working with android.support.v4.app.FragmentTabHost
+ */
+public class FragmentTabHostUtil {
+
+ public static final String CN_FRAGMENT_TAB_HOST = "android.support.v4.app.FragmentTabHost";
+
+ /**
+ * Calls the setup method for the FragmentTabHost tabHost
+ */
+ public static void setup(TabHost tabHost, Context context) {
+ try {
+ invoke(getMethod(tabHost.getClass(), "setup", Context.class,
+ Class.forName("android.support.v4.app.FragmentManager", true,
+ tabHost.getClass().getClassLoader()), int.class), tabHost, context, null,
+ android.R.id.tabcontent);
+ } catch (ReflectionException | ClassNotFoundException e) {
+ Throwable cause = getCause(e);
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "Error occurred while trying to setup FragmentTabHost.", cause, null);
+ }
+ }
+}
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index a1d614da2a..5adba23b2a 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -41,9 +41,11 @@ import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.layoutlib.bridge.android.graphics.NopCanvas;
import com.android.layoutlib.bridge.android.support.DesignLibUtil;
+import com.android.layoutlib.bridge.android.support.FragmentTabHostUtil;
import com.android.layoutlib.bridge.android.support.SupportPreferencesUtil;
import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
+import com.android.layoutlib.bridge.util.ReflectionUtils;
import com.android.resources.ResourceType;
import com.android.tools.layoutlib.java.System_Delegate;
import com.android.util.Pair;
@@ -828,7 +830,11 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
// this must be called before addTab() so that the TabHost searches its TabWidget
// and FrameLayout.
- tabHost.setup();
+ if (ReflectionUtils.isInstanceOf(tabHost, FragmentTabHostUtil.CN_FRAGMENT_TAB_HOST)) {
+ FragmentTabHostUtil.setup(tabHost, getContext());
+ } else {
+ tabHost.setup();
+ }
if (count == 0) {
// Create a dummy child to get a single tab
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 2826050628..e33a2941c8 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -80,55 +80,57 @@ public final class ResourceHelper {
* @return the color as an int
* @throws NumberFormatException if the conversion failed.
*/
- public static int getColor(String value) {
- if (value != null) {
- value = value.trim();
- if (!value.startsWith("#")) {
- if (value.startsWith(SdkConstants.PREFIX_THEME_REF)) {
- throw new NumberFormatException(String.format(
- "Attribute '%s' not found. Are you using the right theme?", value));
- }
- throw new NumberFormatException(
- String.format("Color value '%s' must start with #", value));
- }
+ public static int getColor(@Nullable String value) {
+ if (value == null) {
+ throw new NumberFormatException("null value");
+ }
+
+ value = value.trim();
+ int len = value.length();
- value = value.substring(1);
+ // make sure it's not longer than 32bit or smaller than the RGB format
+ if (len < 2 || len > 9) {
+ throw new NumberFormatException(String.format(
+ "Color value '%s' has wrong size. Format is either" +
+ "#AARRGGBB, #RRGGBB, #RGB, or #ARGB",
+ value));
+ }
- // make sure it's not longer than 32bit
- if (value.length() > 8) {
+ if (value.charAt(0) != '#') {
+ if (value.startsWith(SdkConstants.PREFIX_THEME_REF)) {
throw new NumberFormatException(String.format(
- "Color value '%s' is too long. Format is either" +
- "#AARRGGBB, #RRGGBB, #RGB, or #ARGB",
- value));
- }
-
- if (value.length() == 3) { // RGB format
- char[] color = new char[8];
- color[0] = color[1] = 'F';
- color[2] = color[3] = value.charAt(0);
- color[4] = color[5] = value.charAt(1);
- color[6] = color[7] = value.charAt(2);
- value = new String(color);
- } else if (value.length() == 4) { // ARGB format
- char[] color = new char[8];
- color[0] = color[1] = value.charAt(0);
- color[2] = color[3] = value.charAt(1);
- color[4] = color[5] = value.charAt(2);
- color[6] = color[7] = value.charAt(3);
- value = new String(color);
- } else if (value.length() == 6) {
- value = "FF" + value;
+ "Attribute '%s' not found. Are you using the right theme?", value));
}
+ throw new NumberFormatException(
+ String.format("Color value '%s' must start with #", value));
+ }
- // this is a RRGGBB or AARRGGBB value
-
- // Integer.parseInt will fail to parse strings like "ff191919", so we use
- // a Long, but cast the result back into an int, since we know that we're only
- // dealing with 32 bit values.
- return (int)Long.parseLong(value, 16);
+ value = value.substring(1);
+
+ if (len == 4) { // RGB format
+ char[] color = new char[8];
+ color[0] = color[1] = 'F';
+ color[2] = color[3] = value.charAt(0);
+ color[4] = color[5] = value.charAt(1);
+ color[6] = color[7] = value.charAt(2);
+ value = new String(color);
+ } else if (len == 5) { // ARGB format
+ char[] color = new char[8];
+ color[0] = color[1] = value.charAt(0);
+ color[2] = color[3] = value.charAt(1);
+ color[4] = color[5] = value.charAt(2);
+ color[6] = color[7] = value.charAt(3);
+ value = new String(color);
+ } else if (len == 7) {
+ value = "FF" + value;
}
- throw new NumberFormatException();
+ // this is a RRGGBB or AARRGGBB value
+
+ // Integer.parseInt will fail to parse strings like "ff191919", so we use
+ // a Long, but cast the result back into an int, since we know that we're only
+ // dealing with 32 bit values.
+ return (int)Long.parseLong(value, 16);
}
/**
@@ -149,6 +151,13 @@ public final class ResourceHelper {
return null;
}
+ // try to load the color state list from an int
+ try {
+ int color = getColor(value);
+ return ColorStateList.valueOf(color);
+ } catch (NumberFormatException ignored) {
+ }
+
XmlPullParser parser = null;
// first check if the value is a file (xml most likely)
Boolean psiParserSupport = context.getLayoutlibCallback().getFlag(
@@ -216,16 +225,6 @@ public final class ResourceHelper {
return null;
}
- } else {
- // try to load the color state list from an int
- try {
- int color = getColor(value);
- return ColorStateList.valueOf(color);
- } catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Failed to convert " + value + " into a ColorStateList", e,
- null /*data*/);
- }
}
return null;
@@ -316,6 +315,12 @@ public final class ResourceHelper {
}
String lowerCaseValue = stringValue.toLowerCase();
+ // try the simple case first. Attempt to get a color from the value
+ try {
+ int color = getColor(stringValue);
+ return new ColorDrawable(color);
+ } catch (NumberFormatException ignore) {
+ }
Density density = Density.MEDIUM;
if (value instanceof DensityBasedResourceValue) {
@@ -375,17 +380,6 @@ public final class ResourceHelper {
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
"Failed lot load " + bmpFile.getAbsolutePath(), e, null /*data*/);
}
- } else {
- // attempt to get a color from the value
- try {
- int color = getColor(stringValue);
- return new ColorDrawable(color);
- } catch (NumberFormatException e) {
- // we'll return null below.
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Failed to convert " + stringValue + " into a drawable", e,
- null /*data*/);
- }
}
}
diff --git a/bridge/tests/res/testApp/MyApplication/golden/activity.png b/bridge/tests/res/testApp/MyApplication/golden/activity.png
index 773c5bee5d..650751eaf1 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/activity.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/activity.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index 4391f47bd3..1ac8e1bca1 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
index bca334703b..0328fd127b 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/golden/font_test.png b/bridge/tests/res/testApp/MyApplication/golden/font_test.png
index 7e0c29afd4..3966ccbf02 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/font_test.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/font_test.png
Binary files differ
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/impl/ResourceHelperTest.java b/bridge/tests/src/com/android/layoutlib/bridge/impl/ResourceHelperTest.java
new file mode 100644
index 0000000000..4e18f076a0
--- /dev/null
+++ b/bridge/tests/src/com/android/layoutlib/bridge/impl/ResourceHelperTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 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.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ResourceHelperTest {
+ private static void assertNumberFormatException(Runnable runnable) {
+ try {
+ runnable.run();
+ fail("NumberFormatException expected");
+ } catch (NumberFormatException ignored) {
+ }
+ }
+
+ @Test
+ public void testGetColor() {
+ assertNumberFormatException(() -> ResourceHelper.getColor(""));
+ assertNumberFormatException(() -> ResourceHelper.getColor("AFAFAF"));
+ assertNumberFormatException(() -> ResourceHelper.getColor("AAA"));
+ assertNumberFormatException(() -> ResourceHelper.getColor("#JFAFAF"));
+ assertNumberFormatException(() -> ResourceHelper.getColor("#AABBCCDDEE"));
+ assertNumberFormatException(() -> ResourceHelper.getColor("#JAAA"));
+ assertNumberFormatException(() -> ResourceHelper.getColor("#AA BBCC"));
+
+ assertEquals(0xffaaaaaa, ResourceHelper.getColor("#AAA"));
+ assertEquals(0xffaaaaaa, ResourceHelper.getColor(" #AAA"));
+ assertEquals(0xffaaaaaa, ResourceHelper.getColor("#AAA "));
+ assertEquals(0xffaaaaaa, ResourceHelper.getColor(" #AAA "));
+ assertEquals(0xaaaaaa, ResourceHelper.getColor("#0AAA"));
+ assertEquals(0xffaabbcc, ResourceHelper.getColor("#AABBCC"));
+ assertEquals(0x12aabbcc, ResourceHelper.getColor("#12AABBCC"));
+ assertEquals(0x12345, ResourceHelper.getColor("#12345"));
+ }
+} \ No newline at end of file
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index eb264d655a..e98c78971b 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -20,6 +20,7 @@ import com.android.layoutlib.bridge.BridgeRenderSessionTest;
import com.android.layoutlib.bridge.TestDelegates;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParserTest;
import com.android.layoutlib.bridge.impl.LayoutParserWrapperTest;
+import com.android.layoutlib.bridge.impl.ResourceHelperTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -36,7 +37,7 @@ import android.util.BridgeXmlPullAttributesTest;
RenderTests.class, LayoutParserWrapperTest.class,
BridgeXmlBlockParserTest.class, BridgeXmlPullAttributesTest.class,
Matrix_DelegateTest.class, TestDelegates.class, PerformanceTests.class,
- BridgeRenderSessionTest.class
+ BridgeRenderSessionTest.class, ResourceHelperTest.class
})
public class Main {
}