BridgeContext: Fix typo in attr name (toLeft -> toLeftOf)
am: af0f3bda17
* commit 'af0f3bda17ee3de4ad3560c9a675527b20e2af5f':
BridgeContext: Fix typo in attr name (toLeft -> toLeftOf)
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 5aaaf18..35961a2 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -21,7 +21,5 @@
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
- <bytecodeTargetLevel target="1.6" />
</component>
-</project>
-
+</project>
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 5bb3e3e..3681f2a 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="UTF-8"?>
<component name="InspectionProjectProfileManager">
<profile version="1.0" is_locked="false">
<option name="myName" value="Project Default" />
@@ -8,6 +7,15 @@
<option name="CHECK_TRY_CATCH_SECTION" value="true" />
<option name="CHECK_METHOD_BODY" value="true" />
</inspection_tool>
+ <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
+ <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
+ <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
+ </inspection_tool>
<inspection_tool class="ToArrayCallWithZeroLengthArrayArgument" enabled="false" level="WARNING" enabled_by_default="false" />
+ <inspection_tool class="WeakerAccess" enabled="true" level="WARNING" enabled_by_default="true">
+ <option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="false" />
+ <option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="false" />
+ <option name="SUGGEST_PRIVATE_FOR_INNERS" value="true" />
+ </inspection_tool>
</profile>
</component>
\ No newline at end of file
diff --git a/.idea/libraries/junit.xml b/.idea/libraries/junit.xml
new file mode 100644
index 0000000..c889f5f
--- /dev/null
+++ b/.idea/libraries/junit.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+ <library name="junit">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/junit_intermediates/javalib.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="file://$PROJECT_DIR$/../../../../external/junit/src" />
+ </SOURCES>
+ </library>
+</component>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index b474bdc..44b47f2 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -37,7 +37,7 @@
</value>
</option>
</component>
- <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
\ No newline at end of file
diff --git a/.idea/runConfigurations/Bridge_quick.xml b/.idea/runConfigurations/Bridge_quick.xml
index 4f0eb8d..b402849 100644
--- a/.idea/runConfigurations/Bridge_quick.xml
+++ b/.idea/runConfigurations/Bridge_quick.xml
@@ -26,4 +26,4 @@
<ConfigurationWrapper RunnerId="Run" />
<method />
</configuration>
-</component>
\ No newline at end of file
+</component>
diff --git a/.idea/runConfigurations/Create.xml b/.idea/runConfigurations/Create.xml
index 58f057a..536a23f 100644
--- a/.idea/runConfigurations/Create.xml
+++ b/.idea/runConfigurations/Create.xml
@@ -2,8 +2,8 @@
<configuration default="false" name="Create" type="Application" factoryName="Application" singleton="true">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" value="com.android.tools.layoutlib.create.Main" />
- <option name="VM_PARAMETERS" value="" />
- <option name="PROGRAM_PARAMETERS" value="out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/icu4j-icudata-jarjar_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/icu4j-icutzdata-jarjar_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/javalib.jar" />
+ <option name="VM_PARAMETERS" value="-ea" />
+ <option name="PROGRAM_PARAMETERS" value="out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar out/host/common/obj/JAVA_LIBRARIES/icu4j-icudata-host-jarjar_intermediates/classes-jarjar.jar out/host/common/obj/JAVA_LIBRARIES/icu4j-icutzdata-host-jarjar_intermediates/classes-jarjar.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/javalib.jar" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/../../../../" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" value="" />
diff --git a/Android.mk b/Android.mk
index 61ddb04..663e1e2 100644
--- a/Android.mk
+++ b/Android.mk
@@ -16,7 +16,7 @@
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
-LOCAL_JAVACFLAGS := -source 6 -target 6
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
#
# Define rules to build temp_layoutlib.jar, which contains a subset of
@@ -30,6 +30,9 @@
built_framework_dep := $(call java-lib-deps,framework)
built_framework_classes := $(call java-lib-files,framework)
+built_oj_dep := $(call java-lib-deps,core-oj)
+built_oj_classes := $(call java-lib-files,core-oj)
+
built_core_dep := $(call java-lib-deps,core-libart)
built_core_classes := $(call java-lib-files,core-libart)
@@ -37,10 +40,8 @@
built_ext_classes := $(call java-lib-files,ext)
built_ext_data := $(call intermediates-dir-for, \
JAVA_LIBRARIES,ext,,COMMON)/javalib.jar
-built_icudata_dep := $(call java-lib-deps,icu4j-icudata-jarjar)
-built_icudata_data := $(call java-lib-files,icu4j-icudata-jarjar)
-built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-jarjar)
-built_icutzdata_data := $(call java-lib-files,icu4j-icutzdata-jarjar)
+built_icudata_dep := $(call java-lib-deps,icu4j-icudata-host-jarjar,HOST)
+built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-host-jarjar,HOST)
built_layoutlib_create_jar := $(call intermediates-dir-for, \
JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar
@@ -56,7 +57,8 @@
include $(BUILD_SYSTEM)/base_rules.mk
#######################################
-$(LOCAL_BUILT_MODULE): $(built_core_dep) \
+$(LOCAL_BUILT_MODULE): $(built_oj_dep) \
+ $(built_core_dep) \
$(built_framework_dep) \
$(built_ext_dep) \
$(built_ext_data) \
@@ -69,11 +71,12 @@
$(hide) ls -l $(built_framework_classes)
$(hide) java -ea -jar $(built_layoutlib_create_jar) \
$@ \
+ $(built_oj_classes) \
$(built_core_classes) \
$(built_framework_classes) \
$(built_ext_classes) \
- $(built_icudata_data) \
- $(built_icutzdata_data) \
+ $(built_icudata_dep) \
+ $(built_icutzdata_dep) \
$(built_ext_data)
$(hide) ls -l $(built_framework_classes)
diff --git a/bridge/Android.mk b/bridge/Android.mk
index 0dbdd56..16e5913 100644
--- a/bridge/Android.mk
+++ b/bridge/Android.mk
@@ -18,8 +18,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_JAVA_RESOURCE_DIRS := resources
-LOCAL_JAVACFLAGS := -source 6 -target 6
-
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
LOCAL_JAVA_LIBRARIES := \
layoutlib_api-prebuilt \
diff --git a/bridge/bridge.iml b/bridge/bridge.iml
index ccc10b3..57d08cb 100644
--- a/bridge/bridge.iml
+++ b/bridge/bridge.iml
@@ -84,6 +84,6 @@
</SOURCES>
</library>
</orderEntry>
- <orderEntry type="library" scope="TEST" name="JUnit4" level="application" />
+ <orderEntry type="library" scope="TEST" name="junit" level="project" />
</component>
</module>
\ No newline at end of file
diff --git a/bridge/src/android/content/res/BridgeTypedArray.java b/bridge/src/android/content/res/BridgeTypedArray.java
index c8f1b80..d0e431a 100644
--- a/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/bridge/src/android/content/res/BridgeTypedArray.java
@@ -25,14 +25,9 @@
import com.android.internal.util.XmlUtils;
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.ResourceType;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.Nullable;
import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
@@ -42,7 +37,6 @@
import android.view.LayoutInflater_Delegate;
import android.view.ViewGroup.LayoutParams;
-import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
@@ -305,71 +299,22 @@
return defValue;
}
- /**
- * Retrieve the ColorStateList for the attribute at <var>index</var>.
- * The value may be either a single solid color or a reference to
- * a color or complex {@link android.content.res.ColorStateList} description.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return ColorStateList for the attribute, or null if not defined.
- */
@Override
public ColorStateList getColorStateList(int index) {
if (!hasValue(index)) {
return null;
}
- ResourceValue resValue = mResourceData[index];
- String value = resValue.getValue();
+ return ResourceHelper.getColorStateList(mResourceData[index], mContext);
+ }
- if (value == null) {
+ @Override
+ public ComplexColor getComplexColor(int index) {
+ if (!hasValue(index)) {
return null;
}
-
- try {
- // Get the state list file content from callback to parse PSI file
- XmlPullParser parser = mContext.getLayoutlibCallback().getXmlFileParser(value);
- if (parser == null) {
- // If used with a version of Android Studio that does not implement getXmlFileParser
- // fall back to reading the file from disk
- File f = new File(value);
- if (f.isFile()) {
- parser = ParserFactory.create(f);
- }
- }
- if (parser != null) {
- BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
- parser, mContext, resValue.isFramework());
- try {
- return ColorStateList.createFromXml(mContext.getResources(), blockParser,
- mContext.getTheme());
- } finally {
- blockParser.ensurePopped();
- }
- }
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value, e, null);
- return null;
- } catch (Exception e) {
- // this is an error and not warning since the file existence is checked before
- // attempting to parse it.
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + value, e, null);
-
- return null;
- }
-
- try {
- int color = ResourceHelper.getColor(value);
- return ColorStateList.valueOf(color);
- } catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, e.getMessage(), e, null);
- }
-
- return null;
+ return ResourceHelper.getComplexColor(mResourceData[index], mContext);
}
/**
diff --git a/bridge/src/android/content/res/ComplexColor_Accessor.java b/bridge/src/android/content/res/ComplexColor_Accessor.java
new file mode 100644
index 0000000..09c0260
--- /dev/null
+++ b/bridge/src/android/content/res/ComplexColor_Accessor.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 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 android.content.res;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.Resources.Theme;
+import android.util.AttributeSet;
+
+import java.io.IOException;
+
+/**
+ * Class that provides access to the {@link GradientColor#createFromXmlInner(Resources,
+ * XmlPullParser, AttributeSet, Theme)} and {@link ColorStateList#createFromXmlInner(Resources,
+ * XmlPullParser, AttributeSet, Theme)} methods
+ */
+public class ComplexColor_Accessor {
+ public static GradientColor createGradientColorFromXmlInner(@NonNull Resources r,
+ @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
+ throws IOException, XmlPullParserException {
+ return GradientColor.createFromXmlInner(r, parser, attrs, theme);
+ }
+
+ public static ColorStateList createColorStateListFromXmlInner(@NonNull Resources r,
+ @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
+ throws IOException, XmlPullParserException {
+ return ColorStateList.createFromXmlInner(r, parser, attrs, theme);
+ }
+}
diff --git a/bridge/src/android/content/res/Resources_Delegate.java b/bridge/src/android/content/res/Resources_Delegate.java
index faf79ab..985dd5a 100644
--- a/bridge/src/android/content/res/Resources_Delegate.java
+++ b/bridge/src/android/content/res/Resources_Delegate.java
@@ -89,6 +89,12 @@
// first get the String related to this id in the framework
Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
+ // Set the layoutlib callback and context for resources
+ if (resources != Resources.mSystem && resources.mLayoutlibCallback == null) {
+ resources.mLayoutlibCallback = Resources.mSystem.mLayoutlibCallback;
+ resources.mContext = Resources.mSystem.mContext;
+ }
+
if (resourceInfo != null) {
platformResFlag_out[0] = true;
String attributeName = resourceInfo.getSecond();
@@ -98,12 +104,6 @@
resourceInfo.getFirst(), attributeName));
}
- // Set the layoutlib callback and context for resources
- if (resources != Resources.mSystem && resources.mLayoutlibCallback == null) {
- resources.mLayoutlibCallback = Resources.mSystem.mLayoutlibCallback;
- resources.mContext = Resources.mSystem.mContext;
- }
-
// didn't find a match in the framework? look in the project.
if (resources.mLayoutlibCallback != null) {
resourceInfo = resources.mLayoutlibCallback.resolveResourceId(id);
@@ -609,7 +609,6 @@
if (value != null) {
ResourceValue resValue = value.getSecond();
- assert resValue != null;
if (resValue != null) {
String v = resValue.getValue();
if (v != null) {
diff --git a/bridge/src/android/graphics/Bitmap_Delegate.java b/bridge/src/android/graphics/Bitmap_Delegate.java
index 0737682..e3bb3e3 100644
--- a/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -17,9 +17,14 @@
package android.graphics;
import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.layoutlib.bridge.impl.RenderAction;
import com.android.resources.Density;
+import com.android.resources.ResourceType;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.annotation.Nullable;
@@ -38,6 +43,7 @@
import java.util.Set;
import javax.imageio.ImageIO;
+import libcore.util.NativeAllocationRegistry_Delegate;
/**
* Delegate implementing the native methods of android.graphics.Bitmap
@@ -62,12 +68,13 @@
// ---- delegate manager ----
private static final DelegateManager<Bitmap_Delegate> sManager =
new DelegateManager<Bitmap_Delegate>(Bitmap_Delegate.class);
+ private static long sFinalizer = -1;
// ---- delegate helper data ----
// ---- delegate data ----
private final Config mConfig;
- private BufferedImage mImage;
+ private final BufferedImage mImage;
private boolean mHasAlpha = true;
private boolean mHasMipMap = false; // TODO: check the default.
private boolean mIsPremultiplied = true;
@@ -114,10 +121,25 @@
* @see Bitmap#isMutable()
* @see Bitmap#getDensity()
*/
- public static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
+ private static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
Density density) throws IOException {
// create a delegate with the content of the file.
- Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
+ BufferedImage image = ImageIO.read(input);
+ if (image == null && input.exists()) {
+ // There was a problem decoding the image, or the decoder isn't registered. Webp maybe.
+ // Replace with a broken image icon.
+ BridgeContext currentContext = RenderAction.getCurrentContext();
+ if (currentContext != null) {
+ RenderResources resources = currentContext.getRenderResources();
+ ResourceValue broken = resources.getFrameworkResource(ResourceType.DRAWABLE,
+ "ic_menu_report_image");
+ File brokenFile = new File(broken.getValue());
+ if (brokenFile.exists()) {
+ image = ImageIO.read(brokenFile);
+ }
+ }
+ }
+ Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
return createBitmap(delegate, createFlags, density.getDpiValue());
}
@@ -281,8 +303,13 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeDestructor(long nativeBitmap) {
- sManager.removeJavaReferenceFor(nativeBitmap);
+ /*package*/ static long nativeGetNativeFinalizer() {
+ synchronized (Bitmap_Delegate.class) {
+ if (sFinalizer == -1) {
+ sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
+ }
+ return sFinalizer;
+ }
}
@LayoutlibDelegate
diff --git a/bridge/src/android/graphics/Canvas_Delegate.java b/bridge/src/android/graphics/Canvas_Delegate.java
index ba0d399..fa880f0 100644
--- a/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/bridge/src/android/graphics/Canvas_Delegate.java
@@ -21,6 +21,7 @@
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.GcSnapshot;
import com.android.layoutlib.bridge.impl.PorterDuffUtility;
+import com.android.ninepatch.NinePatchChunk;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.annotation.Nullable;
@@ -38,6 +39,8 @@
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
+import libcore.util.NativeAllocationRegistry_Delegate;
+
/**
* Delegate implementing the native methods of android.graphics.Canvas
@@ -57,6 +60,7 @@
// ---- delegate manager ----
private static final DelegateManager<Canvas_Delegate> sManager =
new DelegateManager<Canvas_Delegate>(Canvas_Delegate.class);
+ private static long sFinalizer = -1;
// ---- delegate helper data ----
@@ -138,7 +142,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setBitmap(long canvas, Bitmap bitmap) {
+ public static void native_setBitmap(long canvas, Bitmap bitmap) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (canvasDelegate == null || bitmapDelegate==null) {
@@ -149,7 +153,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_isOpaque(long nativeCanvas) {
+ public static boolean native_isOpaque(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -160,7 +164,10 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getWidth(long nativeCanvas) {
+ public static void native_setHighContrastText(long nativeCanvas, boolean highContrastText){}
+
+ @LayoutlibDelegate
+ public static int native_getWidth(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -171,7 +178,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getHeight(long nativeCanvas) {
+ public static int native_getHeight(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -182,7 +189,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_save(long nativeCanvas, int saveFlags) {
+ public static int native_save(long nativeCanvas, int saveFlags) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -193,7 +200,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_saveLayer(long nativeCanvas, float l,
+ public static int native_saveLayer(long nativeCanvas, float l,
float t, float r, float b,
long paint, int layerFlags) {
// get the delegate from the native int.
@@ -212,7 +219,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_saveLayerAlpha(long nativeCanvas, float l,
+ public static int native_saveLayerAlpha(long nativeCanvas, float l,
float t, float r, float b,
int alpha, int layerFlags) {
// get the delegate from the native int.
@@ -225,7 +232,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
+ public static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
// FIXME: implement throwOnUnderflow.
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -237,7 +244,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_restoreToCount(long nativeCanvas, int saveCount,
+ public static void native_restoreToCount(long nativeCanvas, int saveCount,
boolean throwOnUnderflow) {
// FIXME: implement throwOnUnderflow.
// get the delegate from the native int.
@@ -250,7 +257,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getSaveCount(long nativeCanvas) {
+ public static int native_getSaveCount(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -261,7 +268,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_translate(long nativeCanvas, float dx, float dy) {
+ public static void native_translate(long nativeCanvas, float dx, float dy) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -272,7 +279,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_scale(long nativeCanvas, float sx, float sy) {
+ public static void native_scale(long nativeCanvas, float sx, float sy) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -283,7 +290,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_rotate(long nativeCanvas, float degrees) {
+ public static void native_rotate(long nativeCanvas, float degrees) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -294,7 +301,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_skew(long nativeCanvas, float kx, float ky) {
+ public static void native_skew(long nativeCanvas, float kx, float ky) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -318,7 +325,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_concat(long nCanvas, long nMatrix) {
+ public static void native_concat(long nCanvas, long nMatrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
@@ -346,7 +353,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setMatrix(long nCanvas, long nMatrix) {
+ public static void native_setMatrix(long nCanvas, long nMatrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
@@ -376,7 +383,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_clipRect(long nCanvas,
+ public static boolean native_clipRect(long nCanvas,
float left, float top,
float right, float bottom,
int regionOp) {
@@ -390,7 +397,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_clipPath(long nativeCanvas,
+ public static boolean native_clipPath(long nativeCanvas,
long nativePath,
int regionOp) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -407,7 +414,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_clipRegion(long nativeCanvas,
+ public static boolean native_clipRegion(long nativeCanvas,
long nativeRegion,
int regionOp) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -424,7 +431,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
+ public static void nativeSetDrawFilter(long nativeCanvas, long nativeFilter) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
@@ -439,7 +446,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_getClipBounds(long nativeCanvas,
+ public static boolean native_getClipBounds(long nativeCanvas,
Rect bounds) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
@@ -460,7 +467,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_getCTM(long canvas, long matrix) {
+ public static void native_getCTM(long canvas, long matrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
if (canvasDelegate == null) {
@@ -477,13 +484,13 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_quickReject(long nativeCanvas, long path) {
+ public static boolean native_quickReject(long nativeCanvas, long path) {
// FIXME properly implement quickReject
return false;
}
@LayoutlibDelegate
- /*package*/ static boolean native_quickReject(long nativeCanvas,
+ public static boolean native_quickReject(long nativeCanvas,
float left, float top,
float right, float bottom) {
// FIXME properly implement quickReject
@@ -491,7 +498,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawColor(long nativeCanvas, final int color, final int mode) {
+ public static void native_drawColor(long nativeCanvas, final int color, final int mode) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -522,14 +529,14 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawPaint(long nativeCanvas, long paint) {
+ public static void native_drawPaint(long nativeCanvas, long paint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawPaint is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
- /*package*/ static void native_drawPoint(long nativeCanvas, float x, float y,
+ public static void native_drawPoint(long nativeCanvas, float x, float y,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -537,7 +544,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
+ public static void native_drawPoints(long nativeCanvas, float[] pts, int offset, int count,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -545,7 +552,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawLine(long nativeCanvas,
+ public static void native_drawLine(long nativeCanvas,
final float startX, final float startY, final float stopX, final float stopY,
long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -558,7 +565,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawLines(long nativeCanvas,
+ public static void native_drawLines(long nativeCanvas,
final float[] pts, final int offset, final int count,
long nativePaint) {
draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
@@ -574,7 +581,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawRect(long nativeCanvas,
+ public static void native_drawRect(long nativeCanvas,
final float left, final float top, final float right, final float bottom, long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -600,7 +607,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawOval(long nativeCanvas, final float left,
+ public static void native_drawOval(long nativeCanvas, final float left,
final float top, final float right, final float bottom, long paint) {
if (right > left && bottom > top) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -627,7 +634,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawCircle(long nativeCanvas,
+ public static void native_drawCircle(long nativeCanvas,
float cx, float cy, float radius, long paint) {
native_drawOval(nativeCanvas,
cx - radius, cy - radius, cx + radius, cy + radius,
@@ -635,7 +642,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawArc(long nativeCanvas,
+ public static void native_drawArc(long nativeCanvas,
final float left, final float top, final float right, final float bottom,
final float startAngle, final float sweep,
final boolean useCenter, long paint) {
@@ -667,7 +674,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawRoundRect(long nativeCanvas,
+ public static void native_drawRoundRect(long nativeCanvas,
final float left, final float top, final float right, final float bottom,
final float rx, final float ry, long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
@@ -697,7 +704,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawPath(long nativeCanvas, long path, long paint) {
+ public static void native_drawPath(long nativeCanvas, long path, long paint) {
final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
if (pathDelegate == null) {
return;
@@ -749,7 +756,62 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
+ public static void native_drawRegion(long nativeCanvas, long nativeRegion,
+ long nativePaint) {
+ // FIXME
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
+ "Some canvas paths may not be drawn", null, null);
+ }
+
+ @LayoutlibDelegate
+ public static void native_drawNinePatch(Canvas thisCanvas, long nativeCanvas,
+ long nativeBitmap, long ninePatch, final float dstLeft, final float dstTop,
+ final float dstRight, final float dstBottom, long nativePaintOrZero,
+ final int screenDensity, final int bitmapDensity) {
+
+ // get the delegate from the native int.
+ final Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmap);
+ if (bitmapDelegate == null) {
+ return;
+ }
+
+ byte[] c = NinePatch_Delegate.getChunk(ninePatch);
+ if (c == null) {
+ // not a 9-patch?
+ BufferedImage image = bitmapDelegate.getImage();
+ drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 0, 0, image.getWidth(),
+ image.getHeight(), (int) dstLeft, (int) dstTop, (int) dstRight,
+ (int) dstBottom);
+ return;
+ }
+
+ final NinePatchChunk chunkObject = NinePatch_Delegate.getChunk(c);
+ assert chunkObject != null;
+ if (chunkObject == null) {
+ return;
+ }
+
+ Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
+ if (canvasDelegate == null) {
+ return;
+ }
+
+ // this one can be null
+ Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
+
+ canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
+ @Override
+ public void draw(Graphics2D graphics, Paint_Delegate paint) {
+ chunkObject.draw(bitmapDelegate.getImage(), graphics, (int) dstLeft, (int) dstTop,
+ (int) (dstRight - dstLeft), (int) (dstBottom - dstTop), screenDensity,
+ bitmapDensity);
+ }
+ }, paintDelegate, true, false);
+
+ }
+
+ @LayoutlibDelegate
+ public static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
float left, float top,
long nativePaintOrZero,
int canvasDensity,
@@ -771,7 +833,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
+ public static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom,
long nativePaintOrZero, int screenDensity, int bitmapDensity) {
@@ -787,7 +849,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(long nativeCanvas, int[] colors,
+ public static void native_drawBitmap(long nativeCanvas, int[] colors,
int offset, int stride, final float x,
final float y, int width, int height,
boolean hasAlpha,
@@ -812,7 +874,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
+ public static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
long nMatrix, long nPaint) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
@@ -853,7 +915,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
+ public static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
int colorOffset, long nPaint) {
// FIXME
@@ -862,7 +924,7 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawVertices(long nCanvas, int mode, int n,
+ public static void nativeDrawVertices(long nCanvas, int mode, int n,
float[] verts, int vertOffset,
float[] texs, int texOffset,
int[] colors, int colorOffset,
@@ -874,14 +936,14 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawText(long nativeCanvas, char[] text, int index, int count,
+ public static void native_drawText(long nativeCanvas, char[] text, int index, int count,
float startX, float startY, int flags, long paint, long typeface) {
drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0,
paint, typeface);
}
@LayoutlibDelegate
- /*package*/ static void native_drawText(long nativeCanvas, String text,
+ public static void native_drawText(long nativeCanvas, String text,
int start, int end, float x, float y, final int flags, long paint,
long typeface) {
int count = end - start;
@@ -892,7 +954,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextRun(long nativeCanvas, String text,
+ public static void native_drawTextRun(long nativeCanvas, String text,
int start, int end, int contextStart, int contextEnd,
float x, float y, boolean isRtl, long paint, long typeface) {
int count = end - start;
@@ -903,14 +965,14 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextRun(long nativeCanvas, char[] text,
+ public static void native_drawTextRun(long nativeCanvas, char[] text,
int start, int count, int contextStart, int contextCount,
float x, float y, boolean isRtl, long paint, long typeface) {
drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextOnPath(long nativeCanvas,
+ public static void native_drawTextOnPath(long nativeCanvas,
char[] text, int index,
int count, long path,
float hOffset,
@@ -922,7 +984,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextOnPath(long nativeCanvas,
+ public static void native_drawTextOnPath(long nativeCanvas,
String text, long path,
float hOffset,
float vOffset,
@@ -934,20 +996,21 @@
}
@LayoutlibDelegate
- /*package*/ static void finalizer(long nativeCanvas) {
- // get the delegate from the native int so that it can be disposed.
- Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return;
+ /*package*/ static long getNativeFinalizer() {
+ synchronized (Canvas_Delegate.class) {
+ if (sFinalizer == -1) {
+ sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(nativePtr -> {
+ Canvas_Delegate delegate = sManager.getDelegate(nativePtr);
+ if (delegate != null) {
+ delegate.dispose();
+ }
+ sManager.removeJavaReferenceFor(nativePtr);
+ });
+ }
}
-
- canvasDelegate.dispose();
-
- // remove it from the manager.
- sManager.removeJavaReferenceFor(nativeCanvas);
+ return sFinalizer;
}
-
// ---- Private delegate/helper methods ----
/**
diff --git a/bridge/src/android/graphics/FontFamily_Delegate.java b/bridge/src/android/graphics/FontFamily_Delegate.java
index c7b24bc..7412bc2 100644
--- a/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -33,13 +33,13 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;
@@ -73,7 +73,7 @@
private static final Map<String, FontInfo> sCache =
new LinkedHashMap<String, FontInfo>(CACHE_SIZE) {
@Override
- protected boolean removeEldestEntry(Entry<String, FontInfo> eldest) {
+ protected boolean removeEldestEntry(Map.Entry<String, FontInfo> eldest) {
return size() > CACHE_SIZE;
}
@@ -213,7 +213,7 @@
return mValid;
}
- /*package*/ static Font loadFont(String path) {
+ private static Font loadFont(String path) {
if (path.startsWith(SYSTEM_FONTS) ) {
String relativePath = path.substring(SYSTEM_FONTS.length());
File f = new File(sFontLocation, relativePath);
@@ -270,16 +270,12 @@
}
@LayoutlibDelegate
- /*package*/ static boolean nAddFont(long nativeFamily, final String path) {
+ /*package*/ static boolean nAddFont(long nativeFamily, final String path, int ttcIndex) {
+ // FIXME: support ttc fonts. Hack JRE??
final FontFamily_Delegate delegate = getDelegate(nativeFamily);
if (delegate != null) {
if (sFontLocation == null) {
- delegate.mPostInitRunnables.add(new Runnable() {
- @Override
- public void run() {
- delegate.addFont(path);
- }
- });
+ delegate.mPostInitRunnables.add(() -> delegate.addFont(path));
return true;
}
return delegate.addFont(path);
@@ -288,17 +284,19 @@
}
@LayoutlibDelegate
- /*package*/ static boolean nAddFontWeightStyle(long nativeFamily, final String path,
- final int weight, final boolean isItalic) {
+ /*package*/ static boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font,
+ int ttcIndex, List<FontListParser.Axis> listOfAxis,
+ int weight, boolean isItalic) {
+ assert false : "The only client of this method has been overriden.";
+ return false;
+ }
+
+ static boolean addFont(long nativeFamily, final String path, final int weight,
+ final boolean isItalic) {
final FontFamily_Delegate delegate = getDelegate(nativeFamily);
if (delegate != null) {
if (sFontLocation == null) {
- delegate.mPostInitRunnables.add(new Runnable() {
- @Override
- public void run() {
- delegate.addFont(path, weight, isItalic);
- }
- });
+ delegate.mPostInitRunnables.add(() -> delegate.addFont(path, weight, isItalic));
return true;
}
return delegate.addFont(path, weight, isItalic);
@@ -309,6 +307,9 @@
@LayoutlibDelegate
/*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) {
FontFamily_Delegate ffd = sManager.getDelegate(nativeFamily);
+ if (ffd == null) {
+ return false;
+ }
ffd.mValid = true;
if (mgr == null) {
return false;
@@ -452,6 +453,7 @@
private FontInfo deriveFont(@NonNull FontInfo srcFont, @NonNull FontInfo outFont) {
int desiredWeight = outFont.mWeight;
int srcWeight = srcFont.mWeight;
+ assert srcFont.mFont != null;
Font derivedFont = srcFont.mFont;
// Embolden the font if required.
if (desiredWeight >= BOLD_FONT_WEIGHT && desiredWeight - srcWeight > BOLD_FONT_WEIGHT_DELTA / 2) {
diff --git a/bridge/src/android/graphics/NinePatch_Delegate.java b/bridge/src/android/graphics/NinePatch_Delegate.java
index e8d34d0..1f0eb3b 100644
--- a/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -169,77 +169,18 @@
sManager.removeJavaReferenceFor(chunk);
}
- @LayoutlibDelegate
- /*package*/ static void nativeDraw(long canvas_instance, RectF loc, Bitmap bitmap_instance,
- long chunk, long paint_instance_or_null, int destDensity, int srcDensity) {
- draw(canvas_instance,
- (int) loc.left, (int) loc.top, (int) loc.right, (int) loc.bottom,
- bitmap_instance, chunk, paint_instance_or_null,
- destDensity, srcDensity);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeDraw(long canvas_instance, Rect loc, Bitmap bitmap_instance,
- long chunk, long paint_instance_or_null, int destDensity, int srcDensity) {
- draw(canvas_instance,
- loc.left, loc.top, loc.right, loc.bottom,
- bitmap_instance, chunk, paint_instance_or_null,
- destDensity, srcDensity);
- }
@LayoutlibDelegate
/*package*/ static long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location) {
return 0;
}
- // ---- Private Helper methods ----
-
- private static void draw(long canvas_instance,
- final int left, final int top, final int right, final int bottom,
- Bitmap bitmap_instance, long chunk, long paint_instance_or_null,
- final int destDensity, final int srcDensity) {
- // get the delegate from the native int.
- final Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance);
- if (bitmap_delegate == null) {
- return;
- }
-
- byte[] c = null;
- NinePatch_Delegate delegate = sManager.getDelegate(chunk);
+ static byte[] getChunk(long nativeNinePatch) {
+ NinePatch_Delegate delegate = sManager.getDelegate(nativeNinePatch);
if (delegate != null) {
- c = delegate.chunk;
+ return delegate.chunk;
}
- if (c == null) {
- // not a 9-patch?
- BufferedImage image = bitmap_delegate.getImage();
- Canvas_Delegate.native_drawBitmap(null, canvas_instance, bitmap_instance,
- 0f, 0f, (float)image.getWidth(), (float)image.getHeight(),
- (float)left, (float)top, (float)right, (float)bottom,
- paint_instance_or_null, destDensity, srcDensity);
- return;
- }
+ return null;
+ }
- final NinePatchChunk chunkObject = getChunk(c);
- assert chunkObject != null;
- if (chunkObject == null) {
- return;
- }
-
- Canvas_Delegate canvas_delegate = Canvas_Delegate.getDelegate(canvas_instance);
- if (canvas_delegate == null) {
- return;
- }
-
- // this one can be null
- Paint_Delegate paint_delegate = Paint_Delegate.getDelegate(paint_instance_or_null);
-
- canvas_delegate.getSnapshot().draw(new GcSnapshot.Drawable() {
- @Override
- public void draw(Graphics2D graphics, Paint_Delegate paint) {
- chunkObject.draw(bitmap_delegate.getImage(), graphics,
- left, top, right - left, bottom - top, destDensity, srcDensity);
- }
- }, paint_delegate, true /*compositeOnly*/, false /*forceSrcMode*/);
-
- }
}
diff --git a/bridge/src/android/graphics/Paint_Delegate.java b/bridge/src/android/graphics/Paint_Delegate.java
index dbd45c4..33296e1 100644
--- a/bridge/src/android/graphics/Paint_Delegate.java
+++ b/bridge/src/android/graphics/Paint_Delegate.java
@@ -39,6 +39,8 @@
import java.util.List;
import java.util.Locale;
+import libcore.util.NativeAllocationRegistry_Delegate;
+
/**
* Delegate implementing the native methods of android.graphics.Paint
*
@@ -65,6 +67,7 @@
// ---- delegate manager ----
private static final DelegateManager<Paint_Delegate> sManager =
new DelegateManager<Paint_Delegate>(Paint_Delegate.class);
+ private static long sFinalizer = -1;
// ---- delegate helper data ----
@@ -220,6 +223,14 @@
return mColorFilter;
}
+ public void setColorFilter(long colorFilterPtr) {
+ mColorFilter = ColorFilter_Delegate.getDelegate(colorFilterPtr);
+ }
+
+ public void setShader(long shaderPtr) {
+ mShader = Shader_Delegate.getDelegate(shaderPtr);
+ }
+
/**
* Returns the {@link Shader} delegate or null if none have been set
*
@@ -250,9 +261,9 @@
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static int getFlags(Paint thisPaint) {
+ /*package*/ static int nGetFlags(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@@ -263,9 +274,9 @@
@LayoutlibDelegate
- /*package*/ static void setFlags(Paint thisPaint, int flags) {
+ /*package*/ static void nSetFlags(Paint thisPaint, long nativePaint, int flags) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@@ -274,14 +285,14 @@
}
@LayoutlibDelegate
- /*package*/ static void setFilterBitmap(Paint thisPaint, boolean filter) {
- setFlag(thisPaint, Paint.FILTER_BITMAP_FLAG, filter);
+ /*package*/ static void nSetFilterBitmap(Paint thisPaint, long nativePaint, boolean filter) {
+ setFlag(nativePaint, Paint.FILTER_BITMAP_FLAG, filter);
}
@LayoutlibDelegate
- /*package*/ static int getHinting(Paint thisPaint) {
+ /*package*/ static int nGetHinting(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return Paint.HINTING_ON;
}
@@ -290,9 +301,9 @@
}
@LayoutlibDelegate
- /*package*/ static void setHinting(Paint thisPaint, int mode) {
+ /*package*/ static void nSetHinting(Paint thisPaint, long nativePaint, int mode) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@@ -301,44 +312,48 @@
}
@LayoutlibDelegate
- /*package*/ static void setAntiAlias(Paint thisPaint, boolean aa) {
- setFlag(thisPaint, Paint.ANTI_ALIAS_FLAG, aa);
+ /*package*/ static void nSetAntiAlias(Paint thisPaint, long nativePaint, boolean aa) {
+ setFlag(nativePaint, Paint.ANTI_ALIAS_FLAG, aa);
}
@LayoutlibDelegate
- /*package*/ static void setSubpixelText(Paint thisPaint, boolean subpixelText) {
- setFlag(thisPaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
+ /*package*/ static void nSetSubpixelText(Paint thisPaint, long nativePaint,
+ boolean subpixelText) {
+ setFlag(nativePaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
}
@LayoutlibDelegate
- /*package*/ static void setUnderlineText(Paint thisPaint, boolean underlineText) {
- setFlag(thisPaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
+ /*package*/ static void nSetUnderlineText(Paint thisPaint, long nativePaint,
+ boolean underlineText) {
+ setFlag(nativePaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
}
@LayoutlibDelegate
- /*package*/ static void setStrikeThruText(Paint thisPaint, boolean strikeThruText) {
- setFlag(thisPaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
+ /*package*/ static void nSetStrikeThruText(Paint thisPaint, long nativePaint,
+ boolean strikeThruText) {
+ setFlag(nativePaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
}
@LayoutlibDelegate
- /*package*/ static void setFakeBoldText(Paint thisPaint, boolean fakeBoldText) {
- setFlag(thisPaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
+ /*package*/ static void nSetFakeBoldText(Paint thisPaint, long nativePaint,
+ boolean fakeBoldText) {
+ setFlag(nativePaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
}
@LayoutlibDelegate
- /*package*/ static void setDither(Paint thisPaint, boolean dither) {
- setFlag(thisPaint, Paint.DITHER_FLAG, dither);
+ /*package*/ static void nSetDither(Paint thisPaint, long nativePaint, boolean dither) {
+ setFlag(nativePaint, Paint.DITHER_FLAG, dither);
}
@LayoutlibDelegate
- /*package*/ static void setLinearText(Paint thisPaint, boolean linearText) {
- setFlag(thisPaint, Paint.LINEAR_TEXT_FLAG, linearText);
+ /*package*/ static void nSetLinearText(Paint thisPaint, long nativePaint, boolean linearText) {
+ setFlag(nativePaint, Paint.LINEAR_TEXT_FLAG, linearText);
}
@LayoutlibDelegate
- /*package*/ static int getColor(Paint thisPaint) {
+ /*package*/ static int nGetColor(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@@ -347,9 +362,9 @@
}
@LayoutlibDelegate
- /*package*/ static void setColor(Paint thisPaint, int color) {
+ /*package*/ static void nSetColor(Paint thisPaint, long nativePaint, int color) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@@ -358,9 +373,9 @@
}
@LayoutlibDelegate
- /*package*/ static int getAlpha(Paint thisPaint) {
+ /*package*/ static int nGetAlpha(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@@ -369,9 +384,9 @@
}
@LayoutlibDelegate
- /*package*/ static void setAlpha(Paint thisPaint, int a) {
+ /*package*/ static void nSetAlpha(Paint thisPaint, long nativePaint, int a) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@@ -380,9 +395,9 @@
}
@LayoutlibDelegate
- /*package*/ static float getStrokeWidth(Paint thisPaint) {
+ /*package*/ static float nGetStrokeWidth(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 1.f;
}
@@ -391,9 +406,9 @@
}
@LayoutlibDelegate
- /*package*/ static void setStrokeWidth(Paint thisPaint, float width) {
+ /*package*/ static void nSetStrokeWidth(Paint thisPaint, long nativePaint, float width) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@@ -402,9 +417,9 @@
}
@LayoutlibDelegate
- /*package*/ static float getStrokeMiter(Paint thisPaint) {
+ /*package*/ static float nGetStrokeMiter(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 1.f;
}
@@ -413,9 +428,9 @@
}
@LayoutlibDelegate
- /*package*/ static void setStrokeMiter(Paint thisPaint, float miter) {
+ /*package*/ static void nSetStrokeMiter(Paint thisPaint, long nativePaint, float miter) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@@ -424,7 +439,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setShadowLayer(long paint, float radius, float dx, float dy,
+ /*package*/ static void nSetShadowLayer(long paint, float radius, float dx, float dy,
int color) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -432,7 +447,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_hasShadowLayer(long paint) {
+ /*package*/ static boolean nHasShadowLayer(long paint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Paint.hasShadowLayer is not supported.", null, null /*data*/);
@@ -440,16 +455,17 @@
}
@LayoutlibDelegate
- /*package*/ static boolean isElegantTextHeight(Paint thisPaint) {
+ /*package*/ static boolean nIsElegantTextHeight(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
return delegate != null && delegate.mFontVariant == FontVariant.ELEGANT;
}
@LayoutlibDelegate
- /*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) {
+ /*package*/ static void nSetElegantTextHeight(Paint thisPaint, long nativePaint,
+ boolean elegant) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@@ -458,9 +474,9 @@
}
@LayoutlibDelegate
- /*package*/ static float getTextSize(Paint thisPaint) {
+ /*package*/ static float nGetTextSize(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 1.f;
}
@@ -469,9 +485,9 @@
}
@LayoutlibDelegate
- /*package*/ static void setTextSize(Paint thisPaint, float textSize) {
+ /*package*/ static void nSetTextSize(Paint thisPaint, long nativePaint, float textSize) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@@ -483,9 +499,9 @@
}
@LayoutlibDelegate
- /*package*/ static float getTextScaleX(Paint thisPaint) {
+ /*package*/ static float nGetTextScaleX(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 1.f;
}
@@ -494,9 +510,9 @@
}
@LayoutlibDelegate
- /*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) {
+ /*package*/ static void nSetTextScaleX(Paint thisPaint, long nativePaint, float scaleX) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@@ -508,9 +524,9 @@
}
@LayoutlibDelegate
- /*package*/ static float getTextSkewX(Paint thisPaint) {
+ /*package*/ static float nGetTextSkewX(Paint thisPaint, long nativePaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 1.f;
}
@@ -519,9 +535,9 @@
}
@LayoutlibDelegate
- /*package*/ static void setTextSkewX(Paint thisPaint, float skewX) {
+ /*package*/ static void nSetTextSkewX(Paint thisPaint, long nativePaint, float skewX) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
@@ -533,9 +549,9 @@
}
@LayoutlibDelegate
- /*package*/ static float ascent(Paint thisPaint) {
+ /*package*/ static float nAscent(Paint thisPaint, long nativePaint, long nativeTypeface) {
// get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@@ -550,9 +566,9 @@
}
@LayoutlibDelegate
- /*package*/ static float descent(Paint thisPaint) {
+ /*package*/ static float nDescent(Paint thisPaint, long nativePaint, long nativeTypeface) {
// get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@@ -567,9 +583,10 @@
}
@LayoutlibDelegate
- /*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) {
+ /*package*/ static float nGetFontMetrics(Paint thisPaint, long nativePaint, long nativeTypeface,
+ FontMetrics metrics) {
// get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@@ -578,9 +595,10 @@
}
@LayoutlibDelegate
- /*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) {
+ /*package*/ static int nGetFontMetricsInt(Paint thisPaint, long nativePaint,
+ long nativeTypeface, FontMetricsInt fmi) {
// get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
@@ -603,31 +621,7 @@
}
@LayoutlibDelegate
- /*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
- int count, int bidiFlags) {
- // get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
- if (delegate == null) {
- return 0;
- }
-
- RectF bounds = delegate.measureText(text, index, count, null, 0, bidiFlags);
- return bounds.right - bounds.left;
- }
-
- @LayoutlibDelegate
- /*package*/ static float native_measureText(Paint thisPaint, String text, int start, int end,
- int bidiFlags) {
- return native_measureText(thisPaint, text.toCharArray(), start, end - start, bidiFlags);
- }
-
- @LayoutlibDelegate
- /*package*/ static float native_measureText(Paint thisPaint, String text, int bidiFlags) {
- return native_measureText(thisPaint, text.toCharArray(), 0, text.length(), bidiFlags);
- }
-
- @LayoutlibDelegate
- /*package*/ static int native_breakText(long nativePaint, long nativeTypeface, char[] text,
+ /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, char[] text,
int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth) {
// get the delegate
@@ -669,21 +663,21 @@
}
@LayoutlibDelegate
- /*package*/ static int native_breakText(long nativePaint, long nativeTypeface, String text,
+ /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, String text,
boolean measureForwards,
float maxWidth, int bidiFlags, float[] measuredWidth) {
- return native_breakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(),
+ return nBreakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(),
maxWidth, bidiFlags, measuredWidth);
}
@LayoutlibDelegate
- /*package*/ static long native_init() {
+ /*package*/ static long nInit() {
Paint_Delegate newDelegate = new Paint_Delegate();
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
- /*package*/ static long native_initWithPaint(long paint) {
+ /*package*/ static long nInitWithPaint(long paint) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(paint);
if (delegate == null) {
@@ -695,7 +689,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_reset(long native_object) {
+ /*package*/ static void nReset(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -706,7 +700,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_set(long native_dst, long native_src) {
+ /*package*/ static void nSet(long native_dst, long native_src) {
// get the delegate from the native int.
Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
if (delegate_dst == null) {
@@ -723,7 +717,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getStyle(long native_object) {
+ /*package*/ static int nGetStyle(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -734,7 +728,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setStyle(long native_object, int style) {
+ /*package*/ static void nSetStyle(long native_object, int style) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -745,7 +739,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getStrokeCap(long native_object) {
+ /*package*/ static int nGetStrokeCap(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -756,7 +750,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setStrokeCap(long native_object, int cap) {
+ /*package*/ static void nSetStrokeCap(long native_object, int cap) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -767,7 +761,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getStrokeJoin(long native_object) {
+ /*package*/ static int nGetStrokeJoin(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -778,7 +772,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setStrokeJoin(long native_object, int join) {
+ /*package*/ static void nSetStrokeJoin(long native_object, int join) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -789,7 +783,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_getFillPath(long native_object, long src, long dst) {
+ /*package*/ static boolean nGetFillPath(long native_object, long src, long dst) {
Paint_Delegate paint = sManager.getDelegate(native_object);
if (paint == null) {
return false;
@@ -815,7 +809,7 @@
}
@LayoutlibDelegate
- /*package*/ static long native_setShader(long native_object, long shader) {
+ /*package*/ static long nSetShader(long native_object, long shader) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -828,7 +822,7 @@
}
@LayoutlibDelegate
- /*package*/ static long native_setColorFilter(long native_object, long filter) {
+ /*package*/ static long nSetColorFilter(long native_object, long filter) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -847,7 +841,7 @@
}
@LayoutlibDelegate
- /*package*/ static long native_setXfermode(long native_object, long xfermode) {
+ /*package*/ static long nSetXfermode(long native_object, long xfermode) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -860,7 +854,7 @@
}
@LayoutlibDelegate
- /*package*/ static long native_setPathEffect(long native_object, long effect) {
+ /*package*/ static long nSetPathEffect(long native_object, long effect) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -873,7 +867,7 @@
}
@LayoutlibDelegate
- /*package*/ static long native_setMaskFilter(long native_object, long maskfilter) {
+ /*package*/ static long nSetMaskFilter(long native_object, long maskfilter) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -892,7 +886,7 @@
}
@LayoutlibDelegate
- /*package*/ static long native_setTypeface(long native_object, long typeface) {
+ /*package*/ static long nSetTypeface(long native_object, long typeface) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -909,7 +903,7 @@
}
@LayoutlibDelegate
- /*package*/ static long native_setRasterizer(long native_object, long rasterizer) {
+ /*package*/ static long nSetRasterizer(long native_object, long rasterizer) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -928,7 +922,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getTextAlign(long native_object) {
+ /*package*/ static int nGetTextAlign(long native_object) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -939,7 +933,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setTextAlign(long native_object, int align) {
+ /*package*/ static void nSetTextAlign(long native_object, int align) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
@@ -950,58 +944,27 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setTextLocale(long native_object, String locale) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return;
- }
-
- delegate.setTextLocale(locale);
- }
-
- @LayoutlibDelegate
- /*package*/ static int native_getTextWidths(long native_object, long native_typeface,
- char[] text, int index, int count, int bidiFlags, float[] widths) {
-
- if (widths != null) {
- for (int i = 0; i< count; i++) {
- widths[i]=0;
- }
- }
+ /*package*/ static int nSetTextLocales(long native_object, String locale) {
// get the delegate from the native int.
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
return 0;
}
- // native_typeface is passed here since Framework's old implementation did not have the
- // typeface object associated with the Paint. Since, we follow the new framework way,
- // we store the typeface with the paint and use it directly.
- assert (native_typeface == delegate.mNativeTypeface);
-
- RectF bounds = delegate.measureText(text, index, count, widths, 0, bidiFlags);
- return ((int) (bounds.right - bounds.left));
- }
-
- @LayoutlibDelegate
- /*package*/ static int native_getTextWidths(long native_object, long native_typeface,
- String text, int start, int end, int bidiFlags, float[] widths) {
- return native_getTextWidths(native_object, native_typeface, text.toCharArray(), start,
- end - start, bidiFlags, widths);
- }
-
- @LayoutlibDelegate
- /* package */static int native_getTextGlyphs(long native_object, String text, int start,
- int end, int contextStart, int contextEnd, int flags, char[] glyphs) {
- // FIXME
+ delegate.setTextLocale(locale);
return 0;
}
@LayoutlibDelegate
- /*package*/ static float native_getTextRunAdvances(long native_object, long native_typeface,
+ /*package*/ static void nSetTextLocalesByMinikinLangListId(long paintPtr,
+ int mMinikinLangListId) {
+ // FIXME
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static float nGetTextAdvances(long native_object, long native_typeface,
char[] text, int index, int count, int contextIndex, int contextCount,
- boolean isRtl, float[] advances, int advancesIndex) {
+ int bidiFlags, float[] advances, int advancesIndex) {
if (advances != null)
for (int i = advancesIndex; i< advancesIndex+count; i++)
@@ -1017,25 +980,25 @@
// we store the typeface with the paint and use it directly.
assert (native_typeface == delegate.mNativeTypeface);
- RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, isRtl);
+ RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, bidiFlags);
return bounds.right - bounds.left;
}
@LayoutlibDelegate
- /*package*/ static float native_getTextRunAdvances(long native_object, long native_typeface,
+ /*package*/ static float nGetTextAdvances(long native_object, long native_typeface,
String text, int start, int end, int contextStart, int contextEnd,
- boolean isRtl, float[] advances, int advancesIndex) {
+ int bidiFlags, float[] advances, int advancesIndex) {
// FIXME: support contextStart and contextEnd
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
- return native_getTextRunAdvances(native_object, native_typeface, buffer, 0, count,
- contextStart, contextEnd - contextStart, isRtl, advances, advancesIndex);
+ return nGetTextAdvances(native_object, native_typeface, buffer, 0, count,
+ contextStart, contextEnd - contextStart, bidiFlags, advances, advancesIndex);
}
@LayoutlibDelegate
- /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, char[] text,
+ /*package*/ static int nGetTextRunCursor(Paint thisPaint, long native_object, char[] text,
int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1044,7 +1007,7 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getTextRunCursor(Paint thisPaint, long native_object, String text,
+ /*package*/ static int nGetTextRunCursor(Paint thisPaint, long native_object, String text,
int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1053,7 +1016,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_getTextPath(long native_object, long native_typeface,
+ /*package*/ static void nGetTextPath(long native_object, long native_typeface,
int bidiFlags, char[] text, int index, int count, float x, float y, long path) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1061,7 +1024,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_getTextPath(long native_object, long native_typeface,
+ /*package*/ static void nGetTextPath(long native_object, long native_typeface,
int bidiFlags, String text, int start, int end, float x, float y, long path) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1069,14 +1032,14 @@
}
@LayoutlibDelegate
- /*package*/ static void nativeGetStringBounds(long nativePaint, long native_typeface,
+ /*package*/ static void nGetStringBounds(long nativePaint, long native_typeface,
String text, int start, int end, int bidiFlags, Rect bounds) {
- nativeGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start,
+ nGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start,
end - start, bidiFlags, bounds);
}
@LayoutlibDelegate
- /*package*/ static void nativeGetCharArrayBounds(long nativePaint, long native_typeface,
+ /*package*/ static void nGetCharArrayBounds(long nativePaint, long native_typeface,
char[] text, int index, int count, int bidiFlags, Rect bounds) {
// get the delegate from the native int.
@@ -1092,12 +1055,18 @@
}
@LayoutlibDelegate
- /*package*/ static void finalizer(long nativePaint) {
- sManager.removeJavaReferenceFor(nativePaint);
+ /*package*/ static long nGetNativeFinalizer() {
+ synchronized (Paint_Delegate.class) {
+ if (sFinalizer == -1) {
+ sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(
+ sManager::removeJavaReferenceFor);
+ }
+ }
+ return sFinalizer;
}
@LayoutlibDelegate
- /*package*/ static float native_getLetterSpacing(long nativePaint) {
+ /*package*/ static float nGetLetterSpacing(long nativePaint) {
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
@@ -1106,7 +1075,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setLetterSpacing(long nativePaint, float letterSpacing) {
+ /*package*/ static void nSetLetterSpacing(long nativePaint, float letterSpacing) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
"Paint.setLetterSpacing() not supported.", null, null);
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
@@ -1117,13 +1086,13 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setFontFeatureSettings(long nativePaint, String settings) {
+ /*package*/ static void nSetFontFeatureSettings(long nativePaint, String settings) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
"Paint.setFontFeatureSettings() not supported.", null, null);
}
@LayoutlibDelegate
- /*package*/ static int native_getHyphenEdit(long nativePaint) {
+ /*package*/ static int nGetHyphenEdit(long nativePaint) {
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
@@ -1132,7 +1101,7 @@
}
@LayoutlibDelegate
- /*package*/ static void native_setHyphenEdit(long nativePaint, int hyphen) {
+ /*package*/ static void nSetHyphenEdit(long nativePaint, int hyphen) {
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
@@ -1141,7 +1110,7 @@
}
@LayoutlibDelegate
- /*package*/ static boolean native_hasGlyph(long nativePaint, long nativeTypeface, int bidiFlags,
+ /*package*/ static boolean nHasGlyph(long nativePaint, long nativeTypeface, int bidiFlags,
String string) {
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
@@ -1169,13 +1138,14 @@
@LayoutlibDelegate
- /*package*/ static float native_getRunAdvance(long nativePaint, long nativeTypeface,
+ /*package*/ static float nGetRunAdvance(long nativePaint, long nativeTypeface,
@NonNull char[] text, int start, int end, int contextStart, int contextEnd,
boolean isRtl, int offset) {
int count = end - start;
float[] advances = new float[count];
- native_getTextRunAdvances(nativePaint, nativeTypeface, text, start, count,
- contextStart, contextEnd - contextStart, isRtl, advances, 0);
+ int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
+ nGetTextAdvances(nativePaint, nativeTypeface, text, start, count,
+ contextStart, contextEnd - contextStart, bidiFlags, advances, 0);
int startOffset = offset - start; // offset from start.
float sum = 0;
for (int i = 0; i < startOffset; i++) {
@@ -1185,13 +1155,14 @@
}
@LayoutlibDelegate
- /*package*/ static int native_getOffsetForAdvance(long nativePaint, long nativeTypeface,
+ /*package*/ static int nGetOffsetForAdvance(long nativePaint, long nativeTypeface,
char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl,
float advance) {
int count = end - start;
float[] advances = new float[count];
- native_getTextRunAdvances(nativePaint, nativeTypeface, text, start, count,
- contextStart, contextEnd - contextStart, isRtl, advances, 0);
+ int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
+ nGetTextAdvances(nativePaint, nativeTypeface, text, start, count,
+ contextStart, contextEnd - contextStart, bidiFlags, advances, 0);
float sum = 0;
int i;
for (i = 0; i < count && sum < advance; i++) {
@@ -1359,9 +1330,9 @@
mLocale = new Locale(locale);
}
- private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) {
+ private static void setFlag(long nativePaint, int flagMask, boolean flagValue) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
diff --git a/bridge/src/android/graphics/Path_Delegate.java b/bridge/src/android/graphics/Path_Delegate.java
index a10ac00..08f0cb4 100644
--- a/bridge/src/android/graphics/Path_Delegate.java
+++ b/bridge/src/android/graphics/Path_Delegate.java
@@ -75,7 +75,7 @@
return sManager.getDelegate(nPath);
}
- public Shape getJavaShape() {
+ public Path2D getJavaShape() {
return mPath;
}
@@ -572,7 +572,7 @@
return null;
}
- private static void addPath(long destPath, long srcPath, AffineTransform transform) {
+ public static void addPath(long destPath, long srcPath, AffineTransform transform) {
Path_Delegate destPathDelegate = sManager.getDelegate(destPath);
if (destPathDelegate == null) {
return;
@@ -630,7 +630,7 @@
* Fills the given {@link RectF} with the path bounds.
* @param bounds the RectF to be filled.
*/
- private void fillBounds(RectF bounds) {
+ public void fillBounds(RectF bounds) {
Rectangle2D rect = mPath.getBounds2D();
bounds.left = (float)rect.getMinX();
bounds.right = (float)rect.getMaxX();
@@ -644,7 +644,7 @@
* @param x The x-coordinate of the start of a new contour
* @param y The y-coordinate of the start of a new contour
*/
- private void moveTo(float x, float y) {
+ public void moveTo(float x, float y) {
mPath.moveTo(mLastX = x, mLastY = y);
}
@@ -658,7 +658,7 @@
* @param dy The amount to add to the y-coordinate of the end of the
* previous contour, to specify the start of a new contour
*/
- private void rMoveTo(float dx, float dy) {
+ public void rMoveTo(float dx, float dy) {
dx += mLastX;
dy += mLastY;
mPath.moveTo(mLastX = dx, mLastY = dy);
@@ -672,7 +672,7 @@
* @param x The x-coordinate of the end of a line
* @param y The y-coordinate of the end of a line
*/
- private void lineTo(float x, float y) {
+ public void lineTo(float x, float y) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
}
@@ -689,7 +689,7 @@
* @param dy The amount to add to the y-coordinate of the previous point on
* this contour, to specify a line
*/
- private void rLineTo(float dx, float dy) {
+ public void rLineTo(float dx, float dy) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
}
@@ -714,7 +714,7 @@
* @param x2 The x-coordinate of the end point on a quadratic curve
* @param y2 The y-coordinate of the end point on a quadratic curve
*/
- private void quadTo(float x1, float y1, float x2, float y2) {
+ public void quadTo(float x1, float y1, float x2, float y2) {
mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2);
}
@@ -732,7 +732,7 @@
* @param dy2 The amount to add to the y-coordinate of the last point on
* this contour, for the end point of a quadratic curve
*/
- private void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
+ public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
}
@@ -755,7 +755,7 @@
* @param x3 The x-coordinate of the end point on a cubic curve
* @param y3 The y-coordinate of the end point on a cubic curve
*/
- private void cubicTo(float x1, float y1, float x2, float y2,
+ public void cubicTo(float x1, float y1, float x2, float y2,
float x3, float y3) {
if (!hasPoints()) {
mPath.moveTo(0, 0);
@@ -768,7 +768,7 @@
* current point on this contour. If there is no previous point, then a
* moveTo(0,0) is inserted automatically.
*/
- private void rCubicTo(float dx1, float dy1, float dx2, float dy2,
+ public void rCubicTo(float dx1, float dy1, float dx2, float dy2,
float dx3, float dy3) {
if (!hasPoints()) {
mPath.moveTo(mLastX = 0, mLastY = 0);
@@ -798,7 +798,7 @@
* mod 360.
* @param forceMoveTo If true, always begin a new contour with the arc
*/
- private void arcTo(float left, float top, float right, float bottom, float startAngle,
+ public void arcTo(float left, float top, float right, float bottom, float startAngle,
float sweepAngle,
boolean forceMoveTo) {
Arc2D arc = new Arc2D.Float(left, top, right - left, bottom - top, -startAngle,
@@ -812,7 +812,7 @@
* Close the current contour. If the current point is not equal to the
* first point of the contour, a line segment is automatically added.
*/
- private void close() {
+ public void close() {
mPath.closePath();
}
@@ -831,7 +831,7 @@
* @param bottom The bottom of a rectangle to add to the path
* @param dir The direction to wind the rectangle's contour
*/
- private void addRect(float left, float top, float right, float bottom,
+ public void addRect(float left, float top, float right, float bottom,
int dir) {
moveTo(left, top);
diff --git a/bridge/src/android/graphics/Typeface_Delegate.java b/bridge/src/android/graphics/Typeface_Delegate.java
index 85e65e6..5cd34f6 100644
--- a/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/bridge/src/android/graphics/Typeface_Delegate.java
@@ -24,8 +24,10 @@
import java.awt.Font;
import java.io.File;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import static android.graphics.FontFamily_Delegate.getFontLocation;
@@ -205,6 +207,17 @@
return new File(getFontLocation());
}
+ @LayoutlibDelegate
+ /*package*/ static FontFamily makeFamilyFromParsed(FontListParser.Family family,
+ Map<String, ByteBuffer> bufferForPath) {
+ FontFamily fontFamily = new FontFamily(family.lang, family.variant);
+ for (FontListParser.Font font : family.fonts) {
+ FontFamily_Delegate.addFont(fontFamily.mNativePtr, font.fontName, font.weight,
+ font.isItalic);
+ }
+ return fontFamily;
+ }
+
// ---- Private delegate/helper methods ----
private Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style) {
diff --git a/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java b/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java
new file mode 100644
index 0000000..200fe3b
--- /dev/null
+++ b/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2016 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 android.graphics.drawable;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.internal.view.animation.NativeInterpolatorFactoryHelper_Delegate;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.PropertyValuesHolder;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
+import android.graphics.drawable.VectorDrawable_Delegate.VFullPath_Delegate;
+import android.graphics.drawable.VectorDrawable_Delegate.VGroup_Delegate;
+import android.graphics.drawable.VectorDrawable_Delegate.VNativeObject;
+import android.graphics.drawable.VectorDrawable_Delegate.VPathRenderer_Delegate;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link
+ * AnimatedVectorDrawable}
+ * <p>
+ * Through the layoutlib_create tool, the original methods of AnimatedVectorDrawable have been
+ * replaced by calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class AnimatedVectorDrawable_Delegate {
+ private static DelegateManager<AnimatorSetHolder> sAnimatorSets = new
+ DelegateManager<>(AnimatorSetHolder.class);
+ private static DelegateManager<PropertySetter> sHolders = new
+ DelegateManager<>(PropertySetter.class);
+
+
+ @LayoutlibDelegate
+ /*package*/ static long nCreateAnimatorSet() {
+ return sAnimatorSets.addNewDelegate(new AnimatorSetHolder());
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nAddAnimator(long setPtr, long propertyValuesHolder,
+ long nativeInterpolator, long startDelay, long duration, int repeatCount) {
+ PropertySetter holder = sHolders.getDelegate(propertyValuesHolder);
+ if (holder == null || holder.getValues() == null) {
+ return;
+ }
+
+ ObjectAnimator animator = new ObjectAnimator();
+ animator.setValues(holder.getValues());
+ animator.setInterpolator(
+ NativeInterpolatorFactoryHelper_Delegate.getDelegate(nativeInterpolator));
+ animator.setStartDelay(startDelay);
+ animator.setDuration(duration);
+ animator.setRepeatCount(repeatCount);
+ animator.setTarget(holder);
+ animator.setPropertyName(holder.getValues().getPropertyName());
+
+ AnimatorSetHolder set = sAnimatorSets.getDelegate(setPtr);
+ assert set != null;
+ set.addAnimator(animator);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
+ float startValue, float endValue) {
+ VGroup_Delegate group = VNativeObject.getDelegate(nativePtr);
+ Consumer<Float> setter = group.getPropertySetter(propertyId);
+
+ return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
+ endValue));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
+ long endValuePtr) {
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "AnimatedVectorDrawable path " +
+ "animations are not supported.", null, null);
+ return 0;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
+ int startValue, int endValue) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
+ Consumer<Integer> setter = path.getIntPropertySetter(propertyId);
+
+ return sHolders.addNewDelegate(IntPropertySetter.of(setter, startValue,
+ endValue));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nCreatePathPropertyHolder(long nativePtr, int propertyId,
+ float startValue, float endValue) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
+ Consumer<Float> setter = path.getFloatPropertySetter(propertyId);
+
+ return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
+ endValue));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
+ float endValue) {
+ VPathRenderer_Delegate renderer = VNativeObject.getDelegate(nativePtr);
+
+ return sHolders.addNewDelegate(FloatPropertySetter.of(renderer::setRootAlpha,
+ startValue,
+ endValue));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nSetPropertyHolderData(long nativePtr, float[] data, int length) {
+ PropertySetter setter = sHolders.getDelegate(nativePtr);
+ assert setter != null;
+
+ setter.setValues(data);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
+ AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+ assert animatorSet != null;
+
+ animatorSet.start();
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
+ AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+ assert animatorSet != null;
+
+ animatorSet.reverse();
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nEnd(long animatorSetPtr) {
+ AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+ assert animatorSet != null;
+
+ animatorSet.end();
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nReset(long animatorSetPtr) {
+ AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
+ assert animatorSet != null;
+
+ animatorSet.end();
+ animatorSet.start();
+ }
+
+ private static class AnimatorSetHolder {
+ private ArrayList<Animator> mAnimators = new ArrayList<>();
+ private AnimatorSet mAnimatorSet = null;
+
+ private void addAnimator(@NonNull Animator animator) {
+ mAnimators.add(animator);
+ }
+
+ private void ensureAnimatorSet() {
+ if (mAnimatorSet == null) {
+ mAnimatorSet = new AnimatorSet();
+ mAnimatorSet.playTogether(mAnimators);
+ }
+ }
+
+ private void start() {
+ ensureAnimatorSet();
+
+ mAnimatorSet.start();
+ }
+
+ private void end() {
+ mAnimatorSet.end();
+ }
+
+ private void reset() {
+ end();
+ start();
+ }
+
+ private void reverse() {
+ mAnimatorSet.reverse();
+ }
+ }
+
+ /**
+ * Class that allows setting a value and holds the range of values for the given property.
+ *
+ * @param <T> the type of the property
+ */
+ private static class PropertySetter<T> {
+ final Consumer<T> mValueSetter;
+ private PropertyValuesHolder mValues;
+
+ private PropertySetter(@NonNull Consumer<T> valueSetter) {
+ mValueSetter = valueSetter;
+ }
+
+ /**
+ * Method to set an {@link Integer} value for this property. The default implementation of
+ * this method doesn't do anything. This method is accessed via reflection by the
+ * PropertyValuesHolder.
+ */
+ public void setIntValue(Integer value) {
+ }
+
+ /**
+ * Method to set an {@link Integer} value for this property. The default implementation of
+ * this method doesn't do anything. This method is accessed via reflection by the
+ * PropertyValuesHolder.
+ */
+ public void setFloatValue(Float value) {
+ }
+
+ void setValues(float... values) {
+ mValues = PropertyValuesHolder.ofFloat("floatValue", values);
+ }
+
+ @Nullable
+ PropertyValuesHolder getValues() {
+ return mValues;
+ }
+
+ void setValues(int... values) {
+ mValues = PropertyValuesHolder.ofInt("intValue", values);
+ }
+ }
+
+ private static class IntPropertySetter extends PropertySetter<Integer> {
+ private IntPropertySetter(Consumer<Integer> valueSetter) {
+ super(valueSetter);
+ }
+
+ private static PropertySetter of(Consumer<Integer> valueSetter, int... values) {
+ PropertySetter setter = new IntPropertySetter(valueSetter);
+ setter.setValues(values);
+
+ return setter;
+ }
+
+ public void setIntValue(Integer value) {
+ mValueSetter.accept(value);
+ }
+ }
+
+ private static class FloatPropertySetter extends PropertySetter<Float> {
+ private FloatPropertySetter(Consumer<Float> valueSetter) {
+ super(valueSetter);
+ }
+
+ private static PropertySetter of(Consumer<Float> valueSetter, float... values) {
+ PropertySetter setter = new FloatPropertySetter(valueSetter);
+ setter.setValues(values);
+
+ return setter;
+ }
+
+ public void setFloatValue(Float value) {
+ mValueSetter.accept(value);
+ }
+
+ }
+}
diff --git a/bridge/src/libcore/util/ZoneInfo_WallTime_Delegate.java b/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java
similarity index 64%
rename from bridge/src/libcore/util/ZoneInfo_WallTime_Delegate.java
rename to bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java
index f29c5c0..3d78931 100644
--- a/bridge/src/libcore/util/ZoneInfo_WallTime_Delegate.java
+++ b/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2016 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.
@@ -14,19 +14,15 @@
* limitations under the License.
*/
-package libcore.util;
+package android.graphics.drawable;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-import java.util.GregorianCalendar;
+import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
-/**
- * Delegate used to provide alternate implementation of select methods in {@link ZoneInfo.WallTime}
- */
-public class ZoneInfo_WallTime_Delegate {
-
+public class AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate {
@LayoutlibDelegate
- static GregorianCalendar createGregorianCalendar() {
- return new GregorianCalendar();
+ /*package*/ static boolean useLastSeenTarget(VectorDrawableAnimatorRT thisDrawableAnimator) {
+ return true;
}
}
diff --git a/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
new file mode 100644
index 0000000..90b84f8
--- /dev/null
+++ b/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -0,0 +1,1196 @@
+/*
+ * Copyright (C) 2016 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 android.graphics.drawable;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.annotation.NonNull;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas_Delegate;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Cap;
+import android.graphics.Paint.Join;
+import android.graphics.Paint_Delegate;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.graphics.Path_Delegate;
+import android.graphics.Rect;
+import android.graphics.Region.Op;
+import android.util.ArrayMap;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.MathUtils;
+import android.util.PathParser_Delegate;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+import static android.graphics.Canvas.CLIP_SAVE_FLAG;
+import static android.graphics.Canvas.MATRIX_SAVE_FLAG;
+import static android.graphics.Paint.Cap.BUTT;
+import static android.graphics.Paint.Cap.ROUND;
+import static android.graphics.Paint.Cap.SQUARE;
+import static android.graphics.Paint.Join.BEVEL;
+import static android.graphics.Paint.Join.MITER;
+import static android.graphics.Paint.Style;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link VectorDrawable}
+ * <p>
+ * Through the layoutlib_create tool, the original methods of VectorDrawable have been replaced by
+ * calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class VectorDrawable_Delegate {
+ private static final String LOGTAG = VectorDrawable_Delegate.class.getSimpleName();
+ private static final boolean DBG_VECTOR_DRAWABLE = false;
+
+ private static final DelegateManager<VNativeObject> sPathManager =
+ new DelegateManager<>(VNativeObject.class);
+
+ /**
+ * Obtains styled attributes from the theme, if available, or unstyled resources if the theme is
+ * null.
+ */
+ private static TypedArray obtainAttributes(
+ Resources res, Theme theme, AttributeSet set, int[] attrs) {
+ if (theme == null) {
+ return res.obtainAttributes(set, attrs);
+ }
+ return theme.obtainStyledAttributes(set, attrs, 0, 0);
+ }
+
+ private static int applyAlpha(int color, float alpha) {
+ int alphaBytes = Color.alpha(color);
+ color &= 0x00FFFFFF;
+ color |= ((int) (alphaBytes * alpha)) << 24;
+ return color;
+ }
+
+ @LayoutlibDelegate
+ static long nCreateRenderer(long rootGroupPtr) {
+ VGroup_Delegate rootGroup = VNativeObject.getDelegate(rootGroupPtr);
+ return sPathManager.addNewDelegate(new VPathRenderer_Delegate(rootGroup));
+ }
+
+ @LayoutlibDelegate
+ static void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
+ float viewportHeight) {
+ VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
+ nativePathRenderer.mViewportWidth = viewportWidth;
+ nativePathRenderer.mViewportHeight = viewportHeight;
+ }
+
+ @LayoutlibDelegate
+ static boolean nSetRootAlpha(long rendererPtr, float alpha) {
+ VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
+ nativePathRenderer.setRootAlpha(alpha);
+
+ return true;
+ }
+
+ @LayoutlibDelegate
+ static float nGetRootAlpha(long rendererPtr) {
+ VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
+
+ return nativePathRenderer.getRootAlpha();
+ }
+
+ @LayoutlibDelegate
+ static void nSetAllowCaching(long rendererPtr, boolean allowCaching) {
+ // ignored
+ }
+
+ @LayoutlibDelegate
+ static void nDraw(long rendererPtr, long canvasWrapperPtr,
+ long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache) {
+ VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
+
+ Canvas_Delegate.native_save(canvasWrapperPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+ Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.left, bounds.top);
+
+ if (needsMirroring) {
+ Canvas_Delegate.native_translate(canvasWrapperPtr, bounds.width(), 0);
+ Canvas_Delegate.native_scale(canvasWrapperPtr, -1.0f, 1.0f);
+ }
+
+ // At this point, canvas has been translated to the right position.
+ // And we use this bound for the destination rect for the drawBitmap, so
+ // we offset to (0, 0);
+ bounds.offsetTo(0, 0);
+ nativePathRenderer.draw(canvasWrapperPtr, colorFilterPtr, bounds.width(), bounds.height());
+
+ Canvas_Delegate.native_restore(canvasWrapperPtr, true);
+ }
+
+ @LayoutlibDelegate
+ static long nCreateFullPath() {
+ return sPathManager.addNewDelegate(new VFullPath_Delegate());
+ }
+
+ @LayoutlibDelegate
+ static long nCreateFullPath(long nativeFullPathPtr) {
+ VFullPath_Delegate original = VNativeObject.getDelegate(nativeFullPathPtr);
+
+ return sPathManager.addNewDelegate(new VFullPath_Delegate(original));
+ }
+
+ @LayoutlibDelegate
+ static boolean nGetFullPathProperties(long pathPtr, byte[] propertiesData,
+ int length) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+
+ ByteBuffer properties = ByteBuffer.wrap(propertiesData);
+ properties.order(ByteOrder.nativeOrder());
+
+ properties.putFloat(VFullPath_Delegate.STROKE_WIDTH_INDEX * 4, path.getStrokeWidth());
+ properties.putInt(VFullPath_Delegate.STROKE_COLOR_INDEX * 4, path.getStrokeColor());
+ properties.putFloat(VFullPath_Delegate.STROKE_ALPHA_INDEX * 4, path.getStrokeAlpha());
+ properties.putInt(VFullPath_Delegate.FILL_COLOR_INDEX * 4, path.getFillColor());
+ properties.putFloat(VFullPath_Delegate.FILL_ALPHA_INDEX * 4, path.getStrokeAlpha());
+ properties.putFloat(VFullPath_Delegate.TRIM_PATH_START_INDEX * 4, path.getTrimPathStart());
+ properties.putFloat(VFullPath_Delegate.TRIM_PATH_END_INDEX * 4, path.getTrimPathEnd());
+ properties.putFloat(VFullPath_Delegate.TRIM_PATH_OFFSET_INDEX * 4,
+ path.getTrimPathOffset());
+ properties.putInt(VFullPath_Delegate.STROKE_LINE_CAP_INDEX * 4, path.getStrokeLineCap());
+ properties.putInt(VFullPath_Delegate.STROKE_LINE_JOIN_INDEX * 4, path.getStrokeLineJoin());
+ properties.putFloat(VFullPath_Delegate.STROKE_MITER_LIMIT_INDEX * 4,
+ path.getStrokeMiterlimit());
+
+ return true;
+ }
+
+ @LayoutlibDelegate
+ static void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
+ int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
+ float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
+ int strokeLineJoin) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+
+ path.setStrokeWidth(strokeWidth);
+ path.setStrokeColor(strokeColor);
+ path.setStrokeAlpha(strokeAlpha);
+ path.setFillColor(fillColor);
+ path.setFillAlpha(fillAlpha);
+ path.setTrimPathStart(trimPathStart);
+ path.setTrimPathEnd(trimPathEnd);
+ path.setTrimPathOffset(trimPathOffset);
+ path.setStrokeMiterlimit(strokeMiterLimit);
+ path.setStrokeLineCap(strokeLineCap);
+ path.setStrokeLineJoin(strokeLineJoin);
+ }
+
+ @LayoutlibDelegate
+ static void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+
+ path.setFillGradient(fillGradientPtr);
+ }
+
+ @LayoutlibDelegate
+ static void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+
+ path.setStrokeGradient(strokeGradientPtr);
+ }
+
+ @LayoutlibDelegate
+ static long nCreateClipPath() {
+ return sPathManager.addNewDelegate(new VClipPath_Delegate());
+ }
+
+ @LayoutlibDelegate
+ static long nCreateClipPath(long clipPathPtr) {
+ VClipPath_Delegate original = VNativeObject.getDelegate(clipPathPtr);
+ return sPathManager.addNewDelegate(new VClipPath_Delegate(original));
+ }
+
+ @LayoutlibDelegate
+ static long nCreateGroup() {
+ return sPathManager.addNewDelegate(new VGroup_Delegate());
+ }
+
+ @LayoutlibDelegate
+ static long nCreateGroup(long groupPtr) {
+ VGroup_Delegate original = VNativeObject.getDelegate(groupPtr);
+ return sPathManager.addNewDelegate(
+ new VGroup_Delegate(original, new ArrayMap<String, Object>()));
+ }
+
+ @LayoutlibDelegate
+ static void nSetName(long nodePtr, String name) {
+ VNativeObject group = VNativeObject.getDelegate(nodePtr);
+ group.setName(name);
+ }
+
+ @LayoutlibDelegate
+ static boolean nGetGroupProperties(long groupPtr, float[] propertiesData,
+ int length) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+
+ FloatBuffer properties = FloatBuffer.wrap(propertiesData);
+
+ properties.put(VGroup_Delegate.ROTATE_INDEX, group.getRotation());
+ properties.put(VGroup_Delegate.PIVOT_X_INDEX, group.getPivotX());
+ properties.put(VGroup_Delegate.PIVOT_Y_INDEX, group.getPivotY());
+ properties.put(VGroup_Delegate.SCALE_X_INDEX, group.getScaleX());
+ properties.put(VGroup_Delegate.SCALE_Y_INDEX, group.getScaleY());
+ properties.put(VGroup_Delegate.TRANSLATE_X_INDEX, group.getTranslateX());
+ properties.put(VGroup_Delegate.TRANSLATE_Y_INDEX, group.getTranslateY());
+
+ return true;
+ }
+ @LayoutlibDelegate
+ static void nUpdateGroupProperties(long groupPtr, float rotate, float pivotX,
+ float pivotY, float scaleX, float scaleY, float translateX, float translateY) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+
+ group.setRotation(rotate);
+ group.setPivotX(pivotX);
+ group.setPivotY(pivotY);
+ group.setScaleX(scaleX);
+ group.setScaleY(scaleY);
+ group.setTranslateX(translateX);
+ group.setTranslateY(translateY);
+ }
+
+ @LayoutlibDelegate
+ static void nAddChild(long groupPtr, long nodePtr) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ group.mChildren.add(VNativeObject.getDelegate(nodePtr));
+ }
+
+ @LayoutlibDelegate
+ static void nSetPathString(long pathPtr, String pathString, int length) {
+ VPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ path.setPathData(PathParser_Delegate.createNodesFromPathData(pathString));
+ }
+
+ /**
+ * The setters and getters below for paths and groups are here temporarily, and will be removed
+ * once the animation in AVD is replaced with RenderNodeAnimator, in which case the animation
+ * will modify these properties in native. By then no JNI hopping would be necessary for VD
+ * during animation, and these setters and getters will be obsolete.
+ */
+ // Setters and getters during animation.
+ @LayoutlibDelegate
+ static float nGetRotation(long groupPtr) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ return group.getRotation();
+ }
+
+ @LayoutlibDelegate
+ static void nSetRotation(long groupPtr, float rotation) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ group.setRotation(rotation);
+ }
+
+ @LayoutlibDelegate
+ static float nGetPivotX(long groupPtr) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ return group.getPivotX();
+ }
+
+ @LayoutlibDelegate
+ static void nSetPivotX(long groupPtr, float pivotX) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ group.setPivotX(pivotX);
+ }
+
+ @LayoutlibDelegate
+ static float nGetPivotY(long groupPtr) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ return group.getPivotY();
+ }
+
+ @LayoutlibDelegate
+ static void nSetPivotY(long groupPtr, float pivotY) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ group.setPivotY(pivotY);
+ }
+
+ @LayoutlibDelegate
+ static float nGetScaleX(long groupPtr) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ return group.getScaleX();
+ }
+
+ @LayoutlibDelegate
+ static void nSetScaleX(long groupPtr, float scaleX) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ group.setScaleX(scaleX);
+ }
+
+ @LayoutlibDelegate
+ static float nGetScaleY(long groupPtr) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ return group.getScaleY();
+ }
+
+ @LayoutlibDelegate
+ static void nSetScaleY(long groupPtr, float scaleY) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ group.setScaleY(scaleY);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTranslateX(long groupPtr) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ return group.getTranslateX();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTranslateX(long groupPtr, float translateX) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ group.setTranslateX(translateX);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTranslateY(long groupPtr) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ return group.getTranslateY();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTranslateY(long groupPtr, float translateY) {
+ VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
+ group.setTranslateY(translateY);
+ }
+
+ @LayoutlibDelegate
+ static void nSetPathData(long pathPtr, long pathDataPtr) {
+ VPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ path.setPathData(PathParser_Delegate.getDelegate(pathDataPtr).getPathDataNodes());
+ }
+
+ @LayoutlibDelegate
+ static float nGetStrokeWidth(long pathPtr) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ return path.getStrokeWidth();
+ }
+
+ @LayoutlibDelegate
+ static void nSetStrokeWidth(long pathPtr, float width) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ path.setStrokeWidth(width);
+ }
+
+ @LayoutlibDelegate
+ static int nGetStrokeColor(long pathPtr) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ return path.getStrokeColor();
+ }
+
+ @LayoutlibDelegate
+ static void nSetStrokeColor(long pathPtr, int strokeColor) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ path.setStrokeColor(strokeColor);
+ }
+
+ @LayoutlibDelegate
+ static float nGetStrokeAlpha(long pathPtr) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ return path.getStrokeAlpha();
+ }
+
+ @LayoutlibDelegate
+ static void nSetStrokeAlpha(long pathPtr, float alpha) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ path.setStrokeAlpha(alpha);
+ }
+
+ @LayoutlibDelegate
+ static int nGetFillColor(long pathPtr) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ return path.getFillColor();
+ }
+
+ @LayoutlibDelegate
+ static void nSetFillColor(long pathPtr, int fillColor) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ path.setFillColor(fillColor);
+ }
+
+ @LayoutlibDelegate
+ static float nGetFillAlpha(long pathPtr) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ return path.getFillAlpha();
+ }
+
+ @LayoutlibDelegate
+ static void nSetFillAlpha(long pathPtr, float fillAlpha) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ path.setFillAlpha(fillAlpha);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTrimPathStart(long pathPtr) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ return path.getTrimPathStart();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTrimPathStart(long pathPtr, float trimPathStart) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ path.setTrimPathStart(trimPathStart);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTrimPathEnd(long pathPtr) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ return path.getTrimPathEnd();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTrimPathEnd(long pathPtr, float trimPathEnd) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ path.setTrimPathEnd(trimPathEnd);
+ }
+
+ @LayoutlibDelegate
+ static float nGetTrimPathOffset(long pathPtr) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ return path.getTrimPathOffset();
+ }
+
+ @LayoutlibDelegate
+ static void nSetTrimPathOffset(long pathPtr, float trimPathOffset) {
+ VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
+ path.setTrimPathOffset(trimPathOffset);
+ }
+
+ /**
+ * Base class for all the internal Delegates that does two functions:
+ * <ol>
+ * <li>Serves as base class to store all the delegates in one {@link DelegateManager}
+ * <li>Provides setName for all the classes. {@link VPathRenderer_Delegate} does actually
+ * not need it
+ * </ol>
+ */
+ interface VNativeObject {
+ @NonNull
+ static <T> T getDelegate(long nativePtr) {
+ //noinspection unchecked
+ T vNativeObject = (T) sPathManager.getDelegate(nativePtr);
+
+ assert vNativeObject != null;
+ return vNativeObject;
+ }
+
+ void setName(String name);
+ }
+
+ private static class VClipPath_Delegate extends VPath_Delegate {
+ private VClipPath_Delegate() {
+ // Empty constructor.
+ }
+
+ private VClipPath_Delegate(VClipPath_Delegate copy) {
+ super(copy);
+ }
+
+ @Override
+ public boolean isClipPath() {
+ return true;
+ }
+ }
+
+ static class VFullPath_Delegate extends VPath_Delegate {
+ // These constants need to be kept in sync with their values in VectorDrawable.VFullPath
+ private static final int STROKE_WIDTH_INDEX = 0;
+ private static final int STROKE_COLOR_INDEX = 1;
+ private static final int STROKE_ALPHA_INDEX = 2;
+ private static final int FILL_COLOR_INDEX = 3;
+ private static final int FILL_ALPHA_INDEX = 4;
+ private static final int TRIM_PATH_START_INDEX = 5;
+ private static final int TRIM_PATH_END_INDEX = 6;
+ private static final int TRIM_PATH_OFFSET_INDEX = 7;
+ private static final int STROKE_LINE_CAP_INDEX = 8;
+ private static final int STROKE_LINE_JOIN_INDEX = 9;
+ private static final int STROKE_MITER_LIMIT_INDEX = 10;
+
+ private static final int LINECAP_BUTT = 0;
+ private static final int LINECAP_ROUND = 1;
+ private static final int LINECAP_SQUARE = 2;
+
+ private static final int LINEJOIN_MITER = 0;
+ private static final int LINEJOIN_ROUND = 1;
+ private static final int LINEJOIN_BEVEL = 2;
+
+ @NonNull
+ public Consumer<Float> getFloatPropertySetter(int propertyIdx) {
+ switch (propertyIdx) {
+ case STROKE_ALPHA_INDEX:
+ return this::setStrokeAlpha;
+ case FILL_ALPHA_INDEX:
+ return this::setFillAlpha;
+ case TRIM_PATH_START_INDEX:
+ return this::setTrimPathStart;
+ case TRIM_PATH_END_INDEX:
+ return this::setTrimPathEnd;
+ case TRIM_PATH_OFFSET_INDEX:
+ return this::setTrimPathOffset;
+ }
+
+ throw new IllegalArgumentException("Invalid VFullPath_Delegate property index "
+ + propertyIdx);
+ }
+
+ @NonNull
+ public Consumer<Integer> getIntPropertySetter(int propertyIdx) {
+ switch (propertyIdx) {
+ case STROKE_COLOR_INDEX:
+ return this::setStrokeColor;
+ case FILL_COLOR_INDEX:
+ return this::setFillColor;
+ }
+
+ throw new IllegalArgumentException("Invalid VFullPath_Delegate property index "
+ + propertyIdx);
+ }
+
+ /////////////////////////////////////////////////////
+ // Variables below need to be copied (deep copy if applicable) for mutation.
+
+ int mStrokeColor = Color.TRANSPARENT;
+ float mStrokeWidth = 0;
+
+ int mFillColor = Color.TRANSPARENT;
+ long mStrokeGradient = 0;
+ long mFillGradient = 0;
+ float mStrokeAlpha = 1.0f;
+ float mFillAlpha = 1.0f;
+ float mTrimPathStart = 0;
+ float mTrimPathEnd = 1;
+ float mTrimPathOffset = 0;
+
+ Cap mStrokeLineCap = BUTT;
+ Join mStrokeLineJoin = MITER;
+ float mStrokeMiterlimit = 4;
+
+ private VFullPath_Delegate() {
+ // Empty constructor.
+ }
+
+ private VFullPath_Delegate(VFullPath_Delegate copy) {
+ super(copy);
+
+ mStrokeColor = copy.mStrokeColor;
+ mStrokeWidth = copy.mStrokeWidth;
+ mStrokeAlpha = copy.mStrokeAlpha;
+ mFillColor = copy.mFillColor;
+ mFillAlpha = copy.mFillAlpha;
+ mTrimPathStart = copy.mTrimPathStart;
+ mTrimPathEnd = copy.mTrimPathEnd;
+ mTrimPathOffset = copy.mTrimPathOffset;
+
+ mStrokeLineCap = copy.mStrokeLineCap;
+ mStrokeLineJoin = copy.mStrokeLineJoin;
+ mStrokeMiterlimit = copy.mStrokeMiterlimit;
+
+ mStrokeGradient = copy.mStrokeGradient;
+ mFillGradient = copy.mFillGradient;
+ }
+
+ private int getStrokeLineCap() {
+ switch (mStrokeLineCap) {
+ case BUTT:
+ return LINECAP_BUTT;
+ case ROUND:
+ return LINECAP_ROUND;
+ case SQUARE:
+ return LINECAP_SQUARE;
+ default:
+ assert false;
+ }
+
+ return -1;
+ }
+
+ private void setStrokeLineCap(int cap) {
+ switch (cap) {
+ case LINECAP_BUTT:
+ mStrokeLineCap = BUTT;
+ break;
+ case LINECAP_ROUND:
+ mStrokeLineCap = ROUND;
+ break;
+ case LINECAP_SQUARE:
+ mStrokeLineCap = SQUARE;
+ break;
+ default:
+ assert false;
+ }
+ }
+
+ private int getStrokeLineJoin() {
+ switch (mStrokeLineJoin) {
+ case MITER:
+ return LINEJOIN_MITER;
+ case ROUND:
+ return LINEJOIN_ROUND;
+ case BEVEL:
+ return LINEJOIN_BEVEL;
+ default:
+ assert false;
+ }
+
+ return -1;
+ }
+
+ private void setStrokeLineJoin(int join) {
+ switch (join) {
+ case LINEJOIN_BEVEL:
+ mStrokeLineJoin = BEVEL;
+ break;
+ case LINEJOIN_MITER:
+ mStrokeLineJoin = MITER;
+ break;
+ case LINEJOIN_ROUND:
+ mStrokeLineJoin = Join.ROUND;
+ break;
+ default:
+ assert false;
+ }
+ }
+
+ private int getStrokeColor() {
+ return mStrokeColor;
+ }
+
+ private void setStrokeColor(int strokeColor) {
+ mStrokeColor = strokeColor;
+ }
+
+ private float getStrokeWidth() {
+ return mStrokeWidth;
+ }
+
+ private void setStrokeWidth(float strokeWidth) {
+ mStrokeWidth = strokeWidth;
+ }
+
+ private float getStrokeAlpha() {
+ return mStrokeAlpha;
+ }
+
+ private void setStrokeAlpha(float strokeAlpha) {
+ mStrokeAlpha = strokeAlpha;
+ }
+
+ private int getFillColor() {
+ return mFillColor;
+ }
+
+ private void setFillColor(int fillColor) {
+ mFillColor = fillColor;
+ }
+
+ private float getFillAlpha() {
+ return mFillAlpha;
+ }
+
+ private void setFillAlpha(float fillAlpha) {
+ mFillAlpha = fillAlpha;
+ }
+
+ private float getTrimPathStart() {
+ return mTrimPathStart;
+ }
+
+ private void setTrimPathStart(float trimPathStart) {
+ mTrimPathStart = trimPathStart;
+ }
+
+ private float getTrimPathEnd() {
+ return mTrimPathEnd;
+ }
+
+ private void setTrimPathEnd(float trimPathEnd) {
+ mTrimPathEnd = trimPathEnd;
+ }
+
+ private float getTrimPathOffset() {
+ return mTrimPathOffset;
+ }
+
+ private void setTrimPathOffset(float trimPathOffset) {
+ mTrimPathOffset = trimPathOffset;
+ }
+
+ private void setStrokeMiterlimit(float limit) {
+ mStrokeMiterlimit = limit;
+ }
+
+ private float getStrokeMiterlimit() {
+ return mStrokeMiterlimit;
+ }
+
+ private void setStrokeGradient(long gradientPtr) {
+ mStrokeGradient = gradientPtr;
+ }
+
+ private void setFillGradient(long gradientPtr) {
+ mFillGradient = gradientPtr;
+ }
+ }
+
+ static class VGroup_Delegate implements VNativeObject {
+ // This constants need to be kept in sync with their definitions in VectorDrawable.Group
+ private static final int ROTATE_INDEX = 0;
+ private static final int PIVOT_X_INDEX = 1;
+ private static final int PIVOT_Y_INDEX = 2;
+ private static final int SCALE_X_INDEX = 3;
+ private static final int SCALE_Y_INDEX = 4;
+ private static final int TRANSLATE_X_INDEX = 5;
+ private static final int TRANSLATE_Y_INDEX = 6;
+
+ public Consumer<Float> getPropertySetter(int propertyIdx) {
+ switch (propertyIdx) {
+ case ROTATE_INDEX:
+ return this::setRotation;
+ case PIVOT_X_INDEX:
+ return this::setPivotX;
+ case PIVOT_Y_INDEX:
+ return this::setPivotY;
+ case SCALE_X_INDEX:
+ return this::setScaleX;
+ case SCALE_Y_INDEX:
+ return this::setScaleY;
+ case TRANSLATE_X_INDEX:
+ return this::setTranslateX;
+ case TRANSLATE_Y_INDEX:
+ return this::setTranslateY;
+ }
+
+ throw new IllegalArgumentException("Invalid VGroup_Delegate property index "
+ + propertyIdx);
+ }
+
+ /////////////////////////////////////////////////////
+ // Variables below need to be copied (deep copy if applicable) for mutation.
+ final ArrayList<Object> mChildren = new ArrayList<>();
+ // mStackedMatrix is only used temporarily when drawing, it combines all
+ // the parents' local matrices with the current one.
+ private final Matrix mStackedMatrix = new Matrix();
+ // mLocalMatrix is updated based on the update of transformation information,
+ // either parsed from the XML or by animation.
+ private final Matrix mLocalMatrix = new Matrix();
+ private float mRotate = 0;
+ private float mPivotX = 0;
+ private float mPivotY = 0;
+ private float mScaleX = 1;
+ private float mScaleY = 1;
+ private float mTranslateX = 0;
+ private float mTranslateY = 0;
+ private int mChangingConfigurations;
+ private String mGroupName = null;
+
+ private VGroup_Delegate(VGroup_Delegate copy, ArrayMap<String, Object> targetsMap) {
+ mRotate = copy.mRotate;
+ mPivotX = copy.mPivotX;
+ mPivotY = copy.mPivotY;
+ mScaleX = copy.mScaleX;
+ mScaleY = copy.mScaleY;
+ mTranslateX = copy.mTranslateX;
+ mTranslateY = copy.mTranslateY;
+ mGroupName = copy.mGroupName;
+ mChangingConfigurations = copy.mChangingConfigurations;
+ if (mGroupName != null) {
+ targetsMap.put(mGroupName, this);
+ }
+
+ mLocalMatrix.set(copy.mLocalMatrix);
+
+ final ArrayList<Object> children = copy.mChildren;
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0; i < children.size(); i++) {
+ Object copyChild = children.get(i);
+ if (copyChild instanceof VGroup_Delegate) {
+ VGroup_Delegate copyGroup = (VGroup_Delegate) copyChild;
+ mChildren.add(new VGroup_Delegate(copyGroup, targetsMap));
+ } else {
+ VPath_Delegate newPath;
+ if (copyChild instanceof VFullPath_Delegate) {
+ newPath = new VFullPath_Delegate((VFullPath_Delegate) copyChild);
+ } else if (copyChild instanceof VClipPath_Delegate) {
+ newPath = new VClipPath_Delegate((VClipPath_Delegate) copyChild);
+ } else {
+ throw new IllegalStateException("Unknown object in the tree!");
+ }
+ mChildren.add(newPath);
+ if (newPath.mPathName != null) {
+ targetsMap.put(newPath.mPathName, newPath);
+ }
+ }
+ }
+ }
+
+ private VGroup_Delegate() {
+ }
+
+ private void updateLocalMatrix() {
+ // The order we apply is the same as the
+ // RenderNode.cpp::applyViewPropertyTransforms().
+ mLocalMatrix.reset();
+ mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
+ mLocalMatrix.postScale(mScaleX, mScaleY);
+ mLocalMatrix.postRotate(mRotate, 0, 0);
+ mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
+ }
+
+ /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
+ private float getRotation() {
+ return mRotate;
+ }
+
+ private void setRotation(float rotation) {
+ if (rotation != mRotate) {
+ mRotate = rotation;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getPivotX() {
+ return mPivotX;
+ }
+
+ private void setPivotX(float pivotX) {
+ if (pivotX != mPivotX) {
+ mPivotX = pivotX;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getPivotY() {
+ return mPivotY;
+ }
+
+ private void setPivotY(float pivotY) {
+ if (pivotY != mPivotY) {
+ mPivotY = pivotY;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getScaleX() {
+ return mScaleX;
+ }
+
+ private void setScaleX(float scaleX) {
+ if (scaleX != mScaleX) {
+ mScaleX = scaleX;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getScaleY() {
+ return mScaleY;
+ }
+
+ private void setScaleY(float scaleY) {
+ if (scaleY != mScaleY) {
+ mScaleY = scaleY;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getTranslateX() {
+ return mTranslateX;
+ }
+
+ private void setTranslateX(float translateX) {
+ if (translateX != mTranslateX) {
+ mTranslateX = translateX;
+ updateLocalMatrix();
+ }
+ }
+
+ private float getTranslateY() {
+ return mTranslateY;
+ }
+
+ private void setTranslateY(float translateY) {
+ if (translateY != mTranslateY) {
+ mTranslateY = translateY;
+ updateLocalMatrix();
+ }
+ }
+
+ @Override
+ public void setName(String name) {
+ mGroupName = name;
+ }
+ }
+
+ public static class VPath_Delegate implements VNativeObject {
+ protected PathParser_Delegate.PathDataNode[] mNodes = null;
+ String mPathName;
+ int mChangingConfigurations;
+
+ public VPath_Delegate() {
+ // Empty constructor.
+ }
+
+ public VPath_Delegate(VPath_Delegate copy) {
+ mPathName = copy.mPathName;
+ mChangingConfigurations = copy.mChangingConfigurations;
+ mNodes = PathParser_Delegate.deepCopyNodes(copy.mNodes);
+ }
+
+ public void toPath(Path path) {
+ path.reset();
+ if (mNodes != null) {
+ PathParser_Delegate.PathDataNode.nodesToPath(mNodes,
+ Path_Delegate.getDelegate(path.mNativePath));
+ }
+ }
+
+ @Override
+ public void setName(String name) {
+ mPathName = name;
+ }
+
+ public boolean isClipPath() {
+ return false;
+ }
+
+ private void setPathData(PathParser_Delegate.PathDataNode[] nodes) {
+ if (!PathParser_Delegate.canMorph(mNodes, nodes)) {
+ // This should not happen in the middle of animation.
+ mNodes = PathParser_Delegate.deepCopyNodes(nodes);
+ } else {
+ PathParser_Delegate.updateNodes(mNodes, nodes);
+ }
+ }
+ }
+
+ static class VPathRenderer_Delegate implements VNativeObject {
+ /* Right now the internal data structure is organized as a tree.
+ * Each node can be a group node, or a path.
+ * A group node can have groups or paths as children, but a path node has
+ * no children.
+ * One example can be:
+ * Root Group
+ * / | \
+ * Group Path Group
+ * / \ |
+ * Path Path Path
+ *
+ */
+ // Variables that only used temporarily inside the draw() call, so there
+ // is no need for deep copying.
+ private final Path mPath;
+ private final Path mRenderPath;
+ private final Matrix mFinalPathMatrix = new Matrix();
+ private final VGroup_Delegate mRootGroup;
+ private float mViewportWidth = 0;
+ private float mViewportHeight = 0;
+ private float mRootAlpha = 1.0f;
+ private Paint mStrokePaint;
+ private Paint mFillPaint;
+ private PathMeasure mPathMeasure;
+
+ private VPathRenderer_Delegate(VGroup_Delegate rootGroup) {
+ mRootGroup = rootGroup;
+ mPath = new Path();
+ mRenderPath = new Path();
+ }
+
+ private float getRootAlpha() {
+ return mRootAlpha;
+ }
+
+ void setRootAlpha(float alpha) {
+ mRootAlpha = alpha;
+ }
+
+ private void drawGroupTree(VGroup_Delegate currentGroup, Matrix currentMatrix,
+ long canvasPtr, int w, int h, long filterPtr) {
+ // Calculate current group's matrix by preConcat the parent's and
+ // and the current one on the top of the stack.
+ // Basically the Mfinal = Mviewport * M0 * M1 * M2;
+ // Mi the local matrix at level i of the group tree.
+ currentGroup.mStackedMatrix.set(currentMatrix);
+ currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
+
+ // Save the current clip information, which is local to this group.
+ Canvas_Delegate.native_save(canvasPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+ // Draw the group tree in the same order as the XML file.
+ for (int i = 0; i < currentGroup.mChildren.size(); i++) {
+ Object child = currentGroup.mChildren.get(i);
+ if (child instanceof VGroup_Delegate) {
+ VGroup_Delegate childGroup = (VGroup_Delegate) child;
+ drawGroupTree(childGroup, currentGroup.mStackedMatrix,
+ canvasPtr, w, h, filterPtr);
+ } else if (child instanceof VPath_Delegate) {
+ VPath_Delegate childPath = (VPath_Delegate) child;
+ drawPath(currentGroup, childPath, canvasPtr, w, h, filterPtr);
+ }
+ }
+ Canvas_Delegate.native_restore(canvasPtr, true);
+ }
+
+ public void draw(long canvasPtr, long filterPtr, int w, int h) {
+ // Traverse the tree in pre-order to draw.
+ drawGroupTree(mRootGroup, Matrix.IDENTITY_MATRIX, canvasPtr, w, h, filterPtr);
+ }
+
+ private void drawPath(VGroup_Delegate VGroup, VPath_Delegate VPath, long canvasPtr,
+ int w,
+ int h,
+ long filterPtr) {
+ final float scaleX = w / mViewportWidth;
+ final float scaleY = h / mViewportHeight;
+ final float minScale = Math.min(scaleX, scaleY);
+ final Matrix groupStackedMatrix = VGroup.mStackedMatrix;
+
+ mFinalPathMatrix.set(groupStackedMatrix);
+ mFinalPathMatrix.postScale(scaleX, scaleY);
+
+ final float matrixScale = getMatrixScale(groupStackedMatrix);
+ if (matrixScale == 0) {
+ // When either x or y is scaled to 0, we don't need to draw anything.
+ return;
+ }
+ VPath.toPath(mPath);
+ final Path path = mPath;
+
+ mRenderPath.reset();
+
+ if (VPath.isClipPath()) {
+ mRenderPath.addPath(path, mFinalPathMatrix);
+ Canvas_Delegate.native_clipPath(canvasPtr, mRenderPath.mNativePath, Op
+ .INTERSECT.nativeInt);
+ } else {
+ VFullPath_Delegate fullPath = (VFullPath_Delegate) VPath;
+ if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
+ float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
+ float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
+
+ if (mPathMeasure == null) {
+ mPathMeasure = new PathMeasure();
+ }
+ mPathMeasure.setPath(mPath, false);
+
+ float len = mPathMeasure.getLength();
+ start = start * len;
+ end = end * len;
+ path.reset();
+ if (start > end) {
+ mPathMeasure.getSegment(start, len, path, true);
+ mPathMeasure.getSegment(0f, end, path, true);
+ } else {
+ mPathMeasure.getSegment(start, end, path, true);
+ }
+ path.rLineTo(0, 0); // fix bug in measure
+ }
+ mRenderPath.addPath(path, mFinalPathMatrix);
+
+ if (fullPath.mFillColor != Color.TRANSPARENT) {
+ if (mFillPaint == null) {
+ mFillPaint = new Paint();
+ mFillPaint.setStyle(Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ }
+
+ final Paint fillPaint = mFillPaint;
+ fillPaint.setColor(applyAlpha(fullPath.mFillColor, fullPath.mFillAlpha));
+ Paint_Delegate fillPaintDelegate = Paint_Delegate.getDelegate(fillPaint
+ .getNativeInstance());
+ // mFillPaint can not be null at this point so we will have a delegate
+ assert fillPaintDelegate != null;
+ fillPaintDelegate.setColorFilter(filterPtr);
+ fillPaintDelegate.setShader(fullPath.mFillGradient);
+ Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, fillPaint
+ .getNativeInstance());
+ }
+
+ if (fullPath.mStrokeColor != Color.TRANSPARENT) {
+ if (mStrokePaint == null) {
+ mStrokePaint = new Paint();
+ mStrokePaint.setStyle(Style.STROKE);
+ mStrokePaint.setAntiAlias(true);
+ }
+
+ final Paint strokePaint = mStrokePaint;
+ if (fullPath.mStrokeLineJoin != null) {
+ strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
+ }
+
+ if (fullPath.mStrokeLineCap != null) {
+ strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
+ }
+
+ strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
+ strokePaint.setColor(applyAlpha(fullPath.mStrokeColor, fullPath.mStrokeAlpha));
+ Paint_Delegate strokePaintDelegate = Paint_Delegate.getDelegate(strokePaint
+ .getNativeInstance());
+ // mStrokePaint can not be null at this point so we will have a delegate
+ assert strokePaintDelegate != null;
+ strokePaintDelegate.setColorFilter(filterPtr);
+ final float finalStrokeScale = minScale * matrixScale;
+ strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
+ strokePaintDelegate.setShader(fullPath.mStrokeGradient);
+ Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, strokePaint
+ .getNativeInstance());
+ }
+ }
+ }
+
+ private float getMatrixScale(Matrix groupStackedMatrix) {
+ // Given unit vectors A = (0, 1) and B = (1, 0).
+ // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
+ // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
+ // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
+ // If max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
+ //
+ // For non-skew case, which is most of the cases, matrix scale is computing exactly the
+ // scale on x and y axis, and take the minimal of these two.
+ // For skew case, an unit square will mapped to a parallelogram. And this function will
+ // return the minimal height of the 2 bases.
+ float[] unitVectors = new float[]{0, 1, 1, 0};
+ groupStackedMatrix.mapVectors(unitVectors);
+ float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]);
+ float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]);
+ float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1],
+ unitVectors[2], unitVectors[3]);
+ float maxScale = MathUtils.max(scaleX, scaleY);
+
+ float matrixScale = 0;
+ if (maxScale > 0) {
+ matrixScale = MathUtils.abs(crossProduct) / maxScale;
+ }
+ if (DBG_VECTOR_DRAWABLE) {
+ Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
+ }
+ return matrixScale;
+ }
+
+ @Override
+ public void setName(String name) {
+ }
+ }
+}
diff --git a/bridge/src/android/os/ServiceManager.java b/bridge/src/android/os/ServiceManager.java
index 6a68ee2..549074d 100644
--- a/bridge/src/android/os/ServiceManager.java
+++ b/bridge/src/android/os/ServiceManager.java
@@ -51,8 +51,10 @@
/**
* Return a list of all currently running services.
+ * @return an array of all currently running services, or <code>null</code> in
+ * case of an exception
*/
- public static String[] listServices() throws RemoteException {
+ public static String[] listServices() {
// actual implementation returns null sometimes, so it's ok
// to return null instead of an empty list.
return null;
diff --git a/bridge/src/android/text/Hyphenator_Delegate.java b/bridge/src/android/text/Hyphenator_Delegate.java
index 44ce731..fcd63ea 100644
--- a/bridge/src/android/text/Hyphenator_Delegate.java
+++ b/bridge/src/android/text/Hyphenator_Delegate.java
@@ -25,7 +25,7 @@
/**
* Delegate that overrides implementation for certain methods in {@link android.text.Hyphenator}
* <p/>
- * Through the layoutlib_create tool, selected methods of StaticLayout have been replaced
+ * Through the layoutlib_create tool, selected methods of Hyphenator have been replaced
* by calls to methods of the same name in this delegate class.
*/
public class Hyphenator_Delegate {
@@ -39,7 +39,8 @@
return null;
}
- /*package*/ static long loadHyphenator(ByteBuffer buf, int offset) {
+ /*package*/ @SuppressWarnings("UnusedParameters") // TODO implement this.
+ static long loadHyphenator(ByteBuffer buffer, int offset) {
return sDelegateManager.addNewDelegate(new Hyphenator_Delegate());
}
}
diff --git a/bridge/src/android/util/PathParser_Delegate.java b/bridge/src/android/util/PathParser_Delegate.java
new file mode 100644
index 0000000..6c34c70
--- /dev/null
+++ b/bridge/src/android/util/PathParser_Delegate.java
@@ -0,0 +1,844 @@
+/*
+ * Copyright (C) 2015 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 android.util;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.annotation.NonNull;
+import android.graphics.Path_Delegate;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Delegate that provides implementation for native methods in {@link android.util.PathParser}
+ * <p/>
+ * Through the layoutlib_create tool, selected methods of PathParser have been replaced by calls to
+ * methods of the same name in this delegate class.
+ *
+ * Most of the code has been taken from the implementation in
+ * {@code tools/base/sdk-common/src/main/java/com/android/ide/common/vectordrawable/PathParser.java}
+ * revision be6fe89a3b686db5a75e7e692a148699973957f3
+ */
+public class PathParser_Delegate {
+
+ private static final Logger LOGGER = Logger.getLogger("PathParser");
+
+ // ---- Builder delegate manager ----
+ private static final DelegateManager<PathParser_Delegate> sManager =
+ new DelegateManager<PathParser_Delegate>(PathParser_Delegate.class);
+
+ // ---- delegate data ----
+ @NonNull
+ private PathDataNode[] mPathDataNodes;
+
+ public static PathParser_Delegate getDelegate(long nativePtr) {
+ return sManager.getDelegate(nativePtr);
+ }
+
+ private PathParser_Delegate(@NonNull PathDataNode[] nodes) {
+ mPathDataNodes = nodes;
+ }
+
+ public PathDataNode[] getPathDataNodes() {
+ return mPathDataNodes;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static boolean nParseStringForPath(long pathPtr, @NonNull String pathString, int
+ stringLength) {
+ Path_Delegate path_delegate = Path_Delegate.getDelegate(pathPtr);
+ if (path_delegate == null) {
+ return false;
+ }
+ assert pathString.length() == stringLength;
+ PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate);
+ return true;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nCreatePathFromPathData(long outPathPtr, long pathData) {
+ Path_Delegate path_delegate = Path_Delegate.getDelegate(outPathPtr);
+ PathParser_Delegate source = sManager.getDelegate(outPathPtr);
+ if (source == null || path_delegate == null) {
+ return;
+ }
+ PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nCreateEmptyPathData() {
+ PathParser_Delegate newDelegate = new PathParser_Delegate(new PathDataNode[0]);
+ return sManager.addNewDelegate(newDelegate);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nCreatePathData(long nativePtr) {
+ PathParser_Delegate source = sManager.getDelegate(nativePtr);
+ if (source == null) {
+ return 0;
+ }
+ PathParser_Delegate dest = new PathParser_Delegate(deepCopyNodes(source.mPathDataNodes));
+ return sManager.addNewDelegate(dest);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nCreatePathDataFromString(@NonNull String pathString,
+ int stringLength) {
+ assert pathString.length() == stringLength : "Inconsistent path string length.";
+ PathDataNode[] nodes = createNodesFromPathData(pathString);
+ PathParser_Delegate delegate = new PathParser_Delegate(nodes);
+ return sManager.addNewDelegate(delegate);
+
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static boolean nInterpolatePathData(long outDataPtr, long fromDataPtr,
+ long toDataPtr, float fraction) {
+ PathParser_Delegate out = sManager.getDelegate(outDataPtr);
+ PathParser_Delegate from = sManager.getDelegate(fromDataPtr);
+ PathParser_Delegate to = sManager.getDelegate(toDataPtr);
+ if (out == null || from == null || to == null) {
+ return false;
+ }
+ int length = from.mPathDataNodes.length;
+ if (length != to.mPathDataNodes.length) {
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "Cannot interpolate path data with different lengths (from " + length + " to " +
+ to.mPathDataNodes.length + ").", null);
+ return false;
+ }
+ if (out.mPathDataNodes.length != length) {
+ out.mPathDataNodes = new PathDataNode[length];
+ }
+ for (int i = 0; i < length; i++) {
+ if (out.mPathDataNodes[i] == null) {
+ out.mPathDataNodes[i] = new PathDataNode(from.mPathDataNodes[i]);
+ }
+ out.mPathDataNodes[i].interpolatePathDataNode(from.mPathDataNodes[i],
+ to.mPathDataNodes[i], fraction);
+ }
+ return true;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nFinalize(long nativePtr) {
+ sManager.removeJavaReferenceFor(nativePtr);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static boolean nCanMorph(long fromDataPtr, long toDataPtr) {
+ PathParser_Delegate fromPath = PathParser_Delegate.getDelegate(fromDataPtr);
+ PathParser_Delegate toPath = PathParser_Delegate.getDelegate(toDataPtr);
+ if (fromPath == null || toPath == null || fromPath.getPathDataNodes() == null || toPath
+ .getPathDataNodes() == null) {
+ return true;
+ }
+ return PathParser_Delegate.canMorph(fromPath.getPathDataNodes(), toPath.getPathDataNodes());
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nSetPathData(long outDataPtr, long fromDataPtr) {
+ PathParser_Delegate out = sManager.getDelegate(outDataPtr);
+ PathParser_Delegate from = sManager.getDelegate(fromDataPtr);
+ if (from == null || out == null) {
+ return;
+ }
+ out.mPathDataNodes = deepCopyNodes(from.mPathDataNodes);
+ }
+
+ /**
+ * @param pathData The string representing a path, the same as "d" string in svg file.
+ *
+ * @return an array of the PathDataNode.
+ */
+ @NonNull
+ public static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
+ int start = 0;
+ int end = 1;
+
+ ArrayList<PathDataNode> list = new ArrayList<PathDataNode>();
+ while (end < pathData.length()) {
+ end = nextStart(pathData, end);
+ String s = pathData.substring(start, end).trim();
+ if (s.length() > 0) {
+ float[] val = getFloats(s);
+ addNode(list, s.charAt(0), val);
+ }
+
+ start = end;
+ end++;
+ }
+ if ((end - start) == 1 && start < pathData.length()) {
+ addNode(list, pathData.charAt(start), new float[0]);
+ }
+ return list.toArray(new PathDataNode[list.size()]);
+ }
+
+ /**
+ * @param source The array of PathDataNode to be duplicated.
+ *
+ * @return a deep copy of the <code>source</code>.
+ */
+ @NonNull
+ public static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
+ PathDataNode[] copy = new PathDataNode[source.length];
+ for (int i = 0; i < source.length; i++) {
+ copy[i] = new PathDataNode(source[i]);
+ }
+ return copy;
+ }
+
+ /**
+ * @param nodesFrom The source path represented in an array of PathDataNode
+ * @param nodesTo The target path represented in an array of PathDataNode
+ * @return whether the <code>nodesFrom</code> can morph into <code>nodesTo</code>
+ */
+ public static boolean canMorph(PathDataNode[] nodesFrom, PathDataNode[] nodesTo) {
+ if (nodesFrom == null || nodesTo == null) {
+ return false;
+ }
+
+ if (nodesFrom.length != nodesTo.length) {
+ return false;
+ }
+
+ for (int i = 0; i < nodesFrom.length; i ++) {
+ if (nodesFrom[i].mType != nodesTo[i].mType
+ || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Update the target's data to match the source.
+ * Before calling this, make sure canMorph(target, source) is true.
+ *
+ * @param target The target path represented in an array of PathDataNode
+ * @param source The source path represented in an array of PathDataNode
+ */
+ public static void updateNodes(PathDataNode[] target, PathDataNode[] source) {
+ for (int i = 0; i < source.length; i ++) {
+ target[i].mType = source[i].mType;
+ for (int j = 0; j < source[i].mParams.length; j ++) {
+ target[i].mParams[j] = source[i].mParams[j];
+ }
+ }
+ }
+
+ private static int nextStart(@NonNull String s, int end) {
+ char c;
+
+ while (end < s.length()) {
+ c = s.charAt(end);
+ // Note that 'e' or 'E' are not valid path commands, but could be
+ // used for floating point numbers' scientific notation.
+ // Therefore, when searching for next command, we should ignore 'e'
+ // and 'E'.
+ if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0))
+ && c != 'e' && c != 'E') {
+ return end;
+ }
+ end++;
+ }
+ return end;
+ }
+
+ /**
+ * Calculate the position of the next comma or space or negative sign
+ *
+ * @param s the string to search
+ * @param start the position to start searching
+ * @param result the result of the extraction, including the position of the the starting
+ * position of next number, whether it is ending with a '-'.
+ */
+ private static void extract(@NonNull String s, int start, @NonNull ExtractFloatResult result) {
+ // Now looking for ' ', ',', '.' or '-' from the start.
+ int currentIndex = start;
+ boolean foundSeparator = false;
+ result.mEndWithNegOrDot = false;
+ boolean secondDot = false;
+ boolean isExponential = false;
+ for (; currentIndex < s.length(); currentIndex++) {
+ boolean isPrevExponential = isExponential;
+ isExponential = false;
+ char currentChar = s.charAt(currentIndex);
+ switch (currentChar) {
+ case ' ':
+ case ',':
+ foundSeparator = true;
+ break;
+ case '-':
+ // The negative sign following a 'e' or 'E' is not a separator.
+ if (currentIndex != start && !isPrevExponential) {
+ foundSeparator = true;
+ result.mEndWithNegOrDot = true;
+ }
+ break;
+ case '.':
+ if (!secondDot) {
+ secondDot = true;
+ } else {
+ // This is the second dot, and it is considered as a separator.
+ foundSeparator = true;
+ result.mEndWithNegOrDot = true;
+ }
+ break;
+ case 'e':
+ case 'E':
+ isExponential = true;
+ break;
+ }
+ if (foundSeparator) {
+ break;
+ }
+ }
+ // When there is nothing found, then we put the end position to the end
+ // of the string.
+ result.mEndPosition = currentIndex;
+ }
+
+ /**
+ * Parse the floats in the string. This is an optimized version of
+ * parseFloat(s.split(",|\\s"));
+ *
+ * @param s the string containing a command and list of floats
+ *
+ * @return array of floats
+ */
+ @NonNull
+ private static float[] getFloats(@NonNull String s) {
+ if (s.charAt(0) == 'z' || s.charAt(0) == 'Z') {
+ return new float[0];
+ }
+ try {
+ float[] results = new float[s.length()];
+ int count = 0;
+ int startPosition = 1;
+ int endPosition;
+
+ ExtractFloatResult result = new ExtractFloatResult();
+ int totalLength = s.length();
+
+ // The startPosition should always be the first character of the
+ // current number, and endPosition is the character after the current
+ // number.
+ while (startPosition < totalLength) {
+ extract(s, startPosition, result);
+ endPosition = result.mEndPosition;
+
+ if (startPosition < endPosition) {
+ results[count++] = Float.parseFloat(
+ s.substring(startPosition, endPosition));
+ }
+
+ if (result.mEndWithNegOrDot) {
+ // Keep the '-' or '.' sign with next number.
+ startPosition = endPosition;
+ } else {
+ startPosition = endPosition + 1;
+ }
+ }
+ return Arrays.copyOf(results, count);
+ } catch (NumberFormatException e) {
+ throw new RuntimeException("error in parsing \"" + s + "\"", e);
+ }
+ }
+
+
+ private static void addNode(@NonNull ArrayList<PathDataNode> list, char cmd,
+ @NonNull float[] val) {
+ list.add(new PathDataNode(cmd, val));
+ }
+
+ private static class ExtractFloatResult {
+ // We need to return the position of the next separator and whether the
+ // next float starts with a '-' or a '.'.
+ private int mEndPosition;
+ private boolean mEndWithNegOrDot;
+ }
+
+ /**
+ * Each PathDataNode represents one command in the "d" attribute of the svg file. An array of
+ * PathDataNode can represent the whole "d" attribute.
+ */
+ public static class PathDataNode {
+ private char mType;
+ @NonNull
+ private float[] mParams;
+
+ private PathDataNode(char type, @NonNull float[] params) {
+ mType = type;
+ mParams = params;
+ }
+
+ public char getType() {
+ return mType;
+ }
+
+ @NonNull
+ public float[] getParams() {
+ return mParams;
+ }
+
+ private PathDataNode(@NonNull PathDataNode n) {
+ mType = n.mType;
+ mParams = Arrays.copyOf(n.mParams, n.mParams.length);
+ }
+
+ /**
+ * Convert an array of PathDataNode to Path. Reset the passed path as needed before
+ * calling this method.
+ *
+ * @param node The source array of PathDataNode.
+ * @param path The target Path object.
+ */
+ public static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path_Delegate path) {
+ float[] current = new float[6];
+ char previousCommand = 'm';
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0; i < node.length; i++) {
+ addCommand(path, current, previousCommand, node[i].mType, node[i].mParams);
+ previousCommand = node[i].mType;
+ }
+ }
+
+ /**
+ * The current PathDataNode will be interpolated between the <code>nodeFrom</code> and
+ * <code>nodeTo</code> according to the <code>fraction</code>.
+ *
+ * @param nodeFrom The start value as a PathDataNode.
+ * @param nodeTo The end value as a PathDataNode
+ * @param fraction The fraction to interpolate.
+ */
+ private void interpolatePathDataNode(@NonNull PathDataNode nodeFrom,
+ @NonNull PathDataNode nodeTo, float fraction) {
+ for (int i = 0; i < nodeFrom.mParams.length; i++) {
+ mParams[i] = nodeFrom.mParams[i] * (1 - fraction)
+ + nodeTo.mParams[i] * fraction;
+ }
+ }
+
+ @SuppressWarnings("PointlessArithmeticExpression")
+ private static void addCommand(@NonNull Path_Delegate path, float[] current,
+ char previousCmd, char cmd, @NonNull float[] val) {
+
+ int incr = 2;
+ float currentX = current[0];
+ float currentY = current[1];
+ float ctrlPointX = current[2];
+ float ctrlPointY = current[3];
+ float currentSegmentStartX = current[4];
+ float currentSegmentStartY = current[5];
+ float reflectiveCtrlPointX;
+ float reflectiveCtrlPointY;
+
+ switch (cmd) {
+ case 'z':
+ case 'Z':
+ path.close();
+ // Path is closed here, but we need to move the pen to the
+ // closed position. So we cache the segment's starting position,
+ // and restore it here.
+ currentX = currentSegmentStartX;
+ currentY = currentSegmentStartY;
+ ctrlPointX = currentSegmentStartX;
+ ctrlPointY = currentSegmentStartY;
+ path.moveTo(currentX, currentY);
+ break;
+ case 'm':
+ case 'M':
+ case 'l':
+ case 'L':
+ case 't':
+ case 'T':
+ incr = 2;
+ break;
+ case 'h':
+ case 'H':
+ case 'v':
+ case 'V':
+ incr = 1;
+ break;
+ case 'c':
+ case 'C':
+ incr = 6;
+ break;
+ case 's':
+ case 'S':
+ case 'q':
+ case 'Q':
+ incr = 4;
+ break;
+ case 'a':
+ case 'A':
+ incr = 7;
+ break;
+ }
+
+ for (int k = 0; k < val.length; k += incr) {
+ switch (cmd) {
+ case 'm': // moveto - Start a new sub-path (relative)
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+
+ if (k > 0) {
+ // According to the spec, if a moveto is followed by multiple
+ // pairs of coordinates, the subsequent pairs are treated as
+ // implicit lineto commands.
+ path.rLineTo(val[k + 0], val[k + 1]);
+ } else {
+ path.rMoveTo(val[k + 0], val[k + 1]);
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
+ }
+ break;
+ case 'M': // moveto - Start a new sub-path
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+
+ if (k > 0) {
+ // According to the spec, if a moveto is followed by multiple
+ // pairs of coordinates, the subsequent pairs are treated as
+ // implicit lineto commands.
+ path.lineTo(val[k + 0], val[k + 1]);
+ } else {
+ path.moveTo(val[k + 0], val[k + 1]);
+ currentSegmentStartX = currentX;
+ currentSegmentStartY = currentY;
+ }
+ break;
+ case 'l': // lineto - Draw a line from the current point (relative)
+ path.rLineTo(val[k + 0], val[k + 1]);
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+ break;
+ case 'L': // lineto - Draw a line from the current point
+ path.lineTo(val[k + 0], val[k + 1]);
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+ break;
+ case 'h': // horizontal lineto - Draws a horizontal line (relative)
+ path.rLineTo(val[k + 0], 0);
+ currentX += val[k + 0];
+ break;
+ case 'H': // horizontal lineto - Draws a horizontal line
+ path.lineTo(val[k + 0], currentY);
+ currentX = val[k + 0];
+ break;
+ case 'v': // vertical lineto - Draws a vertical line from the current point (r)
+ path.rLineTo(0, val[k + 0]);
+ currentY += val[k + 0];
+ break;
+ case 'V': // vertical lineto - Draws a vertical line from the current point
+ path.lineTo(currentX, val[k + 0]);
+ currentY = val[k + 0];
+ break;
+ case 'c': // curveto - Draws a cubic Bézier curve (relative)
+ path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+ val[k + 4], val[k + 5]);
+
+ ctrlPointX = currentX + val[k + 2];
+ ctrlPointY = currentY + val[k + 3];
+ currentX += val[k + 4];
+ currentY += val[k + 5];
+
+ break;
+ case 'C': // curveto - Draws a cubic Bézier curve
+ path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+ val[k + 4], val[k + 5]);
+ currentX = val[k + 4];
+ currentY = val[k + 5];
+ ctrlPointX = val[k + 2];
+ ctrlPointY = val[k + 3];
+ break;
+ case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1],
+ val[k + 2], val[k + 3]);
+
+ ctrlPointX = currentX + val[k + 0];
+ ctrlPointY = currentY + val[k + 1];
+ currentX += val[k + 2];
+ currentY += val[k + 3];
+ break;
+ case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'c' || previousCmd == 's'
+ || previousCmd == 'C' || previousCmd == 'S') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ break;
+ case 'q': // Draws a quadratic Bézier (relative)
+ path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ ctrlPointX = currentX + val[k + 0];
+ ctrlPointY = currentY + val[k + 1];
+ currentX += val[k + 2];
+ currentY += val[k + 3];
+ break;
+ case 'Q': // Draws a quadratic Bézier
+ path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+ ctrlPointX = val[k + 0];
+ ctrlPointY = val[k + 1];
+ currentX = val[k + 2];
+ currentY = val[k + 3];
+ break;
+ case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
+ reflectiveCtrlPointX = 0;
+ reflectiveCtrlPointY = 0;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = currentX - ctrlPointX;
+ reflectiveCtrlPointY = currentY - ctrlPointY;
+ }
+ path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = currentX + reflectiveCtrlPointX;
+ ctrlPointY = currentY + reflectiveCtrlPointY;
+ currentX += val[k + 0];
+ currentY += val[k + 1];
+ break;
+ case 'T': // Draws a quadratic Bézier curve (reflective control point)
+ reflectiveCtrlPointX = currentX;
+ reflectiveCtrlPointY = currentY;
+ if (previousCmd == 'q' || previousCmd == 't'
+ || previousCmd == 'Q' || previousCmd == 'T') {
+ reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+ reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+ }
+ path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+ val[k + 0], val[k + 1]);
+ ctrlPointX = reflectiveCtrlPointX;
+ ctrlPointY = reflectiveCtrlPointY;
+ currentX = val[k + 0];
+ currentY = val[k + 1];
+ break;
+ case 'a': // Draws an elliptical arc
+ // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5] + currentX,
+ val[k + 6] + currentY,
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
+ val[k + 4] != 0);
+ currentX += val[k + 5];
+ currentY += val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+ break;
+ case 'A': // Draws an elliptical arc
+ drawArc(path,
+ currentX,
+ currentY,
+ val[k + 5],
+ val[k + 6],
+ val[k + 0],
+ val[k + 1],
+ val[k + 2],
+ val[k + 3] != 0,
+ val[k + 4] != 0);
+ currentX = val[k + 5];
+ currentY = val[k + 6];
+ ctrlPointX = currentX;
+ ctrlPointY = currentY;
+ break;
+ }
+ previousCmd = cmd;
+ }
+ current[0] = currentX;
+ current[1] = currentY;
+ current[2] = ctrlPointX;
+ current[3] = ctrlPointY;
+ current[4] = currentSegmentStartX;
+ current[5] = currentSegmentStartY;
+ }
+
+ private static void drawArc(@NonNull Path_Delegate p, float x0, float y0, float x1,
+ float y1, float a, float b, float theta, boolean isMoreThanHalf,
+ boolean isPositiveArc) {
+
+ LOGGER.log(Level.FINE, "(" + x0 + "," + y0 + ")-(" + x1 + "," + y1
+ + ") {" + a + " " + b + "}");
+ /* Convert rotation angle from degrees to radians */
+ double thetaD = theta * Math.PI / 180.0f;
+ /* Pre-compute rotation matrix entries */
+ double cosTheta = Math.cos(thetaD);
+ double sinTheta = Math.sin(thetaD);
+ /* Transform (x0, y0) and (x1, y1) into unit space */
+ /* using (inverse) rotation, followed by (inverse) scale */
+ double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
+ double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
+ double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
+ double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
+ LOGGER.log(Level.FINE, "unit space (" + x0p + "," + y0p + ")-(" + x1p
+ + "," + y1p + ")");
+ /* Compute differences and averages */
+ double dx = x0p - x1p;
+ double dy = y0p - y1p;
+ double xm = (x0p + x1p) / 2;
+ double ym = (y0p + y1p) / 2;
+ /* Solve for intersecting unit circles */
+ double dsq = dx * dx + dy * dy;
+ if (dsq == 0.0) {
+ LOGGER.log(Level.FINE, " Points are coincident");
+ return; /* Points are coincident */
+ }
+ double disc = 1.0 / dsq - 1.0 / 4.0;
+ if (disc < 0.0) {
+ LOGGER.log(Level.FINE, "Points are too far apart " + dsq);
+ float adjust = (float) (Math.sqrt(dsq) / 1.99999);
+ drawArc(p, x0, y0, x1, y1, a * adjust, b * adjust, theta,
+ isMoreThanHalf, isPositiveArc);
+ return; /* Points are too far apart */
+ }
+ double s = Math.sqrt(disc);
+ double sdx = s * dx;
+ double sdy = s * dy;
+ double cx;
+ double cy;
+ if (isMoreThanHalf == isPositiveArc) {
+ cx = xm - sdy;
+ cy = ym + sdx;
+ } else {
+ cx = xm + sdy;
+ cy = ym - sdx;
+ }
+
+ double eta0 = Math.atan2((y0p - cy), (x0p - cx));
+ LOGGER.log(Level.FINE, "eta0 = Math.atan2( " + (y0p - cy) + " , "
+ + (x0p - cx) + ") = " + Math.toDegrees(eta0));
+
+ double eta1 = Math.atan2((y1p - cy), (x1p - cx));
+ LOGGER.log(Level.FINE, "eta1 = Math.atan2( " + (y1p - cy) + " , "
+ + (x1p - cx) + ") = " + Math.toDegrees(eta1));
+ double sweep = (eta1 - eta0);
+ if (isPositiveArc != (sweep >= 0)) {
+ if (sweep > 0) {
+ sweep -= 2 * Math.PI;
+ } else {
+ sweep += 2 * Math.PI;
+ }
+ }
+
+ cx *= a;
+ cy *= b;
+ double tcx = cx;
+ cx = cx * cosTheta - cy * sinTheta;
+ cy = tcx * sinTheta + cy * cosTheta;
+ LOGGER.log(
+ Level.FINE,
+ "cx, cy, a, b, x0, y0, thetaD, eta0, sweep = " + cx + " , "
+ + cy + " , " + a + " , " + b + " , " + x0 + " , " + y0
+ + " , " + Math.toDegrees(thetaD) + " , "
+ + Math.toDegrees(eta0) + " , " + Math.toDegrees(sweep));
+
+ arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
+ }
+
+ /**
+ * Converts an arc to cubic Bezier segments and records them in p.
+ *
+ * @param p The target for the cubic Bezier segments
+ * @param cx The x coordinate center of the ellipse
+ * @param cy The y coordinate center of the ellipse
+ * @param a The radius of the ellipse in the horizontal direction
+ * @param b The radius of the ellipse in the vertical direction
+ * @param e1x E(eta1) x coordinate of the starting point of the arc
+ * @param e1y E(eta2) y coordinate of the starting point of the arc
+ * @param theta The angle that the ellipse bounding rectangle makes with the horizontal
+ * plane
+ * @param start The start angle of the arc on the ellipse
+ * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
+ */
+ private static void arcToBezier(@NonNull Path_Delegate p, double cx, double cy, double a,
+ double b, double e1x, double e1y, double theta, double start,
+ double sweep) {
+ // Taken from equations at:
+ // http://spaceroots.org/documents/ellipse/node8.html
+ // and http://www.spaceroots.org/documents/ellipse/node22.html
+ // Maximum of 45 degrees per cubic Bezier segment
+ int numSegments = (int) Math.ceil(Math.abs(sweep * 4 / Math.PI));
+
+
+ double eta1 = start;
+ double cosTheta = Math.cos(theta);
+ double sinTheta = Math.sin(theta);
+ double cosEta1 = Math.cos(eta1);
+ double sinEta1 = Math.sin(eta1);
+ double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
+ double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
+
+ double anglePerSegment = sweep / numSegments;
+ for (int i = 0; i < numSegments; i++) {
+ double eta2 = eta1 + anglePerSegment;
+ double sinEta2 = Math.sin(eta2);
+ double cosEta2 = Math.cos(eta2);
+ double e2x = cx + (a * cosTheta * cosEta2)
+ - (b * sinTheta * sinEta2);
+ double e2y = cy + (a * sinTheta * cosEta2)
+ + (b * cosTheta * sinEta2);
+ double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
+ double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
+ double tanDiff2 = Math.tan((eta2 - eta1) / 2);
+ double alpha = Math.sin(eta2 - eta1)
+ * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
+ double q1x = e1x + alpha * ep1x;
+ double q1y = e1y + alpha * ep1y;
+ double q2x = e2x - alpha * ep2x;
+ double q2y = e2y - alpha * ep2y;
+
+ p.cubicTo((float) q1x,
+ (float) q1y,
+ (float) q2x,
+ (float) q2y,
+ (float) e2x,
+ (float) e2y);
+ eta1 = eta2;
+ e1x = e2x;
+ e1y = e2y;
+ ep1x = ep2x;
+ ep1y = ep2y;
+ }
+ }
+ }
+}
diff --git a/bridge/src/android/view/ViewRootImpl_RunQueue_Delegate.java b/bridge/src/android/view/HandlerActionQueue_Delegate.java
similarity index 74%
rename from bridge/src/android/view/ViewRootImpl_RunQueue_Delegate.java
rename to bridge/src/android/view/HandlerActionQueue_Delegate.java
index 51b42a6..e580ed0 100644
--- a/bridge/src/android/view/ViewRootImpl_RunQueue_Delegate.java
+++ b/bridge/src/android/view/HandlerActionQueue_Delegate.java
@@ -20,18 +20,18 @@
/**
* Delegate used to provide new implementation of a select few methods of
- * {@link ViewRootImpl.RunQueue}
+ * {@link HandlerActionQueue}
*
* Through the layoutlib_create tool, the original methods of ViewRootImpl.RunQueue have been
* replaced by calls to methods of the same name in this delegate class.
*
*/
-public class ViewRootImpl_RunQueue_Delegate {
+public class HandlerActionQueue_Delegate {
@LayoutlibDelegate
- /*package*/ static void postDelayed(ViewRootImpl.RunQueue thisQueue, Runnable action, long
+ /*package*/ static void postDelayed(HandlerActionQueue thisQueue, Runnable action, long
delayMillis) {
- // The actual RunQueue is never run and therefore never cleared. This method avoids
- // runnables to be added to the RunQueue so they do not leak resources.
+ // The actual HandlerActionQueue is never run and therefore never cleared. This method
+ // avoids runnables to be added to the RunQueue so they do not leak resources.
}
}
diff --git a/bridge/src/android/view/IWindowManagerImpl.java b/bridge/src/android/view/IWindowManagerImpl.java
index 82012c1..97195e4 100644
--- a/bridge/src/android/view/IWindowManagerImpl.java
+++ b/bridge/src/android/view/IWindowManagerImpl.java
@@ -17,7 +17,10 @@
package android.view;
import android.graphics.Point;
+import android.graphics.Rect;
import com.android.internal.app.IAssistScreenshotReceiver;
+import com.android.internal.os.IResultReceiver;
+import com.android.internal.policy.IShortcutService;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -29,6 +32,7 @@
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.util.DisplayMetrics;
+import android.view.AppTransitionAnimationSpec;
import java.lang.Override;
@@ -73,10 +77,10 @@
@Override
public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, int arg4,
- boolean arg5, boolean arg6, int arg7, int arg8, boolean arg9, boolean arg10)
+ boolean arg5, boolean arg6, int arg7, int arg8, boolean arg9, boolean arg10,
+ Rect arg11, Configuration arg12, int arg13, boolean arg14, boolean arg15)
throws RemoteException {
// TODO Auto-generated method stub
-
}
@Override
@@ -240,6 +244,19 @@
}
@Override
+ public void overridePendingAppTransitionMultiThumbFuture(
+ IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback startedCallback,
+ boolean scaleUp) throws RemoteException {
+
+ }
+
+ @Override
+ public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
+ IRemoteCallback callback0, IRemoteCallback callback1, boolean scaleUp) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
public void pauseKeyDispatching(IBinder arg0) throws RemoteException {
// TODO Auto-generated method stub
@@ -284,7 +301,7 @@
@Override
public Bitmap screenshotApplications(IBinder appToken, int displayId, int maxWidth,
- int maxHeight) throws RemoteException {
+ int maxHeight, float frameScale) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
@@ -307,9 +324,10 @@
}
@Override
- public void setAppTask(IBinder arg0, int arg1) throws RemoteException {
+ public void setAppTask(IBinder arg0, int arg1, int arg2, Rect arg3, Configuration arg4,
+ int arg5, boolean arg6)
+ throws RemoteException {
// TODO Auto-generated method stub
-
}
@Override
@@ -331,7 +349,7 @@
}
@Override
- public void setAppWillBeHidden(IBinder arg0) throws RemoteException {
+ public void notifyAppStopped(IBinder token, boolean stopped) throws RemoteException {
// TODO Auto-generated method stub
}
@@ -511,4 +529,46 @@
// TODO Auto-generated method stub
return null;
}
+
+ @Override
+ public int getDockedStackSide() throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public void setDockedStackResizing(boolean resizing) throws RemoteException {
+ }
+
+ @Override
+ public void cancelTaskWindowTransition(int taskId) {
+ }
+
+ @Override
+ public void cancelTaskThumbnailTransition(int taskId) {
+ }
+
+ @Override
+ public void endProlongedAnimations() {
+ }
+
+ @Override
+ public void registerDockedStackListener(IDockedStackListener listener) throws RemoteException {
+ }
+
+ @Override
+ public void setResizeDimLayer(boolean visible, int targetStackId, float alpha)
+ throws RemoteException {
+ }
+
+ @Override
+ public void requestAppKeyboardShortcuts(IResultReceiver receiver) throws RemoteException {
+ }
+
+ @Override
+ public void getStableInsets(Rect outInsets) throws RemoteException {
+ }
+
+ @Override
+ public void registerShortcutKey(long shortcutCode, IShortcutService service)
+ throws RemoteException {}
}
diff --git a/bridge/src/android/view/WindowCallback.java b/bridge/src/android/view/WindowCallback.java
index d691c8e..411417c 100644
--- a/bridge/src/android/view/WindowCallback.java
+++ b/bridge/src/android/view/WindowCallback.java
@@ -16,10 +16,13 @@
package android.view;
+import android.annotation.Nullable;
import android.view.ActionMode.Callback;
import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityEvent;
+import java.util.List;
+
/**
* An empty implementation of {@link Window.Callback} that always returns null/false.
*/
@@ -138,4 +141,9 @@
public void onActionModeFinished(ActionMode mode) {
}
+
+ @Override
+ public void onProvideKeyboardShortcuts(List<KeyboardShortcutGroup> data, @Nullable Menu menu) {
+
+ }
}
diff --git a/bridge/src/android/widget/TimePickerClockDelegate_Delegate.java b/bridge/src/android/widget/TimePickerClockDelegate_Delegate.java
deleted file mode 100644
index 1bd9830..0000000
--- a/bridge/src/android/widget/TimePickerClockDelegate_Delegate.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.widget;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.view.KeyEvent;
-
-/**
- * Delegate used to provide new implementation of few methods in {@link TimePickerClockDelegate}.
- */
-public class TimePickerClockDelegate_Delegate {
-
- // Copied from TimePickerClockDelegate.
- private static final int AM = 0;
- private static final int PM = 1;
-
- @LayoutlibDelegate
- static int getAmOrPmKeyCode(TimePickerClockDelegate tpcd, int amOrPm) {
- // We don't care about locales here.
- if (amOrPm == AM) {
- return KeyEvent.KEYCODE_A;
- } else if (amOrPm == PM) {
- return KeyEvent.KEYCODE_P;
- } else {
- assert false : "amOrPm value in TimePickerSpinnerDelegate can only be 0 or 1";
- return -1;
- }
- }
-}
diff --git a/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java b/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
new file mode 100644
index 0000000..0f39e80
--- /dev/null
+++ b/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2016 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.internal.view.animation;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.util.MathUtils;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AnticipateInterpolator;
+import android.view.animation.AnticipateOvershootInterpolator;
+import android.view.animation.BaseInterpolator;
+import android.view.animation.BounceInterpolator;
+import android.view.animation.CycleInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.OvershootInterpolator;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link
+ * NativeInterpolatorFactoryHelper}
+ * <p>
+ * Through the layoutlib_create tool, the original methods of NativeInterpolatorFactoryHelper have
+ * been replaced by calls to methods of the same name in this delegate class.
+ */
+@SuppressWarnings("unused")
+public class NativeInterpolatorFactoryHelper_Delegate {
+ private static final DelegateManager<Interpolator> sManager = new DelegateManager<>
+ (Interpolator.class);
+
+ public static Interpolator getDelegate(long nativePtr) {
+ return sManager.getDelegate(nativePtr);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long createAccelerateDecelerateInterpolator() {
+ return sManager.addNewDelegate(new AccelerateDecelerateInterpolator());
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long createAccelerateInterpolator(float factor) {
+ return sManager.addNewDelegate(new AccelerateInterpolator(factor));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long createAnticipateInterpolator(float tension) {
+ return sManager.addNewDelegate(new AnticipateInterpolator(tension));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long createAnticipateOvershootInterpolator(float tension) {
+ return sManager.addNewDelegate(new AnticipateOvershootInterpolator(tension));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long createBounceInterpolator() {
+ return sManager.addNewDelegate(new BounceInterpolator());
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long createCycleInterpolator(float cycles) {
+ return sManager.addNewDelegate(new CycleInterpolator(cycles));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long createDecelerateInterpolator(float factor) {
+ return sManager.addNewDelegate(new DecelerateInterpolator(factor));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long createLinearInterpolator() {
+ return sManager.addNewDelegate(new LinearInterpolator());
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long createOvershootInterpolator(float tension) {
+ return sManager.addNewDelegate(new OvershootInterpolator(tension));
+ }
+
+ private static class LutInterpolator extends BaseInterpolator {
+ private final float[] mValues;
+ private final int mSize;
+
+ private LutInterpolator(float[] values) {
+ mValues = values;
+ mSize = mValues.length;
+ }
+
+ @Override
+ public float getInterpolation(float input) {
+ float lutpos = input * mSize;
+ if (lutpos >= (mSize - 1)) {
+ return mValues[mSize - 1];
+ }
+
+ int ipart = (int) lutpos;
+ float weight = lutpos - ipart;
+
+ int i1 = ipart;
+ int i2 = Math.min(i1 + 1, mSize - 1);
+
+ assert i1 >= 0 && i2 >= 0 : "Negatives in the interpolation";
+
+ return MathUtils.lerp(mValues[i1], mValues[i2], weight);
+ }
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long createLutInterpolator(float[] values) {
+ return sManager.addNewDelegate(new LutInterpolator(values));
+ }
+}
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 2fd1f18..c7ae6fc 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -73,6 +73,7 @@
import android.os.Parcel;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -1135,6 +1136,11 @@
public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
return false;
}
+
+ @Override
+ public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, ResultReceiver resultReceiver) {
+ }
};
}
return mBinder;
@@ -1252,6 +1258,12 @@
}
@Override
+ public boolean migrateDatabaseFrom(Context sourceContext, String name) {
+ // pass
+ return false;
+ }
+
+ @Override
public boolean deleteDatabase(String arg0) {
// pass
return false;
@@ -1364,6 +1376,18 @@
}
@Override
+ public File getSharedPreferencesPath(String name) {
+ // pass
+ return null;
+ }
+
+ @Override
+ public File getDataDir() {
+ // pass
+ return null;
+ }
+
+ @Override
public File getFilesDir() {
// pass
return null;
@@ -1411,12 +1435,6 @@
}
@Override
- public File getSharedPrefsFile(String name) {
- // pass
- return null;
- }
-
- @Override
public SharedPreferences getSharedPreferences(String arg0, int arg1) {
if (mSharedPreferences == null) {
mSharedPreferences = new BridgeSharedPreferences();
@@ -1425,6 +1443,26 @@
}
@Override
+ public SharedPreferences getSharedPreferences(File arg0, int arg1) {
+ if (mSharedPreferences == null) {
+ mSharedPreferences = new BridgeSharedPreferences();
+ }
+ return mSharedPreferences;
+ }
+
+ @Override
+ public boolean migrateSharedPreferencesFrom(Context sourceContext, String name) {
+ // pass
+ return false;
+ }
+
+ @Override
+ public boolean deleteSharedPreferences(String name) {
+ // pass
+ return false;
+ }
+
+ @Override
public Drawable getWallpaper() {
// pass
return null;
@@ -1625,6 +1663,11 @@
}
@Override
+ public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) {
+ // pass
+ }
+
+ @Override
public void sendStickyOrderedBroadcastAsUser(Intent intent,
UserHandle user, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
@@ -1793,4 +1836,26 @@
Integer pos = mScrollYPos.get(view);
return pos != null ? pos : 0;
}
+
+ @Override
+ public Context createDeviceEncryptedStorageContext() {
+ // pass
+ return null;
+ }
+
+ @Override
+ public Context createCredentialEncryptedStorageContext() {
+ // pass
+ return null;
+ }
+
+ @Override
+ public boolean isDeviceEncryptedStorage() {
+ return false;
+ }
+
+ @Override
+ public boolean isCredentialEncryptedStorage() {
+ return false;
+ }
}
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index 8899e53..5c74caf 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -184,13 +184,6 @@
}
@Override
- public InputBindResult startInput(IInputMethodClient client, IInputContext inputContext,
- EditorInfo attribute, int controlFlags) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
public boolean switchToLastInputMethod(IBinder arg0) throws RemoteException {
// TODO Auto-generated method stub
return false;
@@ -226,9 +219,11 @@
}
@Override
- public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
- int controlFlags, int softInputMode, int windowFlags, EditorInfo attribute,
- IInputContext inputContext) throws RemoteException {
+ public InputBindResult startInputOrWindowGainedFocus(
+ /* @InputMethodClient.StartInputReason */ int startInputReason,
+ IInputMethodClient client, IBinder windowToken, int controlFlags, int softInputMode,
+ int windowFlags, EditorInfo attribute, IInputContext inputContext)
+ throws RemoteException {
// TODO Auto-generated method stub
return null;
}
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
index f04654e..4039cdf 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -16,6 +16,7 @@
package com.android.layoutlib.bridge.android;
+import android.annotation.NonNull;
import android.app.PackageInstallObserver;
import android.content.ComponentName;
import android.content.Intent;
@@ -23,7 +24,7 @@
import android.content.IntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
-import android.content.pm.ContainerEncryptionParams;
+import android.content.pm.EphemeralApplicationInfo;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
@@ -32,7 +33,6 @@
import android.content.pm.InstrumentationInfo;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.KeySet;
-import android.content.pm.ManifestDigest;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageItemInfo;
@@ -42,7 +42,6 @@
import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.VerificationParams;
import android.content.pm.VerifierDeviceIdentity;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
@@ -65,6 +64,12 @@
}
@Override
+ public PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
public String[] currentToCanonicalPackageNames(String[] names) {
return new String[0];
}
@@ -90,7 +95,22 @@
}
@Override
- public int getPackageUid(String packageName, int userHandle) throws NameNotFoundException {
+ public int[] getPackageGids(String packageName, int flags) throws NameNotFoundException {
+ return new int[0];
+ }
+
+ @Override
+ public int getPackageUid(String packageName, int flags) throws NameNotFoundException {
+ return 0;
+ }
+
+ @Override
+ public int getPackageUidAsUser(String packageName, int userHandle) throws NameNotFoundException {
+ return 0;
+ }
+
+ @Override
+ public int getPackageUidAsUser(String packageName, int flags, int userHandle) throws NameNotFoundException {
return 0;
}
@@ -123,6 +143,12 @@
}
@Override
+ public ApplicationInfo getApplicationInfoAsUser(String packageName, int flags, int userId)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
public ActivityInfo getActivityInfo(ComponentName component, int flags)
throws NameNotFoundException {
return null;
@@ -157,7 +183,7 @@
}
@Override
- public List<PackageInfo> getInstalledPackages(int flags, int userId) {
+ public List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) {
return null;
}
@@ -245,11 +271,46 @@
}
@Override
+ public List<EphemeralApplicationInfo> getEphemeralApplications() {
+ return null;
+ }
+
+ @Override
+ public Drawable getEphemeralApplicationIcon(String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public byte[] getEphemeralCookie() {
+ return new byte[0];
+ }
+
+ @Override
+ public boolean isEphemeralApplication() {
+ return false;
+ }
+
+ @Override
+ public int getEphemeralCookieMaxSizeBytes() {
+ return 0;
+ }
+
+ @Override
+ public boolean setEphemeralCookie(@NonNull byte[] cookie) {
+ return false;
+ }
+
+ @Override
public String[] getSystemSharedLibraryNames() {
return new String[0];
}
@Override
+ public String getServicesSystemSharedLibraryPackageName() {
+ return null;
+ }
+
+ @Override
public FeatureInfo[] getSystemAvailableFeatures() {
return new FeatureInfo[0];
}
@@ -260,6 +321,11 @@
}
@Override
+ public boolean hasSystemFeature(String name, int version) {
+ return false;
+ }
+
+ @Override
public ResolveInfo resolveActivity(Intent intent, int flags) {
return null;
}
@@ -291,7 +357,7 @@
}
@Override
- public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags, int userId) {
+ public List<ResolveInfo> queryBroadcastReceiversAsUser(Intent intent, int flags, int userId) {
return null;
}
@@ -418,6 +484,12 @@
}
@Override
+ public Drawable getManagedUserBadgedDrawable(Drawable drawable, Rect badgeLocation,
+ int badgeDensity) {
+ return null;
+ }
+
+ @Override
public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
return null;
}
@@ -434,6 +506,11 @@
}
@Override
+ public Drawable getUserBadgeForDensityNoBackground(UserHandle user, int density) {
+ return null;
+ }
+
+ @Override
public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
return null;
}
@@ -482,40 +559,22 @@
}
@Override
- public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
- int flags, String installerPackageName, Uri verificationURI,
- ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
- }
-
- @Override
- public void installPackageWithVerificationAndEncryption(Uri packageURI,
- IPackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
- }
-
- @Override
public void installPackage(Uri packageURI, PackageInstallObserver observer, int flags,
String installerPackageName) {
}
@Override
- public void installPackageWithVerification(Uri packageURI, PackageInstallObserver observer,
- int flags, String installerPackageName, Uri verificationURI,
- ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
- }
-
- @Override
- public void installPackageWithVerificationAndEncryption(Uri packageURI,
- PackageInstallObserver observer, int flags, String installerPackageName,
- VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
- }
-
- @Override
public int installExistingPackage(String packageName) throws NameNotFoundException {
return 0;
}
@Override
+ public int installExistingPackageAsUser(String packageName, int userId)
+ throws NameNotFoundException {
+ return 0;
+ }
+
+ @Override
public void verifyPendingInstall(int id, int verificationCode) {
}
@@ -530,12 +589,12 @@
}
@Override
- public int getIntentVerificationStatus(String packageName, int userId) {
+ public int getIntentVerificationStatusAsUser(String packageName, int userId) {
return 0;
}
@Override
- public boolean updateIntentVerificationStatus(String packageName, int status, int userId) {
+ public boolean updateIntentVerificationStatusAsUser(String packageName, int status, int userId) {
return false;
}
@@ -550,12 +609,12 @@
}
@Override
- public String getDefaultBrowserPackageName(int userId) {
+ public String getDefaultBrowserPackageNameAsUser(int userId) {
return null;
}
@Override
- public boolean setDefaultBrowserPackageName(String packageName, int userId) {
+ public boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) {
return false;
}
@@ -568,6 +627,11 @@
}
@Override
+ public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int flags,
+ int userId) {
+ }
+
+ @Override
public String getInstallerPackageName(String packageName) {
return null;
}
@@ -590,7 +654,7 @@
}
@Override
- public void getPackageSizeInfo(String packageName, int userHandle,
+ public void getPackageSizeInfoAsUser(String packageName, int userHandle,
IPackageStatsObserver observer) {
}
@@ -695,6 +759,17 @@
}
@Override
+ public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
+ int userId) {
+ return new String[]{};
+ }
+
+ @Override
+ public boolean isPackageSuspendedForUser(String packageName, int userId) {
+ return false;
+ }
+
+ @Override
public int getMoveStatus(int moveId) {
return 0;
}
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 895f9c9..e9b7819 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -86,7 +86,7 @@
}
@Override
- public void shutdown(boolean confirm, boolean wait) {
+ public void shutdown(boolean confirm, String reason, boolean wait) {
// pass for now.
}
@@ -152,6 +152,11 @@
}
@Override
+ public boolean isLightDeviceIdleMode() throws RemoteException {
+ return false;
+ }
+
+ @Override
public boolean isScreenBrightnessBoosted() throws RemoteException {
return false;
}
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index 771c3c8..533a10a 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -16,6 +16,8 @@
package com.android.layoutlib.bridge.android;
+import com.android.internal.os.IResultReceiver;
+
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
@@ -48,7 +50,8 @@
@Override
public void resized(Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, Rect rect6,
- boolean b, Configuration configuration) throws RemoteException {
+ boolean b, Configuration configuration, Rect rect7, boolean b2, boolean b3)
+ throws RemoteException {
// pass for now.
}
@@ -85,26 +88,28 @@
}
@Override
+ public void updatePointerIcon(float x, float y) {
+ // pass for now
+ }
+
+ @Override
public void dispatchSystemUiVisibilityChanged(int seq, int globalUi,
int localValue, int localChanges) {
// pass for now.
}
@Override
- public void onAnimationStarted(int remainingFrameCount) {
- }
-
- @Override
- public void onAnimationStopped() {
- }
-
- @Override
public void dispatchWindowShown() {
}
@Override
+ public void requestAppKeyboardShortcuts(IResultReceiver receiver) throws RemoteException {
+ }
+
+ @Override
public IBinder asBinder() {
// pass for now.
return null;
}
+
}
diff --git a/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index bea1f86..fe05b0e 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -89,12 +89,20 @@
@Override
public int relayout(IWindow iWindow, int i, LayoutParams layoutParams, int i2,
int i3, int i4, int i5, Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5,
- Rect rect6, Configuration configuration, Surface surface) throws RemoteException {
+ Rect rect6, Rect rect7, Configuration configuration, Surface surface)
+ throws RemoteException {
// pass for now.
return 0;
}
@Override
+ public void repositionChild(IWindow childWindow, int x, int y, int width, int height,
+ long deferTransactionUntilFrame, Rect outFrame) {
+ // pass for now.
+ return;
+ }
+
+ @Override
public void performDeferredDestroy(IWindow window) {
// pass for now.
}
@@ -140,7 +148,7 @@
@Override
public boolean performDrag(IWindow window, IBinder dragToken,
- float touchX, float touchY, float thumbCenterX, float thumbCenterY,
+ int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
ClipData data)
throws RemoteException {
// pass for now
@@ -148,11 +156,23 @@
}
@Override
+ public boolean startMovingTask(IWindow window, float startX, float startY)
+ throws RemoteException {
+ // pass for now
+ return false;
+ }
+
+ @Override
public void reportDropResult(IWindow window, boolean consumed) throws RemoteException {
// pass for now
}
@Override
+ public void cancelDragAndDrop(IBinder dragToken) throws RemoteException {
+ // pass for now
+ }
+
+ @Override
public void dragRecipientEntered(IWindow window) throws RemoteException {
// pass for now
}
@@ -211,4 +231,14 @@
public void pokeDrawLock(IBinder window) {
// pass for now.
}
+
+ @Override
+ public void prepareToReplaceChildren(IBinder appToken) {
+ // pass for now.
+ }
+
+ @Override
+ public void updatePointerIcon(IWindow window) {
+ // pass for now.
+ }
}
diff --git a/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java b/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
index 7e5ae8d..d417eb7 100644
--- a/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
+++ b/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java
@@ -63,4 +63,9 @@
public void removeViewImmediate(View arg0) {
// pass
}
+
+ @Override
+ public void requestAppKeyboardShortcuts(
+ KeyboardShortcutsReceiver receiver) {
+ }
}
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 99af226..53f1912 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -60,6 +60,7 @@
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
import android.graphics.Canvas;
+import android.os.Looper;
import android.preference.Preference_Delegate;
import android.view.AttachInfo_Accessor;
import android.view.BridgeInflater;
@@ -1398,6 +1399,14 @@
}
public void dispose() {
+ boolean createdLooper = false;
+ if (Looper.myLooper() == null) {
+ // Detaching the root view from the window will try to stop any running animations.
+ // The stop method checks that it can run in the looper so, if there is no current
+ // looper, we create a temporary one to complete the shutdown.
+ Bridge.prepareThread();
+ createdLooper = true;
+ }
AttachInfo_Accessor.detachFromWindow(mViewRoot);
if (mCanvas != null) {
mCanvas.release();
@@ -1412,5 +1421,9 @@
mImage = null;
mViewRoot = null;
mContentRoot = null;
+
+ if (createdLooper) {
+ Bridge.cleanupThread();
+ }
}
}
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index c72eeb1..494b3d2 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -33,7 +33,11 @@
import org.xmlpull.v1.XmlPullParserException;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.res.ColorStateList;
+import android.content.res.ComplexColor;
+import android.content.res.ComplexColor_Accessor;
+import android.content.res.GradientColor;
import android.content.res.Resources.Theme;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
@@ -47,6 +51,7 @@
import java.io.File;
import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
@@ -119,54 +124,128 @@
throw new NumberFormatException();
}
- public static ColorStateList getColorStateList(ResourceValue resValue, BridgeContext context) {
+ /**
+ * Returns a {@link ComplexColor} from the given {@link ResourceValue}
+ *
+ * @param resValue the value containing a color value or a file path to a complex color
+ * definition
+ * @param context the current context
+ * @param theme the theme to use when resolving the complex color
+ * @param allowGradients when false, only {@link ColorStateList} will be returned. If a {@link
+ * GradientColor} is found, null will be returned.
+ */
+ @Nullable
+ private static ComplexColor getInternalComplexColor(@NonNull ResourceValue resValue,
+ @NonNull BridgeContext context, @Nullable Theme theme, boolean allowGradients) {
String value = resValue.getValue();
- if (value != null && !RenderResources.REFERENCE_NULL.equals(value)) {
- // first check if the value is a file (xml most likely)
+ if (value == null || RenderResources.REFERENCE_NULL.equals(value)) {
+ return null;
+ }
+
+ // first check if the value is a file (xml most likely)
+ XmlPullParser parser = context.getLayoutlibCallback().getXmlFileParser(value);
+ if (parser == null) {
File f = new File(value);
if (f.isFile()) {
+ // let the framework inflate the color from the XML file, by
+ // providing an XmlPullParser
try {
- // let the framework inflate the ColorStateList from the XML file, by
- // providing an XmlPullParser
- XmlPullParser parser = ParserFactory.create(f);
-
- BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
- parser, context, resValue.isFramework());
- try {
- return ColorStateList.createFromXml(context.getResources(), blockParser);
- } finally {
- blockParser.ensurePopped();
- }
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value, e, null /*data*/);
- // we'll return null below.
- } catch (Exception e) {
- // this is an error and not warning since the file existence is
- // checked before attempting to parse it.
+ parser = ParserFactory.create(f);
+ } catch (XmlPullParserException | FileNotFoundException e) {
Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
"Failed to parse file " + value, e, null /*data*/);
-
- return null;
- }
- } else {
- // try to load the color state list from an int
- try {
- int color = ResourceHelper.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;
}
}
}
+ if (parser != null) {
+ try {
+ BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
+ parser, context, resValue.isFramework());
+ try {
+ // Advance the parser to the first element so we can detect if it's a
+ // color list or a gradient color
+ int type;
+ //noinspection StatementWithEmptyBody
+ while ((type = blockParser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Seek parser to start tag.
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ throw new XmlPullParserException("No start tag found");
+ }
+
+ final String name = blockParser.getName();
+ if (allowGradients && "gradient".equals(name)) {
+ return ComplexColor_Accessor.createGradientColorFromXmlInner(
+ context.getResources(),
+ blockParser, blockParser,
+ theme);
+ } else if ("selector".equals(name)) {
+ return ComplexColor_Accessor.createColorStateListFromXmlInner(
+ context.getResources(),
+ blockParser, blockParser,
+ theme);
+ }
+ } finally {
+ blockParser.ensurePopped();
+ }
+ } catch (XmlPullParserException e) {
+ Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+ "Failed to configure parser for " + value, e, null /*data*/);
+ // we'll return null below.
+ } catch (Exception e) {
+ // this is an error and not warning since the file existence is
+ // checked before attempting to parse it.
+ Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
+ "Failed to parse file " + value, e, null /*data*/);
+
+ 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;
}
/**
+ * Returns a {@link ColorStateList} from the given {@link ResourceValue}
+ *
+ * @param resValue the value containing a color value or a file path to a complex color
+ * definition
+ * @param context the current context
+ */
+ @Nullable
+ public static ColorStateList getColorStateList(@NonNull ResourceValue resValue,
+ @NonNull BridgeContext context) {
+ return (ColorStateList) getInternalComplexColor(resValue, context, context.getTheme(),
+ false);
+ }
+
+ /**
+ * Returns a {@link ComplexColor} from the given {@link ResourceValue}
+ *
+ * @param resValue the value containing a color value or a file path to a complex color
+ * definition
+ * @param context the current context
+ */
+ @Nullable
+ public static ComplexColor getComplexColor(@NonNull ResourceValue resValue,
+ @NonNull BridgeContext context) {
+ return getInternalComplexColor(resValue, context, context.getTheme(), true);
+ }
+
+ /**
* Returns a drawable from the given value.
* @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable,
* or an hexadecimal color
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java b/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
index 9aab340..c0ca1d5 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java
@@ -36,9 +36,9 @@
/**
* A Helper class to do fake data binding in {@link AdapterView} objects.
*/
-@SuppressWarnings("deprecation")
public class AdapterHelper {
+ @SuppressWarnings("deprecation")
static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent,
LayoutlibCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) {
// we don't care about recycling here because we never scroll.
@@ -114,7 +114,7 @@
if (value != null) {
if (value.getClass() != ViewAttribute.IS_CHECKED.getAttributeClass()) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
- "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s",
+ "Wrong Adapter Item value class for IS_CHECKED. Expected Boolean, got %s",
value.getClass().getName()), null);
} else {
cb.setChecked((Boolean) value);
@@ -134,7 +134,7 @@
if (value != null) {
if (value.getClass() != ViewAttribute.SRC.getAttributeClass()) {
Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
- "Wrong Adapter Item value class for TEXT. Expected Boolean, got %s",
+ "Wrong Adapter Item value class for SRC. Expected Boolean, got %s",
value.getClass().getName()), null);
} else {
// FIXME
diff --git a/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java b/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java
new file mode 100644
index 0000000..6246ec1
--- /dev/null
+++ b/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 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 libcore.util;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate implementing the native methods of {@link NativeAllocationRegistry}
+ *
+ * Through the layoutlib_create tool, the original native methods of NativeAllocationRegistry have
+ * been replaced by calls to methods of the same name in this delegate class.
+ *
+ * This class behaves like the original native implementation, but in Java, keeping previously
+ * native data into its own objects and mapping them to int that are sent back and forth between
+ * it and the original NativeAllocationRegistry class.
+ *
+ * @see DelegateManager
+ */
+public class NativeAllocationRegistry_Delegate {
+
+ // ---- delegate manager ----
+ private static final DelegateManager<NativeAllocationRegistry_Delegate> sManager =
+ new DelegateManager<>(NativeAllocationRegistry_Delegate.class);
+
+ private final FreeFunction mFinalizer;
+
+ private NativeAllocationRegistry_Delegate(FreeFunction finalizer) {
+ mFinalizer = finalizer;
+ }
+
+ /**
+ * The result of this method should be cached by the class and reused.
+ */
+ public static long createFinalizer(FreeFunction finalizer) {
+ return sManager.addNewDelegate(new NativeAllocationRegistry_Delegate(finalizer));
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void applyFreeFunction(long freeFunction, long nativePtr) {
+ NativeAllocationRegistry_Delegate delegate = sManager.getDelegate(freeFunction);
+ if (delegate != null) {
+ delegate.mFinalizer.free(nativePtr);
+ }
+ }
+
+ public interface FreeFunction {
+ void free(long nativePtr);
+ }
+}
diff --git a/bridge/tests/Android.mk b/bridge/tests/Android.mk
index 5eef24a..5c062d0 100644
--- a/bridge/tests/Android.mk
+++ b/bridge/tests/Android.mk
@@ -16,10 +16,11 @@
include $(CLEAR_VARS)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+
# Only compile source java files in this lib.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_JAVA_RESOURCE_DIRS := res
-LOCAL_JAVACFLAGS := -source 6 -target 6
LOCAL_MODULE := layoutlib-tests
LOCAL_MODULE_TAGS := optional
diff --git a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
index 72b87ab..47cb042 100644
--- a/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
+++ b/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/src/main/res/color/gradient.xml b/bridge/tests/res/testApp/MyApplication/src/main/res/color/gradient.xml
new file mode 100644
index 0000000..fc0afa6
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/src/main/res/color/gradient.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2016 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.
+ -->
+
+
+<gradient xmlns:android="http://schemas.android.com/apk/res/android"
+ android:startX="10"
+ android:startY="10"
+ android:endX="50"
+ android:endY="50"
+ android:startColor="#ffff0000"
+ android:endColor="#ff00ff00" />
diff --git a/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml b/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
index ffc70dc..5c19b08 100644
--- a/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
+++ b/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
@@ -53,6 +53,16 @@
android:trimPathStart="0.2"
android:trimPathEnd="0.8"
/>
+
+ <!--
+ Draw a line with gradient stroke color
+ -->
+ <path
+ android:strokeWidth="1"
+ android:strokeColor="#FF00FF"
+ android:fillColor="@color/gradient"
+ android:pathData="M-20,-20 l0, 10 l10, 0 l0, -10 l-10,0 "
+ />
</group>
</vector>
\ No newline at end of file
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java b/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java
index 16911bd..8f9fa8a 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/intensive/ImageUtils.java
@@ -75,8 +75,12 @@
}
}
else {
- BufferedImage goldenImage = ImageIO.read(is);
- assertImageSimilar(relativePath, goldenImage, thumbnail, MAX_PERCENT_DIFFERENCE);
+ try {
+ BufferedImage goldenImage = ImageIO.read(is);
+ assertImageSimilar(relativePath, goldenImage, thumbnail, MAX_PERCENT_DIFFERENCE);
+ } finally {
+ is.close();
+ }
}
}
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 6b23da7..2726042 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -335,7 +335,7 @@
.setNavigation(Navigation.NONAV);
SessionParams params = getSessionParams(parser, customConfigGenerator,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+ layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false,
RenderingMode.V_SCROLL, 22);
renderAndVerify(params, "expand_vert_layout.png");
@@ -348,7 +348,7 @@
parser = new LayoutPullParser(APP_TEST_RES + "/layout/" +
"expand_horz_layout.xml");
params = getSessionParams(parser, customConfigGenerator,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
+ layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false,
RenderingMode.H_SCROLL, 22);
renderAndVerify(params, "expand_horz_layout.png");
diff --git a/create/Android.mk b/create/Android.mk
index e6f0bc3..47377ae 100644
--- a/create/Android.mk
+++ b/create/Android.mk
@@ -16,11 +16,13 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+
LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_JAR_MANIFEST := manifest.txt
LOCAL_STATIC_JAVA_LIBRARIES := \
- asm-4.0
+ asm-5.0
LOCAL_MODULE := layoutlib_create
diff --git a/create/create.iml b/create/create.iml
index 9b18e73..368b46b 100644
--- a/create/create.iml
+++ b/create/create.iml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
@@ -9,12 +9,12 @@
<sourceFolder url="file://$MODULE_DIR$/tests/mock_data" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/.settings" />
</content>
- <orderEntry type="inheritedJdk" />
+ <orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module-library">
- <library name="asm-4.0">
+ <library name="asm-5.0">
<CLASSES>
- <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/asm/asm-4.0.jar!/" />
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/asm/asm-5.0.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
@@ -22,6 +22,6 @@
</SOURCES>
</library>
</orderEntry>
- <orderEntry type="library" scope="TEST" name="JUnit4" level="application" />
+ <orderEntry type="library" scope="TEST" name="junit" level="project" />
</component>
</module>
\ No newline at end of file
diff --git a/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java b/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
index a6902a4..01c940a 100644
--- a/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java
@@ -21,7 +21,6 @@
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;
@@ -44,7 +43,7 @@
abstract String renameInternalType(String name);
public AbstractClassAdapter(ClassVisitor cv) {
- super(Opcodes.ASM4, cv);
+ super(Main.ASM_VERSION, cv);
}
/**
@@ -177,17 +176,6 @@
}
}
- /* Java 7 verifies the StackMapTable of a class if its version number is greater than 50.0.
- * However, the check is disabled if the class version number is 50.0 or less. Generation
- * of the StackMapTable requires a rewrite using the tree API of ASM. As a workaround,
- * we rewrite the version number of the class to be 50.0
- *
- * http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6693236
- */
- if (version > 50) {
- version = 50;
- }
-
super.visit(version, access, name, signature, superName, interfaces);
}
@@ -239,7 +227,7 @@
* The names must be full qualified internal ASM names (e.g. com/blah/MyClass$InnerClass).
*/
public RenameMethodAdapter(MethodVisitor mv) {
- super(Opcodes.ASM4, mv);
+ super(Main.ASM_VERSION, mv);
}
@Override
@@ -276,7 +264,8 @@
}
@Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ public void visitMethodInsn(int opcode, String owner, String name, String desc,
+ boolean itf) {
// The owner sometimes turns out to be a type descriptor. We try to detect it and fix.
if (owner.indexOf(';') > 0) {
owner = renameTypeDesc(owner);
@@ -285,7 +274,7 @@
}
desc = renameMethodDesc(desc);
- super.visitMethodInsn(opcode, owner, name, desc);
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
}
@Override
@@ -330,7 +319,7 @@
private final SignatureVisitor mSv;
public RenameSignatureAdapter(SignatureVisitor sv) {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
mSv = sv;
}
diff --git a/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java b/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
index c8b2b84..48544ca 100644
--- a/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
+++ b/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
@@ -23,7 +23,6 @@
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;
@@ -65,7 +64,7 @@
/** Glob patterns of files to keep as is. */
private final String[] mIncludeFileGlobs;
/** Internal names of classes that contain method calls that need to be rewritten. */
- private final Set<String> mReplaceMethodCallClasses = new HashSet<String>();
+ private final Set<String> mReplaceMethodCallClasses = new HashSet<>();
/**
* Creates a new analyzer.
@@ -97,8 +96,8 @@
*/
public void analyze() throws IOException, LogAbortException {
- TreeMap<String, ClassReader> zipClasses = new TreeMap<String, ClassReader>();
- Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
+ TreeMap<String, ClassReader> zipClasses = new TreeMap<>();
+ Map<String, InputStream> filesFound = new TreeMap<>();
parseZip(mOsSourceJar, zipClasses, filesFound);
mLog.info("Found %d classes in input JAR%s.", zipClasses.size(),
@@ -189,7 +188,7 @@
*/
Map<String, ClassReader> findIncludes(Map<String, ClassReader> zipClasses)
throws LogAbortException {
- TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>();
+ TreeMap<String, ClassReader> found = new TreeMap<>();
mLog.debug("Find classes to include.");
@@ -318,10 +317,10 @@
Map<String, ClassReader> findDeps(Map<String, ClassReader> zipClasses,
Map<String, ClassReader> inOutKeepClasses) {
- TreeMap<String, ClassReader> deps = new TreeMap<String, ClassReader>();
- TreeMap<String, ClassReader> new_deps = new TreeMap<String, ClassReader>();
- TreeMap<String, ClassReader> new_keep = new TreeMap<String, ClassReader>();
- TreeMap<String, ClassReader> temp = new TreeMap<String, ClassReader>();
+ TreeMap<String, ClassReader> deps = new TreeMap<>();
+ TreeMap<String, ClassReader> new_deps = new TreeMap<>();
+ TreeMap<String, ClassReader> new_keep = new TreeMap<>();
+ TreeMap<String, ClassReader> temp = new TreeMap<>();
DependencyVisitor visitor = getVisitor(zipClasses,
inOutKeepClasses, new_keep,
@@ -399,7 +398,7 @@
Map<String, ClassReader> outKeep,
Map<String,ClassReader> inDeps,
Map<String,ClassReader> outDeps) {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
mZipClasses = zipClasses;
mInKeep = inKeep;
mOutKeep = outKeep;
@@ -557,7 +556,7 @@
private class MyFieldVisitor extends FieldVisitor {
public MyFieldVisitor() {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
}
@Override
@@ -630,7 +629,7 @@
private String mOwnerClass;
public MyMethodVisitor(String ownerClass) {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
mOwnerClass = ownerClass;
}
@@ -719,7 +718,8 @@
// instruction that invokes a method
@Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ public void visitMethodInsn(int opcode, String owner, String name, String desc,
+ boolean itf) {
// owner is the internal name of the method's owner class
considerName(owner);
@@ -779,7 +779,7 @@
private class MySignatureVisitor extends SignatureVisitor {
public MySignatureVisitor() {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
}
// ---------------------------------------------------
@@ -878,7 +878,7 @@
private class MyAnnotationVisitor extends AnnotationVisitor {
public MyAnnotationVisitor() {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
}
// Visits a primitive value of an annotation
diff --git a/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index 414b255..3b37612 100644
--- a/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -91,7 +91,7 @@
mLog = log;
mOsDestJar = osDestJar;
ArrayList<Class<?>> injectedClasses =
- new ArrayList<Class<?>>(Arrays.asList(createInfo.getInjectedClasses()));
+ new ArrayList<>(Arrays.asList(createInfo.getInjectedClasses()));
// Search for and add anonymous inner classes also.
ListIterator<Class<?>> iter = injectedClasses.listIterator();
while (iter.hasNext()) {
@@ -107,25 +107,25 @@
}
}
mInjectClasses = injectedClasses.toArray(new Class<?>[0]);
- mStubMethods = new HashSet<String>(Arrays.asList(createInfo.getOverriddenMethods()));
+ mStubMethods = new HashSet<>(Arrays.asList(createInfo.getOverriddenMethods()));
// Create the map/set of methods to change to delegates
- mDelegateMethods = new HashMap<String, Set<String>>();
+ mDelegateMethods = new HashMap<>();
addToMap(createInfo.getDelegateMethods(), mDelegateMethods);
for (String className : createInfo.getDelegateClassNatives()) {
className = binaryToInternalClassName(className);
Set<String> methods = mDelegateMethods.get(className);
if (methods == null) {
- methods = new HashSet<String>();
+ methods = new HashSet<>();
mDelegateMethods.put(className, methods);
}
methods.add(DelegateClassAdapter.ALL_NATIVES);
}
// Create the map of classes to rename.
- mRenameClasses = new HashMap<String, String>();
- mClassesNotRenamed = new HashSet<String>();
+ mRenameClasses = new HashMap<>();
+ mClassesNotRenamed = new HashSet<>();
String[] renameClasses = createInfo.getRenamedClasses();
int n = renameClasses.length;
for (int i = 0; i < n; i += 2) {
@@ -138,7 +138,7 @@
}
// Create a map of classes to be refactored.
- mRefactorClasses = new HashMap<String, String>();
+ mRefactorClasses = new HashMap<>();
String[] refactorClasses = createInfo.getJavaPkgClasses();
n = refactorClasses.length;
for (int i = 0; i < n; i += 2) {
@@ -149,7 +149,7 @@
}
// create the map of renamed class -> return type of method to delete.
- mDeleteReturns = new HashMap<String, Set<String>>();
+ mDeleteReturns = new HashMap<>();
String[] deleteReturns = createInfo.getDeleteReturns();
Set<String> returnTypes = null;
String renamedClass = null;
@@ -172,12 +172,12 @@
// just a standard return type, we add it to the list.
if (returnTypes == null) {
- returnTypes = new HashSet<String>();
+ returnTypes = new HashSet<>();
}
returnTypes.add(binaryToInternalClassName(className));
}
- mPromotedFields = new HashMap<String, Set<String>>();
+ mPromotedFields = new HashMap<>();
addToMap(createInfo.getPromotedFields(), mPromotedFields);
mInjectedMethodsMap = createInfo.getInjectedMethodsMap();
@@ -197,7 +197,7 @@
String methodOrFieldName = entry.substring(pos + 1);
Set<String> set = map.get(className);
if (set == null) {
- set = new HashSet<String>();
+ set = new HashSet<>();
map.put(className, set);
}
set.add(methodOrFieldName);
@@ -247,7 +247,7 @@
/** Generates the final JAR */
public void generate() throws IOException {
- TreeMap<String, byte[]> all = new TreeMap<String, byte[]>();
+ TreeMap<String, byte[]> all = new TreeMap<>();
for (Class<?> clazz : mInjectClasses) {
String name = classToEntryPath(clazz);
@@ -314,7 +314,7 @@
* e.g. for the input "android.view.View" it returns "android/view/View.class"
*/
String classNameToEntryPath(String className) {
- return className.replaceAll("\\.", "/").concat(".class");
+ return className.replace('.', '/').concat(".class");
}
/**
diff --git a/create/src/com/android/tools/layoutlib/create/ClassHasNativeVisitor.java b/create/src/com/android/tools/layoutlib/create/ClassHasNativeVisitor.java
index 2c955fd..4748a7c 100644
--- a/create/src/com/android/tools/layoutlib/create/ClassHasNativeVisitor.java
+++ b/create/src/com/android/tools/layoutlib/create/ClassHasNativeVisitor.java
@@ -31,7 +31,7 @@
*/
public class ClassHasNativeVisitor extends ClassVisitor {
public ClassHasNativeVisitor() {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
}
private boolean mHasNativeMethods = false;
diff --git a/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index e17f1f8..bd37665 100644
--- a/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -111,7 +111,7 @@
public Set<String> getExcludedClasses() {
String[] refactoredClasses = getJavaPkgClasses();
int count = refactoredClasses.length / 2 + EXCLUDED_CLASSES.length;
- Set<String> excludedClasses = new HashSet<String>(count);
+ Set<String> excludedClasses = new HashSet<>(count);
for (int i = 0; i < refactoredClasses.length; i+=2) {
excludedClasses.add(refactoredClasses[i]);
}
@@ -144,11 +144,8 @@
InjectMethodRunnable.class,
InjectMethodRunnables.class,
/* Java package classes */
- AutoCloseable.class,
- Objects.class,
IntegralToString.class,
UnsafeByteSequence.class,
- Charsets.class,
System_Delegate.class,
LinkedHashMap_Delegate.class,
};
@@ -192,8 +189,10 @@
"android.content.res.TypedArray#obtain",
"android.graphics.BitmapFactory#finishDecode",
"android.graphics.BitmapFactory#setDensityFromOptions",
+ "android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#useLastSeenTarget",
"android.graphics.drawable.GradientDrawable#buildRing",
"android.graphics.Typeface#getSystemFontConfigLocation",
+ "android.graphics.Typeface#makeFamilyFromParsed",
"android.os.Handler#sendMessageAtTime",
"android.os.HandlerThread#run",
"android.preference.Preference#getView",
@@ -205,15 +204,16 @@
"android.view.Choreographer#scheduleVsyncLocked",
"android.view.Display#updateDisplayInfoLocked",
"android.view.Display#getWindowManager",
+ "android.view.HandlerActionQueue#postDelayed",
"android.view.LayoutInflater#rInflate",
"android.view.LayoutInflater#parseInclude",
"android.view.View#getWindowToken",
"android.view.View#isInEditMode",
"android.view.ViewRootImpl#isInTouchMode",
- "android.view.ViewRootImpl$RunQueue#postDelayed",
"android.view.WindowManagerGlobal#getWindowManagerService",
"android.view.inputmethod.InputMethodManager#getInstance",
"android.view.MenuInflater#registerMenu",
+ "android.view.RenderNode#getMatrix",
"android.view.RenderNode#nCreate",
"android.view.RenderNode#nDestroyRenderNode",
"android.view.RenderNode#nSetElevation",
@@ -226,7 +226,6 @@
"android.view.RenderNode#nGetTranslationZ",
"android.view.RenderNode#nSetRotation",
"android.view.RenderNode#nGetRotation",
- "android.view.RenderNode#getMatrix",
"android.view.RenderNode#nSetLeft",
"android.view.RenderNode#nSetTop",
"android.view.RenderNode#nSetRight",
@@ -242,7 +241,6 @@
"android.view.RenderNode#nGetScaleY",
"android.view.RenderNode#nIsPivotExplicitlySet",
"android.view.ViewGroup#drawChild",
- "android.widget.TimePickerClockDelegate#getAmOrPmKeyCode",
"com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
"com.android.internal.util.XmlUtils#convertValueToInt",
"com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
@@ -250,7 +248,7 @@
"libcore.io.MemoryMappedFile#mmapRO",
"libcore.io.MemoryMappedFile#close",
"libcore.io.MemoryMappedFile#bigEndianIterator",
- "libcore.util.ZoneInfo$WallTime#createGregorianCalendar",
+ "libcore.util.NativeAllocationRegistry#applyFreeFunction",
};
/**
@@ -297,11 +295,15 @@
"android.graphics.SweepGradient",
"android.graphics.Typeface",
"android.graphics.Xfermode",
+ "android.graphics.drawable.AnimatedVectorDrawable",
+ "android.graphics.drawable.VectorDrawable",
"android.os.SystemClock",
"android.os.SystemProperties",
"android.text.AndroidBidi",
"android.text.StaticLayout",
+ "android.util.PathParser",
"android.view.Display",
+ "com.android.internal.view.animation.NativeInterpolatorFactoryHelper",
"libcore.icu.ICU",
};
@@ -333,12 +335,9 @@
*/
private final static String[] JAVA_PKG_CLASSES =
new String[] {
- "java.lang.AutoCloseable", "com.android.tools.layoutlib.java.AutoCloseable",
- "java.util.Objects", "com.android.tools.layoutlib.java.Objects",
- "java.nio.charset.Charsets", "com.android.tools.layoutlib.java.Charsets",
+ "java.nio.charset.Charsets", "java.nio.charset.StandardCharsets",
"java.lang.IntegralToString", "com.android.tools.layoutlib.java.IntegralToString",
"java.lang.UnsafeByteSequence", "com.android.tools.layoutlib.java.UnsafeByteSequence",
- "java.nio.charset.StandardCharsets", "com.android.tools.layoutlib.java.Charsets",
// Use android.icu.text versions of DateFormat and SimpleDateFormat since the
// original ones do not match the Android implementation
"java.text.DateFormat", "android.icu.text.DateFormat",
@@ -351,11 +350,13 @@
"org.kxml2.io.KXmlParser"
};
+ /**
+ * List of fields for which we will update the visibility to be public. This is sometimes
+ * needed when access from the delegate classes is needed.
+ */
private final static String[] PROMOTED_FIELDS = new String[] {
- "android.view.Choreographer#mLastFrameTimeNanos",
- "android.widget.SimpleMonthView#mTitle",
- "android.widget.SimpleMonthView#mCalendar",
- "android.widget.SimpleMonthView#mDayOfWeekLabelCalendar"
+ "android.graphics.drawable.VectorDrawable#mVectorState",
+ "android.view.Choreographer#mLastFrameTimeNanos"
};
/**
diff --git a/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java b/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
index 7ef7566..cbb3a8a 100644
--- a/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java
@@ -60,7 +60,7 @@
ClassVisitor cv,
String className,
Set<String> delegateMethods) {
- super(Opcodes.ASM4, cv);
+ super(Main.ASM_VERSION, cv);
mLog = log;
mClassName = className;
mDelegateMethods = delegateMethods;
diff --git a/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java b/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java
index cca9e57..da8babc 100644
--- a/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java
@@ -124,7 +124,7 @@
String desc,
boolean isStatic,
boolean isStaticClass) {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
mLog = log;
mOrgWriter = mvOriginal;
mDelWriter = mvDelegate;
@@ -188,7 +188,7 @@
mDelWriter.visitLineNumber((Integer) p[0], (Label) p[1]);
}
- ArrayList<Type> paramTypes = new ArrayList<Type>();
+ ArrayList<Type> paramTypes = new ArrayList<>();
String delegateClassName = mClassName + DELEGATE_SUFFIX;
boolean pushedArg0 = false;
int maxStack = 0;
@@ -253,7 +253,8 @@
mDelWriter.visitMethodInsn(Opcodes.INVOKESTATIC,
delegateClassName,
mMethodName,
- desc);
+ desc,
+ false);
Type returnType = Type.getReturnType(mDesc);
mDelWriter.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
@@ -371,9 +372,9 @@
}
@Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (mOrgWriter != null) {
- mOrgWriter.visitMethodInsn(opcode, owner, name, desc);
+ mOrgWriter.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
diff --git a/create/src/com/android/tools/layoutlib/create/DependencyFinder.java b/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
index 61b64a2..aa68ea0 100644
--- a/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
+++ b/create/src/com/android/tools/layoutlib/create/DependencyFinder.java
@@ -26,7 +26,6 @@
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;
@@ -82,7 +81,7 @@
Map<String, Set<String>> missing = findMissingClasses(deps, zipClasses.keySet());
- List<Map<String, Set<String>>> result = new ArrayList<Map<String,Set<String>>>(2);
+ List<Map<String, Set<String>>> result = new ArrayList<>(2);
result.add(deps);
result.add(missing);
return result;
@@ -151,7 +150,7 @@
* class name => ASM ClassReader. Class names are in the form "android.view.View".
*/
Map<String,ClassReader> parseZip(List<String> jarPathList) throws IOException {
- TreeMap<String, ClassReader> classes = new TreeMap<String, ClassReader>();
+ TreeMap<String, ClassReader> classes = new TreeMap<>();
for (String jarPath : jarPathList) {
ZipFile zip = new ZipFile(jarPath);
@@ -202,7 +201,7 @@
// The dependencies that we'll collect.
// It's a map Class name => uses class names.
- Map<String, Set<String>> dependencyMap = new TreeMap<String, Set<String>>();
+ Map<String, Set<String>> dependencyMap = new TreeMap<>();
DependencyVisitor visitor = getVisitor();
@@ -211,7 +210,7 @@
for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
String name = entry.getKey();
- TreeSet<String> set = new TreeSet<String>();
+ TreeSet<String> set = new TreeSet<>();
dependencyMap.put(name, set);
visitor.setDependencySet(set);
@@ -240,7 +239,7 @@
private Map<String, Set<String>> findMissingClasses(
Map<String, Set<String>> deps,
Set<String> zipClasses) {
- Map<String, Set<String>> missing = new TreeMap<String, Set<String>>();
+ Map<String, Set<String>> missing = new TreeMap<>();
for (Entry<String, Set<String>> entry : deps.entrySet()) {
String name = entry.getKey();
@@ -250,7 +249,7 @@
// This dependency doesn't exist in the zip classes.
Set<String> set = missing.get(dep);
if (set == null) {
- set = new TreeSet<String>();
+ set = new TreeSet<>();
missing.put(dep, set);
}
set.add(name);
@@ -284,7 +283,7 @@
* Creates a new visitor that will find all the dependencies for the visited class.
*/
public DependencyVisitor() {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
}
/**
@@ -435,7 +434,7 @@
private class MyFieldVisitor extends FieldVisitor {
public MyFieldVisitor() {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
}
@Override
@@ -510,7 +509,7 @@
private class MyMethodVisitor extends MethodVisitor {
public MyMethodVisitor() {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
}
@@ -598,7 +597,8 @@
// instruction that invokes a method
@Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ public void visitMethodInsn(int opcode, String owner, String name, String desc,
+ boolean itf) {
// owner is the internal name of the method's owner class
if (!considerDesc(owner) && owner.indexOf('/') != -1) {
@@ -654,7 +654,7 @@
private class MySignatureVisitor extends SignatureVisitor {
public MySignatureVisitor() {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
}
// ---------------------------------------------------
@@ -753,7 +753,7 @@
private class MyAnnotationVisitor extends AnnotationVisitor {
public MyAnnotationVisitor() {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
}
// Visits a primitive value of an annotation
diff --git a/create/src/com/android/tools/layoutlib/create/InjectMethodRunnables.java b/create/src/com/android/tools/layoutlib/create/InjectMethodRunnables.java
index 37fc096..1941ab4 100644
--- a/create/src/com/android/tools/layoutlib/create/InjectMethodRunnables.java
+++ b/create/src/com/android/tools/layoutlib/create/InjectMethodRunnables.java
@@ -42,9 +42,9 @@
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass",
- "()Ljava/lang/Class;");
+ "()Ljava/lang/Class;", false);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getClassLoader",
- "()Ljava/lang/ClassLoader;");
+ "()Ljava/lang/ClassLoader;", false);
mv.visitInsn(ARETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
diff --git a/create/src/com/android/tools/layoutlib/create/InjectMethodsAdapter.java b/create/src/com/android/tools/layoutlib/create/InjectMethodsAdapter.java
index ea2b9c9..c834808 100644
--- a/create/src/com/android/tools/layoutlib/create/InjectMethodsAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/InjectMethodsAdapter.java
@@ -19,7 +19,6 @@
import com.android.tools.layoutlib.create.ICreateInfo.InjectMethodRunnable;
import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.Opcodes;
/**
* Injects methods into some classes.
@@ -29,7 +28,7 @@
private final ICreateInfo.InjectMethodRunnable mRunnable;
public InjectMethodsAdapter(ClassVisitor cv, InjectMethodRunnable runnable) {
- super(Opcodes.ASM4, cv);
+ super(Main.ASM_VERSION, cv);
mRunnable = runnable;
}
diff --git a/create/src/com/android/tools/layoutlib/create/Main.java b/create/src/com/android/tools/layoutlib/create/Main.java
index 383168f..9bb91e5 100644
--- a/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/create/src/com/android/tools/layoutlib/create/Main.java
@@ -16,6 +16,8 @@
package com.android.tools.layoutlib.create;
+import org.objectweb.asm.Opcodes;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -52,13 +54,15 @@
public boolean listOnlyMissingDeps = false;
}
+ public static final int ASM_VERSION = Opcodes.ASM5;
+
public static final Options sOptions = new Options();
public static void main(String[] args) {
Log log = new Log();
- ArrayList<String> osJarPath = new ArrayList<String>();
+ ArrayList<String> osJarPath = new ArrayList<>();
String[] osDestJar = { null };
if (!processArgs(log, args, osJarPath, osDestJar)) {
diff --git a/create/src/com/android/tools/layoutlib/create/MethodListener.java b/create/src/com/android/tools/layoutlib/create/MethodListener.java
index 6fc2b24..faba4d7 100644
--- a/create/src/com/android/tools/layoutlib/create/MethodListener.java
+++ b/create/src/com/android/tools/layoutlib/create/MethodListener.java
@@ -36,41 +36,40 @@
* @param isNative True if the method was a native method.
* @param caller The calling object. Null for static methods, "this" for instance methods.
*/
- public void onInvokeV(String signature, boolean isNative, Object caller);
+ void onInvokeV(String signature, boolean isNative, Object caller);
/**
* Same as {@link #onInvokeV(String, boolean, Object)} but returns an integer or similar.
* @see #onInvokeV(String, boolean, Object)
* @return an integer, or a boolean, or a short or a byte.
*/
- public int onInvokeI(String signature, boolean isNative, Object caller);
+ int onInvokeI(String signature, boolean isNative, Object caller);
/**
* Same as {@link #onInvokeV(String, boolean, Object)} but returns a long.
* @see #onInvokeV(String, boolean, Object)
* @return a long.
*/
- public long onInvokeL(String signature, boolean isNative, Object caller);
+ long onInvokeL(String signature, boolean isNative, Object caller);
/**
* Same as {@link #onInvokeV(String, boolean, Object)} but returns a float.
* @see #onInvokeV(String, boolean, Object)
* @return a float.
*/
- public float onInvokeF(String signature, boolean isNative, Object caller);
+ float onInvokeF(String signature, boolean isNative, Object caller);
/**
* Same as {@link #onInvokeV(String, boolean, Object)} but returns a double.
* @see #onInvokeV(String, boolean, Object)
* @return a double.
*/
- public double onInvokeD(String signature, boolean isNative, Object caller);
+ double onInvokeD(String signature, boolean isNative, Object caller);
/**
* Same as {@link #onInvokeV(String, boolean, Object)} but returns an object.
* @see #onInvokeV(String, boolean, Object)
* @return an object.
*/
- public Object onInvokeA(String signature, boolean isNative, Object caller);
+ Object onInvokeA(String signature, boolean isNative, Object caller);
}
-
diff --git a/create/src/com/android/tools/layoutlib/create/OverrideMethod.java b/create/src/com/android/tools/layoutlib/create/OverrideMethod.java
index 4c87b3c..7ccafc3 100644
--- a/create/src/com/android/tools/layoutlib/create/OverrideMethod.java
+++ b/create/src/com/android/tools/layoutlib/create/OverrideMethod.java
@@ -28,7 +28,7 @@
public final class OverrideMethod {
/** Map of method overridden. */
- private static HashMap<String, MethodListener> sMethods = new HashMap<String, MethodListener>();
+ private static HashMap<String, MethodListener> sMethods = new HashMap<>();
/** Default listener for all method not listed in sMethods. Nothing if null. */
private static MethodListener sDefaultListener = null;
diff --git a/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java b/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java
index e4b70da..05af033 100644
--- a/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java
@@ -24,7 +24,6 @@
import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
-import static org.objectweb.asm.Opcodes.ASM4;
/**
* Promotes given fields to public visibility.
@@ -35,7 +34,7 @@
private static final int ACC_NOT_PUBLIC = ~(ACC_PRIVATE | ACC_PROTECTED);
public PromoteFieldClassAdapter(ClassVisitor cv, Set<String> fieldNames) {
- super(ASM4, cv);
+ super(Main.ASM_VERSION, cv);
mFieldNames = fieldNames;
}
diff --git a/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java b/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
index 91161f5..024e32f 100644
--- a/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java
@@ -16,9 +16,11 @@
package com.android.tools.layoutlib.create;
+import java.util.Arrays;
import java.util.HashMap;
import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
public class RefactorClassAdapter extends AbstractClassAdapter {
@@ -30,6 +32,14 @@
}
@Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions) {
+ MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
+
+ return new RefactorStackMapAdapter(mw);
+ }
+
+ @Override
protected String renameInternalType(String oldClassName) {
if (oldClassName != null) {
String newName = mRefactorClasses.get(oldClassName);
@@ -46,4 +56,49 @@
}
return oldClassName;
}
+
+ /**
+ * A method visitor that renames all references from an old class name to a new class name in
+ * the stackmap of the method.
+ */
+ private class RefactorStackMapAdapter extends MethodVisitor {
+
+ private RefactorStackMapAdapter(MethodVisitor mv) {
+ super(Main.ASM_VERSION, mv);
+ }
+
+
+ private Object[] renameFrame(Object[] elements) {
+ if (elements == null) {
+ return null;
+ }
+
+ // The input array cannot be modified. We only copy the source array on write
+ boolean copied = false;
+ for (int i = 0; i < elements.length; i++) {
+ if (!(elements[i] instanceof String)) {
+ continue;
+ }
+
+ if (!copied) {
+ elements = Arrays.copyOf(elements, elements.length);
+ copied = true;
+ }
+
+ String type = (String)elements[i];
+ if (type.indexOf(';') > 0) {
+ elements[i] = renameTypeDesc(type);
+ } else {
+ elements[i] = renameInternalType(type);
+ }
+ }
+
+ return elements;
+ }
+
+ @Override
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
+ super.visitFrame(type, nLocal, renameFrame(local), nStack, renameFrame(stack));
+ }
+ }
}
diff --git a/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java b/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
index 5e47261..bf94415 100644
--- a/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
@@ -43,11 +43,11 @@
* Descriptors for specialized versions {@link System#arraycopy} that are not present on the
* Desktop VM.
*/
- private static Set<String> ARRAYCOPY_DESCRIPTORS = new HashSet<String>(Arrays.asList(
+ private static Set<String> ARRAYCOPY_DESCRIPTORS = new HashSet<>(Arrays.asList(
"([CI[CII)V", "([BI[BII)V", "([SI[SII)V", "([II[III)V",
"([JI[JII)V", "([FI[FII)V", "([DI[DII)V", "([ZI[ZII)V"));
- private static final List<MethodReplacer> METHOD_REPLACERS = new ArrayList<MethodReplacer>(5);
+ private static final List<MethodReplacer> METHOD_REPLACERS = new ArrayList<>(5);
private static final String ANDROID_LOCALE_CLASS =
"com/android/layoutlib/bridge/android/AndroidLocale";
@@ -232,7 +232,7 @@
private final String mOriginalClassName;
public ReplaceMethodCallsAdapter(ClassVisitor cv, String originalClassName) {
- super(Opcodes.ASM4, cv);
+ super(Main.ASM_VERSION, cv);
mOriginalClassName = originalClassName;
}
@@ -245,11 +245,12 @@
private class MyMethodVisitor extends MethodVisitor {
public MyMethodVisitor(MethodVisitor mv) {
- super(Opcodes.ASM4, mv);
+ super(Main.ASM_VERSION, mv);
}
@Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ public void visitMethodInsn(int opcode, String owner, String name, String desc,
+ boolean itf) {
for (MethodReplacer replacer : METHOD_REPLACERS) {
if (replacer.isNeeded(owner, name, desc, mOriginalClassName)) {
MethodInformation mi = new MethodInformation(opcode, owner, name, desc);
@@ -261,7 +262,7 @@
break;
}
}
- super.visitMethodInsn(opcode, owner, name, desc);
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
diff --git a/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java b/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
index 416b73a..4ba7237 100644
--- a/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java
@@ -50,7 +50,7 @@
public StubMethodAdapter(MethodVisitor mv, String methodName, Type returnType,
String invokeSignature, boolean isStatic, boolean isNative) {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
mParentVisitor = mv;
mReturnType = returnType;
mInvokeSignature = invokeSignature;
@@ -82,7 +82,8 @@
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeV",
- "(Ljava/lang/String;ZLjava/lang/Object;)V");
+ "(Ljava/lang/String;ZLjava/lang/Object;)V",
+ false);
mParentVisitor.visitInsn(Opcodes.RETURN);
break;
case Type.BOOLEAN:
@@ -93,7 +94,8 @@
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeI",
- "(Ljava/lang/String;ZLjava/lang/Object;)I");
+ "(Ljava/lang/String;ZLjava/lang/Object;)I",
+ false);
switch(sort) {
case Type.BOOLEAN:
Label l1 = new Label();
@@ -101,6 +103,7 @@
mParentVisitor.visitInsn(Opcodes.ICONST_1);
mParentVisitor.visitInsn(Opcodes.IRETURN);
mParentVisitor.visitLabel(l1);
+ mParentVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mParentVisitor.visitInsn(Opcodes.ICONST_0);
break;
case Type.CHAR:
@@ -119,21 +122,24 @@
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeL",
- "(Ljava/lang/String;ZLjava/lang/Object;)J");
+ "(Ljava/lang/String;ZLjava/lang/Object;)J",
+ false);
mParentVisitor.visitInsn(Opcodes.LRETURN);
break;
case Type.FLOAT:
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeF",
- "(Ljava/lang/String;ZLjava/lang/Object;)F");
+ "(Ljava/lang/String;ZLjava/lang/Object;)F",
+ false);
mParentVisitor.visitInsn(Opcodes.FRETURN);
break;
case Type.DOUBLE:
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeD",
- "(Ljava/lang/String;ZLjava/lang/Object;)D");
+ "(Ljava/lang/String;ZLjava/lang/Object;)D",
+ false);
mParentVisitor.visitInsn(Opcodes.DRETURN);
break;
case Type.ARRAY:
@@ -141,7 +147,8 @@
mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
"com/android/tools/layoutlib/create/OverrideMethod",
"invokeA",
- "(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;");
+ "(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;",
+ false);
mParentVisitor.visitTypeInsn(Opcodes.CHECKCAST, mReturnType.getInternalName());
mParentVisitor.visitInsn(Opcodes.ARETURN);
break;
@@ -282,9 +289,9 @@
}
@Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (mIsInitMethod) {
- mParentVisitor.visitMethodInsn(opcode, owner, name, desc);
+ mParentVisitor.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
diff --git a/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java b/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
index d9ecf98..a28ae69 100644
--- a/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
+++ b/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java
@@ -49,7 +49,7 @@
public TransformClassAdapter(Log logger, Set<String> stubMethods,
Set<String> deleteReturns, String className, ClassVisitor cv,
boolean stubNativesOnly) {
- super(Opcodes.ASM4, cv);
+ super(Main.ASM_VERSION, cv);
mLog = logger;
mStubMethods = stubMethods;
mClassName = className;
diff --git a/create/src/com/android/tools/layoutlib/java/AutoCloseable.java b/create/src/com/android/tools/layoutlib/java/AutoCloseable.java
index ed2c128..7d6c4ec 100644
--- a/create/src/com/android/tools/layoutlib/java/AutoCloseable.java
+++ b/create/src/com/android/tools/layoutlib/java/AutoCloseable.java
@@ -28,4 +28,5 @@
/**
* Closes the object and release any system resources it holds.
*/
- void close() throws Exception; }
+ void close() throws Exception;
+}
diff --git a/create/tests/Android.mk b/create/tests/Android.mk
index c197d57..c59528e 100644
--- a/create/tests/Android.mk
+++ b/create/tests/Android.mk
@@ -15,6 +15,8 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+
# Only compile source java files in this lib.
LOCAL_SRC_FILES := $(call all-java-files-under, com)
@@ -24,7 +26,7 @@
LOCAL_MODULE_TAGS := optional
LOCAL_JAVA_LIBRARIES := layoutlib_create junit
-LOCAL_STATIC_JAVA_LIBRARIES := asm-4.0
+LOCAL_STATIC_JAVA_LIBRARIES := asm-5.0
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java b/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
index 78e2c48..f86917a 100644
--- a/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
+++ b/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java
@@ -17,13 +17,8 @@
package com.android.tools.layoutlib.create;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
import com.android.tools.layoutlib.create.AsmAnalyzer.DependencyVisitor;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.objectweb.asm.ClassReader;
@@ -32,11 +27,15 @@
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
/**
* Unit tests for some methods of {@link AsmAnalyzer}.
*/
@@ -51,26 +50,22 @@
mLog = new MockLog();
URL url = this.getClass().getClassLoader().getResource("data/mock_android.jar");
- mOsJarPath = new ArrayList<String>();
+ mOsJarPath = new ArrayList<>();
+ //noinspection ConstantConditions
mOsJarPath.add(url.getFile());
- Set<String> excludeClasses = new HashSet<String>(1);
- excludeClasses.add("java.lang.JavaClass");
+ Set<String> excludeClasses = Collections.singleton("java.lang.JavaClass");
String[] includeFiles = new String[]{"mock_android/data/data*"};
mAa = new AsmAnalyzer(mLog, mOsJarPath, null /* gen */, null /* deriveFrom */,
null /* includeGlobs */, excludeClasses, includeFiles);
}
- @After
- public void tearDown() throws Exception {
- }
-
@Test
public void testParseZip() throws IOException {
- Map<String, ClassReader> map = new TreeMap<String, ClassReader>();
- Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
+ Map<String, ClassReader> map = new TreeMap<>();
+ Map<String, InputStream> filesFound = new TreeMap<>();
mAa.parseZip(mOsJarPath, map, filesFound);
@@ -101,11 +96,11 @@
@Test
public void testFindClass() throws IOException, LogAbortException {
- Map<String, ClassReader> zipClasses = new TreeMap<String, ClassReader>();
- Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
+ Map<String, ClassReader> zipClasses = new TreeMap<>();
+ Map<String, InputStream> filesFound = new TreeMap<>();
mAa.parseZip(mOsJarPath, zipClasses, filesFound);
- TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>();
+ TreeMap<String, ClassReader> found = new TreeMap<>();
ClassReader cr = mAa.findClass("mock_android.view.ViewGroup$LayoutParams",
zipClasses, found);
@@ -120,11 +115,11 @@
@Test
public void testFindGlobs() throws IOException, LogAbortException {
- Map<String, ClassReader> zipClasses = new TreeMap<String, ClassReader>();
- Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
+ Map<String, ClassReader> zipClasses = new TreeMap<>();
+ Map<String, InputStream> filesFound = new TreeMap<>();
mAa.parseZip(mOsJarPath, zipClasses, filesFound);
- TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>();
+ TreeMap<String, ClassReader> found = new TreeMap<>();
// this matches classes, a package match returns nothing
found.clear();
@@ -183,11 +178,11 @@
@Test
public void testFindClassesDerivingFrom() throws LogAbortException, IOException {
- Map<String, ClassReader> zipClasses = new TreeMap<String, ClassReader>();
- Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
+ Map<String, ClassReader> zipClasses = new TreeMap<>();
+ Map<String, InputStream> filesFound = new TreeMap<>();
mAa.parseZip(mOsJarPath, zipClasses, filesFound);
- TreeMap<String, ClassReader> found = new TreeMap<String, ClassReader>();
+ TreeMap<String, ClassReader> found = new TreeMap<>();
mAa.findClassesDerivingFrom("mock_android.view.View", zipClasses, found);
@@ -209,14 +204,14 @@
@Test
public void testDependencyVisitor() throws IOException, LogAbortException {
- Map<String, ClassReader> zipClasses = new TreeMap<String, ClassReader>();
- Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
+ Map<String, ClassReader> zipClasses = new TreeMap<>();
+ Map<String, InputStream> filesFound = new TreeMap<>();
mAa.parseZip(mOsJarPath, zipClasses, filesFound);
- TreeMap<String, ClassReader> keep = new TreeMap<String, ClassReader>();
- TreeMap<String, ClassReader> new_keep = new TreeMap<String, ClassReader>();
- TreeMap<String, ClassReader> in_deps = new TreeMap<String, ClassReader>();
- TreeMap<String, ClassReader> out_deps = new TreeMap<String, ClassReader>();
+ TreeMap<String, ClassReader> keep = new TreeMap<>();
+ TreeMap<String, ClassReader> new_keep = new TreeMap<>();
+ TreeMap<String, ClassReader> in_deps = new TreeMap<>();
+ TreeMap<String, ClassReader> out_deps = new TreeMap<>();
ClassReader cr = mAa.findClass("mock_android.widget.LinearLayout", zipClasses, keep);
DependencyVisitor visitor = mAa.getVisitor(zipClasses, keep, new_keep, in_deps, out_deps);
diff --git a/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java b/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
index 8a2235b..c4dd7ee 100644
--- a/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
+++ b/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
@@ -18,12 +18,6 @@
package com.android.tools.layoutlib.create;
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -31,7 +25,6 @@
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import java.io.ByteArrayOutputStream;
@@ -44,7 +37,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -52,11 +44,18 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
/**
* Unit tests for some methods of {@link AsmGenerator}.
*/
public class AsmGeneratorTest {
+ private static final String[] EMPTY_STRING_ARRAY = new String[0];
private MockLog mLog;
private ArrayList<String> mOsJarPath;
private String mOsDestJar;
@@ -70,7 +69,8 @@
mLog = new MockLog();
URL url = this.getClass().getClassLoader().getResource("data/mock_android.jar");
- mOsJarPath = new ArrayList<String>();
+ mOsJarPath = new ArrayList<>();
+ //noinspection ConstantConditions
mOsJarPath.add(url.getFile());
mTempFile = File.createTempFile("mock", ".jar");
@@ -98,18 +98,18 @@
@Override
public String[] getDelegateMethods() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getDelegateClassNatives() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getOverriddenMethods() {
// methods to force override
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
@@ -123,7 +123,7 @@
@Override
public String[] getJavaPkgClasses() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
@@ -134,17 +134,17 @@
@Override
public String[] getDeleteReturns() {
// methods deleted from their return type.
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getPromotedFields() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
- return new HashMap<String, InjectMethodRunnable>(0);
+ return Collections.emptyMap();
}
};
@@ -155,7 +155,7 @@
new String[] { // include classes
"**"
},
- new HashSet<String>(0) /* excluded classes */,
+ Collections.<String>emptySet() /* excluded classes */,
new String[]{} /* include files */);
aa.analyze();
agen.generate();
@@ -178,24 +178,24 @@
@Override
public String[] getDelegateMethods() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getDelegateClassNatives() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getOverriddenMethods() {
// methods to force override
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getRenamedClasses() {
// classes to rename (so that we can replace them)
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
@@ -214,17 +214,17 @@
@Override
public String[] getDeleteReturns() {
// methods deleted from their return type.
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getPromotedFields() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
- return new HashMap<String, InjectMethodRunnable>(0);
+ return Collections.emptyMap();
}
};
@@ -235,14 +235,14 @@
new String[] { // include classes
"**"
},
- new HashSet<String>(1),
+ Collections.<String>emptySet(),
new String[] { /* include files */
"mock_android/data/data*"
});
aa.analyze();
agen.generate();
- Map<String, ClassReader> output = new TreeMap<String, ClassReader>();
- Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
+ Map<String, ClassReader> output = new TreeMap<>();
+ Map<String, InputStream> filesFound = new TreeMap<>();
parseZip(mOsDestJar, output, filesFound);
boolean injectedClassFound = false;
for (ClassReader cr: output.values()) {
@@ -265,35 +265,35 @@
@Override
public String[] getDelegateMethods() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getDelegateClassNatives() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getOverriddenMethods() {
// methods to force override
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getRenamedClasses() {
// classes to rename (so that we can replace them)
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getJavaPkgClasses() {
// classes to refactor (so that we can replace them)
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public Set<String> getExcludedClasses() {
- Set<String> set = new HashSet<String>(2);
+ Set<String> set = new HashSet<>(2);
set.add("mock_android.dummy.InnerTest");
set.add("java.lang.JavaClass");
return set;
@@ -302,17 +302,17 @@
@Override
public String[] getDeleteReturns() {
// methods deleted from their return type.
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getPromotedFields() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
- return new HashMap<String, InjectMethodRunnable>(0);
+ return Collections.emptyMap();
}
};
@@ -329,8 +329,8 @@
});
aa.analyze();
agen.generate();
- Map<String, ClassReader> output = new TreeMap<String, ClassReader>();
- Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
+ Map<String, ClassReader> output = new TreeMap<>();
+ Map<String, InputStream> filesFound = new TreeMap<>();
parseZip(mOsDestJar, output, filesFound);
for (String s : output.keySet()) {
assertFalse(excludedClasses.contains(s));
@@ -351,55 +351,52 @@
@Override
public String[] getDelegateMethods() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getDelegateClassNatives() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getOverriddenMethods() {
// methods to force override
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getRenamedClasses() {
// classes to rename (so that we can replace them)
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getJavaPkgClasses() {
// classes to refactor (so that we can replace them)
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public Set<String> getExcludedClasses() {
- return new HashSet<String>(0);
+ return Collections.emptySet();
}
@Override
public String[] getDeleteReturns() {
// methods deleted from their return type.
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public String[] getPromotedFields() {
- return new String[0];
+ return EMPTY_STRING_ARRAY;
}
@Override
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
- HashMap<String, InjectMethodRunnable> map =
- new HashMap<String, InjectMethodRunnable>(1);
- map.put("mock_android.util.EmptyArray",
+ return Collections.singletonMap("mock_android.util.EmptyArray",
InjectMethodRunnables.CONTEXT_GET_FRAMEWORK_CLASS_LOADER);
- return map;
}
};
@@ -415,8 +412,8 @@
});
aa.analyze();
agen.generate();
- Map<String, ClassReader> output = new TreeMap<String, ClassReader>();
- Map<String, InputStream> filesFound = new TreeMap<String, InputStream>();
+ Map<String, ClassReader> output = new TreeMap<>();
+ Map<String, InputStream> filesFound = new TreeMap<>();
parseZip(mOsDestJar, output, filesFound);
final String modifiedClass = "mock_android.util.EmptyArray";
final String modifiedClassPath = modifiedClass.replace('.', '/').concat(".class");
@@ -424,11 +421,8 @@
ZipEntry entry = zipFile.getEntry(modifiedClassPath);
assertNotNull(entry);
final byte[] bytes;
- final InputStream inputStream = zipFile.getInputStream(entry);
- try {
+ try (InputStream inputStream = zipFile.getInputStream(entry)) {
bytes = getByteArray(inputStream);
- } finally {
- inputStream.close();
}
ClassLoader classLoader = new ClassLoader(getClass().getClassLoader()) {
@Override
@@ -489,7 +483,7 @@
boolean mInjectedClassFound = false;
TestClassVisitor() {
- super(Opcodes.ASM4);
+ super(Main.ASM_VERSION);
}
@Override
@@ -514,7 +508,7 @@
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
- return new MethodVisitor(Opcodes.ASM4, mv) {
+ return new MethodVisitor(Main.ASM_VERSION, mv) {
@Override
public void visitFieldInsn(int opcode, String owner, String name,
@@ -540,10 +534,10 @@
@Override
public void visitMethodInsn(int opcode, String owner, String name,
- String desc) {
+ String desc, boolean itf) {
assertTrue(!getBase(owner).equals(JAVA_CLASS_NAME));
assertTrue(testType(Type.getType(desc)));
- super.visitMethodInsn(opcode, owner, name, desc);
+ super.visitMethodInsn(opcode, owner, name, desc, itf);
}
};
diff --git a/create/tests/com/android/tools/layoutlib/create/ClassHasNativeVisitorTest.java b/create/tests/com/android/tools/layoutlib/create/ClassHasNativeVisitorTest.java
index 0135c40..0cdcdc0 100644
--- a/create/tests/com/android/tools/layoutlib/create/ClassHasNativeVisitorTest.java
+++ b/create/tests/com/android/tools/layoutlib/create/ClassHasNativeVisitorTest.java
@@ -60,7 +60,7 @@
* Overrides {@link ClassHasNativeVisitor} to collec the name of the native methods found.
*/
private static class MockClassHasNativeVisitor extends ClassHasNativeVisitor {
- private ArrayList<String> mMethodsFound = new ArrayList<String>();
+ private ArrayList<String> mMethodsFound = new ArrayList<>();
public String[] getMethodsFound() {
return mMethodsFound.toArray(new String[mMethodsFound.size()]);
diff --git a/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java b/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
index e37a09b..afaa399 100644
--- a/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
+++ b/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
@@ -53,12 +53,10 @@
private MockLog mLog;
- private static final String NATIVE_CLASS_NAME = ClassWithNative.class.getCanonicalName();
- private static final String OUTER_CLASS_NAME = OuterClass.class.getCanonicalName();
- private static final String INNER_CLASS_NAME = OuterClass.class.getCanonicalName() + "$" +
- InnerClass.class.getSimpleName();
- private static final String STATIC_INNER_CLASS_NAME =
- OuterClass.class.getCanonicalName() + "$" + StaticInnerClass.class.getSimpleName();
+ private static final String NATIVE_CLASS_NAME = ClassWithNative.class.getName();
+ private static final String OUTER_CLASS_NAME = OuterClass.class.getName();
+ private static final String INNER_CLASS_NAME = InnerClass.class.getName();
+ private static final String STATIC_INNER_CLASS_NAME = StaticInnerClass.class.getName();
@Before
public void setUp() throws Exception {
@@ -69,12 +67,12 @@
/**
* Tests that a class not being modified still works.
*/
- @SuppressWarnings("unchecked")
@Test
public void testNoOp() throws Throwable {
// create an instance of the class that will be modified
// (load the class in a distinct class loader so that we can trash its definition later)
ClassLoader cl1 = new ClassLoader(this.getClass().getClassLoader()) { };
+ @SuppressWarnings("unchecked")
Class<ClassWithNative> clazz1 = (Class<ClassWithNative>) cl1.loadClass(NATIVE_CLASS_NAME);
ClassWithNative instance1 = clazz1.newInstance();
assertEquals(42, instance1.add(20, 22));
@@ -88,7 +86,7 @@
// Now process it but tell the delegate to not modify any method
ClassWriter cw = new ClassWriter(0 /*flags*/);
- HashSet<String> delegateMethods = new HashSet<String>();
+ HashSet<String> delegateMethods = new HashSet<>();
String internalClassName = NATIVE_CLASS_NAME.replace('.', '/');
DelegateClassAdapter cv = new DelegateClassAdapter(
mLog, cw, internalClassName, delegateMethods);
@@ -152,7 +150,7 @@
String internalClassName = NATIVE_CLASS_NAME.replace('.', '/');
- HashSet<String> delegateMethods = new HashSet<String>();
+ HashSet<String> delegateMethods = new HashSet<>();
delegateMethods.add("<init>");
DelegateClassAdapter cv = new DelegateClassAdapter(
mLog, cw, internalClassName, delegateMethods);
@@ -166,7 +164,7 @@
ClassWriter cw = new ClassWriter(0 /*flags*/);
String internalClassName = NATIVE_CLASS_NAME.replace('.', '/');
- HashSet<String> delegateMethods = new HashSet<String>();
+ HashSet<String> delegateMethods = new HashSet<>();
delegateMethods.add(DelegateClassAdapter.ALL_NATIVES);
DelegateClassAdapter cv = new DelegateClassAdapter(
mLog, cw, internalClassName, delegateMethods);
@@ -217,7 +215,7 @@
@Test
public void testDelegateInner() throws Throwable {
// We'll delegate the "get" method of both the inner and outer class.
- HashSet<String> delegateMethods = new HashSet<String>();
+ HashSet<String> delegateMethods = new HashSet<>();
delegateMethods.add("get");
delegateMethods.add("privateMethod");
@@ -300,7 +298,7 @@
@Test
public void testDelegateStaticInner() throws Throwable {
// We'll delegate the "get" method of both the inner and outer class.
- HashSet<String> delegateMethods = new HashSet<String>();
+ HashSet<String> delegateMethods = new HashSet<>();
delegateMethods.add("get");
// Generate the delegate for the outer class.
@@ -367,7 +365,7 @@
*/
private abstract class ClassLoader2 extends ClassLoader {
- private final Map<String, byte[]> mClassDefs = new HashMap<String, byte[]>();
+ private final Map<String, byte[]> mClassDefs = new HashMap<>();
public ClassLoader2() {
super(null);
diff --git a/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java b/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java
new file mode 100644
index 0000000..3db3e23
--- /dev/null
+++ b/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 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.tools.layoutlib.create;
+
+import com.android.tools.layoutlib.create.dataclass.StubClass;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+import java.lang.reflect.Method;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+
+import static org.junit.Assert.*;
+
+public class StubMethodAdapterTest {
+
+ private static final String STUB_CLASS_NAME = StubClass.class.getName();
+
+ /**
+ * Load a dummy class, stub one of its method and ensure that the modified class works as
+ * intended.
+ */
+ @Test
+ public void testBoolean() throws Exception {
+ final String methodName = "returnTrue";
+ // First don't change the method and assert that it returns true
+ testBoolean((name, type) -> false, Assert::assertTrue, methodName);
+ // Change the method now and assert that it returns false.
+ testBoolean((name, type) -> methodName.equals(name) &&
+ Type.BOOLEAN_TYPE.equals(type.getReturnType()), Assert::assertFalse, methodName);
+ }
+
+ /**
+ * @param methodPredicate tests if the method should be replaced
+ */
+ private void testBoolean(BiPredicate<String, Type> methodPredicate, Consumer<Boolean> assertion,
+ String methodName) throws Exception {
+ ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ // Always rename the class to avoid conflict with the original class.
+ String newClassName = STUB_CLASS_NAME + '_';
+ new ClassReader(STUB_CLASS_NAME).accept(
+ new ClassAdapter(newClassName, writer, methodPredicate), 0);
+ MyClassLoader myClassLoader = new MyClassLoader(newClassName, writer.toByteArray());
+ Class<?> aClass = myClassLoader.loadClass(newClassName);
+ assertTrue("StubClass not loaded by the classloader. Likely a bug in the test.",
+ myClassLoader.findClassCalled);
+ Method method = aClass.getMethod(methodName);
+ Object o = aClass.newInstance();
+ assertion.accept((Boolean) method.invoke(o));
+ }
+
+ private static class ClassAdapter extends ClassVisitor {
+
+ private final String mClassName;
+ private final BiPredicate<String, Type> mMethodPredicate;
+
+ private ClassAdapter(String className, ClassVisitor cv,
+ BiPredicate<String, Type> methodPredicate) {
+ super(Main.ASM_VERSION, cv);
+ mClassName = className.replace('.', '/');
+ mMethodPredicate = methodPredicate;
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName,
+ String[] interfaces) {
+ super.visit(version, access, mClassName, signature, superName,
+ interfaces);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, String name, String desc, String signature,
+ String[] exceptions) {
+ // Copied partly from
+ // com.android.tools.layoutlib.create.DelegateClassAdapter.visitMethod()
+ // but not generating the _Original method.
+ boolean isStatic = (access & Opcodes.ACC_STATIC) != 0;
+ boolean isNative = (access & Opcodes.ACC_NATIVE) != 0;
+ MethodVisitor originalMethod =
+ super.visitMethod(access, name, desc, signature, exceptions);
+ Type descriptor = Type.getMethodType(desc);
+ if (mMethodPredicate.test(name, descriptor)) {
+ String methodSignature = mClassName + "#" + name;
+ String invokeSignature = methodSignature + desc;
+ return new StubMethodAdapter(originalMethod, name, descriptor.getReturnType(),
+ invokeSignature, isStatic, isNative);
+ }
+ return originalMethod;
+ }
+ }
+
+ private static class MyClassLoader extends ClassLoader {
+ private final String mName;
+ private final byte[] mBytes;
+ private boolean findClassCalled;
+
+ private MyClassLoader(String name, byte[] bytes) {
+ mName = name;
+ mBytes = bytes;
+ }
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (name.equals(mName)) {
+ findClassCalled = true;
+ return defineClass(name, mBytes, 0, mBytes.length);
+ }
+ return super.findClass(name);
+ }
+ }
+}
diff --git a/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java b/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
new file mode 100644
index 0000000..3ae8e47
--- /dev/null
+++ b/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 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.tools.layoutlib.create.dataclass;
+
+import com.android.tools.layoutlib.create.StubMethodAdapterTest;
+
+/**
+ * Used by {@link StubMethodAdapterTest}
+ */
+@SuppressWarnings("unused")
+public class StubClass {
+
+ public boolean returnTrue() {
+ return true;
+ }
+}