summaryrefslogtreecommitdiffstats
path: root/tools/layoutlib
diff options
context:
space:
mode:
Diffstat (limited to 'tools/layoutlib')
-rw-r--r--tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml2
-rw-r--r--tools/layoutlib/.idea/libraries/asm_4_0.xml11
-rw-r--r--tools/layoutlib/.idea/libraries/guava.xml11
-rw-r--r--tools/layoutlib/.idea/libraries/icu4j.xml11
-rw-r--r--tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml11
-rw-r--r--tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml11
-rw-r--r--tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml14
-rw-r--r--tools/layoutlib/.idea/runConfigurations/Create.xml2
-rw-r--r--tools/layoutlib/Android.mk8
-rw-r--r--tools/layoutlib/bridge/Android.mk1
-rw-r--r--tools/layoutlib/bridge/bridge.iml54
-rw-r--r--tools/layoutlib/bridge/resources/bars/navigation_bar.xml32
-rw-r--r--tools/layoutlib/bridge/resources/bars/navigation_bar600dp.xml49
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/BridgeResources.java15
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java3
-rw-r--r--tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java23
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java13
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java59
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java77
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java40
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java19
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java155
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java55
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java5
-rw-r--r--tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java192
-rw-r--r--tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java44
-rw-r--r--tools/layoutlib/bridge/src/android/text/LineBreaker.java43
-rw-r--r--tools/layoutlib/bridge/src/android/text/LineWidth.java35
-rw-r--r--tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java261
-rw-r--r--tools/layoutlib/bridge/src/android/text/Primitive.java92
-rw-r--r--tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java238
-rw-r--r--tools/layoutlib/bridge/src/android/text/TabStops.java44
-rw-r--r--tools/layoutlib/bridge/src/android/view/BridgeInflater.java6
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java24
-rw-r--r--tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java98
-rw-r--r--tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java12
-rw-r--r--tools/layoutlib/bridge/src/android/view/View_Delegate.java13
-rw-r--r--tools/layoutlib/bridge/src/android/view/WindowCallback.java10
-rw-r--r--tools/layoutlib/bridge/src/android/widget/SimpleMonthView_Delegate.java99
-rw-r--r--tools/layoutlib/bridge/src/com/android/internal/policy/PolicyManager.java72
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java11
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java4
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java17
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java141
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java3
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java778
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java7
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java6
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java6
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java7
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java16
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java43
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java5
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java24
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java9
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java25
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java3
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java3
-rw-r--r--tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java74
-rw-r--r--tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java24
-rw-r--r--tools/layoutlib/bridge/tests/Android.mk1
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.classbin452 -> 452 bytes
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.classbin538 -> 538 bytes
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.classbin461 -> 461 bytes
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.pngbin5619 -> 7991 bytes
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.pngbin10646 -> 10356 bytes
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.pngbin5104 -> 5188 bytes
-rw-r--r--tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java2
-rw-r--r--tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java13
-rw-r--r--tools/layoutlib/create/create.iml15
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java2
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java53
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java17
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java7
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java3
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java52
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java8
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/SimpleMonthViewAdapter.java90
-rw-r--r--tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java20
-rwxr-xr-xtools/layoutlib/rename_font/build_font.py13
-rwxr-xr-xtools/layoutlib/rename_font/build_font_single.py13
83 files changed, 2789 insertions, 694 deletions
diff --git a/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml b/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml
index 0ac7a44..5bb3e3e 100644
--- a/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml
+++ b/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
<component name="InspectionProjectProfileManager">
<profile version="1.0" is_locked="false">
<option name="myName" value="Project Default" />
@@ -7,5 +8,6 @@
<option name="CHECK_TRY_CATCH_SECTION" value="true" />
<option name="CHECK_METHOD_BODY" value="true" />
</inspection_tool>
+ <inspection_tool class="ToArrayCallWithZeroLengthArrayArgument" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component> \ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/asm_4_0.xml b/tools/layoutlib/.idea/libraries/asm_4_0.xml
deleted file mode 100644
index 7df287f..0000000
--- a/tools/layoutlib/.idea/libraries/asm_4_0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<component name="libraryTable">
- <library name="asm-4.0">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/asm/asm-4.0.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES>
- <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/asm/src.zip!/" />
- </SOURCES>
- </library>
-</component> \ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/guava.xml b/tools/layoutlib/.idea/libraries/guava.xml
deleted file mode 100644
index eb60719..0000000
--- a/tools/layoutlib/.idea/libraries/guava.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<component name="libraryTable">
- <library name="guava">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../prebuilts/tools/common/m2/repository/com/google/guava/guava/15.0/guava-15.0.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES>
- <root url="jar://$PROJECT_DIR$/../../../../prebuilts/tools/common/m2/repository/com/google/guava/guava/15.0/guava-15.0-sources.jar!/" />
- </SOURCES>
- </library>
-</component> \ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/icu4j.xml b/tools/layoutlib/.idea/libraries/icu4j.xml
deleted file mode 100644
index dbe0bd7..0000000
--- a/tools/layoutlib/.idea/libraries/icu4j.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<component name="libraryTable">
- <library name="icu4j">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/icu4j/icu4j.jar!/" />
- </CLASSES>
- <JAVADOC>
- <root url="http://icu-project.org/apiref/icu4j50rc/" />
- </JAVADOC>
- <SOURCES />
- </library>
-</component> \ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml b/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml
deleted file mode 100644
index 2a65050..0000000
--- a/tools/layoutlib/.idea/libraries/kxml2_2_3_0.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<component name="libraryTable">
- <library name="kxml2-2.3.0">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/kxml2/kxml2-2.3.0.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES>
- <root url="file://$PROJECT_DIR$/../../../../libcore/xml/src/main/java" />
- </SOURCES>
- </library>
-</component> \ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml b/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml
deleted file mode 100644
index f34f7dd..0000000
--- a/tools/layoutlib/.idea/libraries/ninepatch_prebuilt.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<component name="libraryTable">
- <library name="ninepatch-prebuilt">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES>
- <root url="file://$ANDROID_SRC$/tools/base/ninepatch/src/main/java" />
- </SOURCES>
- </library>
-</component> \ No newline at end of file
diff --git a/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml b/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml
deleted file mode 100644
index b325ad4..0000000
--- a/tools/layoutlib/.idea/libraries/tools_common_prebuilt.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<component name="libraryTable">
- <library name="tools-common-prebuilt">
- <ANNOTATIONS>
- <root url="file://$PROJECT_DIR$" />
- </ANNOTATIONS>
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/tools-common/tools-common-prebuilt.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES>
- <root url="file://$ANDROID_SRC$/tools/base/common/src/main/java" />
- </SOURCES>
- </library>
-</component> \ No newline at end of file
diff --git a/tools/layoutlib/.idea/runConfigurations/Create.xml b/tools/layoutlib/.idea/runConfigurations/Create.xml
index ff173e5..58f057a 100644
--- a/tools/layoutlib/.idea/runConfigurations/Create.xml
+++ b/tools/layoutlib/.idea/runConfigurations/Create.xml
@@ -3,7 +3,7 @@
<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/ext_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/javalib.jar" />
+ <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="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/../../../../" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" value="" />
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index 9300401..61ddb04 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -37,6 +37,10 @@ built_ext_dep := $(call java-lib-deps,ext)
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_layoutlib_create_jar := $(call intermediates-dir-for, \
JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar
@@ -56,6 +60,8 @@ $(LOCAL_BUILT_MODULE): $(built_core_dep) \
$(built_framework_dep) \
$(built_ext_dep) \
$(built_ext_data) \
+ $(built_icudata_dep) \
+ $(built_icutzdata_dep) \
$(built_layoutlib_create_jar)
$(hide) echo "host layoutlib_create: $@"
$(hide) mkdir -p $(dir $@)
@@ -66,6 +72,8 @@ $(LOCAL_BUILT_MODULE): $(built_core_dep) \
$(built_core_classes) \
$(built_framework_classes) \
$(built_ext_classes) \
+ $(built_icudata_data) \
+ $(built_icutzdata_data) \
$(built_ext_data)
$(hide) ls -l $(built_framework_classes)
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index 80b4d59..0dbdd56 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -22,7 +22,6 @@ LOCAL_JAVACFLAGS := -source 6 -target 6
LOCAL_JAVA_LIBRARIES := \
- icu4j \
layoutlib_api-prebuilt \
tools-common-prebuilt
diff --git a/tools/layoutlib/bridge/bridge.iml b/tools/layoutlib/bridge/bridge.iml
index 0baa5ab..ccc10b3 100644
--- a/tools/layoutlib/bridge/bridge.iml
+++ b/tools/layoutlib/bridge/bridge.iml
@@ -24,15 +24,57 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="library" name="icu4j" level="project" />
<orderEntry type="library" name="layoutlib_api-prebuilt" level="project" />
- <orderEntry type="library" name="ninepatch-prebuilt" level="project" />
- <orderEntry type="library" name="tools-common-prebuilt" level="project" />
+ <orderEntry type="module-library">
+ <library name="ninepatch-prebuilt">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="file://$ANDROID_SRC$/tools/base/ninepatch/src/main/java" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library name="tools-common-prebuilt">
+ <ANNOTATIONS>
+ <root url="file://$MODULE_DIR$/.." />
+ </ANNOTATIONS>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/tools-common/tools-common-prebuilt.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/tools-common/tools-common-prebuilt-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
<orderEntry type="library" name="framework.jar" level="project" />
- <orderEntry type="library" scope="TEST" name="kxml2-2.3.0" level="project" />
- <orderEntry type="library" scope="TEST" name="guava" level="project" />
<orderEntry type="module-library" scope="TEST">
- <library>
+ <library name="kxml2-2.3.0">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/kxml2/kxml2-2.3.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="file://$MODULE_DIR$/../../../../../libcore/xml/src/main/java" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library" scope="TEST">
+ <library name="guava">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/tools/common/m2/repository/com/google/guava/guava/15.0/guava-15.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/tools/common/m2/repository/com/google/guava/guava/15.0/guava-15.0-sources.jar!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library" scope="TEST">
+ <library name="sdk-common">
<CLASSES>
<root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/sdk-common/sdk-common.jar!/" />
</CLASSES>
diff --git a/tools/layoutlib/bridge/resources/bars/navigation_bar.xml b/tools/layoutlib/bridge/resources/bars/navigation_bar.xml
index 79920a1..55bd1d2 100644
--- a/tools/layoutlib/bridge/resources/bars/navigation_bar.xml
+++ b/tools/layoutlib/bridge/resources/bars/navigation_bar.xml
@@ -1,8 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<View
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"
+ android:visibility="invisible"/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
@@ -10,20 +27,23 @@
<View
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- android:layout_weight="1"/>
+ android:layout_weight="1"
+ android:visibility="invisible"/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:scaleType="centerInside"/>
<View
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_weight="1"/>
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_weight="1"
+ android:visibility="invisible"/>
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:scaleType="centerInside"/>
<View
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"
+ android:visibility="invisible"/>
</merge>
diff --git a/tools/layoutlib/bridge/resources/bars/navigation_bar600dp.xml b/tools/layoutlib/bridge/resources/bars/navigation_bar600dp.xml
new file mode 100644
index 0000000..e208a0d
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/navigation_bar600dp.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <View
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:visibility="invisible"/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:scaleType="centerInside"/>
+ <View
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:visibility="invisible"/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:scaleType="centerInside"/>
+ <View
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:visibility="invisible"/>
+ <ImageView
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:scaleType="centerInside"/>
+ <View
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:visibility="invisible"/>
+</merge>
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
index e5b47d6..163fbcb 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeResources.java
@@ -174,7 +174,7 @@ public final class BridgeResources extends Resources {
}
@Override
- public int getColor(int id) throws NotFoundException {
+ public int getColor(int id, Theme theme) throws NotFoundException {
Pair<String, ResourceValue> value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
@@ -197,22 +197,21 @@ public final class BridgeResources extends Resources {
}
}
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(id);
-
- // this is not used since the method above always throws
- return 0;
+ // Suppress possible NPE. getColorStateList will never return null, it will instead
+ // throw an exception, but intelliJ can't figure that out
+ //noinspection ConstantConditions
+ return getColorStateList(id, theme).getDefaultColor();
}
@Override
- public ColorStateList getColorStateList(int id) throws NotFoundException {
+ public ColorStateList getColorStateList(int id, Theme theme) throws NotFoundException {
Pair<String, ResourceValue> resValue = getResourceValue(id, mPlatformResourceFlag);
if (resValue != null) {
ColorStateList stateList = ResourceHelper.getColorStateList(resValue.getSecond(),
mContext);
if (stateList != null) {
- return stateList;
+ return stateList.obtainForTheme(theme);
}
}
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index b8fd1ca..6a61090 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -334,7 +334,8 @@ public final class BridgeTypedArray extends TypedArray {
BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
parser, mContext, resValue.isFramework());
try {
- return ColorStateList.createFromXml(mContext.getResources(), blockParser);
+ return ColorStateList.createFromXml(mContext.getResources(), blockParser,
+ mContext.getTheme());
} finally {
blockParser.ensurePopped();
}
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
index 5d36b2c..f1e8fc2 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
@@ -27,6 +27,7 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.annotation.Nullable;
import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
+import android.content.res.Resources.ThemeKey;
import android.util.AttributeSet;
import android.util.TypedValue;
@@ -110,22 +111,16 @@ public class Resources_Theme_Delegate {
private static boolean setupResources(Theme thisTheme) {
// Key is a space-separated list of theme ids applied that have been merged into the
// BridgeContext's theme to make thisTheme.
- String[] appliedStyles = thisTheme.getKey().split(" ");
+ final ThemeKey key = thisTheme.getKey();
+ final int[] resId = key.mResId;
+ final boolean[] force = key.mForce;
+
boolean changed = false;
- for (String s : appliedStyles) {
- if (s.isEmpty()) {
- continue;
- }
- // See the definition of force parameter in Theme.applyStyle().
- boolean force = false;
- if (s.charAt(s.length() - 1) == '!') {
- force = true;
- s = s.substring(0, s.length() - 1);
- }
- int styleId = Integer.parseInt(s, 16);
- StyleResourceValue style = resolveStyle(styleId);
+ for (int i = 0, N = key.mCount; i < N; i++) {
+ StyleResourceValue style = resolveStyle(resId[i]);
if (style != null) {
- RenderSessionImpl.getCurrentContext().getRenderResources().applyStyle(style, force);
+ RenderSessionImpl.getCurrentContext().getRenderResources().applyStyle(
+ style, force[i]);
changed = true;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
index a4a3b7d..21f36ce 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java
@@ -19,6 +19,12 @@ package android.graphics;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
+import android.graphics.Paint_Delegate.FontInfo;
+import android.icu.lang.UScript;
+import android.icu.lang.UScriptRun;
+import android.icu.text.Bidi;
+import android.icu.text.BidiRun;
+
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Toolkit;
@@ -29,13 +35,6 @@ import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
-import com.ibm.icu.lang.UScript;
-import com.ibm.icu.lang.UScriptRun;
-import com.ibm.icu.text.Bidi;
-import com.ibm.icu.text.BidiRun;
-
-import android.graphics.Paint_Delegate.FontInfo;
-
/**
* Render the text by breaking it into various scripts and using the right font for each script.
* Can be used to measure the text without actually drawing it.
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
index e9b5d6e..af47aeb 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java
@@ -23,7 +23,15 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.Shader.TileMode;
+import java.awt.PaintContext;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
+import java.awt.image.Raster;
/**
* Delegate implementing the native methods of android.graphics.BitmapShader
@@ -67,9 +75,9 @@ public class BitmapShader_Delegate extends Shader_Delegate {
// ---- native methods ----
@LayoutlibDelegate
- /*package*/ static long nativeCreate(long native_bitmap, int shaderTileModeX,
+ /*package*/ static long nativeCreate(Bitmap androidBitmap, int shaderTileModeX,
int shaderTileModeY) {
- Bitmap_Delegate bitmap = Bitmap_Delegate.getDelegate(native_bitmap);
+ Bitmap_Delegate bitmap = Bitmap_Delegate.getDelegate(androidBitmap);
if (bitmap == null) {
return 0;
}
@@ -83,17 +91,17 @@ public class BitmapShader_Delegate extends Shader_Delegate {
// ---- Private delegate/helper methods ----
- private BitmapShader_Delegate(java.awt.image.BufferedImage image,
+ private BitmapShader_Delegate(BufferedImage image,
TileMode tileModeX, TileMode tileModeY) {
mJavaPaint = new BitmapShaderPaint(image, tileModeX, tileModeY);
}
private class BitmapShaderPaint implements java.awt.Paint {
- private final java.awt.image.BufferedImage mImage;
+ private final BufferedImage mImage;
private final TileMode mTileModeX;
private final TileMode mTileModeY;
- BitmapShaderPaint(java.awt.image.BufferedImage image,
+ BitmapShaderPaint(BufferedImage image,
TileMode tileModeX, TileMode tileModeY) {
mImage = image;
mTileModeX = tileModeX;
@@ -101,29 +109,24 @@ public class BitmapShader_Delegate extends Shader_Delegate {
}
@Override
- public java.awt.PaintContext createContext(
- java.awt.image.ColorModel colorModel,
- java.awt.Rectangle deviceBounds,
- java.awt.geom.Rectangle2D userBounds,
- java.awt.geom.AffineTransform xform,
- java.awt.RenderingHints hints) {
-
- java.awt.geom.AffineTransform canvasMatrix;
+ public PaintContext createContext(ColorModel colorModel, Rectangle deviceBounds,
+ Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) {
+ AffineTransform canvasMatrix;
try {
canvasMatrix = xform.createInverse();
- } catch (java.awt.geom.NoninvertibleTransformException e) {
+ } catch (NoninvertibleTransformException e) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
"Unable to inverse matrix in BitmapShader", e, null /*data*/);
- canvasMatrix = new java.awt.geom.AffineTransform();
+ canvasMatrix = new AffineTransform();
}
- java.awt.geom.AffineTransform localMatrix = getLocalMatrix();
+ AffineTransform localMatrix = getLocalMatrix();
try {
localMatrix = localMatrix.createInverse();
- } catch (java.awt.geom.NoninvertibleTransformException e) {
+ } catch (NoninvertibleTransformException e) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
"Unable to inverse matrix in BitmapShader", e, null /*data*/);
- localMatrix = new java.awt.geom.AffineTransform();
+ localMatrix = new AffineTransform();
}
if (!colorModel.isCompatibleRaster(mImage.getRaster())) {
@@ -134,16 +137,16 @@ public class BitmapShader_Delegate extends Shader_Delegate {
return new BitmapShaderContext(canvasMatrix, localMatrix, colorModel);
}
- private class BitmapShaderContext implements java.awt.PaintContext {
+ private class BitmapShaderContext implements PaintContext {
- private final java.awt.geom.AffineTransform mCanvasMatrix;
- private final java.awt.geom.AffineTransform mLocalMatrix;
- private final java.awt.image.ColorModel mColorModel;
+ private final AffineTransform mCanvasMatrix;
+ private final AffineTransform mLocalMatrix;
+ private final ColorModel mColorModel;
public BitmapShaderContext(
- java.awt.geom.AffineTransform canvasMatrix,
- java.awt.geom.AffineTransform localMatrix,
- java.awt.image.ColorModel colorModel) {
+ AffineTransform canvasMatrix,
+ AffineTransform localMatrix,
+ ColorModel colorModel) {
mCanvasMatrix = canvasMatrix;
mLocalMatrix = localMatrix;
mColorModel = colorModel;
@@ -154,13 +157,13 @@ public class BitmapShader_Delegate extends Shader_Delegate {
}
@Override
- public java.awt.image.ColorModel getColorModel() {
+ public ColorModel getColorModel() {
return mColorModel;
}
@Override
- public java.awt.image.Raster getRaster(int x, int y, int w, int h) {
- java.awt.image.BufferedImage image = new java.awt.image.BufferedImage(
+ public Raster getRaster(int x, int y, int w, int h) {
+ BufferedImage image = new BufferedImage(
mColorModel, mColorModel.createCompatibleWritableRaster(w, h),
mColorModel.isAlphaPremultiplied(), null);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 57a8bbc..0737682 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -77,19 +77,18 @@ public final class Bitmap_Delegate {
// ---- Public Helper methods ----
/**
- * Returns the native delegate associated to a given {@link Bitmap_Delegate} object.
- */
- public static Bitmap_Delegate getDelegate(Bitmap bitmap) {
- return sManager.getDelegate(bitmap.mNativeBitmap);
- }
-
- /**
* Returns the native delegate associated to a given an int referencing a {@link Bitmap} object.
*/
public static Bitmap_Delegate getDelegate(long native_bitmap) {
return sManager.getDelegate(native_bitmap);
}
+ @Nullable
+ public static Bitmap_Delegate getDelegate(@Nullable Bitmap bitmap) {
+ // refSkPixelRef is a hack to get the native pointer: see #nativeRefPixelRef()
+ return bitmap == null ? null : getDelegate(bitmap.refSkPixelRef());
+ }
+
/**
* Creates and returns a {@link Bitmap} initialized with the given file content.
*
@@ -188,31 +187,7 @@ public final class Bitmap_Delegate {
return createBitmap(delegate, createFlags, density.getDpiValue());
}
- /**
- * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}.
- */
- public static BufferedImage getImage(Bitmap bitmap) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(bitmap.mNativeBitmap);
- if (delegate == null) {
- return null;
- }
-
- return delegate.mImage;
- }
-
- public static int getBufferedImageType(int nativeBitmapConfig) {
- switch (Config.nativeToConfig(nativeBitmapConfig)) {
- case ALPHA_8:
- return BufferedImage.TYPE_INT_ARGB;
- case RGB_565:
- return BufferedImage.TYPE_INT_ARGB;
- case ARGB_4444:
- return BufferedImage.TYPE_INT_ARGB;
- case ARGB_8888:
- return BufferedImage.TYPE_INT_ARGB;
- }
-
+ private static int getBufferedImageType() {
return BufferedImage.TYPE_INT_ARGB;
}
@@ -239,10 +214,6 @@ public final class Bitmap_Delegate {
return mHasAlpha && mConfig != Config.RGB_565;
}
- public boolean hasMipMap() {
- // TODO: check if more checks are required as in hasAlpha.
- return mHasMipMap;
- }
/**
* Update the generationId.
*
@@ -257,7 +228,7 @@ public final class Bitmap_Delegate {
@LayoutlibDelegate
/*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width,
int height, int nativeConfig, boolean isMutable) {
- int imageType = getBufferedImageType(nativeConfig);
+ int imageType = getBufferedImageType();
// create the image
BufferedImage image = new BufferedImage(width, height, imageType);
@@ -285,7 +256,7 @@ public final class Bitmap_Delegate {
int width = srcImage.getWidth();
int height = srcImage.getHeight();
- int imageType = getBufferedImageType(nativeConfig);
+ int imageType = getBufferedImageType();
// create the image
BufferedImage image = new BufferedImage(width, height, imageType);
@@ -303,6 +274,13 @@ public final class Bitmap_Delegate {
}
@LayoutlibDelegate
+ /*package*/ static Bitmap nativeCopyAshmem(long nativeSrcBitmap) {
+ // Unused method; no implementation provided.
+ assert false;
+ return null;
+ }
+
+ @LayoutlibDelegate
/*package*/ static void nativeDestructor(long nativeBitmap) {
sManager.removeJavaReferenceFor(nativeBitmap);
}
@@ -374,22 +352,16 @@ public final class Bitmap_Delegate {
/*package*/ static boolean nativeHasAlpha(long nativeBitmap) {
// get the delegate from the native int.
Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return true;
- }
+ return delegate == null || delegate.mHasAlpha;
- return delegate.mHasAlpha;
}
@LayoutlibDelegate
/*package*/ static boolean nativeHasMipMap(long nativeBitmap) {
// get the delegate from the native int.
Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return true;
- }
+ return delegate == null || delegate.mHasMipMap;
- return delegate.mHasMipMap;
}
@LayoutlibDelegate
@@ -510,11 +482,6 @@ public final class Bitmap_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void nativePrepareToDraw(long nativeBitmap) {
- // nothing to be done here.
- }
-
- @LayoutlibDelegate
/*package*/ static boolean nativeIsPremultiplied(long nativeBitmap) {
// get the delegate from the native int.
Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
@@ -600,6 +567,14 @@ public final class Bitmap_Delegate {
return Arrays.equals(argb1, argb2);
}
+ // Only used by AssetAtlasService, which we don't care about.
+ @LayoutlibDelegate
+ /*package*/ static long nativeRefPixelRef(long nativeBitmap) {
+ // Hack: This is called by Bitmap.refSkPixelRef() and LayoutLib uses that method to get
+ // the native pointer from a Bitmap. So, we return nativeBitmap here.
+ return nativeBitmap;
+ }
+
// ---- Private delegate/helper methods ----
private Bitmap_Delegate(BufferedImage image, Config config) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 0b95cf3..f8b3739 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -115,7 +115,11 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static long initRaster(long nativeBitmapOrZero) {
+ /*package*/ static long initRaster(@Nullable Bitmap bitmap) {
+ long nativeBitmapOrZero = 0;
+ if (bitmap != null) {
+ nativeBitmapOrZero = bitmap.refSkPixelRef();
+ }
if (nativeBitmapOrZero > 0) {
// get the Bitmap from the int
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero);
@@ -133,8 +137,7 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/
- static void native_setBitmap(long canvas, long bitmap, boolean copyState) {
+ /*package*/ 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) {
@@ -221,7 +224,8 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_restore(long nativeCanvas) {
+ /*package*/ static void native_restore(long nativeCanvas, boolean throwOnUnderflow) {
+ // FIXME: implement throwOnUnderflow.
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -232,7 +236,9 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_restoreToCount(long nativeCanvas, int saveCount) {
+ /*package*/ static void native_restoreToCount(long nativeCanvas, int saveCount,
+ boolean throwOnUnderflow) {
+ // FIXME: implement throwOnUnderflow.
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
@@ -425,8 +431,7 @@ public final class Canvas_Delegate {
canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter);
- if (canvasDelegate.mDrawFilter != null &&
- canvasDelegate.mDrawFilter.isSupported() == false) {
+ if (canvasDelegate.mDrawFilter != null && !canvasDelegate.mDrawFilter.isSupported()) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER,
canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/);
}
@@ -442,7 +447,7 @@ public final class Canvas_Delegate {
}
Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds();
- if (rect != null && rect.isEmpty() == false) {
+ if (rect != null && !rect.isEmpty()) {
bounds.left = rect.x;
bounds.top = rect.y;
bounds.right = rect.x + rect.width;
@@ -718,7 +723,7 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, long bitmap,
+ /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
float left, float top,
long nativePaintOrZero,
int canvasDensity,
@@ -740,7 +745,7 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_drawBitmap(Canvas thisCanvas, long nativeCanvas, long bitmap,
+ /*package*/ 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) {
@@ -781,7 +786,7 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, long nBitmap,
+ /*package*/ static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
long nMatrix, long nPaint) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
@@ -793,7 +798,7 @@ public final class Canvas_Delegate {
Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
// get the delegate from the native int.
- Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nBitmap);
+ Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (bitmapDelegate == null) {
return;
}
@@ -822,7 +827,7 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void nativeDrawBitmapMesh(long nCanvas, long nBitmap,
+ /*package*/ static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
int colorOffset, long nPaint) {
// FIXME
@@ -845,7 +850,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ 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 == Canvas.DIRECTION_RTL,
+ drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0,
paint, typeface);
}
@@ -1039,8 +1044,7 @@ public final class Canvas_Delegate {
}
/**
- * Restores the {@link GcSnapshot} to <var>saveCount</var>
- * @param saveCount the saveCount
+ * Restores the top {@link GcSnapshot}
*/
private void restore() {
mSnapshot = mSnapshot.restore();
@@ -1103,7 +1107,7 @@ public final class Canvas_Delegate {
// before drawing it.
if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
fixAlpha8Bitmap(image);
- } else if (bitmap.hasAlpha() == false) {
+ } else if (!bitmap.hasAlpha()) {
// hasAlpha is merely a rendering hint. There can in fact be alpha values
// in the bitmap but it should be ignored at drawing time.
// There is two ways to do this:
@@ -1123,7 +1127,7 @@ public final class Canvas_Delegate {
}
// if we can't force SRC mode, then create a temp bitmap of TYPE_RGB
- if (forceSrcMode[0] == false) {
+ if (!forceSrcMode[0]) {
image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF);
}
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
index e16dbda..e8d34d0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java
@@ -90,7 +90,7 @@ public final class NinePatch_Delegate {
if (oos != null) {
try {
oos.close();
- } catch (IOException e) {
+ } catch (IOException ignored) {
}
}
}
@@ -136,7 +136,7 @@ public final class NinePatch_Delegate {
if (ois != null) {
try {
ois.close();
- } catch (IOException e) {
+ } catch (IOException ignored) {
}
}
}
@@ -150,15 +150,12 @@ public final class NinePatch_Delegate {
@LayoutlibDelegate
/*package*/ static boolean isNinePatchChunk(byte[] chunk) {
NinePatchChunk chunkObject = getChunk(chunk);
- if (chunkObject != null) {
- return true;
- }
+ return chunkObject != null;
- return false;
}
@LayoutlibDelegate
- /*package*/ static long validateNinePatchChunk(long bitmap, byte[] chunk) {
+ /*package*/ static long validateNinePatchChunk(byte[] chunk) {
// the default JNI implementation only checks that the byte[] has the same
// size as the C struct it represent. Since we cannot do the same check (serialization
// will return different size depending on content), we do nothing.
@@ -173,7 +170,7 @@ public final class NinePatch_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void nativeDraw(long canvas_instance, RectF loc, long bitmap_instance,
+ /*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,
@@ -182,7 +179,7 @@ public final class NinePatch_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void nativeDraw(long canvas_instance, Rect loc, long bitmap_instance,
+ /*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,
@@ -191,7 +188,7 @@ public final class NinePatch_Delegate {
}
@LayoutlibDelegate
- /*package*/ static long nativeGetTransparentRegion(long bitmap, long chunk, Rect location) {
+ /*package*/ static long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location) {
return 0;
}
@@ -199,7 +196,7 @@ public final class NinePatch_Delegate {
private static void draw(long canvas_instance,
final int left, final int top, final int right, final int bottom,
- long bitmap_instance, long chunk, long paint_instance_or_null,
+ 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);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 9355474..65b65ec 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -85,6 +85,8 @@ public class Paint_Delegate {
private float mTextScaleX;
private float mTextSkewX;
private int mHintingMode = Paint.HINTING_ON;
+ private int mHyphenEdit;
+ private float mLetterSpacing; // not used in actual text rendering.
// Variant of the font. A paint's variant can only be compact or elegant.
private FontVariant mFontVariant = FontVariant.COMPACT;
@@ -102,6 +104,7 @@ public class Paint_Delegate {
// ---- Public Helper methods ----
+ @Nullable
public static Paint_Delegate getDelegate(long native_paint) {
return sManager.getDelegate(native_paint);
}
@@ -253,7 +256,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static int getFlags(Paint thisPaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 0;
}
@@ -266,7 +269,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void setFlags(Paint thisPaint, int flags) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
@@ -282,7 +285,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static int getHinting(Paint thisPaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return Paint.HINTING_ON;
}
@@ -293,7 +296,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void setHinting(Paint thisPaint, int mode) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
@@ -339,7 +342,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static int getColor(Paint thisPaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 0;
}
@@ -350,7 +353,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void setColor(Paint thisPaint, int color) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
@@ -361,7 +364,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static int getAlpha(Paint thisPaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 0;
}
@@ -372,7 +375,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void setAlpha(Paint thisPaint, int a) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
@@ -383,7 +386,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float getStrokeWidth(Paint thisPaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 1.f;
}
@@ -394,7 +397,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void setStrokeWidth(Paint thisPaint, float width) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
@@ -405,7 +408,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float getStrokeMiter(Paint thisPaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 1.f;
}
@@ -416,7 +419,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void setStrokeMiter(Paint thisPaint, float miter) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
@@ -443,14 +446,14 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static boolean isElegantTextHeight(Paint thisPaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
return delegate != null && delegate.mFontVariant == FontVariant.ELEGANT;
}
@LayoutlibDelegate
/*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
@@ -461,7 +464,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float getTextSize(Paint thisPaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 1.f;
}
@@ -472,7 +475,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void setTextSize(Paint thisPaint, float textSize) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
@@ -484,7 +487,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float getTextScaleX(Paint thisPaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 1.f;
}
@@ -495,7 +498,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void setTextScaleX(Paint thisPaint, float scaleX) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
@@ -507,7 +510,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float getTextSkewX(Paint thisPaint) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 1.f;
}
@@ -518,7 +521,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static void setTextSkewX(Paint thisPaint, float skewX) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
@@ -530,7 +533,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float ascent(Paint thisPaint) {
// get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 0;
}
@@ -547,7 +550,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float descent(Paint thisPaint) {
// get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 0;
}
@@ -564,7 +567,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float getFontMetrics(Paint thisPaint, FontMetrics metrics) {
// get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 0;
}
@@ -575,7 +578,7 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static int getFontMetricsInt(Paint thisPaint, FontMetricsInt fmi) {
// get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 0;
}
@@ -601,7 +604,7 @@ public class Paint_Delegate {
/*package*/ static float native_measureText(Paint thisPaint, char[] text, int index,
int count, int bidiFlags) {
// get the delegate
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return 0;
}
@@ -1090,18 +1093,108 @@ public class Paint_Delegate {
@LayoutlibDelegate
/*package*/ static float native_getLetterSpacing(long nativePaint) {
- // TODO: throw a fidelity warning.
- return 0;
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
+ if (delegate == null) {
+ return 0;
+ }
+ return delegate.mLetterSpacing;
}
@LayoutlibDelegate
/*package*/ static void native_setLetterSpacing(long nativePaint, float letterSpacing) {
- // pass.
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
+ "Paint.setLetterSpacing() not supported.", null, null);
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
+ if (delegate == null) {
+ return;
+ }
+ delegate.mLetterSpacing = letterSpacing;
}
@LayoutlibDelegate
/*package*/ static void native_setFontFeatureSettings(long nativePaint, String settings) {
- // pass.
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
+ "Paint.setFontFeatureSettings() not supported.", null, null);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static int native_getHyphenEdit(long nativePaint) {
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
+ if (delegate == null) {
+ return 0;
+ }
+ return delegate.mHyphenEdit;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void native_setHyphenEdit(long nativePaint, int hyphen) {
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
+ if (delegate == null) {
+ return;
+ }
+ delegate.mHyphenEdit = hyphen;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static boolean native_hasGlyph(long nativePaint, long nativeTypeface, int bidiFlags,
+ String string) {
+ Paint_Delegate delegate = sManager.getDelegate(nativePaint);
+ if (delegate == null) {
+ return false;
+ }
+ if (string.length() == 0) {
+ return false;
+ }
+ if (string.length() > 1) {
+ Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
+ "Paint.hasGlyph() is not supported for ligatures.", null, null);
+ return false;
+ }
+ assert nativeTypeface == delegate.mNativeTypeface;
+ Typeface_Delegate typeface_delegate = Typeface_Delegate.getDelegate(nativeTypeface);
+
+ char c = string.charAt(0);
+ for (Font font : typeface_delegate.getFonts(delegate.mFontVariant)) {
+ if (font.canDisplay(c)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ @LayoutlibDelegate
+ /*package*/ static float native_getRunAdvance(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 startOffset = offset - start; // offset from start.
+ float sum = 0;
+ for (int i = 0; i < startOffset; i++) {
+ sum += advances[i];
+ }
+ return sum;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static int native_getOffsetForAdvance(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);
+ float sum = 0;
+ int i;
+ for (i = 0; i < count && sum < advance; i++) {
+ sum += advances[i];
+ }
+ float distanceToI = sum - advance;
+ float distanceToIMinus1 = advance - (sum - advances[i]);
+ return distanceToI > distanceToIMinus1 ? i : i - 1;
}
// ---- Private delegate/helper methods ----
@@ -1139,7 +1232,7 @@ public class Paint_Delegate {
}
private void reset() {
- mFlags = Paint.DEFAULT_PAINT_FLAGS;
+ mFlags = Paint.HIDDEN_DEFAULT_PAINT_FLAGS;
mColor = 0xFF000000;
mStyle = Paint.Style.FILL.nativeInt;
mCap = Paint.Cap.BUTT.nativeInt;
@@ -1234,7 +1327,7 @@ public class Paint_Delegate {
private static void setFlag(Paint thisPaint, int flagMask, boolean flagValue) {
// get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
+ Paint_Delegate delegate = sManager.getDelegate(thisPaint.getNativeInstance());
if (delegate == null) {
return;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 776398f..3c9a062 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -21,6 +21,7 @@ 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.Direction;
import android.graphics.Path.FillType;
@@ -30,6 +31,7 @@ import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
+import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
@@ -56,7 +58,7 @@ public final class Path_Delegate {
// ---- delegate data ----
private FillType mFillType = FillType.WINDING;
- private GeneralPath mPath = new GeneralPath();
+ private Path2D mPath = new Path2D.Double();
private float mLastX = 0;
private float mLastY = 0;
@@ -486,8 +488,54 @@ public final class Path_Delegate {
@LayoutlibDelegate
/*package*/ static float[] native_approximate(long nPath, float error) {
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "Path.approximate() not supported", null);
- return new float[0];
+ Bridge.getLog().warning(LayoutLog.TAG_UNSUPPORTED, "Path.approximate() not fully supported",
+ null);
+ Path_Delegate pathDelegate = sManager.getDelegate(nPath);
+ if (pathDelegate == null) {
+ return null;
+ }
+ PathIterator pathIterator = pathDelegate.mPath.getPathIterator(null);
+ float[] tmp = new float[6];
+ float[] coords = new float[6];
+ boolean isFirstPoint = true;
+ while (!pathIterator.isDone()) {
+ int type = pathIterator.currentSegment(tmp);
+ switch (type) {
+ case PathIterator.SEG_MOVETO:
+ case PathIterator.SEG_LINETO:
+ store(tmp, coords, 1, isFirstPoint);
+ break;
+ case PathIterator.SEG_QUADTO:
+ store(tmp, coords, 2, isFirstPoint);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ store(tmp, coords, 3, isFirstPoint);
+ break;
+ case PathIterator.SEG_CLOSE:
+ // No points returned.
+ }
+ isFirstPoint = false;
+ pathIterator.next();
+ }
+ if (isFirstPoint) {
+ // No points found
+ return new float[0];
+ } else {
+ return coords;
+ }
+ }
+
+ private static void store(float[] src, float[] dst, int count, boolean isFirst) {
+ if (isFirst) {
+ dst[0] = 0; // fraction
+ dst[1] = src[0]; // abscissa
+ dst[2] = src[1]; // ordinate
+ }
+ if (count > 1 || !isFirst) {
+ dst[3] = 1;
+ dst[4] = src[2 * count - 2];
+ dst[5] = src[2 * count - 1];
+ }
}
// ---- Private helper methods ----
@@ -522,6 +570,7 @@ public final class Path_Delegate {
throw new IllegalArgumentException();
}
+ @NonNull
private static Direction getDirection(int direction) {
for (Direction d : Direction.values()) {
if (direction == d.nativeInt) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index 14e9960..0d491a0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -81,14 +81,15 @@ public abstract class Shader_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void nativeSetLocalMatrix(long native_shader, long matrix_instance) {
+ /*package*/ static long nativeSetLocalMatrix(long native_shader, long matrix_instance) {
// get the delegate from the native int.
Shader_Delegate shaderDelegate = sManager.getDelegate(native_shader);
if (shaderDelegate == null) {
- return;
+ return native_shader;
}
shaderDelegate.mLocalMatrix = Matrix_Delegate.getDelegate(matrix_instance);
+ return native_shader;
}
// ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
index 6247dae..38171dc 100644
--- a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
@@ -19,8 +19,8 @@ package android.text;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-import com.ibm.icu.text.Bidi;
+import android.icu.text.Bidi;
/**
* Delegate used to provide new implementation for the native methods of {@link AndroidBidi}
diff --git a/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java b/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java
new file mode 100644
index 0000000..50289e9
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java
@@ -0,0 +1,192 @@
+/*
+ * 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.text;
+
+import android.annotation.NonNull;
+import android.text.Primitive.PrimitiveType;
+import android.text.StaticLayout.LineBreaks;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.text.Primitive.PrimitiveType.PENALTY_INFINITY;
+
+// Based on the native implementation of GreedyLineBreaker in
+// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260
+public class GreedyLineBreaker extends LineBreaker {
+
+ public GreedyLineBreaker(@NonNull List<Primitive> primitives, @NonNull LineWidth lineWidth,
+ @NonNull TabStops tabStops) {
+ super(primitives, lineWidth, tabStops);
+ }
+
+ @Override
+ public void computeBreaks(@NonNull LineBreaks lineBreaks) {
+ BreakInfo breakInfo = new BreakInfo();
+ int lineNum = 0;
+ float width = 0, printedWidth = 0;
+ boolean breakFound = false, goodBreakFound = false;
+ int breakIndex = 0, goodBreakIndex = 0;
+ float breakWidth = 0, goodBreakWidth = 0;
+ int firstTabIndex = Integer.MAX_VALUE;
+
+ float maxWidth = mLineWidth.getLineWidth(lineNum);
+
+ int numPrimitives = mPrimitives.size();
+ // greedily fit as many characters as possible on each line
+ // loop over all primitives, and choose the best break point
+ // (if possible, a break point without splitting a word)
+ // after going over the maximum length
+ for (int i = 0; i < numPrimitives; i++) {
+ Primitive p = mPrimitives.get(i);
+
+ // update the current line width
+ if (p.type == PrimitiveType.BOX || p.type == PrimitiveType.GLUE) {
+ width += p.width;
+ if (p.type == PrimitiveType.BOX) {
+ printedWidth = width;
+ }
+ } else if (p.type == PrimitiveType.VARIABLE) {
+ width = mTabStops.width(width);
+ // keep track of first tab character in the region we are examining
+ // so we can determine whether or not a line contains a tab
+ firstTabIndex = Math.min(firstTabIndex, i);
+ }
+
+ // find the best break point for the characters examined so far
+ if (printedWidth > maxWidth) {
+ //noinspection StatementWithEmptyBody
+ if (breakFound || goodBreakFound) {
+ if (goodBreakFound) {
+ // a true line break opportunity existed in the characters examined so far,
+ // so there is no need to split a word
+ i = goodBreakIndex; // no +1 because of i++
+ lineNum++;
+ maxWidth = mLineWidth.getLineWidth(lineNum);
+ breakInfo.mBreaksList.add(mPrimitives.get(goodBreakIndex).location);
+ breakInfo.mWidthsList.add(goodBreakWidth);
+ breakInfo.mFlagsList.add(firstTabIndex < goodBreakIndex);
+ firstTabIndex = Integer.MAX_VALUE;
+ } else {
+ // must split a word because there is no other option
+ i = breakIndex; // no +1 because of i++
+ lineNum++;
+ maxWidth = mLineWidth.getLineWidth(lineNum);
+ breakInfo.mBreaksList.add(mPrimitives.get(breakIndex).location);
+ breakInfo.mWidthsList.add(breakWidth);
+ breakInfo.mFlagsList.add(firstTabIndex < breakIndex);
+ firstTabIndex = Integer.MAX_VALUE;
+ }
+ printedWidth = width = 0;
+ goodBreakFound = breakFound = false;
+ goodBreakWidth = breakWidth = 0;
+ continue;
+ } else {
+ // no choice, keep going... must make progress by putting at least one
+ // character on a line, even if part of that character is cut off --
+ // there is no other option
+ }
+ }
+
+ // update possible break points
+ if (p.type == PrimitiveType.PENALTY &&
+ p.penalty < PENALTY_INFINITY) {
+ // this does not handle penalties with width
+
+ // handle forced line break
+ if (p.penalty == -PENALTY_INFINITY) {
+ lineNum++;
+ maxWidth = mLineWidth.getLineWidth(lineNum);
+ breakInfo.mBreaksList.add(p.location);
+ breakInfo.mWidthsList.add(printedWidth);
+ breakInfo.mFlagsList.add(firstTabIndex < i);
+ firstTabIndex = Integer.MAX_VALUE;
+ printedWidth = width = 0;
+ goodBreakFound = breakFound = false;
+ goodBreakWidth = breakWidth = 0;
+ continue;
+ }
+ if (i > breakIndex && (printedWidth <= maxWidth || !breakFound)) {
+ breakFound = true;
+ breakIndex = i;
+ breakWidth = printedWidth;
+ }
+ if (i > goodBreakIndex && printedWidth <= maxWidth) {
+ goodBreakFound = true;
+ goodBreakIndex = i;
+ goodBreakWidth = printedWidth;
+ }
+ } else if (p.type == PrimitiveType.WORD_BREAK) {
+ // only do this if necessary -- we don't want to break words
+ // when possible, but sometimes it is unavoidable
+ if (i > breakIndex && (printedWidth <= maxWidth || !breakFound)) {
+ breakFound = true;
+ breakIndex = i;
+ breakWidth = printedWidth;
+ }
+ }
+ }
+
+ if (breakFound || goodBreakFound) {
+ // output last break if there are more characters to output
+ if (goodBreakFound) {
+ breakInfo.mBreaksList.add(mPrimitives.get(goodBreakIndex).location);
+ breakInfo.mWidthsList.add(goodBreakWidth);
+ breakInfo.mFlagsList.add(firstTabIndex < goodBreakIndex);
+ } else {
+ breakInfo.mBreaksList.add(mPrimitives.get(breakIndex).location);
+ breakInfo.mWidthsList.add(breakWidth);
+ breakInfo.mFlagsList.add(firstTabIndex < breakIndex);
+ }
+ }
+ breakInfo.copyTo(lineBreaks);
+ }
+
+ private static class BreakInfo {
+ List<Integer> mBreaksList = new ArrayList<Integer>();
+ List<Float> mWidthsList = new ArrayList<Float>();
+ List<Boolean> mFlagsList = new ArrayList<Boolean>();
+
+ public void copyTo(LineBreaks lineBreaks) {
+ if (lineBreaks.breaks.length != mBreaksList.size()) {
+ lineBreaks.breaks = new int[mBreaksList.size()];
+ lineBreaks.widths = new float[mWidthsList.size()];
+ lineBreaks.flags = new int[mFlagsList.size()];
+ }
+
+ int i = 0;
+ for (int b : mBreaksList) {
+ lineBreaks.breaks[i] = b;
+ i++;
+ }
+ i = 0;
+ for (float b : mWidthsList) {
+ lineBreaks.widths[i] = b;
+ i++;
+ }
+ i = 0;
+ for (boolean b : mFlagsList) {
+ lineBreaks.flags[i] = b ? TAB_MASK : 0;
+ i++;
+ }
+
+ mBreaksList = null;
+ mWidthsList = null;
+ mFlagsList = null;
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
new file mode 100644
index 0000000..5a59597
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java
@@ -0,0 +1,44 @@
+/*
+ * 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.text;
+
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import java.io.File;
+
+/**
+ * Delegate that overrides implementation for certain methods in {@link android.text.StaticLayout}
+ * <p/>
+ * Through the layoutlib_create tool, selected methods of StaticLayout have been replaced
+ * by calls to methods of the same name in this delegate class.
+ */
+public class Hyphenator_Delegate {
+
+ private static final DelegateManager<Hyphenator_Delegate> sDelegateManager = new
+ DelegateManager<Hyphenator_Delegate>(Hyphenator_Delegate.class);
+
+ @LayoutlibDelegate
+ /*package*/ static File getSystemHyphenatorLocation() {
+ // FIXME
+ return null;
+ }
+
+ /*package*/ static long loadHyphenator(String patternData) {
+ return sDelegateManager.addNewDelegate(new Hyphenator_Delegate());
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/text/LineBreaker.java b/tools/layoutlib/bridge/src/android/text/LineBreaker.java
new file mode 100644
index 0000000..06e9c84
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/LineBreaker.java
@@ -0,0 +1,43 @@
+/*
+ * 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.text;
+
+import android.annotation.NonNull;
+import android.text.StaticLayout.LineBreaks;
+
+import java.util.Collections;
+import java.util.List;
+
+// Based on the native implementation of LineBreaker in
+// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260
+public abstract class LineBreaker {
+
+ protected static final int TAB_MASK = 0x20000000; // keep in sync with StaticLayout
+
+ protected final @NonNull List<Primitive> mPrimitives;
+ protected final @NonNull LineWidth mLineWidth;
+ protected final @NonNull TabStops mTabStops;
+
+ public LineBreaker(@NonNull List<Primitive> primitives, @NonNull LineWidth lineWidth,
+ @NonNull TabStops tabStops) {
+ mPrimitives = Collections.unmodifiableList(primitives);
+ mLineWidth = lineWidth;
+ mTabStops = tabStops;
+ }
+
+ public abstract void computeBreaks(@NonNull LineBreaks breakInfo);
+}
diff --git a/tools/layoutlib/bridge/src/android/text/LineWidth.java b/tools/layoutlib/bridge/src/android/text/LineWidth.java
new file mode 100644
index 0000000..2ea886d
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/LineWidth.java
@@ -0,0 +1,35 @@
+/*
+ * 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.text;
+
+// Based on the native implementation of LineWidth in
+// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260
+public class LineWidth {
+ private final float mFirstWidth;
+ private final int mFirstWidthLineCount;
+ private float mRestWidth;
+
+ public LineWidth(float firstWidth, int firstWidthLineCount, float restWidth) {
+ mFirstWidth = firstWidth;
+ mFirstWidthLineCount = firstWidthLineCount;
+ mRestWidth = restWidth;
+ }
+
+ public float getLineWidth(int line) {
+ return (line < mFirstWidthLineCount) ? mFirstWidth : mRestWidth;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java b/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java
new file mode 100644
index 0000000..ed8e33a
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java
@@ -0,0 +1,261 @@
+/*
+ * 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.text;
+
+import android.annotation.NonNull;
+import android.text.Primitive.PrimitiveType;
+import android.text.StaticLayout.LineBreaks;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+
+import static android.text.Primitive.PrimitiveType.PENALTY_INFINITY;
+
+
+// Based on the native implementation of OptimizingLineBreaker in
+// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260
+/**
+ * A more complex version of line breaking where we try to prevent the right edge from being too
+ * jagged.
+ */
+public class OptimizingLineBreaker extends LineBreaker {
+
+ public OptimizingLineBreaker(@NonNull List<Primitive> primitives, @NonNull LineWidth lineWidth,
+ @NonNull TabStops tabStops) {
+ super(primitives, lineWidth, tabStops);
+ }
+
+ @Override
+ public void computeBreaks(@NonNull LineBreaks breakInfo) {
+ int numBreaks = mPrimitives.size();
+ assert numBreaks > 0;
+ if (numBreaks == 1) {
+ // This can be true only if it's an empty paragraph.
+ Primitive p = mPrimitives.get(0);
+ assert p.type == PrimitiveType.PENALTY;
+ breakInfo.breaks = new int[]{0};
+ breakInfo.widths = new float[]{p.width};
+ breakInfo.flags = new int[]{0};
+ return;
+ }
+ Node[] opt = new Node[numBreaks];
+ opt[0] = new Node(-1, 0, 0, 0, false);
+ opt[numBreaks - 1] = new Node(-1, 0, 0, 0, false);
+
+ ArrayList<Integer> active = new ArrayList<Integer>();
+ active.add(0);
+ int lastBreak = 0;
+ for (int i = 0; i < numBreaks; i++) {
+ Primitive p = mPrimitives.get(i);
+ if (p.type == PrimitiveType.PENALTY) {
+ boolean finalBreak = (i + 1 == numBreaks);
+ Node bestBreak = null;
+
+ for (ListIterator<Integer> it = active.listIterator(); it.hasNext();
+ /* incrementing done in loop */) {
+ int pos = it.next();
+ int lines = opt[pos].mPrevCount;
+ float maxWidth = mLineWidth.getLineWidth(lines);
+ // we have to compute metrics every time --
+ // we can't really pre-compute this stuff and just deal with breaks
+ // because of the way tab characters work, this makes it computationally
+ // harder, but this way, we can still optimize while treating tab characters
+ // correctly
+ LineMetrics lineMetrics = computeMetrics(pos, i);
+ if (lineMetrics.mPrintedWidth <= maxWidth) {
+ float demerits = computeDemerits(maxWidth, lineMetrics.mPrintedWidth,
+ finalBreak, p.penalty) + opt[pos].mDemerits;
+ if (bestBreak == null || demerits < bestBreak.mDemerits) {
+ if (bestBreak == null) {
+ bestBreak = new Node(pos, opt[pos].mPrevCount + 1, demerits,
+ lineMetrics.mPrintedWidth, lineMetrics.mHasTabs);
+ } else {
+ bestBreak.mPrev = pos;
+ bestBreak.mPrevCount = opt[pos].mPrevCount + 1;
+ bestBreak.mDemerits = demerits;
+ bestBreak.mWidth = lineMetrics.mPrintedWidth;
+ bestBreak.mHasTabs = lineMetrics.mHasTabs;
+ }
+ }
+ } else {
+ it.remove();
+ }
+ }
+ if (p.penalty == -PENALTY_INFINITY) {
+ active.clear();
+ }
+ if (bestBreak != null) {
+ opt[i] = bestBreak;
+ active.add(i);
+ lastBreak = i;
+ }
+ if (active.isEmpty()) {
+ // we can't give up!
+ LineMetrics lineMetrics = new LineMetrics();
+ int lines = opt[lastBreak].mPrevCount;
+ float maxWidth = mLineWidth.getLineWidth(lines);
+ int breakIndex = desperateBreak(lastBreak, numBreaks, maxWidth, lineMetrics);
+ opt[breakIndex] = new Node(lastBreak, lines + 1, 0 /*doesn't matter*/,
+ lineMetrics.mWidth, lineMetrics.mHasTabs);
+ active.add(breakIndex);
+ lastBreak = breakIndex;
+ i = breakIndex; // incremented by i++
+ }
+ }
+ }
+
+ int idx = numBreaks - 1;
+ int count = opt[idx].mPrevCount;
+ resize(breakInfo, count);
+ while (opt[idx].mPrev != -1) {
+ count--;
+ assert count >=0;
+
+ breakInfo.breaks[count] = mPrimitives.get(idx).location;
+ breakInfo.widths[count] = opt[idx].mWidth;
+ breakInfo.flags [count] = opt[idx].mHasTabs ? TAB_MASK : 0;
+ idx = opt[idx].mPrev;
+ }
+ }
+
+ private static void resize(LineBreaks lineBreaks, int size) {
+ if (lineBreaks.breaks.length == size) {
+ return;
+ }
+ int[] breaks = new int[size];
+ float[] widths = new float[size];
+ int[] flags = new int[size];
+
+ int toCopy = Math.min(size, lineBreaks.breaks.length);
+ System.arraycopy(lineBreaks.breaks, 0, breaks, 0, toCopy);
+ System.arraycopy(lineBreaks.widths, 0, widths, 0, toCopy);
+ System.arraycopy(lineBreaks.flags, 0, flags, 0, toCopy);
+
+ lineBreaks.breaks = breaks;
+ lineBreaks.widths = widths;
+ lineBreaks.flags = flags;
+ }
+
+ @NonNull
+ private LineMetrics computeMetrics(int start, int end) {
+ boolean f = false;
+ float w = 0, pw = 0;
+ for (int i = start; i < end; i++) {
+ Primitive p = mPrimitives.get(i);
+ if (p.type == PrimitiveType.BOX || p.type == PrimitiveType.GLUE) {
+ w += p.width;
+ if (p.type == PrimitiveType.BOX) {
+ pw = w;
+ }
+ } else if (p.type == PrimitiveType.VARIABLE) {
+ w = mTabStops.width(w);
+ f = true;
+ }
+ }
+ return new LineMetrics(w, pw, f);
+ }
+
+ private static float computeDemerits(float maxWidth, float width, boolean finalBreak,
+ float penalty) {
+ float deviation = finalBreak ? 0 : maxWidth - width;
+ return (deviation * deviation) + penalty;
+ }
+
+ /**
+ * @return the last break position or -1 if failed.
+ */
+ @SuppressWarnings("ConstantConditions") // method too complex to be analyzed.
+ private int desperateBreak(int start, int limit, float maxWidth,
+ @NonNull LineMetrics lineMetrics) {
+ float w = 0, pw = 0;
+ boolean breakFound = false;
+ int breakIndex = 0, firstTabIndex = Integer.MAX_VALUE;
+ for (int i = start; i < limit; i++) {
+ Primitive p = mPrimitives.get(i);
+
+ if (p.type == PrimitiveType.BOX || p.type == PrimitiveType.GLUE) {
+ w += p.width;
+ if (p.type == PrimitiveType.BOX) {
+ pw = w;
+ }
+ } else if (p.type == PrimitiveType.VARIABLE) {
+ w = mTabStops.width(w);
+ firstTabIndex = Math.min(firstTabIndex, i);
+ }
+
+ if (pw > maxWidth && breakFound) {
+ break;
+ }
+
+ // must make progress
+ if (i > start &&
+ (p.type == PrimitiveType.PENALTY || p.type == PrimitiveType.WORD_BREAK)) {
+ breakFound = true;
+ breakIndex = i;
+ }
+ }
+
+ if (breakFound) {
+ lineMetrics.mWidth = w;
+ lineMetrics.mPrintedWidth = pw;
+ lineMetrics.mHasTabs = (start <= firstTabIndex && firstTabIndex < breakIndex);
+ return breakIndex;
+ } else {
+ return -1;
+ }
+ }
+
+ private static class LineMetrics {
+ /** Actual width of the line. */
+ float mWidth;
+ /** Width of the line minus trailing whitespace. */
+ float mPrintedWidth;
+ boolean mHasTabs;
+
+ public LineMetrics() {
+ }
+
+ public LineMetrics(float width, float printedWidth, boolean hasTabs) {
+ mWidth = width;
+ mPrintedWidth = printedWidth;
+ mHasTabs = hasTabs;
+ }
+ }
+
+ /**
+ * A struct to store the info about a break.
+ */
+ @SuppressWarnings("SpellCheckingInspection") // For the word struct.
+ private static class Node {
+ // -1 for the first node.
+ int mPrev;
+ // number of breaks so far.
+ int mPrevCount;
+ float mDemerits;
+ float mWidth;
+ boolean mHasTabs;
+
+ public Node(int prev, int prevCount, float demerits, float width, boolean hasTabs) {
+ mPrev = prev;
+ mPrevCount = prevCount;
+ mDemerits = demerits;
+ mWidth = width;
+ mHasTabs = hasTabs;
+ }
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/text/Primitive.java b/tools/layoutlib/bridge/src/android/text/Primitive.java
new file mode 100644
index 0000000..37ed072
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/Primitive.java
@@ -0,0 +1,92 @@
+/*
+ * 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.text;
+
+import android.annotation.NonNull;
+
+// Based on the native implementation of Primitive in
+// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260
+public class Primitive {
+ public final @NonNull PrimitiveType type;
+ public final int location;
+ // The following fields don't make sense for all types.
+ // Box and Glue have width only.
+ // Penalty has both width and penalty.
+ // Word_break has penalty only.
+ public final float width;
+ public final float penalty;
+
+ /**
+ * Use {@code PrimitiveType#getNewPrimitive()}
+ */
+ private Primitive(@NonNull PrimitiveType type, int location, float width, float penalty) {
+ this.type = type;
+ this.location = location;
+ this.width = width;
+ this.penalty = penalty;
+ }
+
+ public static enum PrimitiveType {
+ /**
+ * Something with a constant width that is to be typeset - like a character.
+ */
+ BOX,
+ /**
+ * Blank space with fixed width.
+ */
+ GLUE,
+ /**
+ * Aesthetic cost indicating how desirable breaking at this point will be. A penalty of
+ * {@link #PENALTY_INFINITY} means a forced non-break, whereas a penalty of negative
+ * {@code #PENALTY_INFINITY} means a forced break.
+ * <p/>
+ * Currently, it only stores penalty with values 0 or -infinity.
+ */
+ PENALTY,
+ /**
+ * For tabs - variable width space.
+ */
+ VARIABLE,
+ /**
+ * Possible breakpoints within a word. Think of this as a high cost {@link #PENALTY}.
+ */
+ WORD_BREAK;
+
+ public Primitive getNewPrimitive(int location) {
+ assert this == VARIABLE;
+ return new Primitive(this, location, 0f, 0f);
+ }
+
+ public Primitive getNewPrimitive(int location, float value) {
+ assert this == BOX || this == GLUE || this == WORD_BREAK;
+ if (this == BOX || this == GLUE) {
+ return new Primitive(this, location, value, 0f);
+ } else {
+ return new Primitive(this, location, 0f, value);
+ }
+ }
+
+ public Primitive getNewPrimitive(int location, float width, float penalty) {
+ assert this == PENALTY;
+ return new Primitive(this, location, width, penalty);
+ }
+
+ // forced non-break, negative infinity is forced break.
+ public static final float PENALTY_INFINITY = 1e7f;
+ }
+}
+
diff --git a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
index b0d79a8..1b0ba51 100644
--- a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java
@@ -1,14 +1,22 @@
package android.text;
+import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-import java.text.CharacterIterator;
+import android.annotation.NonNull;
+import android.graphics.BidiRenderer;
+import android.graphics.Paint;
+import android.graphics.Paint_Delegate;
+import android.graphics.RectF;
+import android.icu.text.BreakIterator;
+import android.icu.util.ULocale;
+import android.text.Primitive.PrimitiveType;
+import android.text.StaticLayout.LineBreaks;
+
+import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Locale;
+import java.util.List;
-import com.ibm.icu.lang.UCharacter;
-import com.ibm.icu.text.BreakIterator;
-import com.ibm.icu.util.ULocale;
import javax.swing.text.Segment;
/**
@@ -20,36 +28,206 @@ import javax.swing.text.Segment;
*/
public class StaticLayout_Delegate {
+ private static final char CHAR_SPACE = 0x20;
+ private static final char CHAR_TAB = 0x09;
+ private static final char CHAR_NEWLINE = 0x0A;
+ private static final char CHAR_ZWSP = 0x200B; // Zero width space.
+
+ // ---- Builder delegate manager ----
+ private static final DelegateManager<Builder> sBuilderManager =
+ new DelegateManager<Builder>(Builder.class);
+
+ @LayoutlibDelegate
+ /*package*/ static long nNewBuilder() {
+ return sBuilderManager.addNewDelegate(new Builder());
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nFreeBuilder(long nativeBuilder) {
+ sBuilderManager.removeJavaReferenceFor(nativeBuilder);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nFinishBuilder(long nativeBuilder) {
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static long nLoadHyphenator(String patternData) {
+ return Hyphenator_Delegate.loadHyphenator(patternData);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nSetLocale(long nativeBuilder, String locale, long nativeHyphenator) {
+ Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+ if (builder != null) {
+ builder.mLocale = locale;
+ builder.mNativeHyphenator = nativeHyphenator;
+ }
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nSetIndents(long nativeBuilder, int[] indents) {
+ // TODO.
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nSetupParagraph(long nativeBuilder, char[] text, int length,
+ float firstWidth, int firstWidthLineCount, float restWidth,
+ int[] variableTabStops, int defaultTabStop, int breakStrategy,
+ int hyphenationFrequency) {
+ Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+ if (builder == null) {
+ return;
+ }
+
+ builder.mText = text;
+ builder.mWidths = new float[length];
+ builder.mLineWidth = new LineWidth(firstWidth, firstWidthLineCount, restWidth);
+ builder.mTabStopCalculator = new TabStops(variableTabStops, defaultTabStop);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static float nAddStyleRun(long nativeBuilder, long nativePaint, long nativeTypeface,
+ int start, int end, boolean isRtl) {
+ Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+
+ int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
+ return builder == null ? 0 :
+ measureText(nativePaint, builder.mText, start, end - start, builder.mWidths,
+ bidiFlags);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nAddMeasuredRun(long nativeBuilder, int start, int end, float[] widths) {
+ Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+ if (builder != null) {
+ System.arraycopy(widths, start, builder.mWidths, start, end - start);
+ }
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nAddReplacementRun(long nativeBuilder, int start, int end, float width) {
+ Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+ if (builder == null) {
+ return;
+ }
+ builder.mWidths[start] = width;
+ Arrays.fill(builder.mWidths, start + 1, end, 0.0f);
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static void nGetWidths(long nativeBuilder, float[] floatsArray) {
+ Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+ if (builder != null) {
+ System.arraycopy(builder.mWidths, 0, floatsArray, 0, builder.mWidths.length);
+ }
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static int nComputeLineBreaks(long nativeBuilder,
+ LineBreaks recycle, int[] recycleBreaks, float[] recycleWidths,
+ int[] recycleFlags, int recycleLength) {
+
+ Builder builder = sBuilderManager.getDelegate(nativeBuilder);
+ if (builder == null) {
+ return 0;
+ }
+
+ // compute all possible breakpoints.
+ int length = builder.mWidths.length;
+ BreakIterator it = BreakIterator.getLineInstance(new ULocale(builder.mLocale));
+ it.setText(new Segment(builder.mText, 0, length));
+
+ // average word length in english is 5. So, initialize the possible breaks with a guess.
+ List<Integer> breaks = new ArrayList<Integer>((int) Math.ceil(length / 5d));
+ int loc;
+ it.first();
+ while ((loc = it.next()) != BreakIterator.DONE) {
+ breaks.add(loc);
+ }
+
+ List<Primitive> primitives =
+ computePrimitives(builder.mText, builder.mWidths, length, breaks);
+ switch (builder.mBreakStrategy) {
+ case Layout.BREAK_STRATEGY_SIMPLE:
+ builder.mLineBreaker = new GreedyLineBreaker(primitives, builder.mLineWidth,
+ builder.mTabStopCalculator);
+ break;
+ case Layout.BREAK_STRATEGY_HIGH_QUALITY:
+ // TODO
+// break;
+ case Layout.BREAK_STRATEGY_BALANCED:
+ builder.mLineBreaker = new OptimizingLineBreaker(primitives, builder.mLineWidth,
+ builder.mTabStopCalculator);
+ break;
+ default:
+ throw new AssertionError("Unknown break strategy: " + builder.mBreakStrategy);
+ }
+ builder.mLineBreaker.computeBreaks(recycle);
+ return recycle.breaks.length;
+ }
+
/**
- * Fills the recycle array with positions that are suitable to break the text at. The array
- * must be terminated by '-1'.
+ * Compute metadata each character - things which help in deciding if it's possible to break
+ * at a point or not.
*/
- @LayoutlibDelegate
- /*package*/ static int[] nLineBreakOpportunities(String locale, char[] text, int length,
- int[] recycle) {
- BreakIterator iterator = BreakIterator.getLineInstance(new ULocale(locale));
- Segment segment = new Segment(text, 0, length);
- iterator.setText(segment);
- if (recycle == null) {
- // Because 42 is the answer to everything.
- recycle = new int[42];
- }
- int breakOpp = iterator.first();
- recycle[0] = breakOpp;
- //noinspection ConstantConditions
- assert BreakIterator.DONE == -1;
- for (int i = 1; breakOpp != BreakIterator.DONE; ++i) {
- if (i >= recycle.length) {
- recycle = doubleSize(recycle);
+ @NonNull
+ private static List<Primitive> computePrimitives(@NonNull char[] text, @NonNull float[] widths,
+ int length, @NonNull List<Integer> breaks) {
+ // Initialize the list with a guess of the number of primitives:
+ // 2 Primitives per non-whitespace char and approx 5 chars per word (i.e. 83% chars)
+ List<Primitive> primitives = new ArrayList<Primitive>(((int) Math.ceil(length * 1.833)));
+ int breaksSize = breaks.size();
+ int breakIndex = 0;
+ for (int i = 0; i < length; i++) {
+ char c = text[i];
+ if (c == CHAR_SPACE || c == CHAR_ZWSP) {
+ primitives.add(PrimitiveType.GLUE.getNewPrimitive(i, widths[i]));
+ } else if (c == CHAR_TAB) {
+ primitives.add(PrimitiveType.VARIABLE.getNewPrimitive(i));
+ } else if (c != CHAR_NEWLINE) {
+ while (breakIndex < breaksSize && breaks.get(breakIndex) < i) {
+ breakIndex++;
+ }
+ Primitive p;
+ if (widths[i] != 0) {
+ if (breakIndex < breaksSize && breaks.get(breakIndex) == i) {
+ p = PrimitiveType.PENALTY.getNewPrimitive(i, 0, 0);
+ } else {
+ p = PrimitiveType.WORD_BREAK.getNewPrimitive(i, 0);
+ }
+ primitives.add(p);
+ }
+
+ primitives.add(PrimitiveType.BOX.getNewPrimitive(i, widths[i]));
}
- assert (i < recycle.length);
- breakOpp = iterator.next();
- recycle[i] = breakOpp;
}
- return recycle;
+ // final break at end of everything
+ primitives.add(
+ PrimitiveType.PENALTY.getNewPrimitive(length, 0, -PrimitiveType.PENALTY_INFINITY));
+ return primitives;
}
- private static int[] doubleSize(int[] array) {
- return Arrays.copyOf(array, array.length * 2);
+ private static float measureText(long nativePaint, char []text, int index, int count,
+ float[] widths, int bidiFlags) {
+ Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint);
+ RectF bounds = new BidiRenderer(null, paint, text)
+ .renderText(index, index + count, bidiFlags, widths, 0, false);
+ return bounds.right - bounds.left;
+ }
+
+ // TODO: Rename to LineBreakerRef and move everything other than LineBreaker to LineBreaker.
+ /**
+ * Java representation of the native Builder class.
+ */
+ private static class Builder {
+ String mLocale;
+ char[] mText;
+ float[] mWidths;
+ LineBreaker mLineBreaker;
+ long mNativeHyphenator;
+ int mBreakStrategy;
+ LineWidth mLineWidth;
+ TabStops mTabStopCalculator;
}
}
diff --git a/tools/layoutlib/bridge/src/android/text/TabStops.java b/tools/layoutlib/bridge/src/android/text/TabStops.java
new file mode 100644
index 0000000..6c2f1e1
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/TabStops.java
@@ -0,0 +1,44 @@
+/*
+ * 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.text;
+
+import android.annotation.Nullable;
+
+// Based on the native implementation of TabStops in
+// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260
+public class TabStops {
+ @Nullable
+ private int[] mStops;
+ private final int mTabWidth;
+
+ public TabStops(@Nullable int[] stops, int defaultTabWidth) {
+ mTabWidth = defaultTabWidth;
+ mStops = stops;
+ }
+
+ public float width(float widthSoFar) {
+ if (mStops != null) {
+ for (int i : mStops) {
+ if (i > widthSoFar) {
+ return i;
+ }
+ }
+ }
+ // find the next tabStop after widthSoFar.
+ return (int) ((widthSoFar + mTabWidth) / mTabWidth) * mTabWidth;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index da37fe0..1e33e3a 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -134,11 +134,11 @@ public final class BridgeInflater extends LayoutInflater {
}
@Override
- public View createViewFromTag(View parent, String name, AttributeSet attrs,
- boolean inheritContext) {
+ public View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
+ boolean ignoreThemeAttrs) {
View view;
try {
- view = super.createViewFromTag(parent, name, attrs, inheritContext);
+ view = super.createViewFromTag(parent, name, context, attrs, ignoreThemeAttrs);
} catch (InflateException e) {
// try to load the class from using the custom view loader
try {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 5176419..82012c1 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -17,6 +17,7 @@
package android.view;
import android.graphics.Point;
+import com.android.internal.app.IAssistScreenshotReceiver;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
@@ -215,6 +216,12 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
+ public void overridePendingAppTransitionClipReveal(int startX, int startY,
+ int startWidth, int startHeight) throws RemoteException {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
IRemoteCallback startedCallback, boolean scaleUp) throws RemoteException {
// TODO Auto-generated method stub
@@ -269,8 +276,15 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
- public Bitmap screenshotApplications(IBinder arg0, int displayId, int arg1,
- int arg2, boolean arg3) throws RemoteException {
+ public boolean requestAssistScreenshot(IAssistScreenshotReceiver receiver)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public Bitmap screenshotApplications(IBinder appToken, int displayId, int maxWidth,
+ int maxHeight) throws RemoteException {
// TODO Auto-generated method stub
return null;
}
@@ -293,7 +307,7 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
- public void setAppGroupId(IBinder arg0, int arg1) throws RemoteException {
+ public void setAppTask(IBinder arg0, int arg1) throws RemoteException {
// TODO Auto-generated method stub
}
@@ -362,6 +376,10 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
+ public void setForcedDisplayScalingMode(int displayId, int mode) {
+ }
+
+ @Override
public void setInTouchMode(boolean arg0) throws RemoteException {
// TODO Auto-generated method stub
}
diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
index 579f274..27b406a 100644
--- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java
@@ -21,9 +21,11 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.content.Context;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.util.Xml;
import java.io.IOException;
@@ -36,9 +38,13 @@ import java.io.IOException;
*
*/
public class LayoutInflater_Delegate {
-
private static final String TAG_MERGE = "merge";
+ private static final String ATTR_LAYOUT = "layout";
+
+ private static final int[] ATTRS_THEME = new int[] {
+ com.android.internal.R.attr.theme };
+
public static boolean sIsInInclude = false;
/**
@@ -49,7 +55,7 @@ public class LayoutInflater_Delegate {
*/
@LayoutlibDelegate
/* package */ static void rInflate(LayoutInflater thisInflater, XmlPullParser parser,
- View parent, final AttributeSet attrs, boolean finishInflate, boolean inheritContext)
+ View parent, Context context, AttributeSet attrs, boolean finishInflate)
throws XmlPullParserException, IOException {
if (finishInflate == false) {
@@ -61,7 +67,7 @@ public class LayoutInflater_Delegate {
// ---- START DEFAULT IMPLEMENTATION.
- thisInflater.rInflate_Original(parser, parent, attrs, finishInflate, inheritContext);
+ thisInflater.rInflate_Original(parser, parent, context, attrs, finishInflate);
// ---- END DEFAULT IMPLEMENTATION.
@@ -74,15 +80,50 @@ public class LayoutInflater_Delegate {
}
@LayoutlibDelegate
- public static void parseInclude(LayoutInflater thisInflater, XmlPullParser parser, View parent,
- AttributeSet attrs, boolean inheritContext) throws XmlPullParserException, IOException {
-
+ public static void parseInclude(LayoutInflater thisInflater, XmlPullParser parser,
+ Context context, View parent, AttributeSet attrs)
+ throws XmlPullParserException, IOException {
int type;
if (parent instanceof ViewGroup) {
- final int layout = attrs.getAttributeResourceValue(null, "layout", 0);
+ // Apply a theme wrapper, if requested. This is sort of a weird
+ // edge case, since developers think the <include> overwrites
+ // values in the AttributeSet of the included View. So, if the
+ // included View has a theme attribute, we'll need to ignore it.
+ final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
+ final int themeResId = ta.getResourceId(0, 0);
+ final boolean hasThemeOverride = themeResId != 0;
+ if (hasThemeOverride) {
+ context = new ContextThemeWrapper(context, themeResId);
+ }
+ ta.recycle();
+
+ // If the layout is pointing to a theme attribute, we have to
+ // massage the value to get a resource identifier out of it.
+ int layout = attrs.getAttributeResourceValue(null, ATTR_LAYOUT, 0);
if (layout == 0) {
- final String value = attrs.getAttributeValue(null, "layout");
+ final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
+ if (value == null || value.length() <= 0) {
+ throw new InflateException("You must specify a layout in the"
+ + " include tag: <include layout=\"@layout/layoutID\" />");
+ }
+
+ // Attempt to resolve the "?attr/name" string to an identifier.
+ layout = context.getResources().getIdentifier(value.substring(1), null, null);
+ }
+
+ // The layout might be referencing a theme attribute.
+ // ---- START CHANGES
+ if (layout != 0) {
+ final TypedValue tempValue = new TypedValue();
+ if (context.getTheme().resolveAttribute(layout, tempValue, true)) {
+ layout = tempValue.resourceId;
+ }
+ }
+ // ---- END CHANGES
+
+ if (layout == 0) {
+ final String value = attrs.getAttributeValue(null, ATTR_LAYOUT);
if (value == null) {
throw new InflateException("You must specifiy a layout in the"
+ " include tag: <include layout=\"@layout/layoutID\" />");
@@ -111,13 +152,20 @@ public class LayoutInflater_Delegate {
if (TAG_MERGE.equals(childName)) {
// Inflate all children.
- thisInflater.rInflate(childParser, parent, childAttrs, false,
- inheritContext);
+ thisInflater.rInflate(childParser, parent, context, childAttrs, false);
} else {
final View view = thisInflater.createViewFromTag(parent, childName,
- childAttrs, inheritContext);
+ context, childAttrs, hasThemeOverride);
final ViewGroup group = (ViewGroup) parent;
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, com.android.internal.R.styleable.Include);
+ final int id = a.getResourceId(
+ com.android.internal.R.styleable.Include_id, View.NO_ID);
+ final int visibility = a.getInt(
+ com.android.internal.R.styleable.Include_visibility, -1);
+ a.recycle();
+
// We try to load the layout params set in the <include /> tag. If
// they don't exist, we will rely on the layout params set in the
// included XML file.
@@ -133,30 +181,20 @@ public class LayoutInflater_Delegate {
// ---- END CHANGES
params = group.generateLayoutParams(attrs);
-
} catch (RuntimeException ignored) {
// Ignore, just fail over to child attrs.
} finally {
// ---- START CHANGES
sIsInInclude = false;
// ---- END CHANGES
-
- if (params != null) {
- view.setLayoutParams(params);
- }
}
+ if (params == null) {
+ params = group.generateLayoutParams(childAttrs);
+ }
+ view.setLayoutParams(params);
// Inflate all children.
- thisInflater.rInflate(childParser, view, childAttrs, true, true);
-
- // Attempt to override the included layout's android:id with the
- // one set on the <include /> tag itself.
- TypedArray a = thisInflater.mContext.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.View, 0, 0);
- int id = a.getResourceId(com.android.internal.R.styleable.View_id, View.NO_ID);
- // While we're at it, let's try to override android:visibility.
- int visibility = a.getInt(com.android.internal.R.styleable.View_visibility, -1);
- a.recycle();
+ thisInflater.rInflateChildren(childParser, view, childAttrs, true);
if (id != View.NO_ID) {
view.setId(id);
@@ -184,12 +222,6 @@ public class LayoutInflater_Delegate {
throw new InflateException("<include /> can only be used inside of a ViewGroup");
}
- final int currentDepth = parser.getDepth();
- while (((type = parser.next()) != XmlPullParser.END_TAG ||
- parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
- // Empty
- }
+ LayoutInflater.consumeChildElements(parser);
}
-
-
}
diff --git a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
index e72a0db..51d32e3 100644
--- a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java
@@ -46,16 +46,12 @@ public class ViewGroup_Delegate {
/*package*/ static boolean drawChild(ViewGroup thisVG, Canvas canvas, View child,
long drawingTime) {
if (child.getZ() > thisVG.getZ()) {
+ // The background's bounds are set lazily. Make sure they are set correctly so that
+ // the outline obtained is correct.
+ child.setBackgroundBounds();
ViewOutlineProvider outlineProvider = child.getOutlineProvider();
- Outline outline = new Outline();
+ Outline outline = child.mAttachInfo.mTmpOutline;
outlineProvider.getOutline(child, outline);
- if (outline.mPath == null && outline.mRect == null) {
- // Sometimes, the bounds of the background drawable are not set until View.draw()
- // is called. So, we set the bounds manually and try to get the outline again.
- child.getBackground().setBounds(0, 0, child.mRight - child.mLeft,
- child.mBottom - child.mTop);
- outlineProvider.getOutline(child, outline);
- }
if (outline.mPath != null || (outline.mRect != null && !outline.mRect.isEmpty())) {
int restoreTo = transformCanvas(thisVG, canvas, child);
drawShadow(thisVG, canvas, child, outline);
diff --git a/tools/layoutlib/bridge/src/android/view/View_Delegate.java b/tools/layoutlib/bridge/src/android/view/View_Delegate.java
index 8215f7c..408ec54 100644
--- a/tools/layoutlib/bridge/src/android/view/View_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/View_Delegate.java
@@ -16,8 +16,12 @@
package android.view;
+import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import android.content.Context;
+import android.os.IBinder;
+
/**
* Delegate used to provide new implementation of a select few methods of {@link View}
*
@@ -31,4 +35,13 @@ public class View_Delegate {
/*package*/ static boolean isInEditMode(View thisView) {
return true;
}
+
+ @LayoutlibDelegate
+ /*package*/ static IBinder getWindowToken(View thisView) {
+ Context baseContext = BridgeContext.getBaseContext(thisView.getContext());
+ if (baseContext instanceof BridgeContext) {
+ return ((BridgeContext) baseContext).getBinder();
+ }
+ return null;
+ }
}
diff --git a/tools/layoutlib/bridge/src/android/view/WindowCallback.java b/tools/layoutlib/bridge/src/android/view/WindowCallback.java
index 78242a8..d691c8e 100644
--- a/tools/layoutlib/bridge/src/android/view/WindowCallback.java
+++ b/tools/layoutlib/bridge/src/android/view/WindowCallback.java
@@ -110,6 +110,11 @@ public class WindowCallback implements Window.Callback {
}
@Override
+ public boolean onSearchRequested(SearchEvent searchEvent) {
+ return onSearchRequested();
+ }
+
+ @Override
public boolean onSearchRequested() {
return false;
}
@@ -120,6 +125,11 @@ public class WindowCallback implements Window.Callback {
}
@Override
+ public ActionMode onWindowStartingActionMode(Callback callback, int type) {
+ return null;
+ }
+
+ @Override
public void onActionModeStarted(ActionMode mode) {
}
diff --git a/tools/layoutlib/bridge/src/android/widget/SimpleMonthView_Delegate.java b/tools/layoutlib/bridge/src/android/widget/SimpleMonthView_Delegate.java
new file mode 100644
index 0000000..8e41e51
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/widget/SimpleMonthView_Delegate.java
@@ -0,0 +1,99 @@
+/*
+ * 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.widget;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.icu.text.SimpleDateFormat;
+import android.text.format.DateFormat;
+
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * Delegate that provides implementation for some methods in {@link SimpleMonthView}.
+ * <p/>
+ * Through the layoutlib_create tool, selected methods of SimpleMonthView have been replaced by
+ * calls to methods of the same name in this delegate class.
+ * <p/>
+ * The main purpose of this class is to use {@link android.icu.text.SimpleDateFormat} instead of
+ * {@link java.text.SimpleDateFormat}.
+ */
+public class SimpleMonthView_Delegate {
+
+ private static final String DEFAULT_TITLE_FORMAT = "MMMMy";
+ private static final String DAY_OF_WEEK_FORMAT = "EEEEE";
+
+ // Maintain a cache of the last view used, so that the formatters can be reused.
+ @Nullable private static SimpleMonthView sLastView;
+ @Nullable private static SimpleMonthView_Delegate sLastDelegate;
+
+ private SimpleDateFormat mTitleFormatter;
+ private SimpleDateFormat mDayOfWeekFormatter;
+
+ private Locale locale;
+
+ @LayoutlibDelegate
+ /*package*/ static CharSequence getTitle(SimpleMonthView view) {
+ if (view.mTitle == null) {
+ SimpleMonthView_Delegate delegate = getDelegate(view);
+ if (delegate.mTitleFormatter == null) {
+ delegate.mTitleFormatter = new SimpleDateFormat(DateFormat.getBestDateTimePattern(
+ getLocale(delegate, view), DEFAULT_TITLE_FORMAT));
+ }
+ view.mTitle = delegate.mTitleFormatter.format(view.mCalendar.getTime());
+ }
+ return view.mTitle;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static String getDayOfWeekLabel(SimpleMonthView view, int dayOfWeek) {
+ view.mDayOfWeekLabelCalendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
+ SimpleMonthView_Delegate delegate = getDelegate(view);
+ if (delegate.mDayOfWeekFormatter == null) {
+ delegate.mDayOfWeekFormatter =
+ new SimpleDateFormat(DAY_OF_WEEK_FORMAT, getLocale(delegate, view));
+ }
+ return delegate.mDayOfWeekFormatter.format(view.mDayOfWeekLabelCalendar.getTime());
+ }
+
+ private static Locale getLocale(SimpleMonthView_Delegate delegate, SimpleMonthView view) {
+ if (delegate.locale == null) {
+ delegate.locale = view.getContext().getResources().getConfiguration().locale;
+ }
+ return delegate.locale;
+ }
+
+ @NonNull
+ private static SimpleMonthView_Delegate getDelegate(SimpleMonthView view) {
+ if (view == sLastView) {
+ assert sLastDelegate != null;
+ return sLastDelegate;
+ } else {
+ sLastView = view;
+ sLastDelegate = new SimpleMonthView_Delegate();
+ return sLastDelegate;
+ }
+ }
+
+ public static void clearCache() {
+ sLastView = null;
+ sLastDelegate = null;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/internal/policy/PolicyManager.java b/tools/layoutlib/bridge/src/com/android/internal/policy/PolicyManager.java
deleted file mode 100644
index 6558b6a..0000000
--- a/tools/layoutlib/bridge/src/com/android/internal/policy/PolicyManager.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2012 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.policy;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.RenderAction;
-
-import android.content.Context;
-import android.view.BridgeInflater;
-import android.view.FallbackEventHandler;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManagerPolicy;
-
-/**
- * Custom implementation of PolicyManager that does nothing to run in LayoutLib.
- *
- */
-public class PolicyManager {
-
- public static Window makeNewWindow(Context context) {
- // this will likely crash somewhere beyond so we log it.
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "Call to PolicyManager.makeNewWindow is not supported", null);
- return null;
- }
-
- public static LayoutInflater makeNewLayoutInflater(Context context) {
- return new BridgeInflater(context, RenderAction.getCurrentContext().getLayoutlibCallback());
- }
-
- public static WindowManagerPolicy makeNewWindowManager() {
- // this will likely crash somewhere beyond so we log it.
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "Call to PolicyManager.makeNewWindowManager is not supported", null);
- return null;
- }
-
- public static FallbackEventHandler makeNewFallbackEventHandler(Context context) {
- return new FallbackEventHandler() {
- @Override
- public void setView(View v) {
- }
-
- @Override
- public void preDispatchKeyEvent(KeyEvent event) {
- }
-
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- return false;
- }
- };
- }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 0fede75..48ca7d8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -16,9 +16,6 @@
package com.android.layoutlib.bridge;
-import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
-import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
-
import com.android.ide.common.rendering.api.Capability;
import com.android.ide.common.rendering.api.DrawableParams;
import com.android.ide.common.rendering.api.Features;
@@ -35,14 +32,13 @@ import com.android.resources.ResourceType;
import com.android.tools.layoutlib.create.MethodAdapter;
import com.android.tools.layoutlib.create.OverrideMethod;
import com.android.util.Pair;
-import com.ibm.icu.util.ULocale;
-import libcore.io.MemoryMappedFile_Delegate;
import android.annotation.NonNull;
import android.content.res.BridgeAssetManager;
import android.graphics.Bitmap;
import android.graphics.FontFamily_Delegate;
import android.graphics.Typeface_Delegate;
+import android.icu.util.ULocale;
import android.os.Looper;
import android.os.Looper_Accessor;
import android.view.View;
@@ -61,6 +57,11 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
+import libcore.io.MemoryMappedFile_Delegate;
+
+import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
+import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
+
/**
* Main entry point of the LayoutLib Bridge.
* <p/>To use this bridge, simply instantiate an object of type {@link Bridge} and call
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
index 4a9f718..44a9aad 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
@@ -30,6 +30,10 @@ import android.widget.TextView;
*/
public class MockView extends TextView {
+ public MockView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
public MockView(Context context, AttributeSet attrs, int defStyle) {
this(context, attrs, defStyle, 0);
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java
index ea5f1ea..faaf105 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java
@@ -16,9 +16,11 @@
package com.android.layoutlib.bridge.android;
-import java.util.Locale;
+import com.android.layoutlib.bridge.impl.RenderAction;
+
+import android.icu.util.ULocale;
-import com.ibm.icu.util.ULocale;
+import java.util.Locale;
/**
* This class provides an alternate implementation for {@code java.util.Locale#toLanguageTag}
@@ -56,4 +58,15 @@ public class AndroidLocale {
public static String getScript(Locale locale) {
return ULocale.forLocale(locale).getScript();
}
+
+ public static Locale getDefault() {
+ BridgeContext context = RenderAction.getCurrentContext();
+ if (context != null) {
+ Locale locale = context.getConfiguration().locale;
+ if (locale != null) {
+ return locale;
+ }
+ }
+ return Locale.getDefault();
+ }
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 9555e9e..689e359 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -68,6 +68,7 @@ import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IInterface;
import android.os.Looper;
import android.os.Parcel;
import android.os.PowerManager;
@@ -79,6 +80,7 @@ import android.util.TypedValue;
import android.view.BridgeInflater;
import android.view.Display;
import android.view.DisplayAdjustments;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -86,6 +88,7 @@ import android.view.accessibility.AccessibilityManager;
import android.view.textservice.TextServicesManager;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -146,6 +149,8 @@ public final class BridgeContext extends Context {
private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<BridgeXmlBlockParser>();
private SharedPreferences mSharedPreferences;
private ClassLoader mClassLoader;
+ private IBinder mBinder;
+ private PackageManager mPackageManager;
/**
@@ -559,6 +564,34 @@ public final class BridgeContext extends Context {
throw new UnsupportedOperationException("Unsupported Service: " + service);
}
+ @Override
+ public String getSystemServiceName(Class<?> serviceClass) {
+ if (serviceClass.equals(LayoutInflater.class)) {
+ return LAYOUT_INFLATER_SERVICE;
+ }
+
+ if (serviceClass.equals(TextServicesManager.class)) {
+ return TEXT_SERVICES_MANAGER_SERVICE;
+ }
+
+ if (serviceClass.equals(WindowManager.class)) {
+ return WINDOW_SERVICE;
+ }
+
+ if (serviceClass.equals(PowerManager.class)) {
+ return POWER_SERVICE;
+ }
+
+ if (serviceClass.equals(DisplayManager.class)) {
+ return DISPLAY_SERVICE;
+ }
+
+ if (serviceClass.equals(AccessibilityManager.class)) {
+ return ACCESSIBILITY_SERVICE;
+ }
+
+ throw new UnsupportedOperationException("Unsupported Service: " + serviceClass);
+ }
@Override
public final BridgeTypedArray obtainStyledAttributes(int[] attrs) {
@@ -880,6 +913,14 @@ public final class BridgeContext extends Context {
return mApplicationInfo.packageName;
}
+ @Override
+ public PackageManager getPackageManager() {
+ if (mPackageManager == null) {
+ mPackageManager = new BridgePackageManager();
+ }
+ return mPackageManager;
+ }
+
// ------------- private new methods
/**
@@ -1039,6 +1080,61 @@ public final class BridgeContext extends Context {
return context;
}
+ public IBinder getBinder() {
+ if (mBinder == null) {
+ // create a dummy binder. We only need it be not null.
+ mBinder = new IBinder() {
+ @Override
+ public String getInterfaceDescriptor() throws RemoteException {
+ return null;
+ }
+
+ @Override
+ public boolean pingBinder() {
+ return false;
+ }
+
+ @Override
+ public boolean isBinderAlive() {
+ return false;
+ }
+
+ @Override
+ public IInterface queryLocalInterface(String descriptor) {
+ return null;
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, String[] args) throws RemoteException {
+
+ }
+
+ @Override
+ public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException {
+
+ }
+
+ @Override
+ public boolean transact(int code, Parcel data, Parcel reply, int flags)
+ throws RemoteException {
+ return false;
+ }
+
+ @Override
+ public void linkToDeath(DeathRecipient recipient, int flags)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public boolean unlinkToDeath(DeathRecipient recipient, int flags) {
+ return false;
+ }
+ };
+ }
+ return mBinder;
+ }
+
//------------ NOT OVERRIDEN --------------------
@Override
@@ -1078,6 +1174,12 @@ public final class BridgeContext extends Context {
}
@Override
+ public int checkSelfPermission(String arg0) {
+ // pass
+ return 0;
+ }
+
+ @Override
public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) {
// pass
return 0;
@@ -1281,12 +1383,6 @@ public final class BridgeContext extends Context {
}
@Override
- public PackageManager getPackageManager() {
- // pass
- return null;
- }
-
- @Override
public String getBasePackageName() {
// pass
return null;
@@ -1421,6 +1517,18 @@ public final class BridgeContext extends Context {
}
@Override
+ public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
+ // pass
+
+ }
+
+ @Override
+ public void sendBroadcast(Intent arg0, String arg1, Bundle arg2) {
+ // pass
+
+ }
+
+ @Override
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
// pass
}
@@ -1440,6 +1548,14 @@ public final class BridgeContext extends Context {
}
@Override
+ public void sendOrderedBroadcast(Intent arg0, String arg1,
+ Bundle arg7, BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
+ Bundle arg6) {
+ // pass
+
+ }
+
+ @Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {
@@ -1457,6 +1573,11 @@ public final class BridgeContext extends Context {
// pass
}
+ public void sendBroadcastAsUser(Intent intent, UserHandle user,
+ String receiverPermission, int appOp) {
+ // pass
+ }
+
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
@@ -1473,6 +1594,14 @@ public final class BridgeContext extends Context {
}
@Override
+ public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
+ String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
+ Handler scheduler,
+ int initialCode, String initialData, Bundle initialExtras) {
+ // pass
+ }
+
+ @Override
public void sendStickyBroadcast(Intent arg0) {
// pass
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index c44a57c..8899e53 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -164,7 +164,8 @@ public class BridgeIInputMethodManager implements IInputMethodManager {
}
@Override
- public void showInputMethodPickerFromClient(IInputMethodClient arg0) throws RemoteException {
+ public void showInputMethodPickerFromClient(IInputMethodClient arg0,
+ int arg1) throws RemoteException {
// TODO Auto-generated method stub
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
new file mode 100644
index 0000000..f04654e
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java
@@ -0,0 +1,778 @@
+/*
+ * 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 com.android.layoutlib.bridge.android;
+
+import android.app.PackageInstallObserver;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ContainerEncryptionParams;
+import android.content.pm.FeatureInfo;
+import android.content.pm.IPackageDataObserver;
+import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageStatsObserver;
+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;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+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;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.os.storage.VolumeInfo;
+import java.util.List;
+
+/**
+ * An implementation of {@link PackageManager} that does nothing.
+ */
+@SuppressWarnings("deprecation")
+public class BridgePackageManager extends PackageManager {
+ @Override
+ public PackageInfo getPackageInfo(String packageName, int flags) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public String[] currentToCanonicalPackageNames(String[] names) {
+ return new String[0];
+ }
+
+ @Override
+ public String[] canonicalToCurrentPackageNames(String[] names) {
+ return new String[0];
+ }
+
+ @Override
+ public Intent getLaunchIntentForPackage(String packageName) {
+ return null;
+ }
+
+ @Override
+ public Intent getLeanbackLaunchIntentForPackage(String packageName) {
+ return null;
+ }
+
+ @Override
+ public int[] getPackageGids(String packageName) throws NameNotFoundException {
+ return new int[0];
+ }
+
+ @Override
+ public int getPackageUid(String packageName, int userHandle) throws NameNotFoundException {
+ return 0;
+ }
+
+ @Override
+ public PermissionInfo getPermissionInfo(String name, int flags) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public PermissionGroupInfo getPermissionGroupInfo(String name, int flags)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
+ return null;
+ }
+
+ @Override
+ public ApplicationInfo getApplicationInfo(String packageName, int flags)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public ActivityInfo getActivityInfo(ComponentName component, int flags)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public ActivityInfo getReceiverInfo(ComponentName component, int flags)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public ServiceInfo getServiceInfo(ComponentName component, int flags)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public ProviderInfo getProviderInfo(ComponentName component, int flags)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public List<PackageInfo> getInstalledPackages(int flags) {
+ return null;
+ }
+
+ @Override
+ public List<PackageInfo> getPackagesHoldingPermissions(String[] permissions, int flags) {
+ return null;
+ }
+
+ @Override
+ public List<PackageInfo> getInstalledPackages(int flags, int userId) {
+ return null;
+ }
+
+ @Override
+ public int checkPermission(String permName, String pkgName) {
+ return 0;
+ }
+
+ @Override
+ public boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
+ return false;
+ }
+
+ @Override
+ public String getPermissionControllerPackageName() {
+ return null;
+ }
+
+ @Override
+ public boolean addPermission(PermissionInfo info) {
+ return false;
+ }
+
+ @Override
+ public boolean addPermissionAsync(PermissionInfo info) {
+ return false;
+ }
+
+ @Override
+ public void removePermission(String name) {
+ }
+
+ @Override
+ public void grantRuntimePermission(String packageName, String permissionName, UserHandle user) {
+ }
+
+ @Override
+ public void revokeRuntimePermission(String packageName, String permissionName,
+ UserHandle user) {
+ }
+
+ @Override
+ public int getPermissionFlags(String permissionName, String packageName, UserHandle user) {
+ return 0;
+ }
+
+ @Override
+ public void updatePermissionFlags(String permissionName, String packageName, int flagMask,
+ int flagValues, UserHandle user) {
+ }
+
+ @Override
+ public boolean shouldShowRequestPermissionRationale(String permission) {
+ return false;
+ }
+
+ @Override
+ public int checkSignatures(String pkg1, String pkg2) {
+ return 0;
+ }
+
+ @Override
+ public int checkSignatures(int uid1, int uid2) {
+ return 0;
+ }
+
+ @Override
+ public String[] getPackagesForUid(int uid) {
+ return new String[0];
+ }
+
+ @Override
+ public String getNameForUid(int uid) {
+ return null;
+ }
+
+ @Override
+ public int getUidForSharedUser(String sharedUserName) throws NameNotFoundException {
+ return 0;
+ }
+
+ @Override
+ public List<ApplicationInfo> getInstalledApplications(int flags) {
+ return null;
+ }
+
+ @Override
+ public String[] getSystemSharedLibraryNames() {
+ return new String[0];
+ }
+
+ @Override
+ public FeatureInfo[] getSystemAvailableFeatures() {
+ return new FeatureInfo[0];
+ }
+
+ @Override
+ public boolean hasSystemFeature(String name) {
+ return false;
+ }
+
+ @Override
+ public ResolveInfo resolveActivity(Intent intent, int flags) {
+ return null;
+ }
+
+ @Override
+ public ResolveInfo resolveActivityAsUser(Intent intent, int flags, int userId) {
+ return null;
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
+ return null;
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) {
+ return null;
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller, Intent[] specifics,
+ Intent intent, int flags) {
+ return null;
+ }
+
+ @Override
+ public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
+ return null;
+ }
+
+ @Override
+ public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags, int userId) {
+ return null;
+ }
+
+ @Override
+ public ResolveInfo resolveService(Intent intent, int flags) {
+ return null;
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
+ return null;
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
+ return null;
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentContentProvidersAsUser(Intent intent, int flags,
+ int userId) {
+ return null;
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentContentProviders(Intent intent, int flags) {
+ return null;
+ }
+
+ @Override
+ public ProviderInfo resolveContentProvider(String name, int flags) {
+ return null;
+ }
+
+ @Override
+ public ProviderInfo resolveContentProviderAsUser(String name, int flags, int userId) {
+ return null;
+ }
+
+ @Override
+ public List<ProviderInfo> queryContentProviders(String processName, int uid, int flags) {
+ return null;
+ }
+
+ @Override
+ public InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public List<InstrumentationInfo> queryInstrumentation(String targetPackage, int flags) {
+ return null;
+ }
+
+ @Override
+ public Drawable getDrawable(String packageName, int resid, ApplicationInfo appInfo) {
+ return null;
+ }
+
+ @Override
+ public Drawable getActivityIcon(ComponentName activityName) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Drawable getActivityIcon(Intent intent) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Drawable getActivityBanner(ComponentName activityName) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Drawable getActivityBanner(Intent intent) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Drawable getDefaultActivityIcon() {
+ return null;
+ }
+
+ @Override
+ public Drawable getApplicationIcon(ApplicationInfo info) {
+ return null;
+ }
+
+ @Override
+ public Drawable getApplicationIcon(String packageName) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Drawable getApplicationBanner(ApplicationInfo info) {
+ return null;
+ }
+
+ @Override
+ public Drawable getApplicationBanner(String packageName) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Drawable getActivityLogo(ComponentName activityName) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Drawable getActivityLogo(Intent intent) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Drawable getApplicationLogo(ApplicationInfo info) {
+ return null;
+ }
+
+ @Override
+ public Drawable getApplicationLogo(String packageName) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Drawable getUserBadgedIcon(Drawable icon, UserHandle user) {
+ return null;
+ }
+
+ @Override
+ public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user,
+ Rect badgeLocation, int badgeDensity) {
+ return null;
+ }
+
+ @Override
+ public Drawable getUserBadgeForDensity(UserHandle user, int density) {
+ return null;
+ }
+
+ @Override
+ public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
+ return null;
+ }
+
+ @Override
+ public CharSequence getText(String packageName, int resid, ApplicationInfo appInfo) {
+ return null;
+ }
+
+ @Override
+ public XmlResourceParser getXml(String packageName, int resid, ApplicationInfo appInfo) {
+ return null;
+ }
+
+ @Override
+ public CharSequence getApplicationLabel(ApplicationInfo info) {
+ return null;
+ }
+
+ @Override
+ public Resources getResourcesForActivity(ComponentName activityName)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Resources getResourcesForApplication(ApplicationInfo app) throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Resources getResourcesForApplication(String appPackageName)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public Resources getResourcesForApplicationAsUser(String appPackageName, int userId)
+ throws NameNotFoundException {
+ return null;
+ }
+
+ @Override
+ public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
+ String installerPackageName) {
+ }
+
+ @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 void verifyPendingInstall(int id, int verificationCode) {
+ }
+
+ @Override
+ public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
+ long millisecondsToDelay) {
+ }
+
+ @Override
+ public void verifyIntentFilter(int verificationId, int verificationCode,
+ List<String> outFailedDomains) {
+ }
+
+ @Override
+ public int getIntentVerificationStatus(String packageName, int userId) {
+ return 0;
+ }
+
+ @Override
+ public boolean updateIntentVerificationStatus(String packageName, int status, int userId) {
+ return false;
+ }
+
+ @Override
+ public List<IntentFilterVerificationInfo> getIntentFilterVerifications(String packageName) {
+ return null;
+ }
+
+ @Override
+ public List<IntentFilter> getAllIntentFilters(String packageName) {
+ return null;
+ }
+
+ @Override
+ public String getDefaultBrowserPackageName(int userId) {
+ return null;
+ }
+
+ @Override
+ public boolean setDefaultBrowserPackageName(String packageName, int userId) {
+ return false;
+ }
+
+ @Override
+ public void setInstallerPackageName(String targetPackage, String installerPackageName) {
+ }
+
+ @Override
+ public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
+ }
+
+ @Override
+ public String getInstallerPackageName(String packageName) {
+ return null;
+ }
+
+ @Override
+ public void clearApplicationUserData(String packageName, IPackageDataObserver observer) {
+ }
+
+ @Override
+ public void deleteApplicationCacheFiles(String packageName, IPackageDataObserver observer) {
+ }
+
+ @Override
+ public void freeStorageAndNotify(String volumeUuid, long freeStorageSize,
+ IPackageDataObserver observer) {
+ }
+
+ @Override
+ public void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {
+ }
+
+ @Override
+ public void getPackageSizeInfo(String packageName, int userHandle,
+ IPackageStatsObserver observer) {
+ }
+
+ @Override
+ public void addPackageToPreferred(String packageName) {
+ }
+
+ @Override
+ public void removePackageFromPreferred(String packageName) {
+ }
+
+ @Override
+ public List<PackageInfo> getPreferredPackages(int flags) {
+ return null;
+ }
+
+ @Override
+ public void addPreferredActivity(IntentFilter filter, int match, ComponentName[] set,
+ ComponentName activity) {
+ }
+
+ @Override
+ public void replacePreferredActivity(IntentFilter filter, int match, ComponentName[] set,
+ ComponentName activity) {
+ }
+
+ @Override
+ public void clearPackagePreferredActivities(String packageName) {
+ }
+
+ @Override
+ public int getPreferredActivities(List<IntentFilter> outFilters,
+ List<ComponentName> outActivities, String packageName) {
+ return 0;
+ }
+
+ @Override
+ public ComponentName getHomeActivities(List<ResolveInfo> outActivities) {
+ return null;
+ }
+
+ @Override
+ public void setComponentEnabledSetting(ComponentName componentName, int newState, int flags) {
+ }
+
+ @Override
+ public int getComponentEnabledSetting(ComponentName componentName) {
+ return 0;
+ }
+
+ @Override
+ public void setApplicationEnabledSetting(String packageName, int newState, int flags) {
+ }
+
+ @Override
+ public int getApplicationEnabledSetting(String packageName) {
+ return 0;
+ }
+
+ @Override
+ public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
+ UserHandle userHandle) {
+ return false;
+ }
+
+ @Override
+ public boolean getApplicationHiddenSettingAsUser(String packageName, UserHandle userHandle) {
+ return false;
+ }
+
+ @Override
+ public boolean isSafeMode() {
+ return false;
+ }
+
+ @Override
+ public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
+ }
+
+ @Override
+ public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
+ }
+
+ @Override
+ public KeySet getKeySetByAlias(String packageName, String alias) {
+ return null;
+ }
+
+ @Override
+ public KeySet getSigningKeySet(String packageName) {
+ return null;
+ }
+
+ @Override
+ public boolean isSignedBy(String packageName, KeySet ks) {
+ return false;
+ }
+
+ @Override
+ public boolean isSignedByExactly(String packageName, KeySet ks) {
+ return false;
+ }
+
+ @Override
+ public int getMoveStatus(int moveId) {
+ return 0;
+ }
+
+ @Override
+ public void registerMoveCallback(MoveCallback callback, Handler handler) {
+ }
+
+ @Override
+ public void unregisterMoveCallback(MoveCallback callback) {
+ }
+
+ @Override
+ public int movePackage(String packageName, VolumeInfo vol) {
+ return 0;
+ }
+
+ @Override
+ public VolumeInfo getPackageCurrentVolume(ApplicationInfo app) {
+ return null;
+ }
+
+ @Override
+ public List<VolumeInfo> getPackageCandidateVolumes(ApplicationInfo app) {
+ return null;
+ }
+
+ @Override
+ public int movePrimaryStorage(VolumeInfo vol) {
+ return 0;
+ }
+
+ @Override
+ public VolumeInfo getPrimaryStorageCurrentVolume() {
+ return null;
+ }
+
+ @Override
+ public List<VolumeInfo> getPrimaryStorageCandidateVolumes() {
+ return null;
+ }
+
+ @Override
+ public VerifierDeviceIdentity getVerifierDeviceIdentity() {
+ return null;
+ }
+
+ @Override
+ public boolean isUpgrade() {
+ return false;
+ }
+
+ @Override
+ public PackageInstaller getPackageInstaller() {
+ return null;
+ }
+
+ @Override
+ public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId,
+ int flags) {
+ }
+
+ @Override
+ public void clearCrossProfileIntentFilters(int sourceUserId) {
+ }
+
+ @Override
+ public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
+ return null;
+ }
+
+ @Override
+ public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) {
+ return null;
+ }
+
+ @Override
+ public boolean isPackageAvailable(String packageName) {
+ return false;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 9b755cd..895f9c9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -137,7 +137,7 @@ public class BridgePowerManager implements IPowerManager {
}
@Override
- public void wakeUp(long time) throws RemoteException {
+ public void wakeUp(long time, String reason, String opPackageName) throws RemoteException {
// pass for now.
}
@@ -147,6 +147,11 @@ public class BridgePowerManager implements IPowerManager {
}
@Override
+ public boolean isDeviceIdleMode() throws RemoteException {
+ return false;
+ }
+
+ @Override
public boolean isScreenBrightnessBoosted() throws RemoteException {
return false;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index fb5d44f..771c3c8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -91,7 +91,11 @@ public final class BridgeWindow implements IWindow {
}
@Override
- public void doneAnimating() {
+ public void onAnimationStarted(int remainingFrameCount) {
+ }
+
+ @Override
+ public void onAnimationStopped() {
}
@Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index a7de1e6..bea1f86 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -191,12 +191,6 @@ public final class BridgeWindowSession implements IWindowSession {
}
@Override
- public void setUniverseTransform(IBinder window, float alpha, float offx, float offy,
- float dsdx, float dtdx, float dsdy, float dtdy) {
- // pass for now.
- }
-
- @Override
public IBinder asBinder() {
// pass for now.
return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
index 7f2d3b4..868c6d3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
@@ -151,7 +151,7 @@ public class AppCompatActionBar extends BridgeActionBar {
@Override
public void createMenuPopup() {
- // it's hard to addd menus to appcompat's actionbar, since it'll use a lot of reflection.
+ // it's hard to add menus to appcompat's actionbar, since it'll use a lot of reflection.
// so we skip it for now.
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
index dc89d0c..09937bc 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java
@@ -74,8 +74,8 @@ public class Config {
}
public static String getTime(int platformVersion) {
- if (isGreaterOrEqual(platformVersion, LOLLIPOP_MR1)) {
- return "5:10";
+ if (isGreaterOrEqual(platformVersion, M)) {
+ return "6:00";
}
if (platformVersion < GINGERBREAD) {
return "2:20";
@@ -95,6 +95,9 @@ public class Config {
if (platformVersion < LOLLIPOP_MR1) {
return "5:00";
}
+ if (platformVersion < M) {
+ return "5:10";
+ }
// Should never happen.
return "4:04";
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 567002e..b76ec17 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -33,7 +33,6 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Bitmap_Delegate;
@@ -228,18 +227,16 @@ abstract class CustomBar extends LinearLayout {
* Find the background color for this bar from the theme attributes. Only relevant to StatusBar
* and NavigationBar.
* <p/>
- * Returns null if not found.
+ * Returns 0 if not found.
*
* @param colorAttrName the attribute name for the background color
* @param translucentAttrName the attribute name for the translucency property of the bar.
*
* @throws NumberFormatException if color resolved to an invalid string.
*/
- @Nullable
- protected Integer getBarColor(@NonNull String colorAttrName,
- @NonNull String translucentAttrName) {
+ protected int getBarColor(@NonNull String colorAttrName, @NonNull String translucentAttrName) {
if (!Config.isGreaterOrEqual(mSimulatedPlatformVersion, LOLLIPOP)) {
- return null;
+ return 0;
}
RenderResources renderResources = getContext().getRenderResources();
// First check if the bar is translucent.
@@ -254,11 +251,10 @@ abstract class CustomBar extends LinearLayout {
if (transparent) {
return getColor(renderResources, colorAttrName);
}
- return null;
+ return 0;
}
- @Nullable
- private static Integer getColor(RenderResources renderResources, String attr) {
+ private static int getColor(RenderResources renderResources, String attr) {
// From ?attr/foo to @color/bar. This is most likely an ItemResourceValue.
ResourceValue resource = renderResources.findItemInTheme(attr, true);
// Form @color/bar to the #AARRGGBB
@@ -279,7 +275,7 @@ abstract class CustomBar extends LinearLayout {
}
}
}
- return null;
+ return 0;
}
private ResourceValue getResourceValue(String reference) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
index 4666850..9c89bfe 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -41,6 +41,9 @@ public class NavigationBar extends CustomBar {
private static final int WIDTH_DEFAULT = 36;
private static final int WIDTH_SW360 = 40;
private static final int WIDTH_SW600 = 48;
+ private static final String LAYOUT_XML = "/bars/navigation_bar.xml";
+ private static final String LAYOUT_600DP_XML = "/bars/navigation_bar600dp.xml";
+
/**
* Constructor to be used when creating the {@link NavigationBar} as a regular control.
@@ -59,11 +62,11 @@ public class NavigationBar extends CustomBar {
public NavigationBar(BridgeContext context, Density density, int orientation, boolean isRtl,
boolean rtlEnabled, int simulatedPlatformVersion) {
- super(context, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml",
- simulatedPlatformVersion);
+ super(context, orientation, getShortestWidth(context)>= 600 ? LAYOUT_600DP_XML : LAYOUT_XML,
+ "navigation_bar.xml", simulatedPlatformVersion);
- Integer color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
- setBackgroundColor(color == null ? 0xFF000000 : color);
+ int color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
+ setBackgroundColor(color == 0 ? 0xFF000000 : color);
// Cannot access the inside items through id because no R.id values have been
// created for them.
@@ -87,13 +90,19 @@ public class NavigationBar extends CustomBar {
}
private void setupNavBar(BridgeContext context, int orientation) {
+ float sw = getShortestWidth(context);
View leftPadding = getChildAt(0);
View rightPadding = getChildAt(6);
- setSize(context, leftPadding, orientation, getSidePadding(context));
- setSize(context, rightPadding, orientation, getSidePadding(context));
+ setSize(context, leftPadding, orientation, getSidePadding(sw));
+ setSize(context, rightPadding, orientation, getSidePadding(sw));
+ int navButtonWidth = getWidth(sw);
for (int i = 1; i < 6; i += 2) {
View navButton = getChildAt(i);
- setSize(context, navButton, orientation, getWidth(context));
+ setSize(context, navButton, orientation, navButtonWidth);
+ }
+ if (sw >= 600) {
+ setSize(context, getChildAt(2), orientation, 128);
+ setSize(context, getChildAt(4), orientation, 128);
}
}
@@ -108,11 +117,7 @@ public class NavigationBar extends CustomBar {
view.setLayoutParams(layoutParams);
}
- private static int getSidePadding(BridgeContext context) {
- DisplayMetrics metrics = context.getMetrics();
- float sw = metrics.widthPixels > metrics.heightPixels
- ? metrics.heightPixels : metrics.widthPixels;
- sw /= metrics.density;
+ private static int getSidePadding(float sw) {
if (sw >= 400) {
return PADDING_WIDTH_SW400;
}
@@ -122,11 +127,7 @@ public class NavigationBar extends CustomBar {
return PADDING_WIDTH_DEFAULT;
}
- private static int getWidth(BridgeContext context) {
- DisplayMetrics metrics = context.getMetrics();
- float sw = metrics.widthPixels > metrics.heightPixels
- ? metrics.heightPixels : metrics.widthPixels;
- sw /= metrics.density;
+ private static int getWidth(float sw) {
if (sw >= 600) {
return WIDTH_SW600;
}
@@ -136,6 +137,14 @@ public class NavigationBar extends CustomBar {
return WIDTH_DEFAULT;
}
+ private static float getShortestWidth(BridgeContext context) {
+ DisplayMetrics metrics = context.getMetrics();
+ float sw = metrics.widthPixels < metrics.heightPixels ?
+ metrics.widthPixels : metrics.heightPixels;
+ sw /= metrics.density;
+ return sw;
+ }
+
@Override
protected TextView getStyleableTextView() {
return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 95a5a58..2dc7c65 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -71,9 +71,8 @@ public class StatusBar extends CustomBar {
// FIXME: use FILL_H?
setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
- Integer color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
- setBackgroundColor(
- color == null ? Config.getStatusBarColor(simulatedPlatformVersion) : color);
+ int color = getBarColor(ATTR_COLOR, ATTR_TRANSLUCENT);
+ setBackgroundColor(color == 0 ? Config.getStatusBarColor(simulatedPlatformVersion) : color);
// Cannot access the inside items through id because no R.id values have been
// created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
index 7f2a7ae..baf2e2e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
@@ -49,7 +49,7 @@ import java.util.List;
* int -> Delegate class link.
*
* Native methods usually always have the int as parameters. The first thing the delegate method
- * will do is call {@link #getDelegate(int)} to get the Java object matching the int.
+ * will do is call {@link #getDelegate(long)} to get the Java object matching the int.
*
* Typical native init methods are returning a new int back to the Java class, so
* {@link #addNewDelegate(Object)} does the same.
@@ -58,7 +58,7 @@ import java.util.List;
* the Java object needs to count as a reference (even though it only holds an int), we use the
* following mechanism:
*
- * - {@link #addNewDelegate(Object)} and {@link #removeJavaReferenceFor(int)} adds and removes
+ * - {@link #addNewDelegate(Object)} and {@link #removeJavaReferenceFor(long)} adds and removes
* the delegate to/from a list. This list hold the reference and prevents the GC from reclaiming
* the delegate.
*
@@ -71,12 +71,13 @@ import java.util.List;
* @param <T> the delegate class to manage
*/
public final class DelegateManager<T> {
+ @SuppressWarnings("FieldCanBeLocal")
private final Class<T> mClass;
private final SparseWeakArray<T> mDelegates = new SparseWeakArray<T>();
/** list used to store delegates when their main object holds a reference to them.
* This is to ensure that the WeakReference in the SparseWeakArray doesn't get GC'ed
* @see #addNewDelegate(Object)
- * @see #removeJavaReferenceFor(int)
+ * @see #removeJavaReferenceFor(long)
*/
private final List<T> mJavaReferences = new ArrayList<T>();
private int mDelegateCounter = 0;
@@ -95,13 +96,14 @@ public final class DelegateManager<T> {
* @param native_object the native int.
* @return the delegate or null if not found.
*/
- public T getDelegate(long native_object) {
+ @Nullable
+ public synchronized T getDelegate(long native_object) {
if (native_object > 0) {
- T delegate = mDelegates.get(native_object);
+ T delegate = mDelegates.get(native_object);
if (Debug.DEBUG) {
if (delegate == null) {
- System.out.println("Unknown " + mClass.getSimpleName() + " with int " +
+ System.err.println("Unknown " + mClass.getSimpleName() + " with int " +
native_object);
}
}
@@ -117,14 +119,18 @@ public final class DelegateManager<T> {
* @param newDelegate the delegate to add
* @return a unique native int to identify the delegate
*/
- public long addNewDelegate(T newDelegate) {
+ public synchronized long addNewDelegate(T newDelegate) {
long native_object = ++mDelegateCounter;
+
mDelegates.put(native_object, newDelegate);
assert !mJavaReferences.contains(newDelegate);
mJavaReferences.add(newDelegate);
if (Debug.DEBUG) {
- System.out.println("New " + mClass.getSimpleName() + " with int " + native_object);
+ System.out.println(
+ "New " + mClass.getSimpleName() + " " +
+ "with int " +
+ native_object);
}
return native_object;
@@ -134,7 +140,7 @@ public final class DelegateManager<T> {
* Removes the main reference on the given delegate.
* @param native_object the native integer representing the delegate.
*/
- public void removeJavaReferenceFor(long native_object) {
+ public synchronized void removeJavaReferenceFor(long native_object) {
T delegate = getDelegate(native_object);
if (Debug.DEBUG) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index 9228d87..cbd0415 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
@@ -330,9 +330,12 @@ class Layout extends RelativeLayout {
mWindowIsFloating = getBooleanThemeValue(mResources, ATTR_WINDOW_FLOATING, true, true);
findBackground();
- findStatusBar();
- findActionBar();
- findNavBar();
+
+ if (!mParams.isForceNoDecor()) {
+ findStatusBar();
+ findActionBar();
+ findNavBar();
+ }
}
private void findBackground() {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
index de77d57..92b39e3 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java
@@ -27,6 +27,7 @@ import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.resources.Density;
import com.android.resources.ResourceType;
import com.android.resources.ScreenOrientation;
+import com.android.resources.ScreenRound;
import com.android.resources.ScreenSize;
import android.content.res.Configuration;
@@ -35,7 +36,9 @@ import android.util.DisplayMetrics;
import android.view.ViewConfiguration_Accessor;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodManager_Accessor;
+import android.widget.SimpleMonthView_Delegate;
+import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
@@ -275,6 +278,7 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
mContext.getRenderResources().setLogger(null);
}
ParserFactory.setParserFactory(null);
+ SimpleMonthView_Delegate.clearCache();
}
public static BridgeContext getCurrentContext() {
@@ -378,6 +382,27 @@ public abstract class RenderAction<T extends RenderParams> extends FrameworkReso
config.orientation = Configuration.ORIENTATION_UNDEFINED;
}
+ try {
+ ScreenRound roundness = hardwareConfig.getScreenRoundness();
+ if (roundness != null) {
+ switch (roundness) {
+ case ROUND:
+ config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_YES;
+ break;
+ case NOTROUND:
+ config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_NO;
+ }
+ } else {
+ config.screenLayout |= Configuration.SCREENLAYOUT_ROUND_UNDEFINED;
+ }
+ } catch (NoSuchMethodError ignored) {
+ // getScreenRoundness was added in later stages of API 15. So, it's not present on some
+ // preview releases of API 15.
+ // TODO: Remove the try catch around Oct 2015.
+ }
+ String locale = getParams().getLocale();
+ if (locale != null && !locale.isEmpty()) config.locale = new Locale(locale);
+
// TODO: fill in more config info.
return config;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
index 9e26502..26f9000 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java
@@ -38,6 +38,9 @@ import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 24e1ce7..ac7c409 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -421,7 +421,8 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
gc.setComposite(AlphaComposite.Src);
gc.setColor(new Color(0x00000000, true));
- gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
+ gc.fillRect(0, 0,
+ mMeasuredScreenWidth, mMeasuredScreenHeight);
// done
gc.dispose();
diff --git a/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java
deleted file mode 100644
index d94c205..0000000
--- a/tools/layoutlib/bridge/src/libcore/icu/DateIntervalFormat_Delegate.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2013 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.icu;
-
-import java.text.FieldPosition;
-
-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 com.ibm.icu.text.DateIntervalFormat;
-import com.ibm.icu.util.DateInterval;
-import com.ibm.icu.util.TimeZone;
-import com.ibm.icu.util.ULocale;
-
-public class DateIntervalFormat_Delegate {
-
- // ---- delegate manager ----
- private static final DelegateManager<DateIntervalFormat_Delegate> sManager =
- new DelegateManager<DateIntervalFormat_Delegate>(DateIntervalFormat_Delegate.class);
-
- // ---- delegate data ----
- private DateIntervalFormat mFormat;
-
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/static String formatDateInterval(long address, long fromDate, long toDate) {
- DateIntervalFormat_Delegate delegate = sManager.getDelegate((int)address);
- if (delegate == null) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Unable for find native DateIntervalFormat", null);
- return null;
- }
- DateInterval interval = new DateInterval(fromDate, toDate);
- StringBuffer sb = new StringBuffer();
- FieldPosition pos = new FieldPosition(0);
- delegate.mFormat.format(interval, sb, pos);
- return sb.toString();
- }
-
- @LayoutlibDelegate
- /*package*/ static long createDateIntervalFormat(String skeleton, String localeName,
- String tzName) {
- TimeZone prevDefaultTz = TimeZone.getDefault();
- TimeZone.setDefault(TimeZone.getTimeZone(tzName));
- DateIntervalFormat_Delegate newDelegate = new DateIntervalFormat_Delegate();
- newDelegate.mFormat =
- DateIntervalFormat.getInstance(skeleton, new ULocale(localeName));
- TimeZone.setDefault(prevDefaultTz);
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static void destroyDateIntervalFormat(long address) {
- sManager.removeJavaReferenceFor((int)address);
- }
-
-}
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
index b8b5fed..9c58010 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -17,9 +17,11 @@
package libcore.icu;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-import com.ibm.icu.text.DateTimePatternGenerator;
-import com.ibm.icu.util.Currency;
-import com.ibm.icu.util.ULocale;
+
+import android.icu.text.DateTimePatternGenerator;
+import android.icu.util.Currency;
+import android.icu.util.ULocale;
+import android.icu.util.VersionInfo;
import java.util.Locale;
@@ -53,18 +55,19 @@ public class ICU_Delegate {
}
@LayoutlibDelegate
+ @SuppressWarnings("deprecation")
/*package*/ static String getCldrVersion() {
- return "22.1.1"; // TODO: check what the right value should be.
+ return VersionInfo.ICU_DATA_VERSION.toString();
}
@LayoutlibDelegate
/*package*/ static String getIcuVersion() {
- return "unknown_layoutlib";
+ return VersionInfo.ICU_VERSION.toString();
}
@LayoutlibDelegate
/*package*/ static String getUnicodeVersion() {
- return "5.2";
+ return VersionInfo.UNICODE_7_0.toString();
}
@LayoutlibDelegate
@@ -181,8 +184,8 @@ public class ICU_Delegate {
/*package*/ static boolean initLocaleDataNative(String locale, LocaleData result) {
// Used by Calendar.
- result.firstDayOfWeek = Integer.valueOf(1);
- result.minimalDaysInFirstWeek = Integer.valueOf(1);
+ result.firstDayOfWeek = 1;
+ result.minimalDaysInFirstWeek = 1;
// Used by DateFormatSymbols.
result.amPm = new String[] { "AM", "PM" };
@@ -252,4 +255,9 @@ public class ICU_Delegate {
/*package*/ static String getDefaultLocale() {
return ICU.getDefaultLocale();
}
+
+ @LayoutlibDelegate
+ /*package*/ static String getTZDataVersion() {
+ return ICU.getTZDataVersion();
+ }
}
diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk
index 11390c3..5eef24a 100644
--- a/tools/layoutlib/bridge/tests/Android.mk
+++ b/tools/layoutlib/bridge/tests/Android.mk
@@ -26,7 +26,6 @@ LOCAL_MODULE_TAGS := optional
LOCAL_JAVA_LIBRARIES := layoutlib \
kxml2-2.3.0 \
- icu4j \
layoutlib_api-prebuilt \
tools-common-prebuilt \
sdk-common \
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class
index 8b32ba6..aecbff6 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class
index 1c84476..fc3f236 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class
index 672782f..83ad35b 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png
index 1a96c47..9bf302a 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
index e7d7967..2b86bfb 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png
index d8ad0b9..336f9d8 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java
index 8b362ec..d8937f4 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java
@@ -192,12 +192,12 @@ public class TestDelegates extends TestCase {
StringBuilder sb = new StringBuilder(method.getName() + "(");
for (int j = 0; j < parameters.length; j++) {
Class<?> theClass = parameters[j];
- sb.append(theClass.getName());
int dimensions = 0;
while (theClass.isArray()) {
dimensions++;
theClass = theClass.getComponentType();
}
+ sb.append(theClass.getName());
for (int i = 0; i < dimensions; i++) {
sb.append("[]");
}
diff --git a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index 5562ec5..9ebeebd 100644
--- a/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -40,6 +40,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import java.io.File;
import java.io.FileFilter;
@@ -356,6 +357,7 @@ public class Main {
// TODO: Set up action bar handler properly to test menu rendering.
// Create session params.
RenderSession session = sBridge.createSession(params);
+
if (!session.getResult().isSuccess()) {
getLogger().error(session.getResult().getException(),
session.getResult().getErrorMessage());
@@ -426,13 +428,14 @@ public class Main {
}
@Override
- public void fidelityWarning(String tag, String message, Throwable throwable,
- Object data) {
+ public void fidelityWarning(@Nullable String tag, String message,
+ Throwable throwable, Object data) {
+
System.out.println("FidelityWarning " + tag + ": " + message);
if (throwable != null) {
throwable.printStackTrace();
}
- failWithMsg(message);
+ failWithMsg(message == null ? "" : message);
}
@Override
@@ -458,11 +461,11 @@ public class Main {
if (sLogger == null) {
sLogger = new ILogger() {
@Override
- public void error(Throwable t, String msgFormat, Object... args) {
+ public void error(Throwable t, @Nullable String msgFormat, Object... args) {
if (t != null) {
t.printStackTrace();
}
- failWithMsg(msgFormat, args);
+ failWithMsg(msgFormat == null ? "" : msgFormat, args);
}
@Override
diff --git a/tools/layoutlib/create/create.iml b/tools/layoutlib/create/create.iml
index b7e8eb3..9b18e73 100644
--- a/tools/layoutlib/create/create.iml
+++ b/tools/layoutlib/create/create.iml
@@ -11,8 +11,17 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="library" name="asm-4.0" level="project" />
+ <orderEntry type="module-library">
+ <library name="asm-4.0">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/asm/asm-4.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/asm/src.zip!/" />
+ </SOURCES>
+ </library>
+ </orderEntry>
<orderEntry type="library" scope="TEST" name="JUnit4" level="application" />
</component>
-</module>
-
+</module> \ No newline at end of file
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
index d37a93e..c8b2b84 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
@@ -112,8 +112,6 @@ public class AsmAnalyzer {
mGen.setDeps(deps);
mGen.setCopyFiles(filesFound);
mGen.setRewriteMethodCallClasses(mReplaceMethodCallClasses);
- // hack hack hack
- mGen.mSimpleMonthViewReader = zipClasses.get(AsmGenerator.SIMPLE_MONTH_VIEW);
}
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index 2bfceb4..8f0ad01 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -77,9 +77,8 @@ public class AsmGenerator {
/** Methods to inject. FQCN of class in which method should be injected => runnable that does
* the injection. */
private final Map<String, ICreateInfo.InjectMethodRunnable> mInjectedMethodsMap;
- // A hack to do some modifications to simple month view.
- static final String SIMPLE_MONTH_VIEW = "android/widget/SimpleMonthView";
- ClassReader mSimpleMonthViewReader;
+ /** A map { FQCN => set { field names } } which should be promoted to public visibility */
+ private final Map<String, Set<String>> mPromotedFields;
/**
* Creates a new generator that can generate the output JAR with the stubbed classes.
@@ -112,20 +111,8 @@ public class AsmGenerator {
// Create the map/set of methods to change to delegates
mDelegateMethods = new HashMap<String, Set<String>>();
- for (String signature : createInfo.getDelegateMethods()) {
- int pos = signature.indexOf('#');
- if (pos <= 0 || pos >= signature.length() - 1) {
- continue;
- }
- String className = binaryToInternalClassName(signature.substring(0, pos));
- String methodName = signature.substring(pos + 1);
- Set<String> methods = mDelegateMethods.get(className);
- if (methods == null) {
- methods = new HashSet<String>();
- mDelegateMethods.put(className, methods);
- }
- methods.add(methodName);
- }
+ addToMap(createInfo.getDelegateMethods(), mDelegateMethods);
+
for (String className : createInfo.getDelegateClassNatives()) {
className = binaryToInternalClassName(className);
Set<String> methods = mDelegateMethods.get(className);
@@ -190,10 +177,34 @@ public class AsmGenerator {
returnTypes.add(binaryToInternalClassName(className));
}
+ mPromotedFields = new HashMap<String, Set<String>>();
+ addToMap(createInfo.getPromotedFields(), mPromotedFields);
+
mInjectedMethodsMap = createInfo.getInjectedMethodsMap();
}
/**
+ * For each value in the array, split the value on '#' and add the parts to the map as key
+ * and value.
+ */
+ private void addToMap(String[] entries, Map<String, Set<String>> map) {
+ for (String entry : entries) {
+ int pos = entry.indexOf('#');
+ if (pos <= 0 || pos >= entry.length() - 1) {
+ return;
+ }
+ String className = binaryToInternalClassName(entry.substring(0, pos));
+ String methodOrFieldName = entry.substring(pos + 1);
+ Set<String> set = map.get(className);
+ if (set == null) {
+ set = new HashSet<String>();
+ map.put(className, set);
+ }
+ set.add(methodOrFieldName);
+ }
+ }
+
+ /**
* Returns the list of classes that have not been renamed yet.
* <p/>
* The names are "internal class names" rather than FQCN, i.e. they use "/" instead "."
@@ -207,7 +218,7 @@ public class AsmGenerator {
* Utility that returns the internal ASM class name from a fully qualified binary class
* name. E.g. it returns android/view/View from android.view.View.
*/
- static String binaryToInternalClassName(String className) {
+ String binaryToInternalClassName(String className) {
if (className == null) {
return null;
} else {
@@ -383,10 +394,10 @@ public class AsmGenerator {
}
}
- if (SIMPLE_MONTH_VIEW.equals(className)) {
- cv = new SimpleMonthViewAdapter(cv);
+ Set<String> promoteFields = mPromotedFields.get(className);
+ if (promoteFields != null && !promoteFields.isEmpty()) {
+ cv = new PromoteFieldClassAdapter(cv, promoteFields);
}
-
cr.accept(cv, 0);
return cw.toByteArray();
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 33fa679..484240f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -120,6 +120,11 @@ public final class CreateInfo implements ICreateInfo {
}
@Override
+ public String[] getPromotedFields() {
+ return PROMOTED_FIELDS;
+ }
+
+ @Override
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
return INJECTED_METHODS;
}
@@ -167,12 +172,14 @@ public final class CreateInfo implements ICreateInfo {
"android.os.HandlerThread#run",
"android.preference.Preference#getView",
"android.text.format.DateFormat#is24HourFormat",
+ "android.text.Hyphenator#getSystemHyphenatorLocation",
"android.util.Xml#newPullParser",
"android.view.Choreographer#getRefreshRate",
"android.view.Display#updateDisplayInfoLocked",
"android.view.Display#getWindowManager",
"android.view.LayoutInflater#rInflate",
"android.view.LayoutInflater#parseInclude",
+ "android.view.View#getWindowToken",
"android.view.View#isInEditMode",
"android.view.ViewRootImpl#isInTouchMode",
"android.view.WindowManagerGlobal#getWindowManagerService",
@@ -183,6 +190,8 @@ public final class CreateInfo implements ICreateInfo {
"android.view.RenderNode#nSetElevation",
"android.view.RenderNode#nGetElevation",
"android.view.ViewGroup#drawChild",
+ "android.widget.SimpleMonthView#getTitle",
+ "android.widget.SimpleMonthView#getDayOfWeekLabel",
"android.widget.TimePickerClockDelegate#getAmOrPmKeyCode",
"com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
"com.android.internal.util.XmlUtils#convertValueToInt",
@@ -242,7 +251,6 @@ public final class CreateInfo implements ICreateInfo {
"android.text.AndroidBidi",
"android.text.StaticLayout",
"android.view.Display",
- "libcore.icu.DateIntervalFormat",
"libcore.icu.ICU",
};
@@ -265,7 +273,6 @@ public final class CreateInfo implements ICreateInfo {
"android.view.SurfaceView", "android.view._Original_SurfaceView",
"android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
"android.webkit.WebView", "android.webkit._Original_WebView",
- "com.android.internal.policy.PolicyManager", "com.android.internal.policy._Original_PolicyManager",
};
/**
@@ -289,6 +296,12 @@ public final class CreateInfo implements ICreateInfo {
"org.kxml2.io.KXmlParser"
};
+ private final static String[] PROMOTED_FIELDS = new String[] {
+ "android.widget.SimpleMonthView#mTitle",
+ "android.widget.SimpleMonthView#mCalendar",
+ "android.widget.SimpleMonthView#mDayOfWeekLabelCalendar"
+ };
+
/**
* List of classes for which the methods returning them should be deleted.
* The array contains a list of null terminated section starting with the name of the class
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
index 54b1fe6..6c62423 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java
@@ -78,6 +78,13 @@ public interface ICreateInfo {
Set<String> getExcludedClasses();
/**
+ * Returns a list of fields which should be promoted to public visibility. The array values
+ * are in the form of the binary FQCN of the class containing the field and the field name
+ * separated by a '#'.
+ */
+ String[] getPromotedFields();
+
+ /**
* Returns a map from binary FQCN className to {@link InjectMethodRunnable} which will be
* called to inject methods into a class.
* Can be empty but must not be null.
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index 97716fd..383168f 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -116,12 +116,15 @@ public class Main {
"android.app.DatePickerDialog", // b.android.com/28318
"android.app.TimePickerDialog", // b.android.com/61515
"com.android.internal.view.menu.ActionMenu",
+ "android.icu.**", // needed by LayoutLib
"android.annotation.NonNull", // annotations
"android.annotation.Nullable", // annotations
+ "com.android.internal.transition.EpicenterTranslateClipReveal",
},
excludeClasses,
new String[] {
"com/android/i18n/phonenumbers/data/*",
+ "android/icu/impl/data/**"
});
aa.analyze();
agen.generate();
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java
new file mode 100644
index 0000000..e4b70da
--- /dev/null
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * 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 com.android.tools.layoutlib.create;
+
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.FieldVisitor;
+
+import java.util.Set;
+
+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.
+ */
+public class PromoteFieldClassAdapter extends ClassVisitor {
+
+ private final Set<String> mFieldNames;
+ private static final int ACC_NOT_PUBLIC = ~(ACC_PRIVATE | ACC_PROTECTED);
+
+ public PromoteFieldClassAdapter(ClassVisitor cv, Set<String> fieldNames) {
+ super(ASM4, cv);
+ mFieldNames = fieldNames;
+ }
+
+ @Override
+ public FieldVisitor visitField(int access, String name, String desc, String signature,
+ Object value) {
+ if (mFieldNames.contains(name)) {
+ if ((access & ACC_PUBLIC) == 0) {
+ access = (access & ACC_NOT_PUBLIC) | ACC_PUBLIC;
+ }
+ }
+ return super.visitField(access, name, desc, signature, value);
+ }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
index 4369148..0b85c48 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java
@@ -93,18 +93,22 @@ public class ReplaceMethodCallsAdapter extends ClassVisitor {
}
});
- // Case 3: java.util.Locale.adjustLanguageCode() or java.util.Locale.forLanguageTag()
+ // Case 3: java.util.Locale.adjustLanguageCode() or java.util.Locale.forLanguageTag() or
+ // java.util.Locale.getDefault()
METHOD_REPLACERS.add(new MethodReplacer() {
private final String STRING_TO_STRING = Type.getMethodDescriptor(STRING, STRING);
private final String STRING_TO_LOCALE = Type.getMethodDescriptor(
Type.getType(Locale.class), STRING);
+ private final String VOID_TO_LOCALE =
+ Type.getMethodDescriptor(Type.getType(Locale.class));
@Override
public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
return JAVA_LOCALE_CLASS.equals(owner) &&
("adjustLanguageCode".equals(name) && desc.equals(STRING_TO_STRING) ||
- "forLanguageTag".equals(name) && desc.equals(STRING_TO_LOCALE));
+ "forLanguageTag".equals(name) && desc.equals(STRING_TO_LOCALE) ||
+ "getDefault".equals(name) && desc.equals(VOID_TO_LOCALE));
}
@Override
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/SimpleMonthViewAdapter.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/SimpleMonthViewAdapter.java
deleted file mode 100644
index 49fd456..0000000
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/SimpleMonthViewAdapter.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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 com.android.tools.layoutlib.create;
-
-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.text.SimpleDateFormat;
-
-import static com.android.tools.layoutlib.create.AsmGenerator.binaryToInternalClassName;
-
-/**
- * A very ugly hack to transform all references to {@link java.text.SimpleDateFormat} in {@code
- * android.widget.SimpleMonthView} to {@code com.ibm.icu.text.SimpleDateFormat}.
- */
-public class SimpleMonthViewAdapter extends ClassVisitor {
-
- private static final String JAVA_SDF_DESC = Type.getDescriptor(SimpleDateFormat.class);
- private static final String JAVA_SDF_INTERNAL_NAME =
- binaryToInternalClassName(SimpleDateFormat.class.getName());
- private static final String ICU_SDF_INTERNAL_NAME = "com/ibm/icu/text/SimpleDateFormat";
-
- public SimpleMonthViewAdapter(ClassVisitor cv) {
- super(Opcodes.ASM4, cv);
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc, String signature,
- Object value) {
- if (JAVA_SDF_DESC.equals(desc)) {
- desc = "L" + ICU_SDF_INTERNAL_NAME + ";";
- }
- return super.visitField(access, name, desc, signature, value);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc, String signature,
- String[] exceptions) {
- return new MyMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions));
- }
-
- private static class MyMethodVisitor extends MethodVisitor {
- public MyMethodVisitor(MethodVisitor mv) {
- super(Opcodes.ASM4, mv);
- }
-
- @Override
- public void visitTypeInsn(int opcode, String type) {
- if (JAVA_SDF_INTERNAL_NAME.equals(type) && opcode == Opcodes.NEW) {
- type = ICU_SDF_INTERNAL_NAME;
- }
- super.visitTypeInsn(opcode, type);
- }
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc) {
- if (JAVA_SDF_INTERNAL_NAME.equals(owner)) {
- owner = ICU_SDF_INTERNAL_NAME;
- }
- super.visitMethodInsn(opcode, owner, name, desc);
- }
-
- @Override
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- if (JAVA_SDF_DESC.equals(desc) &&
- (opcode == Opcodes.PUTFIELD || opcode == Opcodes.GETFIELD) &&
- name.equals("mDayFormatter")) {
- desc = "L" + ICU_SDF_INTERNAL_NAME + ";";
- }
- super.visitFieldInsn(opcode, owner, name, desc);
- }
- }
-}
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
index 2c21470..8a2235b 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java
@@ -138,6 +138,11 @@ public class AsmGeneratorTest {
}
@Override
+ public String[] getPromotedFields() {
+ return new String[0];
+ }
+
+ @Override
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
return new HashMap<String, InjectMethodRunnable>(0);
}
@@ -213,6 +218,11 @@ public class AsmGeneratorTest {
}
@Override
+ public String[] getPromotedFields() {
+ return new String[0];
+ }
+
+ @Override
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
return new HashMap<String, InjectMethodRunnable>(0);
}
@@ -296,6 +306,11 @@ public class AsmGeneratorTest {
}
@Override
+ public String[] getPromotedFields() {
+ return new String[0];
+ }
+
+ @Override
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
return new HashMap<String, InjectMethodRunnable>(0);
}
@@ -374,6 +389,11 @@ public class AsmGeneratorTest {
}
@Override
+ public String[] getPromotedFields() {
+ return new String[0];
+ }
+
+ @Override
public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
HashMap<String, InjectMethodRunnable> map =
new HashMap<String, InjectMethodRunnable>(1);
diff --git a/tools/layoutlib/rename_font/build_font.py b/tools/layoutlib/rename_font/build_font.py
index c747d92..9713a4c 100755
--- a/tools/layoutlib/rename_font/build_font.py
+++ b/tools/layoutlib/rename_font/build_font.py
@@ -209,15 +209,18 @@ def ends_in_regular(string):
def get_version(string):
- # The string must begin with 'Version n.nn '
- # to extract n.nn, we return the second entry in the split strings.
string = string.strip()
- if not string.startswith('Version '):
- raise InvalidFontException('mal-formed font version')
- return sanitize(string.split()[1])
+ # The spec says that the version string should start with "Version ". But not
+ # all fonts do. So, we return the complete string if it doesn't start with
+ # the prefix, else we return the rest of the string after sanitizing it.
+ prefix = 'Version '
+ if string.startswith(prefix):
+ string = string[len(prefix):]
+ return sanitize(string)
def sanitize(string):
+ """ Remove non-standard chars. """
return re.sub(r'[^\w-]+', '', string)
if __name__ == '__main__':
diff --git a/tools/layoutlib/rename_font/build_font_single.py b/tools/layoutlib/rename_font/build_font_single.py
index 5f7dad9..4245cdc 100755
--- a/tools/layoutlib/rename_font/build_font_single.py
+++ b/tools/layoutlib/rename_font/build_font_single.py
@@ -193,15 +193,18 @@ def ends_in_regular(string):
def get_version(string):
- # The string must begin with 'Version n.nn '
- # to extract n.nn, we return the second entry in the split strings.
string = string.strip()
- if not string.startswith('Version '):
- raise InvalidFontException('mal-formed font version')
- return sanitize(string.split()[1])
+ # The spec says that the version string should start with "Version ". But not
+ # all fonts do. So, we return the complete string if it doesn't start with
+ # the prefix, else we return the rest of the string after sanitizing it.
+ prefix = 'Version '
+ if string.startswith(prefix):
+ string = string[len(prefix):]
+ return sanitize(string)
def sanitize(string):
+ """ Remove non-standard chars. """
return re.sub(r'[^\w-]+', '', string)
if __name__ == '__main__':