+++ /dev/null
-bin
-/.idea/workspace.xml
-/out
-/bridge/out
-/.idea/kotlinc.xml
\ No newline at end of file
+++ /dev/null
-layoutlib
\ No newline at end of file
+++ /dev/null
-<component name="ArtifactManager">
- <artifact type="jar" name="studio-android-widgets:jar">
- <output-path>$PROJECT_DIR$/out/artifacts/studio_android_widgets_jar</output-path>
- <root id="archive" name="studio-android-widgets.jar">
- <element id="module-output" name="studio-android-widgets" />
- </root>
- </artifact>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="ArtifactManager">
- <artifact type="jar" name="studio-android-widgets-src:jar">
- <output-path>$PROJECT_DIR$/out/artifacts/studio_android_widgets_src_jar</output-path>
- <root id="archive" name="studio-android-widgets-src.jar">
- <element id="dir-copy" path="$PROJECT_DIR$/studio-custom-widgets/src" />
- </root>
- </artifact>
-</component>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="ProjectCodeStyleSettingsManager">
- <option name="PER_PROJECT_SETTINGS">
- <value>
- <option name="FIELD_NAME_PREFIX" value="m" />
- <option name="STATIC_FIELD_NAME_PREFIX" value="s" />
- <option name="INSERT_INNER_CLASS_IMPORTS" value="true" />
- <option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" />
- <option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999" />
- <option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
- <value />
- </option>
- <option name="IMPORT_LAYOUT_TABLE">
- <value>
- <package name="com.android" withSubpackages="true" static="false" />
- <emptyLine />
- <package name="org" withSubpackages="true" static="false" />
- <emptyLine />
- <package name="android" withSubpackages="true" static="false" />
- <emptyLine />
- <package name="java" withSubpackages="true" static="false" />
- <emptyLine />
- <package name="" withSubpackages="true" static="false" />
- <emptyLine />
- <package name="" withSubpackages="true" static="true" />
- </value>
- </option>
- <option name="RIGHT_MARGIN" value="100" />
- <option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
- <option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
- <option name="JD_ADD_BLANK_AFTER_PARM_COMMENTS" value="true" />
- <option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
- <option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true" />
- <option name="WRAP_COMMENTS" value="true" />
- <JavaCodeStyleSettings>
- <option name="CLASS_NAMES_IN_JAVADOC" value="3" />
- </JavaCodeStyleSettings>
- <XML>
- <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
- </XML>
- <codeStyleSettings language="JAVA">
- <option name="KEEP_LINE_BREAKS" value="false" />
- <option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
- <option name="CALL_PARAMETERS_WRAP" value="1" />
- <option name="METHOD_PARAMETERS_WRAP" value="1" />
- <option name="THROWS_LIST_WRAP" value="1" />
- <option name="EXTENDS_KEYWORD_WRAP" value="1" />
- <option name="THROWS_KEYWORD_WRAP" value="1" />
- <option name="BINARY_OPERATION_WRAP" value="1" />
- <option name="TERNARY_OPERATION_WRAP" value="1" />
- <option name="ARRAY_INITIALIZER_WRAP" value="1" />
- <option name="ASSIGNMENT_WRAP" value="1" />
- <option name="ASSERT_STATEMENT_WRAP" value="1" />
- <option name="IF_BRACE_FORCE" value="3" />
- <option name="DOWHILE_BRACE_FORCE" value="3" />
- <option name="WHILE_BRACE_FORCE" value="3" />
- <option name="FOR_BRACE_FORCE" value="3" />
- <option name="WRAP_LONG_LINES" value="true" />
- <arrangement>
- <groups>
- <group>
- <type>GETTERS_AND_SETTERS</type>
- <order>KEEP</order>
- </group>
- <group>
- <type>OVERRIDDEN_METHODS</type>
- <order>KEEP</order>
- </group>
- </groups>
- </arrangement>
- </codeStyleSettings>
- <codeStyleSettings language="XML">
- <indentOptions>
- <option name="CONTINUATION_INDENT_SIZE" value="4" />
- </indentOptions>
- </codeStyleSettings>
- </value>
- </option>
- <option name="USE_PER_PROJECT_SETTINGS" value="true" />
- </component>
-</project>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="CompilerConfiguration">
- <option name="DEFAULT_COMPILER" value="Javac" />
- <excludeFromCompile>
- <directory url="file://$PROJECT_DIR$/create/tests/mock_data" includeSubdirectories="true" />
- </excludeFromCompile>
- <resourceExtensions />
- <wildcardResourcePatterns>
- <entry name="!?*.java" />
- <entry name="!?*.form" />
- <entry name="!?*.class" />
- <entry name="!?*.groovy" />
- <entry name="!?*.scala" />
- <entry name="!?*.flex" />
- <entry name="!?*.kt" />
- <entry name="!?*.clj" />
- </wildcardResourcePatterns>
- <annotationProcessing>
- <profile default="true" name="Default" enabled="false">
- <processorPath useClasspath="true" />
- </profile>
- </annotationProcessing>
- </component>
-</project>
\ No newline at end of file
+++ /dev/null
-<component name="CopyrightManager">
- <copyright>
- <option name="notice" value="Copyright (C) &#36;today.year 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." />
- <option name="keyword" value="Copyright" />
- <option name="allowReplaceKeyword" value="" />
- <option name="myName" value="Android" />
- <option name="myLocal" value="true" />
- </copyright>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="CopyrightManager">
- <settings default="Android" />
-</component>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false">
- <file url="PROJECT" charset="UTF-8" />
- </component>
-</project>
\ No newline at end of file
+++ /dev/null
-<component name="InspectionProjectProfileManager">
- <profile version="1.0" is_locked="false">
- <option name="myName" value="Project Default" />
- <option name="myLocal" value="false" />
- <inspection_tool class="DefaultFileTemplate" enabled="false" level="WARNING" enabled_by_default="false">
- <option name="CHECK_FILE_HEADER" value="true" />
- <option name="CHECK_TRY_CATCH_SECTION" value="true" />
- <option name="CHECK_METHOD_BODY" value="true" />
- </inspection_tool>
- <inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
- <option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
- <option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
- </inspection_tool>
- <inspection_tool class="WeakerAccess" enabled="true" level="WARNING" enabled_by_default="true">
- <option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="false" />
- <option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="false" />
- <option name="SUGGEST_PRIVATE_FOR_INNERS" value="true" />
- </inspection_tool>
- </profile>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="InspectionProjectProfileManager">
- <settings>
- <option name="PROJECT_PROFILE" value="Project Default" />
- <option name="USE_PROJECT_PROFILE" value="true" />
- <version value="1.0" />
- </settings>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="libraryTable">
- <library name="framework.jar">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES>
- <root url="file://$PROJECT_DIR$/../../core/java" />
- <root url="file://$PROJECT_DIR$/../../graphics/java" />
- <root url="file://$PROJECT_DIR$/../../../../libcore/luni/src/main/java" />
- </SOURCES>
- </library>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="libraryTable">
- <library name="junit">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/junit-host_intermediates/javalib.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES>
- <root url="file://$PROJECT_DIR$/../../../../external/junit/src" />
- </SOURCES>
- </library>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="libraryTable">
- <library name="layoutlib_api-prebuilt">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES>
- <root url="jar://$PROJECT_DIR$/../../../../prebuilts/misc/common/layoutlib_api/layoutlib_api-sources.jar!/" />
- </SOURCES>
- </library>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="libraryTable">
- <library name="mockito">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/mockito-host_intermediates/javalib.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES />
- </library>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="libraryTable">
- <library name="objenesis">
- <CLASSES>
- <root url="jar://$PROJECT_DIR$/../../../../out/host/common/obj/JAVA_LIBRARIES/objenesis-host_intermediates/javalib.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES />
- </library>
-</component>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="EntryPointsManager">
- <entry_points version="2.0" />
- <list size="1">
- <item index="0" class="java.lang.String" itemvalue="com.android.tools.layoutlib.annotations.LayoutlibDelegate" />
- </list>
- </component>
- <component name="FrameworkDetectionExcludesConfiguration">
- <type id="android" />
- </component>
- <component name="NullableNotNullManager">
- <option name="myDefaultNullable" value="android.annotation.Nullable" />
- <option name="myDefaultNotNull" value="android.annotation.NonNull" />
- <option name="myNullables">
- <value>
- <list size="6">
- <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
- <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
- <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
- <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
- <item index="4" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
- <item index="5" class="java.lang.String" itemvalue="android.annotation.Nullable" />
- </list>
- </value>
- </option>
- <option name="myNotNulls">
- <value>
- <list size="6">
- <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
- <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
- <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
- <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
- <item index="4" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
- <item index="5" class="java.lang.String" itemvalue="android.annotation.NonNull" />
- </list>
- </value>
- </option>
- </component>
- <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
- <output url="file://$PROJECT_DIR$/out" />
- </component>
-</project>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="ProjectModuleManager">
- <modules>
- <module fileurl="file://$PROJECT_DIR$/bridge/bridge.iml" filepath="$PROJECT_DIR$/bridge/bridge.iml" />
- <module fileurl="file://$PROJECT_DIR$/create/create.iml" filepath="$PROJECT_DIR$/create/create.iml" />
- <module fileurl="file://$PROJECT_DIR$/legacy/legacy.iml" filepath="$PROJECT_DIR$/legacy/legacy.iml" />
- <module fileurl="file://$PROJECT_DIR$/studio-custom-widgets/studio-android-widgets.iml" filepath="$PROJECT_DIR$/studio-custom-widgets/studio-android-widgets.iml" />
- </modules>
- </component>
-</project>
\ No newline at end of file
+++ /dev/null
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="All in bridge" type="JUnit" factoryName="JUnit" singleton="true">
- <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
- <module name="bridge" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
- <option name="ALTERNATIVE_JRE_PATH" value="" />
- <option name="PACKAGE_NAME" value="" />
- <option name="MAIN_CLASS_NAME" value="" />
- <option name="METHOD_NAME" value="" />
- <option name="TEST_OBJECT" value="package" />
- <option name="VM_PARAMETERS" value="-ea" />
- <option name="PARAMETERS" value="" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ENV_VARIABLES" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <option name="TEST_SEARCH_SCOPE">
- <value defaultName="singleModule" />
- </option>
- <envs />
- <patterns />
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Run" />
- <method />
- </configuration>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="All in create" type="JUnit" factoryName="JUnit" singleton="false" nameIsGenerated="true">
- <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
- <module name="create" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
- <option name="ALTERNATIVE_JRE_PATH" value="" />
- <option name="PACKAGE_NAME" value="" />
- <option name="MAIN_CLASS_NAME" value="" />
- <option name="METHOD_NAME" value="" />
- <option name="TEST_OBJECT" value="package" />
- <option name="VM_PARAMETERS" value="-ea" />
- <option name="PARAMETERS" value="" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ENV_VARIABLES" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <option name="TEST_SEARCH_SCOPE">
- <value defaultName="singleModule" />
- </option>
- <envs />
- <patterns />
- <RunnerSettings RunnerId="Debug">
- <option name="DEBUG_PORT" value="" />
- <option name="TRANSPORT" value="0" />
- <option name="LOCAL" value="true" />
- </RunnerSettings>
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Debug" />
- <ConfigurationWrapper RunnerId="Run" />
- <method />
- </configuration>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="Bridge quick" type="JUnit" factoryName="JUnit">
- <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
- <module name="bridge" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
- <option name="ALTERNATIVE_JRE_PATH" value="" />
- <option name="PACKAGE_NAME" />
- <option name="MAIN_CLASS_NAME" value="" />
- <option name="METHOD_NAME" value="" />
- <option name="TEST_OBJECT" value="pattern" />
- <option name="VM_PARAMETERS" value="-ea" />
- <option name="PARAMETERS" value="" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$" />
- <option name="ENV_VARIABLES" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <option name="TEST_SEARCH_SCOPE">
- <value defaultName="singleModule" />
- </option>
- <envs />
- <patterns>
- <pattern testClass="com.android.layoutlib.bridge.TestDelegates" />
- <pattern testClass="android.graphics.Matrix_DelegateTest" />
- <pattern testClass="com.android.layoutlib.bridge.android.BridgeXmlBlockParserTest" />
- </patterns>
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Run" />
- <method />
- </configuration>
-</component>
+++ /dev/null
-<component name="ProjectRunConfigurationManager">
- <configuration default="false" name="Create" type="Application" factoryName="Application" singleton="true">
- <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
- <option name="MAIN_CLASS_NAME" value="com.android.tools.layoutlib.create.Main" />
- <option name="VM_PARAMETERS" value="-ea" />
- <option name="PROGRAM_PARAMETERS" value="out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar out/target/common/obj/JAVA_LIBRARIES/core-libart_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar out/host/common/obj/JAVA_LIBRARIES/icu4j-icudata-host-jarjar_intermediates/classes-jarjar.jar out/host/common/obj/JAVA_LIBRARIES/icu4j-icutzdata-host-jarjar_intermediates/classes-jarjar.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/javalib.jar" />
- <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/../../../../" />
- <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
- <option name="ALTERNATIVE_JRE_PATH" value="" />
- <option name="ENABLE_SWING_INSPECTOR" value="false" />
- <option name="ENV_VARIABLES" />
- <option name="PASS_PARENT_ENVS" value="true" />
- <module name="create" />
- <envs />
- <RunnerSettings RunnerId="Debug">
- <option name="DEBUG_PORT" value="" />
- <option name="TRANSPORT" value="0" />
- <option name="LOCAL" value="true" />
- </RunnerSettings>
- <RunnerSettings RunnerId="Run" />
- <ConfigurationWrapper RunnerId="Debug" />
- <ConfigurationWrapper RunnerId="Run" />
- <method />
- </configuration>
-</component>
\ No newline at end of file
+++ /dev/null
-<component name="DependencyValidationManager">
- <state>
- <option name="SKIP_IMPORT_STATEMENTS" value="false" />
- </state>
-</component>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="Palette2">
- <group name="Swing">
- <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
- <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
- </item>
- <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
- <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
- </item>
- <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
- <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
- </item>
- <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
- <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
- </item>
- <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
- <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
- <initial-values>
- <property name="text" value="Button" />
- </initial-values>
- </item>
- <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
- <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
- <initial-values>
- <property name="text" value="RadioButton" />
- </initial-values>
- </item>
- <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
- <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
- <initial-values>
- <property name="text" value="CheckBox" />
- </initial-values>
- </item>
- <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
- <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
- <initial-values>
- <property name="text" value="Label" />
- </initial-values>
- </item>
- <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
- <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
- <preferred-size width="150" height="-1" />
- </default-constraints>
- </item>
- <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
- <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
- <preferred-size width="150" height="-1" />
- </default-constraints>
- </item>
- <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
- <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
- <preferred-size width="150" height="-1" />
- </default-constraints>
- </item>
- <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
- <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
- <preferred-size width="150" height="50" />
- </default-constraints>
- </item>
- <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
- <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
- <preferred-size width="150" height="50" />
- </default-constraints>
- </item>
- <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
- <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
- <preferred-size width="150" height="50" />
- </default-constraints>
- </item>
- <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
- <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
- </item>
- <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
- <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
- <preferred-size width="150" height="50" />
- </default-constraints>
- </item>
- <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
- <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
- <preferred-size width="150" height="50" />
- </default-constraints>
- </item>
- <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
- <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
- <preferred-size width="150" height="50" />
- </default-constraints>
- </item>
- <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
- <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
- <preferred-size width="200" height="200" />
- </default-constraints>
- </item>
- <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
- <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
- <preferred-size width="200" height="200" />
- </default-constraints>
- </item>
- <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
- <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
- </item>
- <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
- <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
- </item>
- <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
- <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
- </item>
- <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
- <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
- </item>
- <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
- <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
- <preferred-size width="-1" height="20" />
- </default-constraints>
- </item>
- <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
- <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
- </item>
- <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
- <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
- </item>
- </group>
- </component>
-</project>
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="VcsDirectoryMappings">
- <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
- </component>
-</project>
-
+++ /dev/null
-#
-# Copyright (C) 2008 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.
-#
-LOCAL_PATH := $(my-dir)
-include $(CLEAR_VARS)
-
-#
-# Define rules to build temp_layoutlib.jar, which contains a subset of
-# the classes in framework.jar. The layoutlib_create tool is used to
-# transform the framework jar into the temp_layoutlib jar.
-#
-
-# We need to process the framework classes.jar file, but we can't
-# depend directly on it (private vars won't be inherited correctly).
-# So, we depend on framework's BUILT file.
-built_framework_dep := $(call java-lib-deps,framework)
-built_framework_classes := $(call java-lib-files,framework)
-
-built_oj_dep := $(call java-lib-deps,core-oj)
-built_oj_classes := $(call java-lib-files,core-oj)
-
-built_core_dep := $(call java-lib-deps,core-libart)
-built_core_classes := $(call java-lib-files,core-libart)
-
-built_ext_dep := $(call java-lib-deps,ext)
-built_ext_classes := $(call java-lib-files,ext)
-
-built_icudata_dep := $(call java-lib-deps,icu4j-icudata-host-jarjar,HOST)
-built_icutzdata_dep := $(call java-lib-deps,icu4j-icutzdata-host-jarjar,HOST)
-
-built_layoutlib_create_jar := $(call java-lib-files,layoutlib_create,HOST)
-
-# This is mostly a copy of config/host_java_library.mk
-LOCAL_MODULE := temp_layoutlib
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-LOCAL_MODULE_SUFFIX := $(COMMON_JAVA_PACKAGE_SUFFIX)
-LOCAL_IS_HOST_MODULE := true
-LOCAL_BUILT_MODULE_STEM := classes.jar
-
-#######################################
-include $(BUILD_SYSTEM)/base_rules.mk
-#######################################
-
-$(LOCAL_BUILT_MODULE): $(built_oj_dep) \
- $(built_core_dep) \
- $(built_framework_dep) \
- $(built_ext_dep) \
- $(built_icudata_dep) \
- $(built_icutzdata_dep) \
- $(built_layoutlib_create_jar)
- $(hide) echo "host layoutlib_create: $@"
- $(hide) mkdir -p $(dir $@)
- $(hide) rm -f $@
- $(hide) ls -l $(built_framework_classes)
- $(hide) java -ea -jar $(built_layoutlib_create_jar) \
- $@ \
- $(built_oj_classes) \
- $(built_core_classes) \
- $(built_framework_classes) \
- $(built_ext_classes) \
- $(built_icudata_dep) \
- $(built_icutzdata_dep) \
- $(built_ext_data)
- $(hide) ls -l $(built_framework_classes)
-
-
-#
-# Include the subdir makefiles.
-#
-include $(call all-makefiles-under,$(LOCAL_PATH))
+++ /dev/null
-Layoutlib is a custom version of the android View framework designed to run inside Eclipse.
-The goal of the library is to provide layout rendering in Eclipse that are very very close to their rendering on devices.
-
-None of the com.android.* or android.* classes in layoutlib run on devices.
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry excluding="org/kxml2/io/" kind="src" path="src"/>
- <classpathentry kind="src" path="tests/src"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/layoutlib_api/layoutlib_api-prebuilt.jar" sourcepath="/ANDROID_SRC/tools/base/layoutlib-api/src/main"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/ninepatch/ninepatch-prebuilt.jar"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/tools-common/tools-common-prebuilt.jar"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/icu4j/icu4j.jar"/>
- <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/sdk-common/sdk-common.jar"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/guavalib_intermediates/javalib.jar"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>layoutlib_bridge</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-Copy this in eclipse project as a .settings folder at the root.
-This ensure proper compilation compliance and warning/error levels.
\ No newline at end of file
+++ /dev/null
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull
-org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault
-org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled
-org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable
-org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.nullReference=error
-org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning
-org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.6
+++ /dev/null
-#
-# Copyright (C) 2008 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.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_JAVA_RESOURCE_DIRS := resources
-
-LOCAL_JAVA_LIBRARIES := \
- layoutlib_api-prebuilt \
- tools-common-prebuilt
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- temp_layoutlib \
- ninepatch-prebuilt
-
-LOCAL_MODULE := layoutlib
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-# Build all sub-directories
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$">
- <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
- <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/tests/res" type="java-test-resource" />
- <sourceFolder url="file://$MODULE_DIR$/tests/src" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/src/main/myapplication.widgets" isTestSource="true" />
- <excludeFolder url="file://$MODULE_DIR$/.settings" />
- <excludeFolder url="file://$MODULE_DIR$/bin" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/.gradle" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/.idea" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/build/generated" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/build/intermediates/assets" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/build/intermediates/dependency-cache" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/build/intermediates/incremental" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/build/intermediates/libs" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/build/intermediates/manifests" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/build/intermediates/res" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/build/intermediates/rs" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/build/intermediates/symbols" />
- <excludeFolder url="file://$MODULE_DIR$/tests/res/testApp/MyApplication/gradle" />
- </content>
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="library" name="layoutlib_api-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="module-library" scope="TEST">
- <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>
- <JAVADOC />
- <SOURCES>
- <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/sdk-common/sdk-common-sources.jar!/" />
- </SOURCES>
- </library>
- </orderEntry>
- <orderEntry type="library" scope="TEST" name="junit" level="project" />
- <orderEntry type="library" scope="TEST" name="mockito" level="project" />
- <orderEntry type="library" scope="TEST" name="objenesis" level="project" />
- </component>
-</module>
\ No newline at end of file
+++ /dev/null
-The directory contains the resources for StatusBar and Navigation Bar.
-
-The resources are not arranged as per the standard resources configuration.
-They are stored per API. However, to prevent duplication of resources, each API
-resource directory is used as a backup for all earlier API levels.
-
-For example, for the back icon for ICS, we search first in v18, where we don't
-find it, and then in v19.
+++ /dev/null
-<?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: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: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: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:visibility="invisible"/>
-</merge>
+++ /dev/null
-<?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>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"/>
- <!-- The exact size of the wifi icon is specified in order to scale it properly.
- Without scaling, it appeared huge. This is currently, 70% of the actual size. -->
- <ImageView
- android:layout_height="22.4dp"
- android:layout_width="20.65dp"
- android:layout_marginTop="1dp"/>
- <ImageView
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layout_marginLeft="3dp"
- android:layout_marginRight="5dp"
- android:layout_marginTop="4dp"/>
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="4dp"
- android:layout_marginRight="5dp"
- android:gravity="center_vertical"
- android:textSize="16dp"
- android:fontFamily="sans-serif-medium"/>
-</merge>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-</merge>
+++ /dev/null
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32.0dp"
- android:height="29.5dp"
- android:viewportWidth="26.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FFFFFFFF"
- android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/>
-</vector>
+++ /dev/null
-/*
- * Copyright (C) 2010 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.animation;
-
-import com.android.ide.common.rendering.api.IAnimationListener;
-import com.android.ide.common.rendering.api.RenderSession;
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.Result.Status;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.RenderSessionImpl;
-
-import android.os.Handler;
-import android.os.Handler_Delegate;
-import android.os.Message;
-
-import java.util.PriorityQueue;
-import java.util.Queue;
-
-/**
- * Abstract animation thread.
- * <p/>
- * This does not actually start an animation, instead it fakes a looper that will play whatever
- * animation is sending messages to its own {@link Handler}.
- * <p/>
- * Classes should implement {@link #preAnimation()} and {@link #postAnimation()}.
- * <p/>
- * If {@link #preAnimation()} does not start an animation somehow then the thread doesn't do
- * anything.
- *
- */
-public abstract class AnimationThread extends Thread {
-
- private static class MessageBundle implements Comparable<MessageBundle> {
- final Handler mTarget;
- final Message mMessage;
- final long mUptimeMillis;
-
- MessageBundle(Handler target, Message message, long uptimeMillis) {
- mTarget = target;
- mMessage = message;
- mUptimeMillis = uptimeMillis;
- }
-
- @Override
- public int compareTo(MessageBundle bundle) {
- if (mUptimeMillis < bundle.mUptimeMillis) {
- return -1;
- }
- return 1;
- }
- }
-
- private final RenderSessionImpl mSession;
-
- private Queue<MessageBundle> mQueue = new PriorityQueue<MessageBundle>();
- private final IAnimationListener mListener;
-
- public AnimationThread(RenderSessionImpl scene, String threadName,
- IAnimationListener listener) {
- super(threadName);
- mSession = scene;
- mListener = listener;
- }
-
- public abstract Result preAnimation();
- public abstract void postAnimation();
-
- @Override
- public void run() {
- Bridge.prepareThread();
- try {
- /* FIXME: The ANIMATION_FRAME message no longer exists. Instead, the
- * animation timing loop is completely based on a Choreographer objects
- * that schedules animation and drawing frames. The animation handler is
- * no longer even a handler; it is just a Runnable enqueued on the Choreographer.
- Handler_Delegate.setCallback(new IHandlerCallback() {
- @Override
- public void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) {
- if (msg.what == ValueAnimator.ANIMATION_START ||
- msg.what == ValueAnimator.ANIMATION_FRAME) {
- mQueue.add(new MessageBundle(handler, msg, uptimeMillis));
- } else {
- // just ignore.
- }
- }
- });
- */
-
- // call out to the pre-animation work, which should start an animation or more.
- Result result = preAnimation();
- if (result.isSuccess() == false) {
- mListener.done(result);
- }
-
- // loop the animation
- RenderSession session = mSession.getSession();
- do {
- // check early.
- if (mListener.isCanceled()) {
- break;
- }
-
- // get the next message.
- MessageBundle bundle = mQueue.poll();
- if (bundle == null) {
- break;
- }
-
- // sleep enough for this bundle to be on time
- long currentTime = System.currentTimeMillis();
- if (currentTime < bundle.mUptimeMillis) {
- try {
- sleep(bundle.mUptimeMillis - currentTime);
- } catch (InterruptedException e) {
- // FIXME log/do something/sleep again?
- e.printStackTrace();
- }
- }
-
- // check after sleeping.
- if (mListener.isCanceled()) {
- break;
- }
-
- // ready to do the work, acquire the scene.
- result = mSession.acquire(250);
- if (result.isSuccess() == false) {
- mListener.done(result);
- return;
- }
-
- // process the bundle. If the animation is not finished, this will enqueue
- // the next message, so mQueue will have another one.
- try {
- // check after acquiring in case it took a while.
- if (mListener.isCanceled()) {
- break;
- }
-
- bundle.mTarget.handleMessage(bundle.mMessage);
- if (mSession.render(false /*freshRender*/).isSuccess()) {
- mListener.onNewFrame(session);
- }
- } finally {
- mSession.release();
- }
- } while (mListener.isCanceled() == false && mQueue.size() > 0);
-
- mListener.done(Status.SUCCESS.createResult());
-
- } catch (Throwable throwable) {
- // can't use Bridge.getLog() as the exception might be thrown outside
- // of an acquire/release block.
- mListener.done(Status.ERROR_UNKNOWN.createResult("Error playing animation", throwable));
-
- } finally {
- postAnimation();
- Handler_Delegate.setCallback(null);
- Bridge.cleanupThread();
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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.animation;
-
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Delegate implementing the native methods of android.animation.PropertyValuesHolder
- *
- * Through the layoutlib_create tool, the original native methods of PropertyValuesHolder have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
- * around to map int to instance of the delegate.
- *
- * The main goal of this class' methods are to provide a native way to access setters and getters
- * on some object. We override these methods to use reflection since the original reflection
- * implementation of the PropertyValuesHolder won't be able to access protected methods.
- *
- */
-/*package*/
-@SuppressWarnings("unused")
-class PropertyValuesHolder_Delegate {
- // This code is copied from android.animation.PropertyValuesHolder and must be kept in sync
- // We try several different types when searching for appropriate setter/getter functions.
- // The caller may have supplied values in a type that does not match the setter/getter
- // functions (such as the integers 0 and 1 to represent floating point values for alpha).
- // Also, the use of generics in constructors means that we end up with the Object versions
- // of primitive types (Float vs. float). But most likely, the setter/getter functions
- // will take primitive types instead.
- // So we supply an ordered array of other types to try before giving up.
- private static Class[] FLOAT_VARIANTS = {float.class, Float.class, double.class, int.class,
- Double.class, Integer.class};
- private static Class[] INTEGER_VARIANTS = {int.class, Integer.class, float.class, double.class,
- Float.class, Double.class};
-
- private static final Object sMethodIndexLock = new Object();
- private static final Map<Long, Method> ID_TO_METHOD = new HashMap<Long, Method>();
- private static final Map<String, Long> METHOD_NAME_TO_ID = new HashMap<String, Long>();
- private static long sNextId = 1;
-
- private static long registerMethod(Class<?> targetClass, String methodName, Class[] types,
- int nArgs) {
- // Encode the number of arguments in the method name
- String methodIndexName = String.format("%1$s.%2$s#%3$d", targetClass.getSimpleName(),
- methodName, nArgs);
- synchronized (sMethodIndexLock) {
- Long methodId = METHOD_NAME_TO_ID.get(methodIndexName);
-
- if (methodId != null) {
- // The method was already registered
- return methodId;
- }
-
- Class[] args = new Class[nArgs];
- Method method = null;
- for (Class typeVariant : types) {
- for (int i = 0; i < nArgs; i++) {
- args[i] = typeVariant;
- }
- try {
- method = targetClass.getDeclaredMethod(methodName, args);
- } catch (NoSuchMethodException ignore) {
- }
- }
-
- if (method != null) {
- methodId = sNextId++;
- ID_TO_METHOD.put(methodId, method);
- METHOD_NAME_TO_ID.put(methodIndexName, methodId);
-
- return methodId;
- }
- }
-
- // Method not found
- return 0;
- }
-
- private static void callMethod(Object target, long methodID, Object... args) {
- Method method = ID_TO_METHOD.get(methodID);
- assert method != null;
-
- try {
- method.setAccessible(true);
- method.invoke(target, args);
- } catch (IllegalAccessException e) {
- Bridge.getLog().error(null, "Unable to update property during animation", e, null);
- } catch (InvocationTargetException e) {
- Bridge.getLog().error(null, "Unable to update property during animation", e, null);
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static long nGetIntMethod(Class<?> targetClass, String methodName) {
- return nGetMultipleIntMethod(targetClass, methodName, 1);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nGetFloatMethod(Class<?> targetClass, String methodName) {
- return nGetMultipleFloatMethod(targetClass, methodName, 1);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nGetMultipleIntMethod(Class<?> targetClass, String methodName,
- int numParams) {
- return registerMethod(targetClass, methodName, INTEGER_VARIANTS, numParams);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nGetMultipleFloatMethod(Class<?> targetClass, String methodName,
- int numParams) {
- return registerMethod(targetClass, methodName, FLOAT_VARIANTS, numParams);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nCallIntMethod(Object target, long methodID, int arg) {
- callMethod(target, methodID, arg);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nCallFloatMethod(Object target, long methodID, float arg) {
- callMethod(target, methodID, arg);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nCallTwoIntMethod(Object target, long methodID, int arg1,
- int arg2) {
- callMethod(target, methodID, arg1, arg2);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nCallFourIntMethod(Object target, long methodID, int arg1,
- int arg2, int arg3, int arg4) {
- callMethod(target, methodID, arg1, arg2, arg3, arg4);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nCallMultipleIntMethod(Object target, long methodID,
- int[] args) {
- assert args != null;
-
- // Box parameters
- Object[] params = new Object[args.length];
- for (int i = 0; i < args.length; i++) {
- params[i] = args;
- }
- callMethod(target, methodID, params);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nCallTwoFloatMethod(Object target, long methodID, float arg1,
- float arg2) {
- callMethod(target, methodID, arg1, arg2);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nCallFourFloatMethod(Object target, long methodID, float arg1,
- float arg2, float arg3, float arg4) {
- callMethod(target, methodID, arg1, arg2, arg3, arg4);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nCallMultipleFloatMethod(Object target, long methodID,
- float[] args) {
- assert args != null;
-
- // Box parameters
- Object[] params = new Object[args.length];
- for (int i = 0; i < args.length; i++) {
- params[i] = args;
- }
- callMethod(target, methodID, params);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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.app;
-
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.content.Context;
-import android.os.Bundle;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link Fragment}
- *
- * Through the layoutlib_create tool, the original methods of Fragment have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * The methods being re-implemented are the ones responsible for instantiating Fragment objects.
- * Because the classes of these objects are found in the project, these methods need access to
- * {@link LayoutlibCallback} object. They are however static methods, so the callback is set
- * before the inflation through {@link #setLayoutlibCallback(LayoutlibCallback)}.
- */
-public class Fragment_Delegate {
-
- private static LayoutlibCallback sLayoutlibCallback;
-
- /**
- * Sets the current {@link LayoutlibCallback} to be used to instantiate classes coming
- * from the project being rendered.
- */
- public static void setLayoutlibCallback(LayoutlibCallback layoutlibCallback) {
- sLayoutlibCallback = layoutlibCallback;
- }
-
- /**
- * Like {@link #instantiate(Context, String, Bundle)} but with a null
- * argument Bundle.
- */
- @LayoutlibDelegate
- /*package*/ static Fragment instantiate(Context context, String fname) {
- return instantiate(context, fname, null);
- }
-
- /**
- * Create a new instance of a Fragment with the given class name. This is
- * the same as calling its empty constructor.
- *
- * @param context The calling context being used to instantiate the fragment.
- * This is currently just used to get its ClassLoader.
- * @param fname The class name of the fragment to instantiate.
- * @param args Bundle of arguments to supply to the fragment, which it
- * can retrieve with {@link Fragment#getArguments()}. May be null.
- * @return Returns a new fragment instance.
- * @throws Fragment.InstantiationException If there is a failure in instantiating
- * the given fragment class. This is a runtime exception; it is not
- * normally expected to happen.
- */
- @LayoutlibDelegate
- /*package*/ static Fragment instantiate(Context context, String fname, Bundle args) {
- try {
- if (sLayoutlibCallback != null) {
- Fragment f = (Fragment) sLayoutlibCallback.loadView(fname,
- new Class[0], new Object[0]);
-
- if (args != null) {
- args.setClassLoader(f.getClass().getClassLoader());
- f.mArguments = args;
- }
- return f;
- }
-
- return null;
- } catch (ClassNotFoundException e) {
- throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
- + ": make sure class name exists, is public, and has an"
- + " empty constructor that is public", e);
- } catch (java.lang.InstantiationException e) {
- throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
- + ": make sure class name exists, is public, and has an"
- + " empty constructor that is public", e);
- } catch (IllegalAccessException e) {
- throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
- + ": make sure class name exists, is public, and has an"
- + " empty constructor that is public", e);
- } catch (Exception e) {
- throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
- + ": make sure class name exists, is public, and has an"
- + " empty constructor that is public", e);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-/**
- * Class to allow accessing {@link SystemServiceRegistry#getSystemServiceName}
- */
-public class SystemServiceRegistry_Accessor {
- /**
- * Gets the name of the system-level service that is represented by the specified class.
- */
- public static String getSystemServiceName(Class<?> serviceClass) {
- return SystemServiceRegistry.getSystemServiceName(serviceClass);
- }
-}
+++ /dev/null
-/*
- * 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.content.res;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.util.SparseArray;
-
-/**
- * Delegate used to provide implementation of a select few native methods of {@link AssetManager}
- * <p/>
- * Through the layoutlib_create tool, the original native methods of AssetManager have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-public class AssetManager_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static long newTheme(AssetManager manager) {
- return Resources_Theme_Delegate.getDelegateManager()
- .addNewDelegate(new Resources_Theme_Delegate());
- }
-
- @LayoutlibDelegate
- /*package*/ static void deleteTheme(AssetManager manager, long theme) {
- Resources_Theme_Delegate.getDelegateManager().removeJavaReferenceFor(theme);
- }
-
- @LayoutlibDelegate
- /*package*/ static SparseArray<String> getAssignedPackageIdentifiers(AssetManager manager) {
- return new SparseArray<>();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import com.android.ide.common.rendering.api.AssetRepository;
-import com.android.layoutlib.bridge.Bridge;
-
-public class BridgeAssetManager extends AssetManager {
-
- private AssetRepository mAssetRepository;
-
- /**
- * This initializes the static field {@link AssetManager#sSystem} which is used
- * by methods who get a global asset manager using {@link AssetManager#getSystem()}.
- * <p/>
- * They will end up using our bridge asset manager.
- * <p/>
- * {@link Bridge} calls this method after setting up a new bridge.
- */
- public static AssetManager initSystem() {
- if (!(AssetManager.sSystem instanceof BridgeAssetManager)) {
- // Note that AssetManager() creates a system AssetManager and we override it
- // with our BridgeAssetManager.
- AssetManager.sSystem = new BridgeAssetManager();
- AssetManager.sSystem.makeStringBlocks(null);
- }
- return AssetManager.sSystem;
- }
-
- /**
- * Clears the static {@link AssetManager#sSystem} to make sure we don't leave objects
- * around that would prevent us from unloading the library.
- */
- public static void clearSystem() {
- AssetManager.sSystem = null;
- }
-
- public void setAssetRepository(AssetRepository assetRepository) {
- mAssetRepository = assetRepository;
- }
-
- public AssetRepository getAssetRepository() {
- return mAssetRepository;
- }
-
- public BridgeAssetManager() {
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import com.android.ide.common.rendering.api.ArrayResourceValue;
-import com.android.ide.common.rendering.api.AttrResourceValue;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.StyleResourceValue;
-import com.android.internal.util.XmlUtils;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.ResourceHelper;
-import com.android.resources.ResourceType;
-
-import android.annotation.Nullable;
-import android.content.res.Resources.NotFoundException;
-import android.content.res.Resources.Theme;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.LayoutInflater_Delegate;
-import android.view.ViewGroup.LayoutParams;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Map;
-
-import static android.util.TypedValue.TYPE_ATTRIBUTE;
-import static android.util.TypedValue.TYPE_DIMENSION;
-import static android.util.TypedValue.TYPE_FLOAT;
-import static android.util.TypedValue.TYPE_INT_BOOLEAN;
-import static android.util.TypedValue.TYPE_INT_COLOR_ARGB4;
-import static android.util.TypedValue.TYPE_INT_COLOR_ARGB8;
-import static android.util.TypedValue.TYPE_INT_COLOR_RGB4;
-import static android.util.TypedValue.TYPE_INT_COLOR_RGB8;
-import static android.util.TypedValue.TYPE_INT_DEC;
-import static android.util.TypedValue.TYPE_INT_HEX;
-import static android.util.TypedValue.TYPE_NULL;
-import static android.util.TypedValue.TYPE_REFERENCE;
-import static android.util.TypedValue.TYPE_STRING;
-import static com.android.SdkConstants.PREFIX_RESOURCE_REF;
-import static com.android.SdkConstants.PREFIX_THEME_REF;
-import static com.android.ide.common.rendering.api.RenderResources.REFERENCE_EMPTY;
-import static com.android.ide.common.rendering.api.RenderResources.REFERENCE_NULL;
-import static com.android.ide.common.rendering.api.RenderResources.REFERENCE_UNDEFINED;
-
-/**
- * Custom implementation of TypedArray to handle non compiled resources.
- */
-public final class BridgeTypedArray extends TypedArray {
-
- private final Resources mBridgeResources;
- private final BridgeContext mContext;
- private final boolean mPlatformFile;
-
- private final ResourceValue[] mResourceData;
- private final String[] mNames;
- private final boolean[] mIsFramework;
-
- // Contains ids that are @empty. We still store null in mResourceData for that index, since we
- // want to save on the check against empty, each time a resource value is requested.
- @Nullable
- private int[] mEmptyIds;
-
- public BridgeTypedArray(Resources resources, BridgeContext context, int len,
- boolean platformFile) {
- super(resources);
- mBridgeResources = resources;
- mContext = context;
- mPlatformFile = platformFile;
- mResourceData = new ResourceValue[len];
- mNames = new String[len];
- mIsFramework = new boolean[len];
- }
-
- /**
- * A bridge-specific method that sets a value in the type array
- * @param index the index of the value in the TypedArray
- * @param name the name of the attribute
- * @param isFramework whether the attribute is in the android namespace.
- * @param value the value of the attribute
- */
- public void bridgeSetValue(int index, String name, boolean isFramework, ResourceValue value) {
- mResourceData[index] = value;
- mNames[index] = name;
- mIsFramework[index] = isFramework;
- }
-
- /**
- * Seals the array after all calls to
- * {@link #bridgeSetValue(int, String, boolean, ResourceValue)} have been done.
- * <p/>This allows to compute the list of non default values, permitting
- * {@link #getIndexCount()} to return the proper value.
- */
- public void sealArray() {
- // fills TypedArray.mIndices which is used to implement getIndexCount/getIndexAt
- // first count the array size
- int count = 0;
- ArrayList<Integer> emptyIds = null;
- for (int i = 0; i < mResourceData.length; i++) {
- ResourceValue data = mResourceData[i];
- if (data != null) {
- String dataValue = data.getValue();
- if (REFERENCE_NULL.equals(dataValue) || REFERENCE_UNDEFINED.equals(dataValue)) {
- mResourceData[i] = null;
- } else if (REFERENCE_EMPTY.equals(dataValue)) {
- mResourceData[i] = null;
- if (emptyIds == null) {
- emptyIds = new ArrayList<Integer>(4);
- }
- emptyIds.add(i);
- } else {
- count++;
- }
- }
- }
-
- if (emptyIds != null) {
- mEmptyIds = new int[emptyIds.size()];
- for (int i = 0; i < emptyIds.size(); i++) {
- mEmptyIds[i] = emptyIds.get(i);
- }
- }
-
- // allocate the table with an extra to store the size
- mIndices = new int[count+1];
- mIndices[0] = count;
-
- // fill the array with the indices.
- int index = 1;
- for (int i = 0 ; i < mResourceData.length ; i++) {
- if (mResourceData[i] != null) {
- mIndices[index++] = i;
- }
- }
- }
-
- /**
- * Set the theme to be used for inflating drawables.
- */
- public void setTheme(Theme theme) {
- mTheme = theme;
- }
-
- /**
- * Return the number of values in this array.
- */
- @Override
- public int length() {
- return mResourceData.length;
- }
-
- /**
- * Return the Resources object this array was loaded from.
- */
- @Override
- public Resources getResources() {
- return mBridgeResources;
- }
-
- /**
- * Retrieve the styled string value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return CharSequence holding string data. May be styled. Returns
- * null if the attribute is not defined.
- */
- @Override
- public CharSequence getText(int index) {
- // FIXME: handle styled strings!
- return getString(index);
- }
-
- /**
- * Retrieve the string value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return String holding string data. Any styling information is
- * removed. Returns null if the attribute is not defined.
- */
- @Override
- public String getString(int index) {
- if (!hasValue(index)) {
- return null;
- }
- // As unfortunate as it is, it's possible to use enums with all attribute formats,
- // not just integers/enums. So, we need to search the enums always. In case
- // enums are used, the returned value is an integer.
- Integer v = resolveEnumAttribute(index);
- return v == null ? mResourceData[index].getValue() : String.valueOf((int) v);
- }
-
- /**
- * Retrieve the boolean value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined.
- *
- * @return Attribute boolean value, or defValue if not defined.
- */
- @Override
- public boolean getBoolean(int index, boolean defValue) {
- String s = getString(index);
- return s == null ? defValue : XmlUtils.convertValueToBoolean(s, defValue);
-
- }
-
- /**
- * Retrieve the integer value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined.
- *
- * @return Attribute int value, or defValue if not defined.
- */
- @Override
- public int getInt(int index, int defValue) {
- String s = getString(index);
- try {
- return convertValueToInt(s, defValue);
- } catch (NumberFormatException e) {
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- String.format("\"%1$s\" in attribute \"%2$s\" is not a valid integer",
- s, mNames[index]),
- null);
- }
- return defValue;
- }
-
- /**
- * Retrieve the float value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return Attribute float value, or defValue if not defined..
- */
- @Override
- public float getFloat(int index, float defValue) {
- String s = getString(index);
- try {
- if (s != null) {
- return Float.parseFloat(s);
- }
- } catch (NumberFormatException e) {
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- String.format("\"%1$s\" in attribute \"%2$s\" cannot be converted to float.",
- s, mNames[index]),
- null);
- }
- return defValue;
- }
-
- /**
- * Retrieve the color value for the attribute at <var>index</var>. If
- * the attribute references a color resource holding a complex
- * {@link android.content.res.ColorStateList}, then the default color from
- * the set is returned.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute color value, or defValue if not defined.
- */
- @Override
- public int getColor(int index, int defValue) {
- if (index < 0 || index >= mResourceData.length) {
- return defValue;
- }
-
- if (mResourceData[index] == null) {
- return defValue;
- }
-
- ColorStateList colorStateList = ResourceHelper.getColorStateList(
- mResourceData[index], mContext);
- if (colorStateList != null) {
- return colorStateList.getDefaultColor();
- }
-
- return defValue;
- }
-
- @Override
- public ColorStateList getColorStateList(int index) {
- if (!hasValue(index)) {
- return null;
- }
-
- return ResourceHelper.getColorStateList(mResourceData[index], mContext);
- }
-
- @Override
- public ComplexColor getComplexColor(int index) {
- if (!hasValue(index)) {
- return null;
- }
-
- return ResourceHelper.getComplexColor(mResourceData[index], mContext);
- }
-
- /**
- * Retrieve the integer value for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute integer value, or defValue if not defined.
- */
- @Override
- public int getInteger(int index, int defValue) {
- return getInt(index, defValue);
- }
-
- /**
- * Retrieve a dimensional unit attribute at <var>index</var>. Unit
- * conversions are based on the current {@link DisplayMetrics}
- * associated with the resources this {@link TypedArray} object
- * came from.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
- * metric, or defValue if not defined.
- *
- * @see #getDimensionPixelOffset
- * @see #getDimensionPixelSize
- */
- @Override
- public float getDimension(int index, float defValue) {
- String s = getString(index);
- if (s == null) {
- return defValue;
- }
- // Check if the value is a magic constant that doesn't require a unit.
- try {
- int i = Integer.parseInt(s);
- if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) {
- return i;
- }
- } catch (NumberFormatException ignored) {
- // pass
- }
-
- if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
- return mValue.getDimension(mBridgeResources.getDisplayMetrics());
- }
-
- return defValue;
- }
-
- /**
- * Retrieve a dimensional unit attribute at <var>index</var> for use
- * as an offset in raw pixels. This is the same as
- * {@link #getDimension}, except the returned value is converted to
- * integer pixels for you. An offset conversion involves simply
- * truncating the base value to an integer.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
- * metric and truncated to integer pixels, or defValue if not defined.
- *
- * @see #getDimension
- * @see #getDimensionPixelSize
- */
- @Override
- public int getDimensionPixelOffset(int index, int defValue) {
- return (int) getDimension(index, defValue);
- }
-
- /**
- * Retrieve a dimensional unit attribute at <var>index</var> for use
- * as a size in raw pixels. This is the same as
- * {@link #getDimension}, except the returned value is converted to
- * integer pixels for use as a size. A size conversion involves
- * rounding the base value, and ensuring that a non-zero base value
- * is at least one pixel in size.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute dimension value multiplied by the appropriate
- * metric and truncated to integer pixels, or defValue if not defined.
- *
- * @see #getDimension
- * @see #getDimensionPixelOffset
- */
- @Override
- public int getDimensionPixelSize(int index, int defValue) {
- try {
- return getDimension(index, null);
- } catch (RuntimeException e) {
- String s = getString(index);
-
- if (s != null) {
- // looks like we were unable to resolve the dimension value
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- String.format("\"%1$s\" in attribute \"%2$s\" is not a valid format.",
- s, mNames[index]), null);
- }
-
- return defValue;
- }
- }
-
- /**
- * Special version of {@link #getDimensionPixelSize} for retrieving
- * {@link android.view.ViewGroup}'s layout_width and layout_height
- * attributes. This is only here for performance reasons; applications
- * should use {@link #getDimensionPixelSize}.
- *
- * @param index Index of the attribute to retrieve.
- * @param name Textual name of attribute for error reporting.
- *
- * @return Attribute dimension value multiplied by the appropriate
- * metric and truncated to integer pixels.
- */
- @Override
- public int getLayoutDimension(int index, String name) {
- try {
- // this will throw an exception if not found.
- return getDimension(index, name);
- } catch (RuntimeException e) {
-
- if (LayoutInflater_Delegate.sIsInInclude) {
- throw new RuntimeException("Layout Dimension '" + name + "' not found.");
- }
-
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- "You must supply a " + name + " attribute.", null);
-
- return 0;
- }
- }
-
- @Override
- public int getLayoutDimension(int index, int defValue) {
- return getDimensionPixelSize(index, defValue);
- }
-
- /** @param name attribute name, used for error reporting. */
- private int getDimension(int index, @Nullable String name) {
- String s = getString(index);
- if (s == null) {
- if (name != null) {
- throw new RuntimeException("Attribute '" + name + "' not found");
- }
- throw new RuntimeException();
- }
- // Check if the value is a magic constant that doesn't require a unit.
- try {
- int i = Integer.parseInt(s);
- if (i == LayoutParams.MATCH_PARENT || i == LayoutParams.WRAP_CONTENT) {
- return i;
- }
- } catch (NumberFormatException ignored) {
- // pass
- }
- if (ResourceHelper.parseFloatAttribute(mNames[index], s, mValue, true)) {
- float f = mValue.getDimension(mBridgeResources.getDisplayMetrics());
-
- final int res = (int)(f+0.5f);
- if (res != 0) return res;
- if (f == 0) return 0;
- if (f > 0) return 1;
- }
-
- throw new RuntimeException();
- }
-
- /**
- * Retrieve a fractional unit attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param base The base value of this fraction. In other words, a
- * standard fraction is multiplied by this value.
- * @param pbase The parent base value of this fraction. In other
- * words, a parent fraction (nn%p) is multiplied by this
- * value.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute fractional value multiplied by the appropriate
- * base value, or defValue if not defined.
- */
- @Override
- public float getFraction(int index, int base, int pbase, float defValue) {
- String value = getString(index);
- if (value == null) {
- return defValue;
- }
-
- if (ResourceHelper.parseFloatAttribute(mNames[index], value, mValue, false)) {
- return mValue.getFraction(base, pbase);
- }
-
- // looks like we were unable to resolve the fraction value
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- String.format(
- "\"%1$s\" in attribute \"%2$s\" cannot be converted to a fraction.",
- value, mNames[index]), null);
-
- return defValue;
- }
-
- /**
- * Retrieve the resource identifier for the attribute at
- * <var>index</var>. Note that attribute resource as resolved when
- * the overall {@link TypedArray} object is retrieved. As a
- * result, this function will return the resource identifier of the
- * final resource value that was found, <em>not</em> necessarily the
- * original resource that was specified by the attribute.
- *
- * @param index Index of attribute to retrieve.
- * @param defValue Value to return if the attribute is not defined or
- * not a resource.
- *
- * @return Attribute resource identifier, or defValue if not defined.
- */
- @Override
- public int getResourceId(int index, int defValue) {
- if (index < 0 || index >= mResourceData.length) {
- return defValue;
- }
-
- // get the Resource for this index
- ResourceValue resValue = mResourceData[index];
-
- // no data, return the default value.
- if (resValue == null) {
- return defValue;
- }
-
- // check if this is a style resource
- if (resValue instanceof StyleResourceValue) {
- // get the id that will represent this style.
- return mContext.getDynamicIdByStyle((StyleResourceValue)resValue);
- }
-
- // if the attribute was a reference to a resource, and not a declaration of an id (@+id),
- // then the xml attribute value was "resolved" which leads us to a ResourceValue with a
- // valid getType() and getName() returning a resource name.
- // (and getValue() returning null!). We need to handle this!
- if (resValue.getResourceType() != null) {
- // if this is a framework id
- if (mPlatformFile || resValue.isFramework()) {
- // look for idName in the android R classes
- return mContext.getFrameworkResourceValue(
- resValue.getResourceType(), resValue.getName(), defValue);
- }
-
- // look for idName in the project R class.
- return mContext.getProjectResourceValue(
- resValue.getResourceType(), resValue.getName(), defValue);
- }
-
- // else, try to get the value, and resolve it somehow.
- String value = resValue.getValue();
- if (value == null) {
- return defValue;
- }
- value = value.trim();
-
- // if the value is just an integer, return it.
- try {
- int i = Integer.parseInt(value);
- if (Integer.toString(i).equals(value)) {
- return i;
- }
- } catch (NumberFormatException e) {
- // pass
- }
-
- if (value.startsWith("#")) {
- // this looks like a color, do not try to parse it
- return defValue;
- }
-
- // Handle the @id/<name>, @+id/<name> and @android:id/<name>
- // We need to return the exact value that was compiled (from the various R classes),
- // as these values can be reused internally with calls to findViewById().
- // There's a trick with platform layouts that not use "android:" but their IDs are in
- // fact in the android.R and com.android.internal.R classes.
- // The field mPlatformFile will indicate that all IDs are to be looked up in the android R
- // classes exclusively.
-
- // if this is a reference to an id, find it.
- if (value.startsWith("@id/") || value.startsWith("@+") ||
- value.startsWith("@android:id/")) {
-
- int pos = value.indexOf('/');
- String idName = value.substring(pos + 1);
- boolean create = value.startsWith("@+");
- boolean isFrameworkId =
- mPlatformFile || value.startsWith("@android") || value.startsWith("@+android");
-
- // Look for the idName in project or android R class depending on isPlatform.
- if (create) {
- Integer idValue;
- if (isFrameworkId) {
- idValue = Bridge.getResourceId(ResourceType.ID, idName);
- } else {
- idValue = mContext.getLayoutlibCallback().getResourceId(ResourceType.ID, idName);
- }
- return idValue == null ? defValue : idValue;
- }
- // This calls the same method as in if(create), but doesn't create a dynamic id, if
- // one is not found.
- if (isFrameworkId) {
- return mContext.getFrameworkResourceValue(ResourceType.ID, idName, defValue);
- } else {
- return mContext.getProjectResourceValue(ResourceType.ID, idName, defValue);
- }
- }
- else if (value.startsWith("@aapt:_aapt")) {
- return mContext.getLayoutlibCallback().getResourceId(ResourceType.AAPT, value);
- }
-
- // not a direct id valid reference. First check if it's an enum (this is a corner case
- // for attributes that have a reference|enum type), then fallback to resolve
- // as an ID without prefix.
- Integer enumValue = resolveEnumAttribute(index);
- if (enumValue != null) {
- return enumValue;
- }
-
- // Ok, not an enum, resolve as an ID
- Integer idValue;
-
- if (resValue.isFramework()) {
- idValue = Bridge.getResourceId(resValue.getResourceType(),
- resValue.getName());
- } else {
- idValue = mContext.getLayoutlibCallback().getResourceId(
- resValue.getResourceType(), resValue.getName());
- }
-
- if (idValue != null) {
- return idValue;
- }
-
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
- String.format(
- "Unable to resolve id \"%1$s\" for attribute \"%2$s\"", value, mNames[index]),
- resValue);
-
- return defValue;
- }
-
- @Override
- public int getThemeAttributeId(int index, int defValue) {
- // TODO: Get the right Theme Attribute ID to enable caching of the drawables.
- return defValue;
- }
-
- /**
- * Retrieve the Drawable for the attribute at <var>index</var>. This
- * gets the resource ID of the selected attribute, and uses
- * {@link Resources#getDrawable Resources.getDrawable} of the owning
- * Resources object to retrieve its Drawable.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return Drawable for the attribute, or null if not defined.
- */
- @Override
- public Drawable getDrawable(int index) {
- if (!hasValue(index)) {
- return null;
- }
-
- ResourceValue value = mResourceData[index];
- return ResourceHelper.getDrawable(value, mContext, mTheme);
- }
-
- /**
- * Version of {@link #getDrawable(int)} that accepts an override density.
- * @hide
- */
- @Override
- public Drawable getDrawableForDensity(int index, int density) {
- return getDrawable(index);
- }
-
- /**
- * Retrieve the Typeface for the attribute at <var>index</var>.
- * @param index Index of attribute to retrieve.
- *
- * @return Typeface for the attribute, or null if not defined.
- */
- @Override
- public Typeface getFont(int index) {
- if (!hasValue(index)) {
- return null;
- }
-
- ResourceValue value = mResourceData[index];
- return ResourceHelper.getFont(value, mContext, mTheme);
- }
-
- /**
- * Retrieve the CharSequence[] for the attribute at <var>index</var>.
- * This gets the resource ID of the selected attribute, and uses
- * {@link Resources#getTextArray Resources.getTextArray} of the owning
- * Resources object to retrieve its String[].
- *
- * @param index Index of attribute to retrieve.
- *
- * @return CharSequence[] for the attribute, or null if not defined.
- */
- @Override
- public CharSequence[] getTextArray(int index) {
- if (!hasValue(index)) {
- return null;
- }
- ResourceValue resVal = mResourceData[index];
- if (resVal instanceof ArrayResourceValue) {
- ArrayResourceValue array = (ArrayResourceValue) resVal;
- int count = array.getElementCount();
- return count >= 0 ? Resources_Delegate.fillValues(mBridgeResources, array, new CharSequence[count]) :
- null;
- }
- int id = getResourceId(index, 0);
- String resIdMessage = id > 0 ? " (resource id 0x" + Integer.toHexString(id) + ')' : "";
- assert false :
- String.format("%1$s in %2$s%3$s is not a valid array resource.", resVal.getValue(),
- mNames[index], resIdMessage);
-
- return new CharSequence[0];
- }
-
- @Override
- public int[] extractThemeAttrs() {
- // The drawables are always inflated with a Theme and we don't care about caching. So,
- // just return.
- return null;
- }
-
- @Override
- public int getChangingConfigurations() {
- // We don't care about caching. Any change in configuration is a fresh render. So,
- // just return.
- return 0;
- }
-
- /**
- * Retrieve the raw TypedValue for the attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- * @param outValue TypedValue object in which to place the attribute's
- * data.
- *
- * @return Returns true if the value was retrieved, else false.
- */
- @Override
- public boolean getValue(int index, TypedValue outValue) {
- // TODO: more switch cases for other types.
- outValue.type = getType(index);
- switch (outValue.type) {
- case TYPE_NULL:
- return false;
- case TYPE_STRING:
- outValue.string = getString(index);
- return true;
- default:
- // For back-compatibility, parse as float.
- String s = getString(index);
- return s != null &&
- ResourceHelper.parseFloatAttribute(mNames[index], s, outValue, false);
- }
- }
-
- @Override
- @SuppressWarnings("ResultOfMethodCallIgnored")
- public int getType(int index) {
- String value = getString(index);
- if (value == null) {
- return TYPE_NULL;
- }
- if (value.startsWith(PREFIX_RESOURCE_REF)) {
- return TYPE_REFERENCE;
- }
- if (value.startsWith(PREFIX_THEME_REF)) {
- return TYPE_ATTRIBUTE;
- }
- try {
- // Don't care about the value. Only called to check if an exception is thrown.
- convertValueToInt(value, 0);
- if (value.startsWith("0x") || value.startsWith("0X")) {
- return TYPE_INT_HEX;
- }
- // is it a color?
- if (value.startsWith("#")) {
- int length = value.length() - 1;
- if (length == 3) { // rgb
- return TYPE_INT_COLOR_RGB4;
- }
- if (length == 4) { // argb
- return TYPE_INT_COLOR_ARGB4;
- }
- if (length == 6) { // rrggbb
- return TYPE_INT_COLOR_RGB8;
- }
- if (length == 8) { // aarrggbb
- return TYPE_INT_COLOR_ARGB8;
- }
- }
- if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) {
- return TYPE_INT_BOOLEAN;
- }
- return TYPE_INT_DEC;
- } catch (NumberFormatException ignored) {
- try {
- Float.parseFloat(value);
- return TYPE_FLOAT;
- } catch (NumberFormatException ignore) {
- }
- // Might be a dimension.
- if (ResourceHelper.parseFloatAttribute(null, value, new TypedValue(), false)) {
- return TYPE_DIMENSION;
- }
- }
- // TODO: handle fractions.
- return TYPE_STRING;
- }
-
- /**
- * Determines whether there is an attribute at <var>index</var>.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return True if the attribute has a value, false otherwise.
- */
- @Override
- public boolean hasValue(int index) {
- return index >= 0 && index < mResourceData.length && mResourceData[index] != null;
- }
-
- @Override
- public boolean hasValueOrEmpty(int index) {
- return hasValue(index) || index >= 0 && index < mResourceData.length &&
- mEmptyIds != null && Arrays.binarySearch(mEmptyIds, index) >= 0;
- }
-
- /**
- * Retrieve the raw TypedValue for the attribute at <var>index</var>
- * and return a temporary object holding its data. This object is only
- * valid until the next call on to {@link TypedArray}.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return Returns a TypedValue object if the attribute is defined,
- * containing its data; otherwise returns null. (You will not
- * receive a TypedValue whose type is TYPE_NULL.)
- */
- @Override
- public TypedValue peekValue(int index) {
- if (index < 0 || index >= mResourceData.length) {
- return null;
- }
-
- if (getValue(index, mValue)) {
- return mValue;
- }
-
- return null;
- }
-
- /**
- * Returns a message about the parser state suitable for printing error messages.
- */
- @Override
- public String getPositionDescription() {
- return "<internal -- stub if needed>";
- }
-
- /**
- * Give back a previously retrieved TypedArray, for later re-use.
- */
- @Override
- public void recycle() {
- // pass
- }
-
- @Override
- public String toString() {
- return Arrays.toString(mResourceData);
- }
-
- /**
- * Searches for the string in the attributes (flag or enums) and returns the integer.
- * If found, it will return an integer matching the value.
- *
- * @param index Index of attribute to retrieve.
- *
- * @return Attribute int value, or null if not defined.
- */
- private Integer resolveEnumAttribute(int index) {
- // Get the map of attribute-constant -> IntegerValue
- Map<String, Integer> map = null;
- if (mIsFramework[index]) {
- map = Bridge.getEnumValues(mNames[index]);
- } else {
- // get the styleable matching the resolved name
- RenderResources res = mContext.getRenderResources();
- ResourceValue attr = res.getProjectResource(ResourceType.ATTR, mNames[index]);
- if (attr instanceof AttrResourceValue) {
- map = ((AttrResourceValue) attr).getAttributeValues();
- }
- }
-
- if (map != null) {
- // accumulator to store the value of the 1+ constants.
- int result = 0;
- boolean found = false;
-
- // split the value in case this is a mix of several flags.
- String[] keywords = mResourceData[index].getValue().split("\\|");
- for (String keyword : keywords) {
- Integer i = map.get(keyword.trim());
- if (i != null) {
- result |= i;
- found = true;
- }
- // TODO: We should act smartly and log a warning for incorrect keywords. However,
- // this method is currently called even if the resourceValue is not an enum.
- }
- if (found) {
- return result;
- }
- }
-
- return null;
- }
-
- /**
- * Copied from {@link XmlUtils#convertValueToInt(CharSequence, int)}, but adapted to account
- * for aapt, and the fact that host Java VM's Integer.parseInt("XXXXXXXX", 16) cannot handle
- * "XXXXXXXX" > 80000000.
- */
- private static int convertValueToInt(@Nullable String charSeq, int defValue) {
- if (null == charSeq || charSeq.isEmpty())
- return defValue;
-
- int sign = 1;
- int index = 0;
- int len = charSeq.length();
- int base = 10;
-
- if ('-' == charSeq.charAt(0)) {
- sign = -1;
- index++;
- }
-
- if ('0' == charSeq.charAt(index)) {
- // Quick check for a zero by itself
- if (index == (len - 1))
- return 0;
-
- char c = charSeq.charAt(index + 1);
-
- if ('x' == c || 'X' == c) {
- index += 2;
- base = 16;
- } else {
- index++;
- // Leave the base as 10. aapt removes the preceding zero, and thus when framework
- // sees the value, it only gets the decimal value.
- }
- } else if ('#' == charSeq.charAt(index)) {
- return ResourceHelper.getColor(charSeq) * sign;
- } else if ("true".equals(charSeq) || "TRUE".equals(charSeq)) {
- return -1;
- } else if ("false".equals(charSeq) || "FALSE".equals(charSeq)) {
- return 0;
- }
-
- // Use Long, since we want to handle hex ints > 80000000.
- return ((int)Long.parseLong(charSeq.substring(index), base)) * sign;
- }
-
- static TypedArray obtain(Resources res, int len) {
- return new BridgeTypedArray(res, null, len, true);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.res.Resources.Theme;
-import android.util.AttributeSet;
-
-import java.io.IOException;
-
-/**
- * Class that provides access to the {@link GradientColor#createFromXmlInner(Resources,
- * XmlPullParser, AttributeSet, Theme)} and {@link ColorStateList#createFromXmlInner(Resources,
- * XmlPullParser, AttributeSet, Theme)} methods
- */
-public class ComplexColor_Accessor {
- public static GradientColor createGradientColorFromXmlInner(@NonNull Resources r,
- @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
- throws IOException, XmlPullParserException {
- return GradientColor.createFromXmlInner(r, parser, attrs, theme);
- }
-
- public static ColorStateList createColorStateListFromXmlInner(@NonNull Resources r,
- @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme)
- throws IOException, XmlPullParserException {
- return ColorStateList.createFromXmlInner(r, parser, attrs, theme);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import com.android.SdkConstants;
-import com.android.ide.common.rendering.api.ArrayResourceValue;
-import com.android.ide.common.rendering.api.DensityBasedResourceValue;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.PluralsResourceValue;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.BridgeConstants;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.impl.ParserFactory;
-import com.android.layoutlib.bridge.impl.ResourceHelper;
-import com.android.layoutlib.bridge.util.NinePatchInputStream;
-import com.android.ninepatch.NinePatch;
-import com.android.resources.ResourceType;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-import com.android.util.Pair;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.res.Resources.NotFoundException;
-import android.content.res.Resources.Theme;
-import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
-import android.icu.text.PluralRules;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.LruCache;
-import android.util.TypedValue;
-import android.view.DisplayAdjustments;
-import android.view.ViewGroup.LayoutParams;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.Iterator;
-
-@SuppressWarnings("deprecation")
-public class Resources_Delegate {
-
- private static boolean[] mPlatformResourceFlag = new boolean[1];
- // TODO: This cache is cleared every time a render session is disposed. Look into making this
- // more long lived.
- private static LruCache<String, Drawable.ConstantState> sDrawableCache = new LruCache<>(50);
-
- public static Resources initSystem(BridgeContext context,
- AssetManager assets,
- DisplayMetrics metrics,
- Configuration config,
- LayoutlibCallback layoutlibCallback) {
- Resources resources = new Resources(Resources_Delegate.class.getClassLoader());
- resources.setImpl(new ResourcesImpl(assets, metrics, config, new DisplayAdjustments()));
- resources.mContext = context;
- resources.mLayoutlibCallback = layoutlibCallback;
- return Resources.mSystem = resources;
- }
-
- /**
- * Disposes the static {@link Resources#mSystem} to make sure we don't leave objects around that
- * would prevent us from unloading the library.
- */
- public static void disposeSystem() {
- sDrawableCache.evictAll();
- Resources.mSystem.mContext = null;
- Resources.mSystem.mLayoutlibCallback = null;
- Resources.mSystem = null;
- }
-
- public static BridgeTypedArray newTypeArray(Resources resources, int numEntries,
- boolean platformFile) {
- return new BridgeTypedArray(resources, resources.mContext, numEntries, platformFile);
- }
-
- private static Pair<ResourceType, String> getResourceInfo(Resources resources, int id,
- boolean[] platformResFlag_out) {
- // first get the String related to this id in the framework
- Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
-
- // Set the layoutlib callback and context for resources
- if (resources != Resources.mSystem && resources.mLayoutlibCallback == null) {
- resources.mLayoutlibCallback = Resources.mSystem.mLayoutlibCallback;
- resources.mContext = Resources.mSystem.mContext;
- }
-
- if (resourceInfo != null) {
- platformResFlag_out[0] = true;
- return resourceInfo;
- }
-
- // didn't find a match in the framework? look in the project.
- if (resources.mLayoutlibCallback != null) {
- resourceInfo = resources.mLayoutlibCallback.resolveResourceId(id);
-
- if (resourceInfo != null) {
- platformResFlag_out[0] = false;
- return resourceInfo;
- }
- }
- return null;
- }
-
- private static Pair<String, ResourceValue> getResourceValue(Resources resources, int id,
- boolean[] platformResFlag_out) {
- Pair<ResourceType, String> resourceInfo =
- getResourceInfo(resources, id, platformResFlag_out);
-
- if (resourceInfo != null) {
- String attributeName = resourceInfo.getSecond();
- RenderResources renderResources = resources.mContext.getRenderResources();
- ResourceValue value = platformResFlag_out[0] ?
- renderResources.getFrameworkResource(resourceInfo.getFirst(), attributeName) :
- renderResources.getProjectResource(resourceInfo.getFirst(), attributeName);
-
- if (value == null) {
- // Unable to resolve the attribute, just leave the unresolved value
- value = new ResourceValue(resourceInfo.getFirst(), attributeName, attributeName,
- platformResFlag_out[0]);
- }
- return Pair.of(attributeName, value);
- }
-
- return null;
- }
-
- @LayoutlibDelegate
- static Drawable getDrawable(Resources resources, int id) {
- return getDrawable(resources, id, null);
- }
-
- @LayoutlibDelegate
- static Drawable getDrawable(Resources resources, int id, Theme theme) {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
- if (value != null) {
- String key = value.getSecond().getValue();
-
- Drawable.ConstantState constantState = key != null ? sDrawableCache.get(key) : null;
- Drawable drawable;
- if (constantState != null) {
- drawable = constantState.newDrawable(resources, theme);
- } else {
- drawable =
- ResourceHelper.getDrawable(value.getSecond(), resources.mContext, theme);
-
- if (key != null) {
- sDrawableCache.put(key, drawable.getConstantState());
- }
- }
-
- return drawable;
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static int getColor(Resources resources, int id) {
- return getColor(resources, id, null);
- }
-
- @LayoutlibDelegate
- static int getColor(Resources resources, int id, Theme theme) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- ResourceValue resourceValue = value.getSecond();
- try {
- return ResourceHelper.getColor(resourceValue.getValue());
- } catch (NumberFormatException e) {
- // Check if the value passed is a file. If it is, mostly likely, user is referencing
- // a color state list from a place where they should reference only a pure color.
- String message;
- if (new File(resourceValue.getValue()).isFile()) {
- String resource = (resourceValue.isFramework() ? "@android:" : "@") + "color/"
- + resourceValue.getName();
- message = "Hexadecimal color expected, found Color State List for " + resource;
- } else {
- message = e.getMessage();
- }
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, message, e, null);
- 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(resources, id, theme).getDefaultColor();
- }
-
- @LayoutlibDelegate
- static ColorStateList getColorStateList(Resources resources, int id) throws NotFoundException {
- return getColorStateList(resources, id, null);
- }
-
- @LayoutlibDelegate
- static ColorStateList getColorStateList(Resources resources, int id, Theme theme)
- throws NotFoundException {
- Pair<String, ResourceValue> resValue =
- getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (resValue != null) {
- ColorStateList stateList = ResourceHelper.getColorStateList(resValue.getSecond(),
- resources.mContext);
- if (stateList != null) {
- return stateList.obtainForTheme(theme);
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static CharSequence getText(Resources resources, int id, CharSequence def) {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- ResourceValue resValue = value.getSecond();
-
- assert resValue != null;
- if (resValue != null) {
- String v = resValue.getValue();
- if (v != null) {
- return v;
- }
- }
- }
-
- return def;
- }
-
- @LayoutlibDelegate
- static CharSequence getText(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- ResourceValue resValue = value.getSecond();
-
- assert resValue != null;
- if (resValue != null) {
- String v = resValue.getValue();
- if (v != null) {
- return v;
- }
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static CharSequence[] getTextArray(Resources resources, int id) throws NotFoundException {
- ResourceValue resValue = getArrayResourceValue(resources, id);
- if (resValue == null) {
- // Error already logged by getArrayResourceValue.
- return new CharSequence[0];
- } else if (!(resValue instanceof ArrayResourceValue)) {
- return new CharSequence[]{
- resolveReference(resources, resValue.getValue(), resValue.isFramework())};
- }
- ArrayResourceValue arv = ((ArrayResourceValue) resValue);
- return fillValues(resources, arv, new CharSequence[arv.getElementCount()]);
- }
-
- @LayoutlibDelegate
- static String[] getStringArray(Resources resources, int id) throws NotFoundException {
- ResourceValue resValue = getArrayResourceValue(resources, id);
- if (resValue == null) {
- // Error already logged by getArrayResourceValue.
- return new String[0];
- } else if (!(resValue instanceof ArrayResourceValue)) {
- return new String[]{
- resolveReference(resources, resValue.getValue(), resValue.isFramework())};
- }
- ArrayResourceValue arv = ((ArrayResourceValue) resValue);
- return fillValues(resources, arv, new String[arv.getElementCount()]);
- }
-
- /**
- * Resolve each element in resValue and copy them to {@code values}. The values copied are
- * always Strings. The ideal signature for the method should be <T super String>, but java
- * generics don't support it.
- */
- static <T extends CharSequence> T[] fillValues(Resources resources, ArrayResourceValue resValue,
- T[] values) {
- int i = 0;
- for (Iterator<String> iterator = resValue.iterator(); iterator.hasNext(); i++) {
- @SuppressWarnings("unchecked")
- T s = (T) resolveReference(resources, iterator.next(), resValue.isFramework());
- values[i] = s;
- }
- return values;
- }
-
- @LayoutlibDelegate
- static int[] getIntArray(Resources resources, int id) throws NotFoundException {
- ResourceValue rv = getArrayResourceValue(resources, id);
- if (rv == null) {
- // Error already logged by getArrayResourceValue.
- return new int[0];
- } else if (!(rv instanceof ArrayResourceValue)) {
- // This is an older IDE that can only give us the first element of the array.
- String firstValue = resolveReference(resources, rv.getValue(), rv.isFramework());
- try {
- return new int[]{getInt(firstValue)};
- } catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Integer resource array contains non-integer value: " +
- firstValue, null);
- return new int[1];
- }
- }
- ArrayResourceValue resValue = ((ArrayResourceValue) rv);
- int[] values = new int[resValue.getElementCount()];
- int i = 0;
- for (Iterator<String> iterator = resValue.iterator(); iterator.hasNext(); i++) {
- String element = resolveReference(resources, iterator.next(), resValue.isFramework());
- try {
- values[i] = getInt(element);
- } catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Integer resource array contains non-integer value: " + element, null);
- }
- }
- return values;
- }
-
- /**
- * Try to find the ArrayResourceValue for the given id.
- * <p/>
- * If the ResourceValue found is not of type {@link ResourceType#ARRAY}, the method logs an
- * error and return null. However, if the ResourceValue found has type {@code
- * ResourceType.ARRAY}, but the value is not an instance of {@link ArrayResourceValue}, the
- * method returns the ResourceValue. This happens on older versions of the IDE, which did not
- * parse the array resources properly.
- * <p/>
- *
- * @throws NotFoundException if no resource if found
- */
- @Nullable
- private static ResourceValue getArrayResourceValue(Resources resources, int id)
- throws NotFoundException {
- Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (v != null) {
- ResourceValue resValue = v.getSecond();
-
- assert resValue != null;
- if (resValue != null) {
- final ResourceType type = resValue.getResourceType();
- if (type != ResourceType.ARRAY) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
- String.format(
- "Resource with id 0x%1$X is not an array resource, but %2$s",
- id, type == null ? "null" : type.getDisplayName()),
- null);
- return null;
- }
- if (!(resValue instanceof ArrayResourceValue)) {
- Bridge.getLog().warning(LayoutLog.TAG_UNSUPPORTED,
- "Obtaining resource arrays via getTextArray, getStringArray or getIntArray is not fully supported in this version of the IDE.",
- null);
- }
- return resValue;
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @NonNull
- private static String resolveReference(Resources resources, @NonNull String ref,
- boolean forceFrameworkOnly) {
- if (ref.startsWith(SdkConstants.PREFIX_RESOURCE_REF) || ref.startsWith
- (SdkConstants.PREFIX_THEME_REF)) {
- ResourceValue rv =
- resources.mContext.getRenderResources().findResValue(ref, forceFrameworkOnly);
- rv = resources.mContext.getRenderResources().resolveResValue(rv);
- if (rv != null) {
- return rv.getValue();
- }
- }
- // Not a reference.
- return ref;
- }
-
- @LayoutlibDelegate
- static XmlResourceParser getLayout(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (v != null) {
- ResourceValue value = v.getSecond();
- XmlPullParser parser = null;
-
- try {
- // check if the current parser can provide us with a custom parser.
- if (!mPlatformResourceFlag[0]) {
- parser = resources.mLayoutlibCallback.getParser(value);
- }
-
- // create a new one manually if needed.
- if (parser == null) {
- File xml = new File(value.getValue());
- if (xml.isFile()) {
- // we need to create a pull parser around the layout XML file, and then
- // give that to our XmlBlockParser
- parser = ParserFactory.create(xml, true);
- }
- }
-
- if (parser != null) {
- return new BridgeXmlBlockParser(parser, resources.mContext,
- mPlatformResourceFlag[0]);
- }
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value.getValue(), e, null /*data*/);
- // we'll return null below.
- } catch (FileNotFoundException e) {
- // this shouldn't happen since we check above.
- }
-
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static XmlResourceParser getAnimation(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> v = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (v != null) {
- ResourceValue value = v.getSecond();
- XmlPullParser parser;
-
- try {
- File xml = new File(value.getValue());
- if (xml.isFile()) {
- // we need to create a pull parser around the layout XML file, and then
- // give that to our XmlBlockParser
- parser = ParserFactory.create(xml);
-
- return new BridgeXmlBlockParser(parser, resources.mContext,
- mPlatformResourceFlag[0]);
- }
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value.getValue(), e, null /*data*/);
- // we'll return null below.
- } catch (FileNotFoundException e) {
- // this shouldn't happen since we check above.
- }
-
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static TypedArray obtainAttributes(Resources resources, AttributeSet set, int[] attrs) {
- return resources.mContext.obtainStyledAttributes(set, attrs);
- }
-
- @LayoutlibDelegate
- static TypedArray obtainAttributes(Resources resources, Resources.Theme theme, AttributeSet
- set, int[] attrs) {
- return Resources.obtainAttributes_Original(resources, theme, set, attrs);
- }
-
- @LayoutlibDelegate
- static TypedArray obtainTypedArray(Resources resources, int id) throws NotFoundException {
- throw new UnsupportedOperationException();
- }
-
- @LayoutlibDelegate
- static float getDimension(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- ResourceValue resValue = value.getSecond();
-
- assert resValue != null;
- if (resValue != null) {
- String v = resValue.getValue();
- if (v != null) {
- if (v.equals(BridgeConstants.MATCH_PARENT) ||
- v.equals(BridgeConstants.FILL_PARENT)) {
- return LayoutParams.MATCH_PARENT;
- } else if (v.equals(BridgeConstants.WRAP_CONTENT)) {
- return LayoutParams.WRAP_CONTENT;
- }
- TypedValue tmpValue = new TypedValue();
- if (ResourceHelper.parseFloatAttribute(
- value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
- tmpValue.type == TypedValue.TYPE_DIMENSION) {
- return tmpValue.getDimension(resources.getDisplayMetrics());
- }
- }
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return 0;
- }
-
- @LayoutlibDelegate
- static int getDimensionPixelOffset(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- ResourceValue resValue = value.getSecond();
-
- assert resValue != null;
- if (resValue != null) {
- String v = resValue.getValue();
- if (v != null) {
- TypedValue tmpValue = new TypedValue();
- if (ResourceHelper.parseFloatAttribute(
- value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
- tmpValue.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelOffset(tmpValue.data,
- resources.getDisplayMetrics());
- }
- }
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return 0;
- }
-
- @LayoutlibDelegate
- static int getDimensionPixelSize(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- ResourceValue resValue = value.getSecond();
-
- assert resValue != null;
- if (resValue != null) {
- String v = resValue.getValue();
- if (v != null) {
- TypedValue tmpValue = new TypedValue();
- if (ResourceHelper.parseFloatAttribute(
- value.getFirst(), v, tmpValue, true /*requireUnit*/) &&
- tmpValue.type == TypedValue.TYPE_DIMENSION) {
- return TypedValue.complexToDimensionPixelSize(tmpValue.data,
- resources.getDisplayMetrics());
- }
- }
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return 0;
- }
-
- @LayoutlibDelegate
- static int getInteger(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- ResourceValue resValue = value.getSecond();
-
- assert resValue != null;
- if (resValue != null) {
- String v = resValue.getValue();
- if (v != null) {
- try {
- return getInt(v);
- } catch (NumberFormatException e) {
- // return exception below
- }
- }
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return 0;
- }
-
- @LayoutlibDelegate
- static boolean getBoolean(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- ResourceValue resValue = value.getSecond();
-
- if (resValue != null) {
- String v = resValue.getValue();
- if (v != null) {
- return Boolean.parseBoolean(v);
- }
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return false;
- }
-
- @LayoutlibDelegate
- static String getResourceEntryName(Resources resources, int resid) throws NotFoundException {
- Pair<ResourceType, String> resourceInfo = getResourceInfo(resources, resid, new boolean[1]);
- if (resourceInfo != null) {
- return resourceInfo.getSecond();
- }
- throwException(resid, null);
- return null;
-
- }
-
- @LayoutlibDelegate
- static String getResourceName(Resources resources, int resid) throws NotFoundException {
- boolean[] platformOut = new boolean[1];
- Pair<ResourceType, String> resourceInfo = getResourceInfo(resources, resid, platformOut);
- String packageName;
- if (resourceInfo != null) {
- if (platformOut[0]) {
- packageName = SdkConstants.ANDROID_NS_NAME;
- } else {
- packageName = resources.mContext.getPackageName();
- packageName = packageName == null ? SdkConstants.APP_PREFIX : packageName;
- }
- return packageName + ':' + resourceInfo.getFirst().getName() + '/' +
- resourceInfo.getSecond();
- }
- throwException(resid, null);
- return null;
- }
-
- @LayoutlibDelegate
- static String getResourcePackageName(Resources resources, int resid) throws NotFoundException {
- boolean[] platformOut = new boolean[1];
- Pair<ResourceType, String> resourceInfo = getResourceInfo(resources, resid, platformOut);
- if (resourceInfo != null) {
- if (platformOut[0]) {
- return SdkConstants.ANDROID_NS_NAME;
- }
- String packageName = resources.mContext.getPackageName();
- return packageName == null ? SdkConstants.APP_PREFIX : packageName;
- }
- throwException(resid, null);
- return null;
- }
-
- @LayoutlibDelegate
- static String getResourceTypeName(Resources resources, int resid) throws NotFoundException {
- Pair<ResourceType, String> resourceInfo = getResourceInfo(resources, resid, new boolean[1]);
- if (resourceInfo != null) {
- return resourceInfo.getFirst().getName();
- }
- throwException(resid, null);
- return null;
- }
-
- @LayoutlibDelegate
- static String getString(Resources resources, int id, Object... formatArgs)
- throws NotFoundException {
- String s = getString(resources, id);
- if (s != null) {
- return String.format(s, formatArgs);
-
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static String getString(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null && value.getSecond().getValue() != null) {
- return value.getSecond().getValue();
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static String getQuantityString(Resources resources, int id, int quantity) throws
- NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- if (value.getSecond() instanceof PluralsResourceValue) {
- PluralsResourceValue pluralsResourceValue = (PluralsResourceValue) value.getSecond();
- PluralRules pluralRules = PluralRules.forLocale(resources.getConfiguration().getLocales()
- .get(0));
- String strValue = pluralsResourceValue.getValue(pluralRules.select(quantity));
- if (strValue == null) {
- strValue = pluralsResourceValue.getValue(PluralRules.KEYWORD_OTHER);
- }
-
- return strValue;
- }
- else {
- return value.getSecond().getValue();
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static String getQuantityString(Resources resources, int id, int quantity, Object... formatArgs)
- throws NotFoundException {
- String raw = getQuantityString(resources, id, quantity);
- return String.format(resources.getConfiguration().getLocales().get(0), raw, formatArgs);
- }
-
- @LayoutlibDelegate
- static CharSequence getQuantityText(Resources resources, int id, int quantity) throws
- NotFoundException {
- return getQuantityString(resources, id, quantity);
- }
-
- @LayoutlibDelegate
- static Typeface getFont(Resources resources, int id) throws
- NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
- if (value != null) {
- return ResourceHelper.getFont(value.getSecond(), resources.mContext, null);
- }
-
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static Typeface getFont(Resources resources, TypedValue outValue, int id) throws
- NotFoundException {
- Resources_Delegate.getValue(resources, id, outValue, true);
- if (outValue.string != null) {
- return ResourceHelper.getFont(outValue.string.toString(), resources.mContext, null,
- mPlatformResourceFlag[0]);
- }
-
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static void getValue(Resources resources, int id, TypedValue outValue, boolean resolveRefs)
- throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- ResourceValue resVal = value.getSecond();
- String v = resVal.getValue();
-
- if (v != null) {
- if (ResourceHelper.parseFloatAttribute(value.getFirst(), v, outValue,
- false /*requireUnit*/)) {
- return;
- }
- if (resVal instanceof DensityBasedResourceValue) {
- outValue.density =
- ((DensityBasedResourceValue) resVal).getResourceDensity().getDpiValue();
- }
-
- // else it's a string
- outValue.type = TypedValue.TYPE_STRING;
- outValue.string = v;
- return;
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
- }
-
- @LayoutlibDelegate
- static void getValue(Resources resources, String name, TypedValue outValue, boolean resolveRefs)
- throws NotFoundException {
- throw new UnsupportedOperationException();
- }
-
- @LayoutlibDelegate
- static XmlResourceParser getXml(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- String v = value.getSecond().getValue();
-
- if (v != null) {
- // check this is a file
- File f = new File(v);
- if (f.isFile()) {
- try {
- XmlPullParser parser = ParserFactory.create(f);
-
- return new BridgeXmlBlockParser(parser, resources.mContext,
- mPlatformResourceFlag[0]);
- } catch (XmlPullParserException e) {
- NotFoundException newE = new NotFoundException();
- newE.initCause(e);
- throw newE;
- } catch (FileNotFoundException e) {
- NotFoundException newE = new NotFoundException();
- newE.initCause(e);
- throw newE;
- }
- }
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static XmlResourceParser loadXmlResourceParser(Resources resources, int id,
- String type) throws NotFoundException {
- return resources.loadXmlResourceParser_Original(id, type);
- }
-
- @LayoutlibDelegate
- static XmlResourceParser loadXmlResourceParser(Resources resources, String file, int id,
- int assetCookie, String type) throws NotFoundException {
- // even though we know the XML file to load directly, we still need to resolve the
- // id so that we can know if it's a platform or project resource.
- // (mPlatformResouceFlag will get the result and will be used later).
- getResourceValue(resources, id, mPlatformResourceFlag);
-
- File f = new File(file);
- try {
- XmlPullParser parser = ParserFactory.create(f);
-
- return new BridgeXmlBlockParser(parser, resources.mContext, mPlatformResourceFlag[0]);
- } catch (XmlPullParserException e) {
- NotFoundException newE = new NotFoundException();
- newE.initCause(e);
- throw newE;
- } catch (FileNotFoundException e) {
- NotFoundException newE = new NotFoundException();
- newE.initCause(e);
- throw newE;
- }
- }
-
- @LayoutlibDelegate
- static InputStream openRawResource(Resources resources, int id) throws NotFoundException {
- Pair<String, ResourceValue> value = getResourceValue(resources, id, mPlatformResourceFlag);
-
- if (value != null) {
- String path = value.getSecond().getValue();
-
- if (path != null) {
- // check this is a file
- File f = new File(path);
- if (f.isFile()) {
- try {
- // if it's a nine-patch return a custom input stream so that
- // other methods (mainly bitmap factory) can detect it's a 9-patch
- // and actually load it as a 9-patch instead of a normal bitmap
- if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
- return new NinePatchInputStream(f);
- }
- return new FileInputStream(f);
- } catch (FileNotFoundException e) {
- NotFoundException newE = new NotFoundException();
- newE.initCause(e);
- throw newE;
- }
- }
- }
- }
-
- // id was not found or not resolved. Throw a NotFoundException.
- throwException(resources, id);
-
- // this is not used since the method above always throws
- return null;
- }
-
- @LayoutlibDelegate
- static InputStream openRawResource(Resources resources, int id, TypedValue value) throws
- NotFoundException {
- getValue(resources, id, value, true);
-
- String path = value.string.toString();
-
- File f = new File(path);
- if (f.isFile()) {
- try {
- // if it's a nine-patch return a custom input stream so that
- // other methods (mainly bitmap factory) can detect it's a 9-patch
- // and actually load it as a 9-patch instead of a normal bitmap
- if (path.toLowerCase().endsWith(NinePatch.EXTENSION_9PATCH)) {
- return new NinePatchInputStream(f);
- }
- return new FileInputStream(f);
- } catch (FileNotFoundException e) {
- NotFoundException exception = new NotFoundException();
- exception.initCause(e);
- throw exception;
- }
- }
-
- throw new NotFoundException();
- }
-
- @LayoutlibDelegate
- static AssetFileDescriptor openRawResourceFd(Resources resources, int id) throws
- NotFoundException {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Builds and throws a {@link Resources.NotFoundException} based on a resource id and a resource
- * type.
- *
- * @param id the id of the resource
- *
- * @throws NotFoundException
- */
- private static void throwException(Resources resources, int id) throws NotFoundException {
- throwException(id, getResourceInfo(resources, id, new boolean[1]));
- }
-
- private static void throwException(int id, @Nullable Pair<ResourceType, String> resourceInfo) {
- String message;
- if (resourceInfo != null) {
- message = String.format(
- "Could not find %1$s resource matching value 0x%2$X (resolved name: %3$s) in current configuration.",
- resourceInfo.getFirst(), id, resourceInfo.getSecond());
- } else {
- message = String.format("Could not resolve resource value: 0x%1$X.", id);
- }
-
- throw new NotFoundException(message);
- }
-
- private static int getInt(String v) throws NumberFormatException {
- int radix = 10;
- if (v.startsWith("0x")) {
- v = v.substring(2);
- radix = 16;
- } else if (v.startsWith("0")) {
- radix = 8;
- }
- return Integer.parseInt(v, radix);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import com.android.ide.common.rendering.api.ResourceReference;
-import com.android.ide.common.rendering.api.StyleResourceValue;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.impl.RenderSessionImpl;
-import com.android.resources.ResourceType;
-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;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link Resources.Theme}
- *
- * Through the layoutlib_create tool, the original methods of Theme have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-public class Resources_Theme_Delegate {
-
- // ---- delegate manager ----
-
- private static final DelegateManager<Resources_Theme_Delegate> sManager =
- new DelegateManager<Resources_Theme_Delegate>(Resources_Theme_Delegate.class);
-
- public static DelegateManager<Resources_Theme_Delegate> getDelegateManager() {
- return sManager;
- }
-
- // ---- delegate methods. ----
-
- @LayoutlibDelegate
- /*package*/ static TypedArray obtainStyledAttributes(
- Resources thisResources, Theme thisTheme,
- int[] attrs) {
- boolean changed = setupResources(thisTheme);
- BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
- ta.setTheme(thisTheme);
- restoreResources(changed);
- return ta;
- }
-
- @LayoutlibDelegate
- /*package*/ static TypedArray obtainStyledAttributes(
- Resources thisResources, Theme thisTheme,
- int resid, int[] attrs)
- throws NotFoundException {
- boolean changed = setupResources(thisTheme);
- BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid,
- attrs);
- ta.setTheme(thisTheme);
- restoreResources(changed);
- return ta;
- }
-
- @LayoutlibDelegate
- /*package*/ static TypedArray obtainStyledAttributes(
- Resources thisResources, Theme thisTheme,
- AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
- boolean changed = setupResources(thisTheme);
- BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(set,
- attrs, defStyleAttr, defStyleRes);
- ta.setTheme(thisTheme);
- restoreResources(changed);
- return ta;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean resolveAttribute(
- Resources thisResources, Theme thisTheme,
- int resid, TypedValue outValue,
- boolean resolveRefs) {
- boolean changed = setupResources(thisTheme);
- boolean found = RenderSessionImpl.getCurrentContext().resolveThemeAttribute(resid,
- outValue, resolveRefs);
- restoreResources(changed);
- return found;
- }
-
- @LayoutlibDelegate
- /*package*/ static TypedArray resolveAttributes(Resources thisResources, Theme thisTheme,
- int[] values, int[] attrs) {
- // FIXME
- return null;
- }
-
- // ---- private helper methods ----
-
- 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.
- final ThemeKey key = thisTheme.getKey();
- final int[] resId = key.mResId;
- final boolean[] force = key.mForce;
-
- boolean changed = false;
- for (int i = 0, N = key.mCount; i < N; i++) {
- StyleResourceValue style = resolveStyle(resId[i]);
- if (style != null) {
- RenderSessionImpl.getCurrentContext().getRenderResources().applyStyle(
- style, force[i]);
- changed = true;
- }
-
- }
- return changed;
- }
-
- private static void restoreResources(boolean changed) {
- if (changed) {
- RenderSessionImpl.getCurrentContext().getRenderResources().clearStyles();
- }
- }
-
- @Nullable
- private static StyleResourceValue resolveStyle(int nativeResid) {
- if (nativeResid == 0) {
- return null;
- }
- BridgeContext context = RenderSessionImpl.getCurrentContext();
- ResourceReference theme = context.resolveId(nativeResid);
- if (theme.isFramework()) {
- return (StyleResourceValue) context.getRenderResources()
- .getFrameworkResource(ResourceType.STYLE, theme.getName());
- } else {
- return (StyleResourceValue) context.getRenderResources()
- .getProjectResource(ResourceType.STYLE, theme.getName());
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.res;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.util.TypedValue;
-
-public class TypedArray_Delegate {
-
- @LayoutlibDelegate
- public static boolean getValueAt(TypedArray theTypedArray, int index, TypedValue outValue) {
- // pass
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static TypedArray obtain(Resources res, int len) {
- return BridgeTypedArray.obtain(res, len);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.impl.GcSnapshot;
-import com.android.layoutlib.bridge.impl.PorterDuffUtility;
-import com.android.ninepatch.NinePatchChunk;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.annotation.Nullable;
-import android.text.TextUtils;
-
-import java.awt.*;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Arc2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.ColorModel;
-import java.awt.image.DataBuffer;
-
-public class BaseCanvas_Delegate {
- // ---- delegate manager ----
- protected static DelegateManager<BaseCanvas_Delegate> sManager =
- new DelegateManager<>(BaseCanvas_Delegate.class);
-
- // ---- delegate helper data ----
- private final static boolean[] sBoolOut = new boolean[1];
-
-
- // ---- delegate data ----
- protected Bitmap_Delegate mBitmap;
- protected GcSnapshot mSnapshot;
-
- // ---- Public Helper methods ----
-
- protected BaseCanvas_Delegate(Bitmap_Delegate bitmap) {
- mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap);
- }
-
- protected BaseCanvas_Delegate() {
- mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/);
- }
-
- /**
- * Disposes of the {@link Graphics2D} stack.
- */
- protected void dispose() {
- mSnapshot.dispose();
- }
-
- /**
- * Returns the current {@link Graphics2D} used to draw.
- */
- public GcSnapshot getSnapshot() {
- return mSnapshot;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top,
- long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity) {
- // get the delegate from the native int.
- Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
- if (bitmapDelegate == null) {
- return;
- }
-
- BufferedImage image = bitmapDelegate.getImage();
- float right = left + image.getWidth();
- float bottom = top + image.getHeight();
-
- drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
- 0, 0, image.getWidth(), image.getHeight(),
- (int)left, (int)top, (int)right, (int)bottom);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawBitmap(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) {
- // get the delegate from the native int.
- Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
- if (bitmapDelegate == null) {
- return;
- }
-
- drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, (int) srcLeft, (int) srcTop,
- (int) srcRight, (int) srcBottom, (int) dstLeft, (int) dstTop, (int) dstRight,
- (int) dstBottom);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride,
- final float x, final float y, int width, int height, boolean hasAlpha,
- long nativePaintOrZero) {
- // create a temp BufferedImage containing the content.
- final BufferedImage image = new BufferedImage(width, height,
- hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
- image.setRGB(0, 0, width, height, colors, offset, stride);
-
- draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/,
- (graphics, paint) -> {
- if (paint != null && paint.isFilterBitmap()) {
- graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_BILINEAR);
- }
-
- graphics.drawImage(image, (int) x, (int) y, null);
- });
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawColor(long nativeCanvas, final int color, final int mode) {
- // get the delegate from the native int.
- BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- final int w = canvasDelegate.mBitmap.getImage().getWidth();
- final int h = canvasDelegate.mBitmap.getImage().getHeight();
- draw(nativeCanvas, (graphics, paint) -> {
- // reset its transform just in case
- graphics.setTransform(new AffineTransform());
-
- // set the color
- graphics.setColor(new java.awt.Color(color, true /*alpha*/));
-
- Composite composite = PorterDuffUtility.getComposite(
- PorterDuffUtility.getPorterDuffMode(mode), 0xFF);
- if (composite != null) {
- graphics.setComposite(composite);
- }
-
- graphics.fillRect(0, 0, w, h);
- });
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawPaint(long nativeCanvas, long paint) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Canvas.drawPaint is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawPoint(long nativeCanvas, float x, float y,
- long nativePaint) {
- // TODO: need to support the attribute (e.g. stroke width) of paint
- draw(nativeCanvas, nativePaint, false /*compositeOnly*/, false /*forceSrcMode*/,
- (graphics, paintDelegate) -> graphics.fillRect((int)x, (int)y, 1, 1));
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawPoints(long nativeCanvas, float[] pts, int offset, int count,
- long nativePaint) {
- if (offset < 0 || count < 0 || offset + count > pts.length) {
- throw new IllegalArgumentException("Invalid argument set");
- }
- // ignore the last point if the count is odd (It means it is not paired).
- count = (count >> 1) << 1;
- for (int i = offset; i < offset + count; i += 2) {
- nDrawPoint(nativeCanvas, pts[i], pts[i + 1], nativePaint);
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawLine(long nativeCanvas,
- final float startX, final float startY, final float stopX, final float stopY,
- long paint) {
- draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
- (graphics, paintDelegate) -> graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY));
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawLines(long nativeCanvas,
- final float[] pts, final int offset, final int count,
- long nativePaint) {
- draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
- false /*forceSrcMode*/, (graphics, paintDelegate) -> {
- for (int i = 0; i < count; i += 4) {
- graphics.drawLine((int) pts[i + offset], (int) pts[i + offset + 1],
- (int) pts[i + offset + 2], (int) pts[i + offset + 3]);
- }
- });
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawRect(long nativeCanvas,
- final float left, final float top, final float right, final float bottom, long paint) {
-
- draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
- (graphics, paintDelegate) -> {
- int style = paintDelegate.getStyle();
-
- // draw
- if (style == Paint.Style.FILL.nativeInt ||
- style == Paint.Style.FILL_AND_STROKE.nativeInt) {
- graphics.fillRect((int)left, (int)top,
- (int)(right-left), (int)(bottom-top));
- }
-
- if (style == Paint.Style.STROKE.nativeInt ||
- style == Paint.Style.FILL_AND_STROKE.nativeInt) {
- graphics.drawRect((int)left, (int)top,
- (int)(right-left), (int)(bottom-top));
- }
- });
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawOval(long nativeCanvas, final float left,
- final float top, final float right, final float bottom, long paint) {
- if (right > left && bottom > top) {
- draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
- (graphics, paintDelegate) -> {
- int style = paintDelegate.getStyle();
-
- // draw
- if (style == Paint.Style.FILL.nativeInt ||
- style == Paint.Style.FILL_AND_STROKE.nativeInt) {
- graphics.fillOval((int)left, (int)top,
- (int)(right - left), (int)(bottom - top));
- }
-
- if (style == Paint.Style.STROKE.nativeInt ||
- style == Paint.Style.FILL_AND_STROKE.nativeInt) {
- graphics.drawOval((int)left, (int)top,
- (int)(right - left), (int)(bottom - top));
- }
- });
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawCircle(long nativeCanvas,
- float cx, float cy, float radius, long paint) {
- nDrawOval(nativeCanvas,
- cx - radius, cy - radius, cx + radius, cy + radius,
- paint);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawArc(long nativeCanvas,
- final float left, final float top, final float right, final float bottom,
- final float startAngle, final float sweep,
- final boolean useCenter, long paint) {
- if (right > left && bottom > top) {
- draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
- (graphics, paintDelegate) -> {
- int style = paintDelegate.getStyle();
-
- Arc2D.Float arc = new Arc2D.Float(
- left, top, right - left, bottom - top,
- -startAngle, -sweep,
- useCenter ? Arc2D.PIE : Arc2D.OPEN);
-
- // draw
- if (style == Paint.Style.FILL.nativeInt ||
- style == Paint.Style.FILL_AND_STROKE.nativeInt) {
- graphics.fill(arc);
- }
-
- if (style == Paint.Style.STROKE.nativeInt ||
- style == Paint.Style.FILL_AND_STROKE.nativeInt) {
- graphics.draw(arc);
- }
- });
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawRoundRect(long nativeCanvas,
- final float left, final float top, final float right, final float bottom,
- final float rx, final float ry, long paint) {
- draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
- (graphics, paintDelegate) -> {
- int style = paintDelegate.getStyle();
-
- // draw
- if (style == Paint.Style.FILL.nativeInt ||
- style == Paint.Style.FILL_AND_STROKE.nativeInt) {
- graphics.fillRoundRect(
- (int)left, (int)top,
- (int)(right - left), (int)(bottom - top),
- 2 * (int)rx, 2 * (int)ry);
- }
-
- if (style == Paint.Style.STROKE.nativeInt ||
- style == Paint.Style.FILL_AND_STROKE.nativeInt) {
- graphics.drawRoundRect(
- (int)left, (int)top,
- (int)(right - left), (int)(bottom - top),
- 2 * (int)rx, 2 * (int)ry);
- }
- });
- }
-
- @LayoutlibDelegate
- public static void nDrawPath(long nativeCanvas, long path, long paint) {
- final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
- if (pathDelegate == null) {
- return;
- }
-
- draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
- (graphics, paintDelegate) -> {
- Shape shape = pathDelegate.getJavaShape();
- Rectangle2D bounds = shape.getBounds2D();
- if (bounds.isEmpty()) {
- // Apple JRE 1.6 doesn't like drawing empty shapes.
- // http://b.android.com/178278
-
- if (pathDelegate.isEmpty()) {
- // This means that the path doesn't have any lines or curves so
- // nothing to draw.
- return;
- }
-
- // The stroke width is not consider for the size of the bounds so,
- // for example, a horizontal line, would be considered as an empty
- // rectangle.
- // If the strokeWidth is not 0, we use it to consider the size of the
- // path as well.
- float strokeWidth = paintDelegate.getStrokeWidth();
- if (strokeWidth <= 0.0f) {
- return;
- }
- bounds.setRect(bounds.getX(), bounds.getY(),
- Math.max(strokeWidth, bounds.getWidth()),
- Math.max(strokeWidth, bounds.getHeight()));
- }
-
- int style = paintDelegate.getStyle();
-
- if (style == Paint.Style.FILL.nativeInt ||
- style == Paint.Style.FILL_AND_STROKE.nativeInt) {
- graphics.fill(shape);
- }
-
- if (style == Paint.Style.STROKE.nativeInt ||
- style == Paint.Style.FILL_AND_STROKE.nativeInt) {
- graphics.draw(shape);
- }
- });
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawRegion(long nativeCanvas, long nativeRegion,
- long nativePaint) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Some canvas paths may not be drawn", null, null);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawNinePatch(long nativeCanvas, long nativeBitmap, long ninePatch,
- final float dstLeft, final float dstTop, final float dstRight, final float dstBottom,
- long nativePaintOrZero, final int screenDensity, final int bitmapDensity) {
-
- // get the delegate from the native int.
- final Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmap);
- if (bitmapDelegate == null) {
- return;
- }
-
- byte[] c = NinePatch_Delegate.getChunk(ninePatch);
- if (c == null) {
- // not a 9-patch?
- BufferedImage image = bitmapDelegate.getImage();
- drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 0, 0, image.getWidth(),
- image.getHeight(), (int) dstLeft, (int) dstTop, (int) dstRight,
- (int) dstBottom);
- return;
- }
-
- final NinePatchChunk chunkObject = NinePatch_Delegate.getChunk(c);
- assert chunkObject != null;
- if (chunkObject == null) {
- return;
- }
-
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- // this one can be null
- Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
-
- canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
- @Override
- public void draw(Graphics2D graphics, Paint_Delegate paint) {
- chunkObject.draw(bitmapDelegate.getImage(), graphics, (int) dstLeft, (int) dstTop,
- (int) (dstRight - dstLeft), (int) (dstBottom - dstTop), screenDensity,
- bitmapDensity);
- }
- }, paintDelegate, true, false);
-
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
- long nMatrix, long nPaint) {
- // get the delegate from the native int.
- BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- // get the delegate from the native int, which can be null
- Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
-
- // get the delegate from the native int.
- Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
- if (bitmapDelegate == null) {
- return;
- }
-
- final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut);
-
- Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
- if (matrixDelegate == null) {
- return;
- }
-
- final AffineTransform mtx = matrixDelegate.getAffineTransform();
-
- canvasDelegate.getSnapshot().draw((graphics, paint) -> {
- if (paint != null && paint.isFilterBitmap()) {
- graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_BILINEAR);
- }
-
- //FIXME add support for canvas, screen and bitmap densities.
- graphics.drawImage(image, mtx, null);
- }, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawBitmapMesh(long nCanvas, Bitmap bitmap,
- int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
- int colorOffset, long nPaint) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Canvas.drawBitmapMesh is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawVertices(long nCanvas, int mode, int n,
- float[] verts, int vertOffset,
- float[] texs, int texOffset,
- int[] colors, int colorOffset,
- short[] indices, int indexOffset,
- int indexCount, long nPaint) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Canvas.drawVertices is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawText(long nativeCanvas, char[] text, int index, int count,
- float startX, float startY, int flags, long paint, long typeface) {
- drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0,
- paint, typeface);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawText(long nativeCanvas, String text,
- int start, int end, float x, float y, final int flags, long paint,
- long typeface) {
- int count = end - start;
- char[] buffer = TemporaryBuffer.obtain(count);
- TextUtils.getChars(text, start, end, buffer, 0);
-
- nDrawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawTextRun(long nativeCanvas, String text,
- int start, int end, int contextStart, int contextEnd,
- float x, float y, boolean isRtl, long paint, long typeface) {
- int count = end - start;
- char[] buffer = TemporaryBuffer.obtain(count);
- TextUtils.getChars(text, start, end, buffer, 0);
-
- drawText(nativeCanvas, buffer, 0, count, x, y, isRtl, paint, typeface);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawTextRun(long nativeCanvas, char[] text,
- int start, int count, int contextStart, int contextCount,
- float x, float y, boolean isRtl, long paint, long typeface) {
- drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawTextOnPath(long nativeCanvas,
- char[] text, int index,
- int count, long path,
- float hOffset,
- float vOffset, int bidiFlags,
- long paint, long typeface) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Canvas.drawTextOnPath is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nDrawTextOnPath(long nativeCanvas,
- String text, long path,
- float hOffset,
- float vOffset,
- int bidiFlags, long paint,
- long typeface) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Canvas.drawTextOnPath is not supported.", null, null /*data*/);
- }
-
- // ---- Private delegate/helper methods ----
-
- /**
- * Executes a {@link GcSnapshot.Drawable} with a given canvas and paint.
- * <p>Note that the drawable may actually be executed several times if there are
- * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
- */
- private static void draw(long nCanvas, long nPaint, boolean compositeOnly, boolean forceSrcMode,
- GcSnapshot.Drawable drawable) {
- // get the delegate from the native int.
- BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- // get the paint which can be null if nPaint is 0;
- Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
-
- canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode);
- }
-
- /**
- * Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided
- * to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}.
- * <p>Note that the drawable may actually be executed several times if there are
- * layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
- */
- private static void draw(long nCanvas, GcSnapshot.Drawable drawable) {
- // get the delegate from the native int.
- BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- canvasDelegate.mSnapshot.draw(drawable);
- }
-
- private static void drawText(long nativeCanvas, final char[] text, final int index,
- final int count, final float startX, final float startY, final boolean isRtl,
- long paint, final long typeface) {
-
- draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
- (graphics, paintDelegate) -> {
- // WARNING: the logic in this method is similar to Paint_Delegate.measureText.
- // Any change to this method should be reflected in Paint.measureText
-
- // assert that the typeface passed is actually the one stored in paint.
- assert (typeface == paintDelegate.mNativeTypeface);
-
- // Paint.TextAlign indicates how the text is positioned relative to X.
- // LEFT is the default and there's nothing to do.
- float x = startX;
- int limit = index + count;
- if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
- RectF bounds =
- paintDelegate.measureText(text, index, count, null, 0, isRtl);
- float m = bounds.right - bounds.left;
- if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
- x -= m / 2;
- } else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
- x -= m;
- }
- }
-
- new BidiRenderer(graphics, paintDelegate, text).setRenderLocation(x,
- startY).renderText(index, limit, isRtl, null, 0, true);
- });
- }
-
- private static void drawBitmap(long nativeCanvas, Bitmap_Delegate bitmap,
- long nativePaintOrZero, final int sleft, final int stop, final int sright,
- final int sbottom, final int dleft, final int dtop, final int dright,
- final int dbottom) {
- // get the delegate from the native int.
- BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- // get the paint, which could be null if the int is 0
- Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
-
- final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut);
-
- draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0],
- (graphics, paint) -> {
- if (paint != null && paint.isFilterBitmap()) {
- graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_BILINEAR);
- }
-
- //FIXME add support for canvas, screen and bitmap densities.
- graphics.drawImage(image, dleft, dtop, dright, dbottom, sleft, stop, sright,
- sbottom, null);
- });
- }
-
- /**
- * Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate.
- * The image returns, through a 1-size boolean array, whether the drawing code should
- * use a SRC composite no matter what the paint says.
- *
- * @param bitmap the bitmap
- * @param paint the paint that will be used to draw
- * @param forceSrcMode whether the composite will have to be SRC
- * @return the image to draw
- */
- private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint,
- boolean[] forceSrcMode) {
- BufferedImage image = bitmap.getImage();
- forceSrcMode[0] = false;
-
- // if the bitmap config is alpha_8, then we erase all color value from it
- // before drawing it or apply the texture from the shader if present.
- if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
- Shader_Delegate shader = paint.getShader();
- java.awt.Paint javaPaint = null;
- if (shader instanceof BitmapShader_Delegate) {
- javaPaint = shader.getJavaPaint();
- }
-
- fixAlpha8Bitmap(image, javaPaint);
- } 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:
- // - override the composite to be SRC. This can only be used if the composite
- // was going to be SRC or SRC_OVER in the first place
- // - Create a different bitmap to draw in which all the alpha channel values is set
- // to 0xFF.
- if (paint != null) {
- PorterDuff.Mode mode = PorterDuff.intToMode(paint.getPorterDuffMode());
-
- forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER || mode == PorterDuff.Mode.SRC;
- }
-
- // if we can't force SRC mode, then create a temp bitmap of TYPE_RGB
- if (!forceSrcMode[0]) {
- image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF);
- }
- }
-
- return image;
- }
-
- /**
- * This method will apply the correct color to the passed "only alpha" image. Colors on the
- * passed image will be destroyed.
- * If the passed javaPaint is null, the color will be set to 0. If a paint is passed, it will
- * be used to obtain the color that will be applied.
- * <p/>
- * This will destroy the passed image color channel.
- */
- private static void fixAlpha8Bitmap(final BufferedImage image,
- @Nullable java.awt.Paint javaPaint) {
- int w = image.getWidth();
- int h = image.getHeight();
-
- DataBuffer texture = null;
- if (javaPaint != null) {
- PaintContext context = javaPaint.createContext(ColorModel.getRGBdefault(), null, null,
- new AffineTransform(), null);
- texture = context.getRaster(0, 0, w, h).getDataBuffer();
- }
-
- int[] argb = new int[w * h];
- image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
-
- final int length = argb.length;
- for (int i = 0; i < length; i++) {
- argb[i] &= 0xFF000000;
- if (texture != null) {
- argb[i] |= texture.getElem(i) & 0x00FFFFFF;
- }
- }
-
- image.setRGB(0, 0, w, h, argb, 0, w);
- }
-
- protected int save(int saveFlags) {
- // get the current save count
- int count = mSnapshot.size();
-
- mSnapshot = mSnapshot.save(saveFlags);
-
- // return the old save count
- return count;
- }
-
- protected int saveLayerAlpha(RectF rect, int alpha, int saveFlags) {
- Paint_Delegate paint = new Paint_Delegate();
- paint.setAlpha(alpha);
- return saveLayer(rect, paint, saveFlags);
- }
-
- protected int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) {
- // get the current save count
- int count = mSnapshot.size();
-
- mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags);
-
- // return the old save count
- return count;
- }
-
- /**
- * Restores the {@link GcSnapshot} to <var>saveCount</var>
- * @param saveCount the saveCount
- */
- protected void restoreTo(int saveCount) {
- mSnapshot = mSnapshot.restoreTo(saveCount);
- }
-
- /**
- * Restores the top {@link GcSnapshot}
- */
- protected void restore() {
- mSnapshot = mSnapshot.restore();
- }
-
- protected boolean clipRect(float left, float top, float right, float bottom, int regionOp) {
- return mSnapshot.clipRect(left, top, right, bottom, regionOp);
- }
-}
+++ /dev/null
-/*
- * 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 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;
-import java.awt.font.FontRenderContext;
-import java.awt.font.GlyphVector;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Rectangle2D;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * 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.
- */
-@SuppressWarnings("deprecation")
-public class BidiRenderer {
- private static String JAVA_VENDOR = System.getProperty("java.vendor");
-
- private static class ScriptRun {
- int start;
- int limit;
- boolean isRtl;
- int scriptCode;
- Font font;
-
- public ScriptRun(int start, int limit, boolean isRtl) {
- this.start = start;
- this.limit = limit;
- this.isRtl = isRtl;
- this.scriptCode = UScript.INVALID_CODE;
- }
- }
-
- private final Graphics2D mGraphics;
- private final Paint_Delegate mPaint;
- private char[] mText;
- // This List can contain nulls. A null font implies that the we weren't able to load the font
- // properly. So, if we encounter a situation where we try to use that font, log a warning.
- private List<Font> mFonts;
- // Bounds of the text drawn so far.
- private RectF mBounds;
- private float mBaseline;
-
- /**
- * @param graphics May be null.
- * @param paint The Paint to use to get the fonts. Should not be null.
- * @param text Unidirectional text. Should not be null.
- */
- public BidiRenderer(Graphics2D graphics, Paint_Delegate paint, char[] text) {
- assert (paint != null);
- mGraphics = graphics;
- mPaint = paint;
- mText = text;
- mFonts = new ArrayList<Font>(paint.getFonts().size());
- for (FontInfo fontInfo : paint.getFonts()) {
- if (fontInfo == null) {
- mFonts.add(null);
- continue;
- }
- mFonts.add(fontInfo.mFont);
- }
- mBounds = new RectF();
- }
-
- /**
- *
- * @param x The x-coordinate of the left edge of where the text should be drawn on the given
- * graphics.
- * @param y The y-coordinate at which to draw the text on the given mGraphics.
- *
- */
- public BidiRenderer setRenderLocation(float x, float y) {
- mBounds = new RectF(x, y, x, y);
- mBaseline = y;
- return this;
- }
-
- /**
- * Perform Bidi Analysis on the text and then render it.
- * <p/>
- * To skip the analysis and render unidirectional text, see {@link
- * #renderText(int, int, boolean, float[], int, boolean)}
- */
- public RectF renderText(int start, int limit, int bidiFlags, float[] advances,
- int advancesIndex, boolean draw) {
- Bidi bidi = new Bidi(mText, start, null, 0, limit - start, getIcuFlags(bidiFlags));
- for (int i = 0; i < bidi.countRuns(); i++) {
- BidiRun visualRun = bidi.getVisualRun(i);
- boolean isRtl = visualRun.getDirection() == Bidi.RTL;
- renderText(visualRun.getStart(), visualRun.getLimit(), isRtl, advances,
- advancesIndex, draw);
- }
- return mBounds;
- }
-
- /**
- * Render unidirectional text.
- * <p/>
- * This method can also be used to measure the width of the text without actually drawing it.
- * <p/>
- * @param start index of the first character
- * @param limit index of the first character that should not be rendered.
- * @param isRtl is the text right-to-left
- * @param advances If not null, then advances for each character to be rendered are returned
- * here.
- * @param advancesIndex index into advances from where the advances need to be filled.
- * @param draw If true and {@code graphics} is not null, draw the rendered text on the graphics
- * at the given co-ordinates
- * @return A rectangle specifying the bounds of the text drawn.
- */
- public RectF renderText(int start, int limit, boolean isRtl, float[] advances,
- int advancesIndex, boolean draw) {
- // We break the text into scripts and then select font based on it and then render each of
- // the script runs.
- for (ScriptRun run : getScriptRuns(mText, start, limit, isRtl, mFonts)) {
- int flag = Font.LAYOUT_NO_LIMIT_CONTEXT | Font.LAYOUT_NO_START_CONTEXT;
- flag |= isRtl ? Font.LAYOUT_RIGHT_TO_LEFT : Font.LAYOUT_LEFT_TO_RIGHT;
- renderScript(run.start, run.limit, run.font, flag, advances, advancesIndex, draw);
- advancesIndex += run.limit - run.start;
- }
- return mBounds;
- }
-
- /**
- * Render a script run to the right of the bounds passed. Use the preferred font to render as
- * much as possible. This also implements a fallback mechanism to render characters that cannot
- * be drawn using the preferred font.
- */
- private void renderScript(int start, int limit, Font preferredFont, int flag,
- float[] advances, int advancesIndex, boolean draw) {
- if (mFonts.size() == 0 || preferredFont == null) {
- return;
- }
-
- while (start < limit) {
- boolean foundFont = false;
- int canDisplayUpTo = preferredFont.canDisplayUpTo(mText, start, limit);
- if (canDisplayUpTo == -1) {
- // We can draw all characters in the text.
- render(start, limit, preferredFont, flag, advances, advancesIndex, draw);
- return;
- }
- if (canDisplayUpTo > start) {
- // We can draw something.
- render(start, canDisplayUpTo, preferredFont, flag, advances, advancesIndex, draw);
- advancesIndex += canDisplayUpTo - start;
- start = canDisplayUpTo;
- }
-
- // The current character cannot be drawn with the preferred font. Cycle through all the
- // fonts to check which one can draw it.
- int charCount = Character.isHighSurrogate(mText[start]) ? 2 : 1;
- for (Font font : mFonts) {
- if (font == null) {
- logFontWarning();
- continue;
- }
- canDisplayUpTo = font.canDisplayUpTo(mText, start, start + charCount);
- if (canDisplayUpTo == -1) {
- render(start, start+charCount, font, flag, advances, advancesIndex, draw);
- start += charCount;
- advancesIndex += charCount;
- foundFont = true;
- break;
- }
- }
- if (!foundFont) {
- // No font can display this char. Use the preferred font. The char will most
- // probably appear as a box or a blank space. We could, probably, use some
- // heuristics and break the character into the base character and diacritics and
- // then draw it, but it's probably not worth the effort.
- render(start, start + charCount, preferredFont, flag, advances, advancesIndex,
- draw);
- start += charCount;
- advancesIndex += charCount;
- }
- }
- }
-
- private static void logFontWarning() {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
- "Some fonts could not be loaded. The rendering may not be perfect. " +
- "Try running the IDE with JRE 7.", null, null);
- }
-
- /**
- * Renders the text to the right of the bounds with the given font.
- * @param font The font to render the text with.
- */
- private void render(int start, int limit, Font font, int flag, float[] advances,
- int advancesIndex, boolean draw) {
-
- FontRenderContext frc;
- if (mGraphics != null) {
- frc = mGraphics.getFontRenderContext();
- } else {
- frc = Toolkit.getDefaultToolkit().getFontMetrics(font).getFontRenderContext();
-
- // Metrics obtained this way don't have anti-aliasing set. So,
- // we create a new FontRenderContext with anti-aliasing set.
- AffineTransform transform = font.getTransform();
- if (mPaint.isAntiAliased() &&
- // Workaround for http://b.android.com/211659
- (transform.getScaleX() <= 9.9 ||
- !"JetBrains s.r.o".equals(JAVA_VENDOR))) {
- frc = new FontRenderContext(transform, true, frc.usesFractionalMetrics());
- }
- }
- GlyphVector gv = font.layoutGlyphVector(frc, mText, start, limit, flag);
- int ng = gv.getNumGlyphs();
- int[] ci = gv.getGlyphCharIndices(0, ng, null);
- if (advances != null) {
- for (int i = 0; i < ng; i++) {
- int adv_idx = advancesIndex + ci[i];
- advances[adv_idx] += gv.getGlyphMetrics(i).getAdvanceX();
- }
- }
- if (draw && mGraphics != null) {
- mGraphics.drawGlyphVector(gv, mBounds.right, mBaseline);
- }
-
- // Update the bounds.
- Rectangle2D awtBounds = gv.getLogicalBounds();
- RectF bounds = awtRectToAndroidRect(awtBounds, mBounds.right, mBaseline);
- // If the width of the bounds is zero, no text had been drawn earlier. Hence, use the
- // coordinates from the bounds as an offset.
- if (Math.abs(mBounds.right - mBounds.left) == 0) {
- mBounds = bounds;
- } else {
- mBounds.union(bounds);
- }
- }
-
- // --- Static helper methods ---
-
- private static RectF awtRectToAndroidRect(Rectangle2D awtRec, float offsetX, float offsetY) {
- float left = (float) awtRec.getX();
- float top = (float) awtRec.getY();
- float right = (float) (left + awtRec.getWidth());
- float bottom = (float) (top + awtRec.getHeight());
- RectF androidRect = new RectF(left, top, right, bottom);
- androidRect.offset(offsetX, offsetY);
- return androidRect;
- }
-
- /* package */ static List<ScriptRun> getScriptRuns(char[] text, int start, int limit,
- boolean isRtl, List<Font> fonts) {
- LinkedList<ScriptRun> scriptRuns = new LinkedList<ScriptRun>();
-
- int count = limit - start;
- UScriptRun uScriptRun = new UScriptRun(text, start, count);
- while (uScriptRun.next()) {
- int scriptStart = uScriptRun.getScriptStart();
- int scriptLimit = uScriptRun.getScriptLimit();
- ScriptRun run = new ScriptRun(scriptStart, scriptLimit, isRtl);
- run.scriptCode = uScriptRun.getScriptCode();
- setScriptFont(text, run, fonts);
- scriptRuns.add(run);
- }
-
- return scriptRuns;
- }
-
- // TODO: Replace this method with one which returns the font based on the scriptCode.
- private static void setScriptFont(char[] text, ScriptRun run,
- List<Font> fonts) {
- for (Font font : fonts) {
- if (font == null) {
- logFontWarning();
- continue;
- }
- if (font.canDisplayUpTo(text, run.start, run.limit) == -1) {
- run.font = font;
- return;
- }
- }
- run.font = fonts.get(0);
- }
-
- private static int getIcuFlags(int bidiFlag) {
- switch (bidiFlag) {
- case Paint.BIDI_LTR:
- case Paint.BIDI_FORCE_LTR:
- return Bidi.DIRECTION_LEFT_TO_RIGHT;
- case Paint.BIDI_RTL:
- case Paint.BIDI_FORCE_RTL:
- return Bidi.DIRECTION_RIGHT_TO_LEFT;
- case Paint.BIDI_DEFAULT_LTR:
- return Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
- case Paint.BIDI_DEFAULT_RTL:
- return Bidi.DIRECTION_DEFAULT_RIGHT_TO_LEFT;
- default:
- assert false;
- return Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.ninepatch.NinePatchChunk;
-import com.android.resources.Density;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.annotation.Nullable;
-import com.android.layoutlib.bridge.util.NinePatchInputStream;
-import android.graphics.BitmapFactory.Options;
-import android.graphics.Bitmap_Delegate.BitmapCreateFlags;
-
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.EnumSet;
-import java.util.Set;
-
-/**
- * Delegate implementing the native methods of android.graphics.BitmapFactory
- *
- * Through the layoutlib_create tool, the original native methods of BitmapFactory have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
- * around to map int to instance of the delegate.
- *
- */
-/*package*/ class BitmapFactory_Delegate {
-
- // ------ Native Delegates ------
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage,
- @Nullable Rect padding, @Nullable Options opts) {
- Bitmap bm = null;
-
- Density density = Density.MEDIUM;
- Set<BitmapCreateFlags> bitmapCreateFlags = EnumSet.of(BitmapCreateFlags.MUTABLE);
- if (opts != null) {
- density = Density.getEnum(opts.inDensity);
- if (opts.inPremultiplied) {
- bitmapCreateFlags.add(BitmapCreateFlags.PREMULTIPLIED);
- }
- opts.inScaled = false;
- }
-
- try {
- if (is instanceof NinePatchInputStream) {
- NinePatchInputStream npis = (NinePatchInputStream) is;
- npis.disableFakeMarkSupport();
-
- // load the bitmap as a nine patch
- com.android.ninepatch.NinePatch ninePatch = com.android.ninepatch.NinePatch.load(
- npis, true /*is9Patch*/, false /*convert*/);
-
- // get the bitmap and chunk objects.
- bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), bitmapCreateFlags,
- density);
- NinePatchChunk chunk = ninePatch.getChunk();
-
- // put the chunk in the bitmap
- bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk));
-
- if (padding != null) {
- // read the padding
- int[] paddingArray = chunk.getPadding();
- padding.left = paddingArray[0];
- padding.top = paddingArray[1];
- padding.right = paddingArray[2];
- padding.bottom = paddingArray[3];
- }
- } else {
- // load the bitmap directly.
- bm = Bitmap_Delegate.createBitmap(is, bitmapCreateFlags, density);
- }
- } catch (IOException e) {
- Bridge.getLog().error(null, "Failed to load image", e, null);
- }
-
- return bm;
- }
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
- Rect padding, Options opts) {
- opts.inBitmap = null;
- return null;
- }
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeDecodeAsset(long asset, Rect padding, Options opts) {
- opts.inBitmap = null;
- return null;
- }
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeDecodeByteArray(byte[] data, int offset,
- int length, Options opts) {
- opts.inBitmap = null;
- return null;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeIsSeekable(FileDescriptor fd) {
- return true;
- }
-
- /**
- * Set the newly decoded bitmap's density based on the Options.
- *
- * Copied from {@link BitmapFactory#setDensityFromOptions(Bitmap, Options)}.
- */
- @LayoutlibDelegate
- /*package*/ static void setDensityFromOptions(Bitmap outputBitmap, Options opts) {
- if (outputBitmap == null || opts == null) return;
-
- final int density = opts.inDensity;
- if (density != 0) {
- outputBitmap.setDensity(density);
- final int targetDensity = opts.inTargetDensity;
- if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) {
- return;
- }
-
- // --- Change from original implementation begins ---
- // LayoutLib doesn't scale the nine patch when decoding it. Hence, don't change the
- // density of the source bitmap in case of ninepatch.
-
- if (opts.inScaled) {
- // --- Change from original implementation ends. ---
- outputBitmap.setDensity(targetDensity);
- }
- } else if (opts.inBitmap != null) {
- // bitmap was reused, ensure density is reset
- outputBitmap.setDensity(Bitmap.getDefaultDensity());
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.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
- *
- * Through the layoutlib_create tool, the original native methods of BitmapShader have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original BitmapShader class.
- *
- * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager},
- * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}.
- *
- * @see Shader_Delegate
- *
- */
-public class BitmapShader_Delegate extends Shader_Delegate {
-
- // ---- delegate data ----
- private java.awt.Paint mJavaPaint;
-
- // ---- Public Helper methods ----
-
- @Override
- public java.awt.Paint getJavaPaint() {
- return mJavaPaint;
- }
-
- @Override
- public boolean isSupported() {
- return true;
- }
-
- @Override
- public String getSupportMessage() {
- // no message since isSupported returns true;
- return null;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate(long nativeMatrix, Bitmap androidBitmap,
- int shaderTileModeX, int shaderTileModeY) {
- Bitmap_Delegate bitmap = Bitmap_Delegate.getDelegate(androidBitmap);
- if (bitmap == null) {
- return 0;
- }
-
- BitmapShader_Delegate newDelegate = new BitmapShader_Delegate(nativeMatrix,
- bitmap.getImage(),
- Shader_Delegate.getTileMode(shaderTileModeX),
- Shader_Delegate.getTileMode(shaderTileModeY));
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-
- private BitmapShader_Delegate(long matrix, BufferedImage image,
- TileMode tileModeX, TileMode tileModeY) {
- super(matrix);
- mJavaPaint = new BitmapShaderPaint(image, tileModeX, tileModeY);
- }
-
- private class BitmapShaderPaint implements java.awt.Paint {
- private final BufferedImage mImage;
- private final TileMode mTileModeX;
- private final TileMode mTileModeY;
-
- BitmapShaderPaint(BufferedImage image,
- TileMode tileModeX, TileMode tileModeY) {
- mImage = image;
- mTileModeX = tileModeX;
- mTileModeY = tileModeY;
- }
-
- @Override
- public PaintContext createContext(ColorModel colorModel, Rectangle deviceBounds,
- Rectangle2D userBounds, AffineTransform xform, RenderingHints hints) {
- AffineTransform canvasMatrix;
- try {
- canvasMatrix = xform.createInverse();
- } catch (NoninvertibleTransformException e) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in BitmapShader", e, null /*data*/);
- canvasMatrix = new AffineTransform();
- }
-
- AffineTransform localMatrix = getLocalMatrix();
- try {
- localMatrix = localMatrix.createInverse();
- } catch (NoninvertibleTransformException e) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in BitmapShader", e, null /*data*/);
- localMatrix = new AffineTransform();
- }
-
- if (!colorModel.isCompatibleRaster(mImage.getRaster())) {
- // Fallback to the default ARGB color model
- colorModel = ColorModel.getRGBdefault();
- }
-
- return new BitmapShaderContext(canvasMatrix, localMatrix, colorModel);
- }
-
- private class BitmapShaderContext implements PaintContext {
-
- private final AffineTransform mCanvasMatrix;
- private final AffineTransform mLocalMatrix;
- private final ColorModel mColorModel;
-
- public BitmapShaderContext(
- AffineTransform canvasMatrix,
- AffineTransform localMatrix,
- ColorModel colorModel) {
- mCanvasMatrix = canvasMatrix;
- mLocalMatrix = localMatrix;
- mColorModel = colorModel;
- }
-
- @Override
- public void dispose() {
- }
-
- @Override
- public ColorModel getColorModel() {
- return mColorModel;
- }
-
- @Override
- public Raster getRaster(int x, int y, int w, int h) {
- BufferedImage image = new BufferedImage(
- mColorModel, mColorModel.createCompatibleWritableRaster(w, h),
- mColorModel.isAlphaPremultiplied(), null);
-
- int[] data = new int[w*h];
-
- int index = 0;
- float[] pt1 = new float[2];
- float[] pt2 = new float[2];
- for (int iy = 0 ; iy < h ; iy++) {
- for (int ix = 0 ; ix < w ; ix++) {
- // handle the canvas transform
- pt1[0] = x + ix;
- pt1[1] = y + iy;
- mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
-
- // handle the local matrix.
- pt1[0] = pt2[0];
- pt1[1] = pt2[1];
- mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
-
- data[index++] = getColor(pt2[0], pt2[1]);
- }
- }
-
- image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/);
-
- return image.getRaster();
- }
- }
-
- /**
- * Returns a color for an arbitrary point.
- */
- private int getColor(float fx, float fy) {
- int x = getCoordinate(Math.round(fx), mImage.getWidth(), mTileModeX);
- int y = getCoordinate(Math.round(fy), mImage.getHeight(), mTileModeY);
-
- return mImage.getRGB(x, y);
- }
-
- private int getCoordinate(int i, int size, TileMode mode) {
- if (i < 0) {
- switch (mode) {
- case CLAMP:
- i = 0;
- break;
- case REPEAT:
- i = size - 1 - (-i % size);
- break;
- case MIRROR:
- // this is the same as the positive side, just make the value positive
- // first.
- i = -i;
- int count = i / size;
- i = i % size;
-
- if ((count % 2) == 1) {
- i = size - 1 - i;
- }
- break;
- }
- } else if (i >= size) {
- switch (mode) {
- case CLAMP:
- i = size - 1;
- break;
- case REPEAT:
- i = i % size;
- break;
- case MIRROR:
- int count = i / size;
- i = i % size;
-
- if ((count % 2) == 1) {
- i = size - 1 - i;
- }
- break;
- }
- }
-
- return i;
- }
-
-
- @Override
- public int getTransparency() {
- return java.awt.Paint.TRANSLUCENT;
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.impl.RenderAction;
-import com.android.resources.Density;
-import com.android.resources.ResourceType;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.annotation.Nullable;
-import android.graphics.Bitmap.Config;
-import android.os.Parcel;
-
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.Buffer;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Set;
-
-import javax.imageio.ImageIO;
-import libcore.util.NativeAllocationRegistry_Delegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.Bitmap
- *
- * Through the layoutlib_create tool, the original native methods of Bitmap have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original Bitmap class.
- *
- * @see DelegateManager
- *
- */
-public final class Bitmap_Delegate {
-
-
- public enum BitmapCreateFlags {
- NONE, PREMULTIPLIED, MUTABLE
- }
-
- // ---- delegate manager ----
- private static final DelegateManager<Bitmap_Delegate> sManager =
- new DelegateManager<>(Bitmap_Delegate.class);
- private static long sFinalizer = -1;
-
- // ---- delegate helper data ----
-
- // ---- delegate data ----
- private final Config mConfig;
- private final BufferedImage mImage;
- private boolean mHasAlpha = true;
- private boolean mHasMipMap = false; // TODO: check the default.
- private boolean mIsPremultiplied = true;
- private int mGenerationId = 0;
-
-
- // ---- Public Helper methods ----
-
- /**
- * 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) {
- return bitmap == null ? null : getDelegate(bitmap.getNativeInstance());
- }
-
- /**
- * Creates and returns a {@link Bitmap} initialized with the given file content.
- *
- * @param input the file from which to read the bitmap content
- * @param isMutable whether the bitmap is mutable
- * @param density the density associated with the bitmap
- *
- * @see Bitmap#isMutable()
- * @see Bitmap#getDensity()
- */
- public static Bitmap createBitmap(File input, boolean isMutable, Density density)
- throws IOException {
- return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density);
- }
-
- /**
- * Creates and returns a {@link Bitmap} initialized with the given file content.
- *
- * @param input the file from which to read the bitmap content
- * @param density the density associated with the bitmap
- *
- * @see Bitmap#isPremultiplied()
- * @see Bitmap#isMutable()
- * @see Bitmap#getDensity()
- */
- private static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
- Density density) throws IOException {
- // create a delegate with the content of the file.
- BufferedImage image = ImageIO.read(input);
- if (image == null && input.exists()) {
- // There was a problem decoding the image, or the decoder isn't registered. Webp maybe.
- // Replace with a broken image icon.
- BridgeContext currentContext = RenderAction.getCurrentContext();
- if (currentContext != null) {
- RenderResources resources = currentContext.getRenderResources();
- ResourceValue broken = resources.getFrameworkResource(ResourceType.DRAWABLE,
- "ic_menu_report_image");
- File brokenFile = new File(broken.getValue());
- if (brokenFile.exists()) {
- image = ImageIO.read(brokenFile);
- }
- }
- }
- Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
-
- return createBitmap(delegate, createFlags, density.getDpiValue());
- }
-
- /**
- * Creates and returns a {@link Bitmap} initialized with the given stream content.
- *
- * @param input the stream from which to read the bitmap content
- * @param isMutable whether the bitmap is mutable
- * @param density the density associated with the bitmap
- *
- * @see Bitmap#isMutable()
- * @see Bitmap#getDensity()
- */
- public static Bitmap createBitmap(InputStream input, boolean isMutable, Density density)
- throws IOException {
- return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density);
- }
-
- /**
- * Creates and returns a {@link Bitmap} initialized with the given stream content.
- *
- * @param input the stream from which to read the bitmap content
- * @param density the density associated with the bitmap
- *
- * @see Bitmap#isPremultiplied()
- * @see Bitmap#isMutable()
- * @see Bitmap#getDensity()
- */
- public static Bitmap createBitmap(InputStream input, Set<BitmapCreateFlags> createFlags,
- Density density) throws IOException {
- // create a delegate with the content of the stream.
- Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
-
- return createBitmap(delegate, createFlags, density.getDpiValue());
- }
-
- /**
- * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
- *
- * @param image the bitmap content
- * @param isMutable whether the bitmap is mutable
- * @param density the density associated with the bitmap
- *
- * @see Bitmap#isMutable()
- * @see Bitmap#getDensity()
- */
- public static Bitmap createBitmap(BufferedImage image, boolean isMutable, Density density) {
- return createBitmap(image, getPremultipliedBitmapCreateFlags(isMutable), density);
- }
-
- /**
- * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
- *
- * @param image the bitmap content
- * @param density the density associated with the bitmap
- *
- * @see Bitmap#isPremultiplied()
- * @see Bitmap#isMutable()
- * @see Bitmap#getDensity()
- */
- public static Bitmap createBitmap(BufferedImage image, Set<BitmapCreateFlags> createFlags,
- Density density) {
- // create a delegate with the given image.
- Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
-
- return createBitmap(delegate, createFlags, density.getDpiValue());
- }
-
- private static int getBufferedImageType() {
- return BufferedImage.TYPE_INT_ARGB;
- }
-
- /**
- * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}.
- */
- public BufferedImage getImage() {
- return mImage;
- }
-
- /**
- * Returns the Android bitmap config. Note that this not the config of the underlying
- * Java2D bitmap.
- */
- public Config getConfig() {
- return mConfig;
- }
-
- /**
- * Returns the hasAlpha rendering hint
- * @return true if the bitmap alpha should be used at render time
- */
- public boolean hasAlpha() {
- return mHasAlpha && mConfig != Config.RGB_565;
- }
-
- /**
- * Update the generationId.
- *
- * @see Bitmap#getGenerationId()
- */
- public void change() {
- mGenerationId++;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width,
- int height, int nativeConfig, boolean isMutable, @Nullable float[] xyzD50,
- @Nullable ColorSpace.Rgb.TransferParameters p) {
- int imageType = getBufferedImageType();
-
- // create the image
- BufferedImage image = new BufferedImage(width, height, imageType);
-
- if (colors != null) {
- image.setRGB(0, 0, width, height, colors, offset, stride);
- }
-
- // create a delegate with the content of the stream.
- Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
-
- return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
- Bitmap.getDefaultDensity());
- }
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeCopy(long srcBitmap, int nativeConfig, boolean isMutable) {
- Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(srcBitmap);
- if (srcBmpDelegate == null) {
- return null;
- }
-
- BufferedImage srcImage = srcBmpDelegate.getImage();
-
- int width = srcImage.getWidth();
- int height = srcImage.getHeight();
-
- int imageType = getBufferedImageType();
-
- // create the image
- BufferedImage image = new BufferedImage(width, height, imageType);
-
- // copy the source image into the image.
- int[] argb = new int[width * height];
- srcImage.getRGB(0, 0, width, height, argb, 0, width);
- image.setRGB(0, 0, width, height, argb, 0, width);
-
- // create a delegate with the content of the stream.
- Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
-
- return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
- Bitmap.getDefaultDensity());
- }
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeCopyAshmem(long nativeSrcBitmap) {
- // Unused method; no implementation provided.
- assert false;
- return null;
- }
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig) {
- // Unused method; no implementation provided.
- assert false;
- return null;
- }
-
- @LayoutlibDelegate
- /*package*/ static long nativeGetNativeFinalizer() {
- synchronized (Bitmap_Delegate.class) {
- if (sFinalizer == -1) {
- sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
- }
- return sFinalizer;
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeRecycle(long nativeBitmap) {
- // In our case reycle() is a no-op. We will let the finalizer to dispose the bitmap.
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeReconfigure(long nativeBitmap, int width, int height,
- int config, boolean isPremultiplied) {
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "Bitmap.reconfigure() is not supported", null /*data*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeCompress(long nativeBitmap, int format, int quality,
- OutputStream stream, byte[] tempStorage) {
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "Bitmap.compress() is not supported", null /*data*/);
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeErase(long nativeBitmap, int color) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return;
- }
-
- BufferedImage image = delegate.mImage;
-
- Graphics2D g = image.createGraphics();
- try {
- g.setColor(new java.awt.Color(color, true));
-
- g.fillRect(0, 0, image.getWidth(), image.getHeight());
- } finally {
- g.dispose();
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static int nativeRowBytes(long nativeBitmap) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mImage.getWidth();
- }
-
- @LayoutlibDelegate
- /*package*/ static int nativeConfig(long nativeBitmap) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mConfig.nativeInt;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeHasAlpha(long nativeBitmap) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- return delegate == null || delegate.mHasAlpha;
-
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeHasMipMap(long nativeBitmap) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- return delegate == null || delegate.mHasMipMap;
-
- }
-
- @LayoutlibDelegate
- /*package*/ static int nativeGetPixel(long nativeBitmap, int x, int y) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mImage.getRGB(x, y);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeGetPixels(long nativeBitmap, int[] pixels, int offset,
- int stride, int x, int y, int width, int height) {
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return;
- }
-
- delegate.getImage().getRGB(x, y, width, height, pixels, offset, stride);
- }
-
-
- @LayoutlibDelegate
- /*package*/ static void nativeSetPixel(long nativeBitmap, int x, int y, int color) {
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return;
- }
-
- delegate.getImage().setRGB(x, y, color);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeSetPixels(long nativeBitmap, int[] colors, int offset,
- int stride, int x, int y, int width, int height) {
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return;
- }
-
- delegate.getImage().setRGB(x, y, width, height, colors, offset, stride);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeCopyPixelsToBuffer(long nativeBitmap, Buffer dst) {
- // FIXME implement native delegate
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Bitmap.copyPixelsToBuffer is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeCopyPixelsFromBuffer(long nb, Buffer src) {
- // FIXME implement native delegate
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Bitmap.copyPixelsFromBuffer is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static int nativeGenerationId(long nativeBitmap) {
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mGenerationId;
- }
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) {
- // This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only
- // used during aidl call so really this should not be called.
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "AIDL is not suppored, and therefore Bitmaps cannot be created from parcels.",
- null /*data*/);
- return null;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeWriteToParcel(long nativeBitmap, boolean isMutable,
- int density, Parcel p) {
- // This is only called when sending a bitmap through aidl, so really this should not
- // be called.
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "AIDL is not suppored, and therefore Bitmaps cannot be written to parcels.",
- null /*data*/);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeExtractAlpha(long nativeBitmap, long nativePaint,
- int[] offsetXY) {
- Bitmap_Delegate bitmap = sManager.getDelegate(nativeBitmap);
- if (bitmap == null) {
- return null;
- }
-
- // get the paint which can be null if nativePaint is 0.
- Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint);
-
- if (paint != null && paint.getMaskFilter() != null) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
- "MaskFilter not supported in Bitmap.extractAlpha",
- null, null /*data*/);
- }
-
- int alpha = paint != null ? paint.getAlpha() : 0xFF;
- BufferedImage image = createCopy(bitmap.getImage(), BufferedImage.TYPE_INT_ARGB, alpha);
-
- // create the delegate. The actual Bitmap config is only an alpha channel
- Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8);
-
- // the density doesn't matter, it's set by the Java method.
- return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.MUTABLE),
- Density.DEFAULT_DENSITY /*density*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeIsPremultiplied(long nativeBitmap) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- return delegate != null && delegate.mIsPremultiplied;
-
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeSetPremultiplied(long nativeBitmap, boolean isPremul) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return;
- }
-
- delegate.mIsPremultiplied = isPremul;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeSetHasAlpha(long nativeBitmap, boolean hasAlpha,
- boolean isPremul) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return;
- }
-
- delegate.mHasAlpha = hasAlpha;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return;
- }
-
- delegate.mHasMipMap = hasMipMap;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeSameAs(long nb0, long nb1) {
- Bitmap_Delegate delegate1 = sManager.getDelegate(nb0);
- if (delegate1 == null) {
- return false;
- }
-
- Bitmap_Delegate delegate2 = sManager.getDelegate(nb1);
- if (delegate2 == null) {
- return false;
- }
-
- BufferedImage image1 = delegate1.getImage();
- BufferedImage image2 = delegate2.getImage();
- if (delegate1.mConfig != delegate2.mConfig ||
- image1.getWidth() != image2.getWidth() ||
- image1.getHeight() != image2.getHeight()) {
- return false;
- }
-
- // get the internal data
- int w = image1.getWidth();
- int h = image2.getHeight();
- int[] argb1 = new int[w*h];
- int[] argb2 = new int[w*h];
-
- image1.getRGB(0, 0, w, h, argb1, 0, w);
- image2.getRGB(0, 0, w, h, argb2, 0, w);
-
- // compares
- if (delegate1.mConfig == Config.ALPHA_8) {
- // in this case we have to manually compare the alpha channel as the rest is garbage.
- final int length = w*h;
- for (int i = 0 ; i < length ; i++) {
- if ((argb1[i] & 0xFF000000) != (argb2[i] & 0xFF000000)) {
- return false;
- }
- }
- return true;
- }
-
- return Arrays.equals(argb1, argb2);
- }
-
- @LayoutlibDelegate
- /*package*/ static int nativeGetAllocationByteCount(long nativeBitmap) {
- // get the delegate from the native int.
- Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
- if (delegate == null) {
- return 0;
- }
- return nativeRowBytes(nativeBitmap) * delegate.mImage.getHeight();
-
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativePrepareToDraw(long nativeBitmap) {
- // do nothing as Bitmap_Delegate does not have caches
- }
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap) {
- Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(nativeBitmap);
- if (srcBmpDelegate == null) {
- return null;
- }
-
- BufferedImage srcImage = srcBmpDelegate.getImage();
-
- // create the image
- BufferedImage image = new BufferedImage(srcImage.getColorModel(), srcImage.copyData(null),
- srcImage.isAlphaPremultiplied(), null);
-
- // create a delegate with the content of the stream.
- Bitmap_Delegate delegate = new Bitmap_Delegate(image, srcBmpDelegate.getConfig());
-
- return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.NONE),
- Bitmap.getDefaultDensity());
- }
-
- @LayoutlibDelegate
- /*package*/ static Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer) {
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "Bitmap.nativeCreateHardwareBitmap() is not supported", null /*data*/);
- return null;
- }
-
- @LayoutlibDelegate
- /*package*/ static GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap) {
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "Bitmap.nativeCreateGraphicBufferHandle() is not supported", null /*data*/);
- return null;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeIsSRGB(long nativeBitmap) {
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "Color spaces are not supported", null /*data*/);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params) {
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "Color spaces are not supported", null /*data*/);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeCopyColorSpace(long srcBitmap, long dstBitmap) {
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "Color spaces are not supported", null /*data*/);
- }
-
- // ---- Private delegate/helper methods ----
-
- private Bitmap_Delegate(BufferedImage image, Config config) {
- mImage = image;
- mConfig = config;
- }
-
- private static Bitmap createBitmap(Bitmap_Delegate delegate,
- Set<BitmapCreateFlags> createFlags, int density) {
- // get its native_int
- long nativeInt = sManager.addNewDelegate(delegate);
-
- int width = delegate.mImage.getWidth();
- int height = delegate.mImage.getHeight();
- boolean isMutable = createFlags.contains(BitmapCreateFlags.MUTABLE);
- boolean isPremultiplied = createFlags.contains(BitmapCreateFlags.PREMULTIPLIED);
-
- // and create/return a new Bitmap with it
- return new Bitmap(nativeInt, width, height, density, isMutable,
- isPremultiplied, null /*ninePatchChunk*/, null /* layoutBounds */);
- }
-
- private static Set<BitmapCreateFlags> getPremultipliedBitmapCreateFlags(boolean isMutable) {
- Set<BitmapCreateFlags> createFlags = EnumSet.of(BitmapCreateFlags.PREMULTIPLIED);
- if (isMutable) {
- createFlags.add(BitmapCreateFlags.MUTABLE);
- }
- return createFlags;
- }
-
- /**
- * Creates and returns a copy of a given BufferedImage.
- * <p/>
- * if alpha is different than 255, then it is applied to the alpha channel of each pixel.
- *
- * @param image the image to copy
- * @param imageType the type of the new image
- * @param alpha an optional alpha modifier
- * @return a new BufferedImage
- */
- /*package*/ static BufferedImage createCopy(BufferedImage image, int imageType, int alpha) {
- int w = image.getWidth();
- int h = image.getHeight();
-
- BufferedImage result = new BufferedImage(w, h, imageType);
-
- int[] argb = new int[w * h];
- image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
-
- if (alpha != 255) {
- final int length = argb.length;
- for (int i = 0 ; i < length; i++) {
- int a = (argb[i] >>> 24 * alpha) / 255;
- argb[i] = (a << 24) | (argb[i] & 0x00FFFFFF);
- }
- }
-
- result.setRGB(0, 0, w, h, argb, 0, w);
-
- return result;
- }
-
-}
+++ /dev/null
-/*
- * 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.graphics;
-
-import java.awt.Composite;
-import java.awt.CompositeContext;
-import java.awt.RenderingHints;
-import java.awt.image.ColorModel;
-import java.awt.image.DataBuffer;
-import java.awt.image.Raster;
-import java.awt.image.WritableRaster;
-
-/*
- * (non-Javadoc)
- * The class is adapted from a demo tool for Blending Modes written by
- * Romain Guy (romainguy@android.com). The tool is available at
- * http://www.curious-creature.org/2006/09/20/new-blendings-modes-for-java2d/
- *
- * This class has been adapted for applying color filters. When applying color filters, the src
- * image should not extend beyond the dest image, but in our implementation of the filters, it does.
- * To compensate for the effect, we recompute the alpha value of the src image before applying
- * the color filter as it should have been applied.
- */
-public final class BlendComposite implements Composite {
- public enum BlendingMode {
- MULTIPLY(),
- SCREEN(),
- DARKEN(),
- LIGHTEN(),
- OVERLAY(),
- ADD();
-
- private final BlendComposite mComposite;
-
- BlendingMode() {
- mComposite = new BlendComposite(this);
- }
-
- BlendComposite getBlendComposite() {
- return mComposite;
- }
- }
-
- private float alpha;
- private BlendingMode mode;
-
- private BlendComposite(BlendingMode mode) {
- this(mode, 1.0f);
- }
-
- private BlendComposite(BlendingMode mode, float alpha) {
- this.mode = mode;
- setAlpha(alpha);
- }
-
- public static BlendComposite getInstance(BlendingMode mode) {
- return mode.getBlendComposite();
- }
-
- public static BlendComposite getInstance(BlendingMode mode, float alpha) {
- if (alpha > 0.9999f) {
- return getInstance(mode);
- }
- return new BlendComposite(mode, alpha);
- }
-
- public float getAlpha() {
- return alpha;
- }
-
- public BlendingMode getMode() {
- return mode;
- }
-
- private void setAlpha(float alpha) {
- if (alpha < 0.0f || alpha > 1.0f) {
- assert false : "alpha must be comprised between 0.0f and 1.0f";
- alpha = Math.min(alpha, 1.0f);
- alpha = Math.max(alpha, 0.0f);
- }
-
- this.alpha = alpha;
- }
-
- @Override
- public int hashCode() {
- return Float.floatToIntBits(alpha) * 31 + mode.ordinal();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof BlendComposite)) {
- return false;
- }
-
- BlendComposite bc = (BlendComposite) obj;
-
- return mode == bc.mode && alpha == bc.alpha;
- }
-
- public CompositeContext createContext(ColorModel srcColorModel,
- ColorModel dstColorModel,
- RenderingHints hints) {
- return new BlendingContext(this);
- }
-
- private static final class BlendingContext implements CompositeContext {
- private final Blender blender;
- private final BlendComposite composite;
-
- private BlendingContext(BlendComposite composite) {
- this.composite = composite;
- this.blender = Blender.getBlenderFor(composite);
- }
-
- public void dispose() {
- }
-
- public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
- if (src.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
- dstIn.getSampleModel().getDataType() != DataBuffer.TYPE_INT ||
- dstOut.getSampleModel().getDataType() != DataBuffer.TYPE_INT) {
- throw new IllegalStateException(
- "Source and destination must store pixels as INT.");
- }
-
- int width = Math.min(src.getWidth(), dstIn.getWidth());
- int height = Math.min(src.getHeight(), dstIn.getHeight());
-
- float alpha = composite.getAlpha();
-
- int[] srcPixel = new int[4];
- int[] dstPixel = new int[4];
- int[] result = new int[4];
- int[] srcPixels = new int[width];
- int[] dstPixels = new int[width];
-
- for (int y = 0; y < height; y++) {
- dstIn.getDataElements(0, y, width, 1, dstPixels);
- if (alpha != 0) {
- src.getDataElements(0, y, width, 1, srcPixels);
- for (int x = 0; x < width; x++) {
- // pixels are stored as INT_ARGB
- // our arrays are [R, G, B, A]
- int pixel = srcPixels[x];
- srcPixel[0] = (pixel >> 16) & 0xFF;
- srcPixel[1] = (pixel >> 8) & 0xFF;
- srcPixel[2] = (pixel ) & 0xFF;
- srcPixel[3] = (pixel >> 24) & 0xFF;
-
- pixel = dstPixels[x];
- dstPixel[0] = (pixel >> 16) & 0xFF;
- dstPixel[1] = (pixel >> 8) & 0xFF;
- dstPixel[2] = (pixel ) & 0xFF;
- dstPixel[3] = (pixel >> 24) & 0xFF;
-
- // ---- Modified from original ----
- // recompute src pixel for transparency.
- srcPixel[3] *= dstPixel[3] / 0xFF;
- // ---- Modification ends ----
-
- result = blender.blend(srcPixel, dstPixel, result);
-
- // mixes the result with the opacity
- if (alpha == 1) {
- dstPixels[x] = (result[3] & 0xFF) << 24 |
- (result[0] & 0xFF) << 16 |
- (result[1] & 0xFF) << 8 |
- result[2] & 0xFF;
- } else {
- dstPixels[x] =
- ((int) (dstPixel[3] + (result[3] - dstPixel[3]) * alpha) & 0xFF) << 24 |
- ((int) (dstPixel[0] + (result[0] - dstPixel[0]) * alpha) & 0xFF) << 16 |
- ((int) (dstPixel[1] + (result[1] - dstPixel[1]) * alpha) & 0xFF) << 8 |
- (int) (dstPixel[2] + (result[2] - dstPixel[2]) * alpha) & 0xFF;
- }
-
- }
- }
- dstOut.setDataElements(0, y, width, 1, dstPixels);
- }
- }
- }
-
- private static abstract class Blender {
- public abstract int[] blend(int[] src, int[] dst, int[] result);
-
- public static Blender getBlenderFor(BlendComposite composite) {
- switch (composite.getMode()) {
- case ADD:
- return new Blender() {
- @Override
- public int[] blend(int[] src, int[] dst, int[] result) {
- for (int i = 0; i < 4; i++) {
- result[i] = Math.min(255, src[i] + dst[i]);
- }
- return result;
- }
- };
- case DARKEN:
- return new Blender() {
- @Override
- public int[] blend(int[] src, int[] dst, int[] result) {
- for (int i = 0; i < 3; i++) {
- result[i] = Math.min(src[i], dst[i]);
- }
- result[3] = Math.min(255, src[3] + dst[3]);
- return result;
- }
- };
- case LIGHTEN:
- return new Blender() {
- @Override
- public int[] blend(int[] src, int[] dst, int[] result) {
- for (int i = 0; i < 3; i++) {
- result[i] = Math.max(src[i], dst[i]);
- }
- result[3] = Math.min(255, src[3] + dst[3]);
- return result;
- }
- };
- case MULTIPLY:
- return new Blender() {
- @Override
- public int[] blend(int[] src, int[] dst, int[] result) {
- for (int i = 0; i < 3; i++) {
- result[i] = (src[i] * dst[i]) >> 8;
- }
- result[3] = Math.min(255, src[3] + dst[3] - (src[3] * dst[3]) / 255);
- return result;
- }
- };
- case OVERLAY:
- return new Blender() {
- @Override
- public int[] blend(int[] src, int[] dst, int[] result) {
- for (int i = 0; i < 3; i++) {
- result[i] = dst[i] < 128 ? dst[i] * src[i] >> 7 :
- 255 - ((255 - dst[i]) * (255 - src[i]) >> 7);
- }
- result[3] = Math.min(255, src[3] + dst[3]);
- return result;
- }
- };
- case SCREEN:
- return new Blender() {
- @Override
- public int[] blend(int[] src, int[] dst, int[] result) {
- result[0] = 255 - ((255 - src[0]) * (255 - dst[0]) >> 8);
- result[1] = 255 - ((255 - src[1]) * (255 - dst[1]) >> 8);
- result[2] = 255 - ((255 - src[2]) * (255 - dst[2]) >> 8);
- result[3] = Math.min(255, src[3] + dst[3]);
- return result;
- }
- };
- default:
- assert false : "Blender not implement for " + composite.getMode().name();
-
- // Ignore the blend
- return new Blender() {
- @Override
- public int[] blend(int[] src, int[] dst, int[] result) {
- result[0] = dst[0];
- result[1] = dst[1];
- result[2] = dst[2];
- result[3] = dst[3];
- return result;
- }
- };
- }
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.BlurMaskFilter
- *
- * Through the layoutlib_create tool, the original native methods of BlurMaskFilter have
- * been replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original BlurMaskFilter class.
- *
- * Because this extends {@link MaskFilter_Delegate}, there's no need to use a
- * {@link DelegateManager}, as all the Shader classes will be added to the manager
- * owned by {@link MaskFilter_Delegate}.
- *
- * @see MaskFilter_Delegate
- *
- */
-public class BlurMaskFilter_Delegate extends MaskFilter_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Blur Mask Filters are not supported.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeConstructor(float radius, int style) {
- BlurMaskFilter_Delegate newDelegate = new BlurMaskFilter_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.impl.GcSnapshot;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.annotation.Nullable;
-import android.graphics.Bitmap.Config;
-
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.geom.AffineTransform;
-
-import libcore.util.NativeAllocationRegistry_Delegate;
-
-
-/**
- * Delegate implementing the native methods of android.graphics.Canvas
- *
- * Through the layoutlib_create tool, the original native methods of Canvas have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original Canvas class.
- *
- * @see DelegateManager
- *
- */
-public final class Canvas_Delegate extends BaseCanvas_Delegate {
-
- // ---- delegate manager ----
- private static long sFinalizer = -1;
-
- private DrawFilter_Delegate mDrawFilter = null;
-
- // ---- Public Helper methods ----
-
- /**
- * Returns the native delegate associated to a given {@link Canvas} object.
- */
- public static Canvas_Delegate getDelegate(Canvas canvas) {
- return (Canvas_Delegate) sManager.getDelegate(canvas.getNativeCanvasWrapper());
- }
-
- /**
- * Returns the native delegate associated to a given an int referencing a {@link Canvas} object.
- */
- public static Canvas_Delegate getDelegate(long native_canvas) {
- return (Canvas_Delegate) sManager.getDelegate(native_canvas);
- }
-
- /**
- * Returns the current {@link Graphics2D} used to draw.
- */
- public GcSnapshot getSnapshot() {
- return mSnapshot;
- }
-
- /**
- * Returns the {@link DrawFilter} delegate or null if none have been set.
- *
- * @return the delegate or null.
- */
- public DrawFilter_Delegate getDrawFilter() {
- return mDrawFilter;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static void nFreeCaches() {
- // nothing to be done here.
- }
-
- @LayoutlibDelegate
- /*package*/ static void nFreeTextLayoutCaches() {
- // nothing to be done here yet.
- }
-
- @LayoutlibDelegate
- /*package*/ static long nInitRaster(@Nullable Bitmap bitmap) {
- long nativeBitmapOrZero = 0;
- if (bitmap != null) {
- nativeBitmapOrZero = bitmap.getNativeInstance();
- }
- if (nativeBitmapOrZero > 0) {
- // get the Bitmap from the int
- Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmapOrZero);
-
- // create a new Canvas_Delegate with the given bitmap and return its new native int.
- Canvas_Delegate newDelegate = new Canvas_Delegate(bitmapDelegate);
-
- return sManager.addNewDelegate(newDelegate);
- }
-
- // create a new Canvas_Delegate and return its new native int.
- Canvas_Delegate newDelegate = new Canvas_Delegate();
-
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- public static void nSetBitmap(long canvas, Bitmap bitmap) {
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
- Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
- if (canvasDelegate == null || bitmapDelegate==null) {
- return;
- }
- canvasDelegate.mBitmap = bitmapDelegate;
- canvasDelegate.mSnapshot = GcSnapshot.createDefaultSnapshot(bitmapDelegate);
- }
-
- @LayoutlibDelegate
- public static boolean nIsOpaque(long nativeCanvas) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return false;
- }
-
- return canvasDelegate.mBitmap.getConfig() == Config.RGB_565;
- }
-
- @LayoutlibDelegate
- public static void nSetHighContrastText(long nativeCanvas, boolean highContrastText){}
-
- @LayoutlibDelegate
- public static int nGetWidth(long nativeCanvas) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return 0;
- }
-
- return canvasDelegate.mBitmap.getImage().getWidth();
- }
-
- @LayoutlibDelegate
- public static int nGetHeight(long nativeCanvas) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return 0;
- }
-
- return canvasDelegate.mBitmap.getImage().getHeight();
- }
-
- @LayoutlibDelegate
- public static int nSave(long nativeCanvas, int saveFlags) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return 0;
- }
-
- return canvasDelegate.save(saveFlags);
- }
-
- @LayoutlibDelegate
- public static int nSaveLayer(long nativeCanvas, float l,
- float t, float r, float b,
- long paint, int layerFlags) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return 0;
- }
-
- Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(paint);
- if (paintDelegate == null) {
- return 0;
- }
-
- return canvasDelegate.saveLayer(new RectF(l, t, r, b),
- paintDelegate, layerFlags);
- }
-
- @LayoutlibDelegate
- public static int nSaveLayerAlpha(long nativeCanvas, float l,
- float t, float r, float b,
- int alpha, int layerFlags) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return 0;
- }
-
- return canvasDelegate.saveLayerAlpha(new RectF(l, t, r, b), alpha, layerFlags);
- }
-
- @LayoutlibDelegate
- public static boolean nRestore(long nativeCanvas) {
- // FIXME: implement throwOnUnderflow.
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return false;
- }
-
- canvasDelegate.restore();
- return true;
- }
-
- @LayoutlibDelegate
- public static void nRestoreToCount(long nativeCanvas, int saveCount) {
- // FIXME: implement throwOnUnderflow.
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- canvasDelegate.restoreTo(saveCount);
- }
-
- @LayoutlibDelegate
- public static int nGetSaveCount(long nativeCanvas) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return 0;
- }
-
- return canvasDelegate.getSnapshot().size();
- }
-
- @LayoutlibDelegate
- public static void nTranslate(long nativeCanvas, float dx, float dy) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- canvasDelegate.getSnapshot().translate(dx, dy);
- }
-
- @LayoutlibDelegate
- public static void nScale(long nativeCanvas, float sx, float sy) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- canvasDelegate.getSnapshot().scale(sx, sy);
- }
-
- @LayoutlibDelegate
- public static void nRotate(long nativeCanvas, float degrees) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- canvasDelegate.getSnapshot().rotate(Math.toRadians(degrees));
- }
-
- @LayoutlibDelegate
- public static void nSkew(long nativeCanvas, float kx, float ky) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- // get the current top graphics2D object.
- GcSnapshot g = canvasDelegate.getSnapshot();
-
- // get its current matrix
- AffineTransform currentTx = g.getTransform();
- // get the AffineTransform for the given skew.
- float[] mtx = Matrix_Delegate.getSkew(kx, ky);
- AffineTransform matrixTx = Matrix_Delegate.getAffineTransform(mtx);
-
- // combine them so that the given matrix is applied after.
- currentTx.preConcatenate(matrixTx);
-
- // give it to the graphics2D as a new matrix replacing all previous transform
- g.setTransform(currentTx);
- }
-
- @LayoutlibDelegate
- public static void nConcat(long nCanvas, long nMatrix) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
- if (matrixDelegate == null) {
- return;
- }
-
- // get the current top graphics2D object.
- GcSnapshot snapshot = canvasDelegate.getSnapshot();
-
- // get its current matrix
- AffineTransform currentTx = snapshot.getTransform();
- // get the AffineTransform of the given matrix
- AffineTransform matrixTx = matrixDelegate.getAffineTransform();
-
- // combine them so that the given matrix is applied after.
- currentTx.concatenate(matrixTx);
-
- // give it to the graphics2D as a new matrix replacing all previous transform
- snapshot.setTransform(currentTx);
- }
-
- @LayoutlibDelegate
- public static void nSetMatrix(long nCanvas, long nMatrix) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
- if (matrixDelegate == null) {
- return;
- }
-
- // get the current top graphics2D object.
- GcSnapshot snapshot = canvasDelegate.getSnapshot();
-
- // get the AffineTransform of the given matrix
- AffineTransform matrixTx = matrixDelegate.getAffineTransform();
-
- // give it to the graphics2D as a new matrix replacing all previous transform
- snapshot.setTransform(matrixTx);
-
- if (matrixDelegate.hasPerspective()) {
- assert false;
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
- "android.graphics.Canvas#setMatrix(android.graphics.Matrix) only " +
- "supports affine transformations.", null, null /*data*/);
- }
- }
-
- @LayoutlibDelegate
- public static boolean nClipRect(long nCanvas,
- float left, float top,
- float right, float bottom,
- int regionOp) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nCanvas);
- if (canvasDelegate == null) {
- return false;
- }
-
- return canvasDelegate.clipRect(left, top, right, bottom, regionOp);
- }
-
- @LayoutlibDelegate
- public static boolean nClipPath(long nativeCanvas,
- long nativePath,
- int regionOp) {
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return true;
- }
-
- Path_Delegate pathDelegate = Path_Delegate.getDelegate(nativePath);
- if (pathDelegate == null) {
- return true;
- }
-
- return canvasDelegate.mSnapshot.clip(pathDelegate.getJavaShape(), regionOp);
- }
-
- @LayoutlibDelegate
- public static void nSetDrawFilter(long nativeCanvas, long nativeFilter) {
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return;
- }
-
- canvasDelegate.mDrawFilter = DrawFilter_Delegate.getDelegate(nativeFilter);
-
- if (canvasDelegate.mDrawFilter != null && !canvasDelegate.mDrawFilter.isSupported()) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_DRAWFILTER,
- canvasDelegate.mDrawFilter.getSupportMessage(), null, null /*data*/);
- }
- }
-
- @LayoutlibDelegate
- public static boolean nGetClipBounds(long nativeCanvas,
- Rect bounds) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
- if (canvasDelegate == null) {
- return false;
- }
-
- Rectangle rect = canvasDelegate.getSnapshot().getClip().getBounds();
- if (rect != null && !rect.isEmpty()) {
- bounds.left = rect.x;
- bounds.top = rect.y;
- bounds.right = rect.x + rect.width;
- bounds.bottom = rect.y + rect.height;
- return true;
- }
-
- return false;
- }
-
- @LayoutlibDelegate
- public static void nGetMatrix(long canvas, long matrix) {
- // get the delegate from the native int.
- Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
- if (canvasDelegate == null) {
- return;
- }
-
- Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
- if (matrixDelegate == null) {
- return;
- }
-
- AffineTransform transform = canvasDelegate.getSnapshot().getTransform();
- matrixDelegate.set(Matrix_Delegate.makeValues(transform));
- }
-
- @LayoutlibDelegate
- public static boolean nQuickReject(long nativeCanvas, long path) {
- // FIXME properly implement quickReject
- return false;
- }
-
- @LayoutlibDelegate
- public static boolean nQuickReject(long nativeCanvas,
- float left, float top,
- float right, float bottom) {
- // FIXME properly implement quickReject
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static long nGetNativeFinalizer() {
- synchronized (Canvas_Delegate.class) {
- if (sFinalizer == -1) {
- sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(nativePtr -> {
- Canvas_Delegate delegate = Canvas_Delegate.getDelegate(nativePtr);
- if (delegate != null) {
- delegate.dispose();
- }
- sManager.removeJavaReferenceFor(nativePtr);
- });
- }
- }
- return sFinalizer;
- }
-
- private Canvas_Delegate(Bitmap_Delegate bitmap) {
- super(bitmap);
- }
-
- private Canvas_Delegate() {
- super();
- }
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.Graphics2D;
-
-/**
- * Delegate implementing the native methods of android.graphics.ColorFilter
- *
- * Through the layoutlib_create tool, the original native methods of ColorFilter have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original ColorFilter class.
- *
- * This also serve as a base class for all ColorFilter delegate classes.
- *
- * @see DelegateManager
- *
- */
-public abstract class ColorFilter_Delegate {
-
- // ---- delegate manager ----
- protected static final DelegateManager<ColorFilter_Delegate> sManager =
- new DelegateManager<ColorFilter_Delegate>(ColorFilter_Delegate.class);
-
- // ---- delegate helper data ----
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- public static ColorFilter_Delegate getDelegate(long nativeShader) {
- return sManager.getDelegate(nativeShader);
- }
-
- public abstract String getSupportMessage();
-
- public boolean isSupported() {
- return false;
- }
-
- public void applyFilter(Graphics2D g, int width, int height) {
- // This should never be called directly. If supported, the sub class should override this.
- assert false;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static void nSafeUnref(long native_instance) {
- sManager.removeJavaReferenceFor(native_instance);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.ColorMatrixColorFilter
- *
- * Through the layoutlib_create tool, the original native methods of ColorMatrixColorFilter have
- * been replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original ColorMatrixColorFilter class.
- *
- * Because this extends {@link ColorFilter_Delegate}, there's no need to use a
- * {@link DelegateManager}, as all the Shader classes will be added to the manager
- * owned by {@link ColorFilter_Delegate}.
- *
- * @see ColorFilter_Delegate
- *
- */
-public class ColorMatrixColorFilter_Delegate extends ColorFilter_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public String getSupportMessage() {
- return "ColorMatrix Color Filters are not supported.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeColorMatrixFilter(float[] array) {
- ColorMatrixColorFilter_Delegate newDelegate = new ColorMatrixColorFilter_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.Stroke;
-
-/**
- * Delegate implementing the native methods of android.graphics.ComposePathEffect
- *
- * Through the layoutlib_create tool, the original native methods of ComposePathEffect have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original ComposePathEffect class.
- *
- * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager},
- * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}.
- *
- * @see PathEffect_Delegate
- *
- */
-public class ComposePathEffect_Delegate extends PathEffect_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public Stroke getStroke(Paint_Delegate paint) {
- // FIXME
- return null;
- }
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Compose Path Effects are not supported in Layout Preview mode.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate(long outerpe, long innerpe) {
- ComposePathEffect_Delegate newDelegate = new ComposePathEffect_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.Paint;
-
-/**
- * Delegate implementing the native methods of android.graphics.ComposeShader
- *
- * Through the layoutlib_create tool, the original native methods of ComposeShader have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original ComposeShader class.
- *
- * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager},
- * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}.
- *
- * @see Shader_Delegate
- *
- */
-public class ComposeShader_Delegate extends Shader_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public Paint getJavaPaint() {
- // FIXME
- return null;
- }
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Compose Shaders are not supported in Layout Preview mode.";
- }
-
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate(long nativeMatrix, long native_shaderA,
- long native_shaderB, int native_mode) {
- // FIXME not supported yet.
- ComposeShader_Delegate newDelegate = new ComposeShader_Delegate(nativeMatrix);
- return sManager.addNewDelegate(newDelegate);
- }
-
-
- // ---- Private delegate/helper methods ----
-
- private ComposeShader_Delegate(long nativeMatrix) {
- super(nativeMatrix);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.Stroke;
-
-/**
- * Delegate implementing the native methods of android.graphics.CornerPathEffect
- *
- * Through the layoutlib_create tool, the original native methods of CornerPathEffect have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original CornerPathEffect class.
- *
- * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager},
- * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}.
- *
- * @see PathEffect_Delegate
- *
- */
-public class CornerPathEffect_Delegate extends PathEffect_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public Stroke getStroke(Paint_Delegate paint) {
- // FIXME
- return null;
- }
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Corner Path Effects are not supported in Layout Preview mode.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate(float radius) {
- CornerPathEffect_Delegate newDelegate = new CornerPathEffect_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.BasicStroke;
-import java.awt.Stroke;
-
-/**
- * Delegate implementing the native methods of android.graphics.DashPathEffect
- *
- * Through the layoutlib_create tool, the original native methods of DashPathEffect have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original DashPathEffect class.
- *
- * Because this extends {@link PathEffect_Delegate}, there's no need to use a
- * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by
- * {@link PathEffect_Delegate}.
- *
- * @see PathEffect_Delegate
- *
- */
-public final class DashPathEffect_Delegate extends PathEffect_Delegate {
-
- // ---- delegate data ----
-
- private final float[] mIntervals;
- private final float mPhase;
-
- // ---- Public Helper methods ----
-
- @Override
- public Stroke getStroke(Paint_Delegate paint) {
- return new BasicStroke(
- paint.getStrokeWidth(),
- paint.getJavaCap(),
- paint.getJavaJoin(),
- paint.getJavaStrokeMiter(),
- mIntervals,
- mPhase);
- }
-
- @Override
- public boolean isSupported() {
- return true;
- }
-
- @Override
- public String getSupportMessage() {
- // no message since isSupported returns true;
- return null;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate(float intervals[], float phase) {
- DashPathEffect_Delegate newDelegate = new DashPathEffect_Delegate(intervals, phase);
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-
- private DashPathEffect_Delegate(float intervals[], float phase) {
- mIntervals = new float[intervals.length];
- System.arraycopy(intervals, 0, mIntervals, 0, intervals.length);
- mPhase = phase;
- }
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.Stroke;
-
-/**
- * Delegate implementing the native methods of android.graphics.DiscretePathEffect
- *
- * Through the layoutlib_create tool, the original native methods of DiscretePathEffect have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original DiscretePathEffect class.
- *
- * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager},
- * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}.
- *
- * @see PathEffect_Delegate
- *
- */
-public class DiscretePathEffect_Delegate extends PathEffect_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public Stroke getStroke(Paint_Delegate paint) {
- // FIXME
- return null;
- }
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Discrete Path Effects are not supported in Layout Preview mode.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate(float length, float deviation) {
- DiscretePathEffect_Delegate newDelegate = new DiscretePathEffect_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.DrawFilter
- *
- * Through the layoutlib_create tool, the original native methods of DrawFilter have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original DrawFilter class.
- *
- * This also serve as a base class for all DrawFilter delegate classes.
- *
- * @see DelegateManager
- *
- */
-public abstract class DrawFilter_Delegate {
-
- // ---- delegate manager ----
- protected static final DelegateManager<DrawFilter_Delegate> sManager =
- new DelegateManager<DrawFilter_Delegate>(DrawFilter_Delegate.class);
-
- // ---- delegate helper data ----
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- public static DrawFilter_Delegate getDelegate(long nativeDrawFilter) {
- return sManager.getDelegate(nativeDrawFilter);
- }
-
- public abstract boolean isSupported();
- public abstract String getSupportMessage();
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static void nativeDestructor(long nativeDrawFilter) {
- sManager.removeJavaReferenceFor(nativeDrawFilter);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.EmbossMaskFilter
- *
- * Through the layoutlib_create tool, the original native methods of EmbossMaskFilter have
- * been replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original EmbossMaskFilter class.
- *
- * Because this extends {@link MaskFilter_Delegate}, there's no need to use a
- * {@link DelegateManager}, as all the Shader classes will be added to the manager
- * owned by {@link MaskFilter_Delegate}.
- *
- * @see MaskFilter_Delegate
- *
- */
-public class EmbossMaskFilter_Delegate extends MaskFilter_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Emboss Mask Filters are not supported.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeConstructor(float[] direction, float ambient,
- float specular, float blurRadius) {
- EmbossMaskFilter_Delegate newDelegate = new EmbossMaskFilter_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * 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.graphics;
-
-import com.android.ide.common.rendering.api.AssetRepository;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.res.AssetManager;
-import android.content.res.BridgeAssetManager;
-import android.graphics.fonts.FontVariationAxis;
-import android.text.FontConfig;
-
-import java.awt.Font;
-import java.awt.FontFormatException;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-
-import static android.graphics.Typeface.RESOLVE_BY_FONT_TABLE;
-import static android.graphics.Typeface_Delegate.SYSTEM_FONTS;
-
-/**
- * Delegate implementing the native methods of android.graphics.FontFamily
- *
- * Through the layoutlib_create tool, the original native methods of FontFamily have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original FontFamily class.
- *
- * @see DelegateManager
- */
-public class FontFamily_Delegate {
-
- public static final int DEFAULT_FONT_WEIGHT = 400;
- public static final int BOLD_FONT_WEIGHT_DELTA = 300;
- public static final int BOLD_FONT_WEIGHT = 700;
-
- private static final String FONT_SUFFIX_ITALIC = "Italic.ttf";
- private static final String FN_ALL_FONTS_LIST = "fontsInSdk.txt";
- private static final String EXTENSION_OTF = ".otf";
-
- private static final int CACHE_SIZE = 10;
- // The cache has a drawback that if the font file changed after the font object was created,
- // we will not update it.
- private static final Map<String, FontInfo> sCache =
- new LinkedHashMap<String, FontInfo>(CACHE_SIZE) {
- @Override
- protected boolean removeEldestEntry(Map.Entry<String, FontInfo> eldest) {
- return size() > CACHE_SIZE;
- }
-
- @Override
- public FontInfo put(String key, FontInfo value) {
- // renew this entry.
- FontInfo removed = remove(key);
- super.put(key, value);
- return removed;
- }
- };
-
- /**
- * A class associating {@link Font} with its metadata.
- */
- private static final class FontInfo {
- @Nullable
- Font mFont;
- int mWeight;
- boolean mIsItalic;
- }
-
- // ---- delegate manager ----
- private static final DelegateManager<FontFamily_Delegate> sManager =
- new DelegateManager<FontFamily_Delegate>(FontFamily_Delegate.class);
-
- // ---- delegate helper data ----
- private static String sFontLocation;
- private static final List<FontFamily_Delegate> sPostInitDelegate = new
- ArrayList<FontFamily_Delegate>();
- private static Set<String> SDK_FONTS;
-
-
- // ---- delegate data ----
- private List<FontInfo> mFonts = new ArrayList<FontInfo>();
-
- /**
- * The variant of the Font Family - compact or elegant.
- * <p/>
- * 0 is unspecified, 1 is compact and 2 is elegant. This needs to be kept in sync with values in
- * android.graphics.FontFamily
- *
- * @see Paint#setElegantTextHeight(boolean)
- */
- private FontVariant mVariant;
- // List of runnables to process fonts after sFontLoader is initialized.
- private List<Runnable> mPostInitRunnables = new ArrayList<Runnable>();
- /** @see #isValid() */
- private boolean mValid = false;
-
-
- // ---- Public helper class ----
-
- public enum FontVariant {
- // The order needs to be kept in sync with android.graphics.FontFamily.
- NONE, COMPACT, ELEGANT
- }
-
- // ---- Public Helper methods ----
-
- public static FontFamily_Delegate getDelegate(long nativeFontFamily) {
- return sManager.getDelegate(nativeFontFamily);
- }
-
- public static synchronized void setFontLocation(String fontLocation) {
- sFontLocation = fontLocation;
- // init list of bundled fonts.
- File allFonts = new File(fontLocation, FN_ALL_FONTS_LIST);
- // Current number of fonts is 103. Use the next round number to leave scope for more fonts
- // in the future.
- Set<String> allFontsList = new HashSet<String>(128);
- Scanner scanner = null;
- try {
- scanner = new Scanner(allFonts);
- while (scanner.hasNext()) {
- String name = scanner.next();
- // Skip font configuration files.
- if (!name.endsWith(".xml")) {
- allFontsList.add(name);
- }
- }
- } catch (FileNotFoundException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Unable to load the list of fonts. Try re-installing the SDK Platform from the SDK Manager.",
- e, null);
- } finally {
- if (scanner != null) {
- scanner.close();
- }
- }
- SDK_FONTS = Collections.unmodifiableSet(allFontsList);
- for (FontFamily_Delegate fontFamily : sPostInitDelegate) {
- fontFamily.init();
- }
- sPostInitDelegate.clear();
- }
-
- @Nullable
- public Font getFont(int desiredWeight, boolean isItalic) {
- FontInfo desiredStyle = new FontInfo();
- desiredStyle.mWeight = desiredWeight;
- desiredStyle.mIsItalic = isItalic;
- FontInfo bestFont = null;
- int bestMatch = Integer.MAX_VALUE;
- //noinspection ForLoopReplaceableByForEach (avoid iterator instantiation)
- for (int i = 0, n = mFonts.size(); i < n; i++) {
- FontInfo font = mFonts.get(i);
- int match = computeMatch(font, desiredStyle);
- if (match < bestMatch) {
- bestMatch = match;
- bestFont = font;
- }
- }
- if (bestFont == null) {
- return null;
- }
- if (bestMatch == 0) {
- return bestFont.mFont;
- }
- // Derive the font as required and add it to the list of Fonts.
- deriveFont(bestFont, desiredStyle);
- addFont(desiredStyle);
- return desiredStyle.mFont;
- }
-
- public FontVariant getVariant() {
- return mVariant;
- }
-
- /**
- * Returns if the FontFamily should contain any fonts. If this returns true and
- * {@link #getFont(int, boolean)} returns an empty list, it means that an error occurred while
- * loading the fonts. However, some fonts are deliberately skipped, for example they are not
- * bundled with the SDK. In such a case, this method returns false.
- */
- public boolean isValid() {
- return mValid;
- }
-
- private static Font loadFont(String path) {
- if (path.startsWith(SYSTEM_FONTS) ) {
- String relativePath = path.substring(SYSTEM_FONTS.length());
- File f = new File(sFontLocation, relativePath);
-
- try {
- return Font.createFont(Font.TRUETYPE_FONT, f);
- } catch (Exception e) {
- if (path.endsWith(EXTENSION_OTF) && e instanceof FontFormatException) {
- // If we aren't able to load an Open Type font, don't log a warning just yet.
- // We wait for a case where font is being used. Only then we try to log the
- // warning.
- return null;
- }
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
- String.format("Unable to load font %1$s", relativePath),
- e, null);
- }
- } else {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Only platform fonts located in " + SYSTEM_FONTS + "can be loaded.",
- null, null);
- }
-
- return null;
- }
-
- @Nullable
- /*package*/ static String getFontLocation() {
- return sFontLocation;
- }
-
- // ---- delegate methods ----
- @LayoutlibDelegate
- /*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex,
- FontVariationAxis[] axes, int weight, int italic) {
- if (thisFontFamily.mBuilderPtr == 0) {
- assert false : "Unable to call addFont after freezing.";
- return false;
- }
- final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mBuilderPtr);
- return delegate != null && delegate.addFont(path, ttcIndex, weight, italic);
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nInitBuilder(String lang, int variant) {
- // TODO: support lang. This is required for japanese locale.
- FontFamily_Delegate delegate = new FontFamily_Delegate();
- // variant can be 0, 1 or 2.
- assert variant < 3;
- delegate.mVariant = FontVariant.values()[variant];
- if (sFontLocation != null) {
- delegate.init();
- } else {
- sPostInitDelegate.add(delegate);
- }
- return sManager.addNewDelegate(delegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nCreateFamily(long builderPtr) {
- return builderPtr;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nUnrefFamily(long nativePtr) {
- // Removing the java reference for the object doesn't mean that it's freed for garbage
- // collection. Typeface_Delegate may still hold a reference for it.
- sManager.removeJavaReferenceFor(nativePtr);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex,
- int weight, int isItalic) {
- assert false : "The only client of this method has been overridden.";
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
- int ttcIndex, int weight, int isItalic) {
- assert false : "The only client of this method has been overridden.";
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAddAxisValue(long builderPtr, int tag, float value) {
- assert false : "The only client of this method has been overridden.";
- }
-
- static boolean addFont(long builderPtr, final String path, final int weight,
- final boolean isItalic) {
- final FontFamily_Delegate delegate = getDelegate(builderPtr);
- int italic = isItalic ? 1 : 0;
- if (delegate != null) {
- if (sFontLocation == null) {
- delegate.mPostInitRunnables.add(() -> delegate.addFont(path, weight, italic));
- return true;
- }
- return delegate.addFont(path, weight, italic);
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr, String path,
- int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic) {
- FontFamily_Delegate ffd = sManager.getDelegate(builderPtr);
- if (ffd == null) {
- return false;
- }
- ffd.mValid = true;
- if (mgr == null) {
- return false;
- }
- if (mgr instanceof BridgeAssetManager) {
- InputStream fontStream = null;
- try {
- AssetRepository assetRepository = ((BridgeAssetManager) mgr).getAssetRepository();
- if (assetRepository == null) {
- Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Asset not found: " + path,
- null);
- return false;
- }
- if (!assetRepository.isSupported()) {
- // Don't log any warnings on unsupported IDEs.
- return false;
- }
- // Check cache
- FontInfo fontInfo = sCache.get(path);
- if (fontInfo != null) {
- // renew the font's lease.
- sCache.put(path, fontInfo);
- ffd.addFont(fontInfo);
- return true;
- }
- fontStream = isAsset ?
- assetRepository.openAsset(path, AssetManager.ACCESS_STREAMING) :
- assetRepository.openNonAsset(cookie, path, AssetManager.ACCESS_STREAMING);
- if (fontStream == null) {
- Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Asset not found: " + path,
- path);
- return false;
- }
- Font font = Font.createFont(Font.TRUETYPE_FONT, fontStream);
- fontInfo = new FontInfo();
- fontInfo.mFont = font;
- if (weight == RESOLVE_BY_FONT_TABLE) {
- fontInfo.mWeight = font.isBold() ? BOLD_FONT_WEIGHT : DEFAULT_FONT_WEIGHT;
- } else {
- fontInfo.mWeight = weight;
- }
- fontInfo.mIsItalic = isItalic == RESOLVE_BY_FONT_TABLE ? font.isItalic() :
- isItalic == 1;
- ffd.addFont(fontInfo);
- return true;
- } catch (IOException e) {
- Bridge.getLog().error(LayoutLog.TAG_MISSING_ASSET, "Unable to load font " + path, e,
- path);
- } catch (FontFormatException e) {
- if (path.endsWith(EXTENSION_OTF)) {
- // otf fonts are not supported on the user's config (JRE version + OS)
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "OpenType fonts are not supported yet: " + path, null, path);
- } else {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Unable to load font " + path, e, path);
- }
- } finally {
- if (fontStream != null) {
- try {
- fontStream.close();
- } catch (IOException ignored) {
- }
- }
- }
- return false;
- }
- // This should never happen. AssetManager is a final class (from user's perspective), and
- // we've replaced every creation of AssetManager with our implementation. We create an
- // exception and log it, but continue with rest of the rendering, without loading this font.
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "You have found a bug in the rendering library. Please file a bug at b.android.com.",
- new RuntimeException("Asset Manager is not an instance of BridgeAssetManager"),
- null);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAbort(long builderPtr) {
- sManager.removeJavaReferenceFor(builderPtr);
- }
-
- /**
- * @see FontFamily#allowUnsupportedFont
- */
- @LayoutlibDelegate
- /*package*/ static void nAllowUnsupportedFont(long builderPtr) {
- // Do nothing here as this is used for Minikin fonts
- }
-
- // ---- private helper methods ----
-
- private void init() {
- for (Runnable postInitRunnable : mPostInitRunnables) {
- postInitRunnable.run();
- }
- mPostInitRunnables = null;
- }
-
- private boolean addFont(final String path, int ttcIndex, int weight, int italic) {
- // FIXME: support ttc fonts. Hack JRE??
- if (sFontLocation == null) {
- mPostInitRunnables.add(() -> addFont(path, weight, italic));
- return true;
- }
- return addFont(path, weight, italic);
- }
-
- private boolean addFont(@NonNull String path) {
- return addFont(path, DEFAULT_FONT_WEIGHT, path.endsWith(FONT_SUFFIX_ITALIC) ? 1 : RESOLVE_BY_FONT_TABLE);
- }
-
- private boolean addFont(@NonNull String path, int weight, int italic) {
- if (path.startsWith(SYSTEM_FONTS) &&
- !SDK_FONTS.contains(path.substring(SYSTEM_FONTS.length()))) {
- return mValid = false;
- }
- // Set valid to true, even if the font fails to load.
- mValid = true;
- Font font = loadFont(path);
- if (font == null) {
- return false;
- }
- FontInfo fontInfo = new FontInfo();
- fontInfo.mFont = font;
- fontInfo.mWeight = weight;
- fontInfo.mIsItalic = italic == RESOLVE_BY_FONT_TABLE ? font.isItalic() : italic == 1;
- addFont(fontInfo);
- return true;
- }
-
- private boolean addFont(@NonNull FontInfo fontInfo) {
- int weight = fontInfo.mWeight;
- boolean isItalic = fontInfo.mIsItalic;
- // The list is usually just two fonts big. So iterating over all isn't as bad as it looks.
- // It's biggest for roboto where the size is 12.
- //noinspection ForLoopReplaceableByForEach (avoid iterator instantiation)
- for (int i = 0, n = mFonts.size(); i < n; i++) {
- FontInfo font = mFonts.get(i);
- if (font.mWeight == weight && font.mIsItalic == isItalic) {
- return false;
- }
- }
- mFonts.add(fontInfo);
- return true;
- }
-
- /**
- * Compute matching metric between two styles - 0 is an exact match.
- */
- private static int computeMatch(@NonNull FontInfo font1, @NonNull FontInfo font2) {
- int score = Math.abs(font1.mWeight - font2.mWeight);
- if (font1.mIsItalic != font2.mIsItalic) {
- score += 200;
- }
- return score;
- }
-
- /**
- * Try to derive a font from {@code srcFont} for the style in {@code outFont}.
- * <p/>
- * {@code outFont} is updated to reflect the style of the derived font.
- * @param srcFont the source font
- * @param outFont contains the desired font style. Updated to contain the derived font and
- * its style
- * @return outFont
- */
- @NonNull
- private FontInfo deriveFont(@NonNull FontInfo srcFont, @NonNull FontInfo outFont) {
- int desiredWeight = outFont.mWeight;
- int srcWeight = srcFont.mWeight;
- assert srcFont.mFont != null;
- Font derivedFont = srcFont.mFont;
- // Embolden the font if required.
- if (desiredWeight >= BOLD_FONT_WEIGHT && desiredWeight - srcWeight > BOLD_FONT_WEIGHT_DELTA / 2) {
- derivedFont = derivedFont.deriveFont(Font.BOLD);
- srcWeight += BOLD_FONT_WEIGHT_DELTA;
- }
- // Italicize the font if required.
- if (outFont.mIsItalic && !srcFont.mIsItalic) {
- derivedFont = derivedFont.deriveFont(Font.ITALIC);
- } else if (outFont.mIsItalic != srcFont.mIsItalic) {
- // The desired font is plain, but the src font is italics. We can't convert it back. So
- // we update the value to reflect the true style of the font we're deriving.
- outFont.mIsItalic = srcFont.mIsItalic;
- }
- outFont.mFont = derivedFont;
- outFont.mWeight = srcWeight;
- // No need to update mIsItalics, as it's already been handled above.
- return outFont;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import android.graphics.Shader.TileMode;
-
-/**
- * Base class for true Gradient shader delegate.
- */
-public abstract class Gradient_Delegate extends Shader_Delegate {
-
- protected final int[] mColors;
- protected final float[] mPositions;
-
- @Override
- public boolean isSupported() {
- // all gradient shaders are supported.
- return true;
- }
-
- @Override
- public String getSupportMessage() {
- // all gradient shaders are supported, no need for a gradient support
- return null;
- }
-
- /**
- * Creates the base shader and do some basic test on the parameters.
- *
- * @param nativeMatrix reference to the shader's native transformation matrix
- * @param colors The colors to be distributed along the gradient line
- * @param positions May be null. The relative positions [0..1] of each
- * corresponding color in the colors array. If this is null, the
- * the colors are distributed evenly along the gradient line.
- */
- protected Gradient_Delegate(long nativeMatrix, int colors[], float positions[]) {
- super(nativeMatrix);
- assert colors.length >= 2 : "needs >= 2 number of colors";
-
- if (positions == null) {
- float spacing = 1.f / (colors.length - 1);
- positions = new float[colors.length];
- positions[0] = 0.f;
- positions[colors.length - 1] = 1.f;
- for (int i = 1; i < colors.length - 1; i++) {
- positions[i] = spacing * i;
- }
- } else {
- assert colors.length == positions.length :
- "color and position " + "arrays must be of equal length";
- }
-
- mColors = colors;
- mPositions = positions;
- }
-
- /**
- * Base class for (Java) Gradient Paints. This handles computing the gradient colors based
- * on the color and position lists, as well as the {@link TileMode}
- *
- */
- protected abstract static class GradientPaint implements java.awt.Paint {
- private final static int GRADIENT_SIZE = 100;
-
- private final int[] mColors;
- private final float[] mPositions;
- private final TileMode mTileMode;
- private int[] mGradient;
-
- protected GradientPaint(int[] colors, float[] positions, TileMode tileMode) {
- mColors = colors;
- mPositions = positions;
- mTileMode = tileMode;
- }
-
- @Override
- public int getTransparency() {
- return java.awt.Paint.TRANSLUCENT;
- }
-
- /**
- * Pre-computes the colors for the gradient. This must be called once before any call
- * to {@link #getGradientColor(float)}
- */
- protected void precomputeGradientColors() {
- if (mGradient == null) {
- // actually create an array with an extra size, so that we can really go
- // from 0 to SIZE (100%), or currentPos in the loop below will never equal 1.0
- mGradient = new int[GRADIENT_SIZE+1];
-
- int prevPos = 0;
- int nextPos = 1;
- for (int i = 0 ; i <= GRADIENT_SIZE ; i++) {
- // compute current position
- float currentPos = (float)i/GRADIENT_SIZE;
- while (currentPos > mPositions[nextPos]) {
- prevPos = nextPos++;
- }
-
- float percent = (currentPos - mPositions[prevPos]) /
- (mPositions[nextPos] - mPositions[prevPos]);
-
- mGradient[i] = computeColor(mColors[prevPos], mColors[nextPos], percent);
- }
- }
- }
-
- /**
- * Returns the color based on the position in the gradient.
- * <var>pos</var> can be anything, even < 0 or > > 1, as the gradient
- * will use {@link TileMode} value to convert it into a [0,1] value.
- */
- protected int getGradientColor(float pos) {
- if (pos < 0.f) {
- if (mTileMode != null) {
- switch (mTileMode) {
- case CLAMP:
- pos = 0.f;
- break;
- case REPEAT:
- // remove the integer part to stay in the [0,1] range.
- // we also need to invert the value from [-1,0] to [0, 1]
- pos = pos - (float)Math.floor(pos);
- break;
- case MIRROR:
- // this is the same as the positive side, just make the value positive
- // first.
- pos = Math.abs(pos);
-
- // get the integer and the decimal part
- int intPart = (int)Math.floor(pos);
- pos = pos - intPart;
- // 0 -> 1 : normal order
- // 1 -> 2: mirrored
- // etc..
- // this means if the intpart is odd we invert
- if ((intPart % 2) == 1) {
- pos = 1.f - pos;
- }
- break;
- }
- } else {
- pos = 0.0f;
- }
- } else if (pos > 1f) {
- if (mTileMode != null) {
- switch (mTileMode) {
- case CLAMP:
- pos = 1.f;
- break;
- case REPEAT:
- // remove the integer part to stay in the [0,1] range
- pos = pos - (float)Math.floor(pos);
- break;
- case MIRROR:
- // get the integer and the decimal part
- int intPart = (int)Math.floor(pos);
- pos = pos - intPart;
- // 0 -> 1 : normal order
- // 1 -> 2: mirrored
- // etc..
- // this means if the intpart is odd we invert
- if ((intPart % 2) == 1) {
- pos = 1.f - pos;
- }
- break;
- }
- } else {
- pos = 1.0f;
- }
- }
-
- int index = (int)((pos * GRADIENT_SIZE) + .5);
-
- return mGradient[index];
- }
-
- /**
- * Returns the color between c1, and c2, based on the percent of the distance
- * between c1 and c2.
- */
- private int computeColor(int c1, int c2, float percent) {
- int a = computeChannel((c1 >> 24) & 0xFF, (c2 >> 24) & 0xFF, percent);
- int r = computeChannel((c1 >> 16) & 0xFF, (c2 >> 16) & 0xFF, percent);
- int g = computeChannel((c1 >> 8) & 0xFF, (c2 >> 8) & 0xFF, percent);
- int b = computeChannel((c1 ) & 0xFF, (c2 ) & 0xFF, percent);
- return a << 24 | r << 16 | g << 8 | b;
- }
-
- /**
- * Returns the channel value between 2 values based on the percent of the distance between
- * the 2 values..
- */
- private int computeChannel(int c1, int c2, float percent) {
- return c1 + (int)((percent * (c2-c1)) + .5);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.LightingColorFilter
- *
- * Through the layoutlib_create tool, the original native methods of LightingColorFilter have
- * been replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original LightingColorFilter class.
- *
- * Because this extends {@link ColorFilter_Delegate}, there's no need to use a
- * {@link DelegateManager}, as all the Shader classes will be added to the manager
- * owned by {@link ColorFilter_Delegate}.
- *
- * @see ColorFilter_Delegate
- *
- */
-public class LightingColorFilter_Delegate extends ColorFilter_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public String getSupportMessage() {
- return "Lighting Color Filters are not supported.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long native_CreateLightingFilter(int mul, int add) {
- LightingColorFilter_Delegate newDelegate = new LightingColorFilter_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.Shader.TileMode;
-
-import java.awt.image.ColorModel;
-
-/**
- * Delegate implementing the native methods of android.graphics.LinearGradient
- *
- * Through the layoutlib_create tool, the original native methods of LinearGradient have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original LinearGradient class.
- *
- * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager},
- * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}.
- *
- * @see Shader_Delegate
- *
- */
-public final class LinearGradient_Delegate extends Gradient_Delegate {
-
- // ---- delegate data ----
- private java.awt.Paint mJavaPaint;
-
- // ---- Public Helper methods ----
-
- @Override
- public java.awt.Paint getJavaPaint() {
- return mJavaPaint;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate1(LinearGradient thisGradient, long matrix,
- float x0, float y0, float x1, float y1,
- int colors[], float positions[], int tileMode) {
- LinearGradient_Delegate newDelegate = new LinearGradient_Delegate(matrix, x0, y0,
- x1, y1, colors, positions, Shader_Delegate.getTileMode(tileMode));
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate2(LinearGradient thisGradient, long matrix,
- float x0, float y0, float x1, float y1,
- int color0, int color1, int tileMode) {
- return nativeCreate1(thisGradient, matrix, x0, y0, x1, y1, new int[] { color0, color1},
- null /*positions*/, tileMode);
- }
-
- // ---- Private delegate/helper methods ----
-
- /**
- * Create a shader that draws a linear gradient along a line.
- *
- * @param nativeMatrix reference to the shader's native transformation matrix
- * @param x0 The x-coordinate for the start of the gradient line
- * @param y0 The y-coordinate for the start of the gradient line
- * @param x1 The x-coordinate for the end of the gradient line
- * @param y1 The y-coordinate for the end of the gradient line
- * @param colors The colors to be distributed along the gradient line
- * @param positions May be null. The relative positions [0..1] of each
- * corresponding color in the colors array. If this is null, the
- * the colors are distributed evenly along the gradient line.
- * @param tile The Shader tiling mode
- */
- private LinearGradient_Delegate(long nativeMatrix, float x0, float y0, float x1,
- float y1, int colors[], float positions[], TileMode tile) {
- super(nativeMatrix, colors, positions);
- mJavaPaint = new LinearGradientPaint(x0, y0, x1, y1, mColors, mPositions, tile);
- }
-
- // ---- Custom Java Paint ----
- /**
- * Linear Gradient (Java) Paint able to handle more than 2 points, as
- * {@link java.awt.GradientPaint} only supports 2 points and does not support Android's tile
- * modes.
- */
- private class LinearGradientPaint extends GradientPaint {
-
- private final float mX0;
- private final float mY0;
- private final float mDx;
- private final float mDy;
- private final float mDSize2;
-
- public LinearGradientPaint(float x0, float y0, float x1, float y1, int colors[],
- float positions[], TileMode tile) {
- super(colors, positions, tile);
- mX0 = x0;
- mY0 = y0;
- mDx = x1 - x0;
- mDy = y1 - y0;
- mDSize2 = mDx * mDx + mDy * mDy;
- }
-
- @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) {
- precomputeGradientColors();
-
- java.awt.geom.AffineTransform canvasMatrix;
- try {
- canvasMatrix = xform.createInverse();
- } catch (java.awt.geom.NoninvertibleTransformException e) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in LinearGradient", e, null /*data*/);
- canvasMatrix = new java.awt.geom.AffineTransform();
- }
-
- java.awt.geom.AffineTransform localMatrix = getLocalMatrix();
- try {
- localMatrix = localMatrix.createInverse();
- } catch (java.awt.geom.NoninvertibleTransformException e) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in LinearGradient", e, null /*data*/);
- localMatrix = new java.awt.geom.AffineTransform();
- }
-
- return new LinearGradientPaintContext(canvasMatrix, localMatrix, colorModel);
- }
-
- private class LinearGradientPaintContext implements java.awt.PaintContext {
-
- private final java.awt.geom.AffineTransform mCanvasMatrix;
- private final java.awt.geom.AffineTransform mLocalMatrix;
- private final java.awt.image.ColorModel mColorModel;
-
- private LinearGradientPaintContext(
- java.awt.geom.AffineTransform canvasMatrix,
- java.awt.geom.AffineTransform localMatrix,
- java.awt.image.ColorModel colorModel) {
- mCanvasMatrix = canvasMatrix;
- mLocalMatrix = localMatrix;
- mColorModel = colorModel.hasAlpha() ? colorModel : ColorModel.getRGBdefault();
- }
-
- @Override
- public void dispose() {
- }
-
- @Override
- public java.awt.image.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(
- mColorModel, mColorModel.createCompatibleWritableRaster(w, h),
- mColorModel.isAlphaPremultiplied(), null);
-
- int[] data = new int[w*h];
-
- int index = 0;
- float[] pt1 = new float[2];
- float[] pt2 = new float[2];
- for (int iy = 0 ; iy < h ; iy++) {
- for (int ix = 0 ; ix < w ; ix++) {
- // handle the canvas transform
- pt1[0] = x + ix;
- pt1[1] = y + iy;
- mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
-
- // handle the local matrix.
- pt1[0] = pt2[0];
- pt1[1] = pt2[1];
- mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
-
- data[index++] = getColor(pt2[0], pt2[1]);
- }
- }
-
- image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/);
-
- return image.getRaster();
- }
- }
-
- /**
- * Returns a color for an arbitrary point.
- */
- private int getColor(float x, float y) {
- float pos;
- if (mDx == 0) {
- pos = (y - mY0) / mDy;
- } else if (mDy == 0) {
- pos = (x - mX0) / mDx;
- } else {
- // find the x position on the gradient vector.
- float _x = (mDx*mDy*(y-mY0) + mDy*mDy*mX0 + mDx*mDx*x) / mDSize2;
- // from it get the position relative to the vector
- pos = (_x - mX0) / mDx;
- }
-
- return getGradientColor(pos);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.MaskFilter
- *
- * Through the layoutlib_create tool, the original native methods of MaskFilter have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original MaskFilter class.
- *
- * This also serve as a base class for all MaskFilter delegate classes.
- *
- * @see DelegateManager
- *
- */
-public abstract class MaskFilter_Delegate {
-
- // ---- delegate manager ----
- protected static final DelegateManager<MaskFilter_Delegate> sManager =
- new DelegateManager<MaskFilter_Delegate>(MaskFilter_Delegate.class);
-
- // ---- delegate helper data ----
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- public static MaskFilter_Delegate getDelegate(long nativeShader) {
- return sManager.getDelegate(nativeShader);
- }
-
- public abstract boolean isSupported();
- public abstract String getSupportMessage();
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static void nativeDestructor(long native_filter) {
- sManager.removeJavaReferenceFor(native_filter);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.Matrix.ScaleToFit;
-
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-
-import libcore.util.NativeAllocationRegistry_Delegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.Matrix
- *
- * Through the layoutlib_create tool, the original native methods of Matrix have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original Matrix class.
- *
- * @see DelegateManager
- *
- */
-public final class Matrix_Delegate {
-
- private final static int MATRIX_SIZE = 9;
-
- // ---- delegate manager ----
- private static final DelegateManager<Matrix_Delegate> sManager =
- new DelegateManager<Matrix_Delegate>(Matrix_Delegate.class);
- private static long sFinalizer = -1;
-
- // ---- delegate data ----
- private float mValues[] = new float[MATRIX_SIZE];
-
- // ---- Public Helper methods ----
-
- public static Matrix_Delegate getDelegate(long native_instance) {
- return sManager.getDelegate(native_instance);
- }
-
- /**
- * Returns an {@link AffineTransform} matching the given Matrix.
- */
- public static AffineTransform getAffineTransform(Matrix m) {
- Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
- if (delegate == null) {
- return null;
- }
-
- return delegate.getAffineTransform();
- }
-
- public static boolean hasPerspective(Matrix m) {
- Matrix_Delegate delegate = sManager.getDelegate(m.native_instance);
- if (delegate == null) {
- return false;
- }
-
- return delegate.hasPerspective();
- }
-
- /**
- * Sets the content of the matrix with the content of another matrix.
- */
- public void set(Matrix_Delegate matrix) {
- System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE);
- }
-
- /**
- * Sets the content of the matrix with the content of another matrix represented as an array
- * of values.
- */
- public void set(float[] values) {
- System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
- }
-
- /**
- * Resets the matrix to be the identity matrix.
- */
- public void reset() {
- reset(mValues);
- }
-
- /**
- * Returns whether or not the matrix is identity.
- */
- public boolean isIdentity() {
- for (int i = 0, k = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++, k++) {
- if (mValues[k] != ((i==j) ? 1 : 0)) {
- return false;
- }
- }
- }
-
- return true;
- }
-
- public static float[] makeValues(AffineTransform matrix) {
- float[] values = new float[MATRIX_SIZE];
- values[0] = (float) matrix.getScaleX();
- values[1] = (float) matrix.getShearX();
- values[2] = (float) matrix.getTranslateX();
- values[3] = (float) matrix.getShearY();
- values[4] = (float) matrix.getScaleY();
- values[5] = (float) matrix.getTranslateY();
- values[6] = 0.f;
- values[7] = 0.f;
- values[8] = 1.f;
-
- return values;
- }
-
- public static Matrix_Delegate make(AffineTransform matrix) {
- return new Matrix_Delegate(makeValues(matrix));
- }
-
- public boolean mapRect(RectF dst, RectF src) {
- // array with 4 corners
- float[] corners = new float[] {
- src.left, src.top,
- src.right, src.top,
- src.right, src.bottom,
- src.left, src.bottom,
- };
-
- // apply the transform to them.
- mapPoints(corners);
-
- // now put the result in the rect. We take the min/max of Xs and min/max of Ys
- dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
- dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
-
- dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
- dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
-
-
- return (computeTypeMask() & kRectStaysRect_Mask) != 0;
- }
-
-
- /**
- * Returns an {@link AffineTransform} matching the matrix.
- */
- public AffineTransform getAffineTransform() {
- return getAffineTransform(mValues);
- }
-
- public boolean hasPerspective() {
- return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1);
- }
-
-
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nCreate(long native_src_or_zero) {
- // create the delegate
- Matrix_Delegate newDelegate = new Matrix_Delegate();
-
- // copy from values if needed.
- if (native_src_or_zero > 0) {
- Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero);
- if (oldDelegate != null) {
- System.arraycopy(
- oldDelegate.mValues, 0,
- newDelegate.mValues, 0,
- MATRIX_SIZE);
- }
- }
-
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nIsIdentity(long native_object) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
- }
-
- return d.isIdentity();
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nIsAffine(long native_object) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return true;
- }
-
- return (d.computeTypeMask() & kPerspective_Mask) == 0;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nRectStaysRect(long native_object) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return true;
- }
-
- return (d.computeTypeMask() & kRectStaysRect_Mask) != 0;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nReset(long native_object) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- reset(d.mValues);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSet(long native_object, long other) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- Matrix_Delegate src = sManager.getDelegate(other);
- if (src == null) {
- return;
- }
-
- System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetTranslate(long native_object, float dx, float dy) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- setTranslate(d.mValues, dx, dy);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetScale(long native_object, float sx, float sy,
- float px, float py) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- d.mValues = getScale(sx, sy, px, py);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetScale(long native_object, float sx, float sy) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- d.mValues[0] = sx;
- d.mValues[1] = 0;
- d.mValues[2] = 0;
- d.mValues[3] = 0;
- d.mValues[4] = sy;
- d.mValues[5] = 0;
- d.mValues[6] = 0;
- d.mValues[7] = 0;
- d.mValues[8] = 1;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetRotate(long native_object, float degrees, float px, float py) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- d.mValues = getRotate(degrees, px, py);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetRotate(long native_object, float degrees) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- setRotate(d.mValues, degrees);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetSinCos(long native_object, float sinValue, float cosValue,
- float px, float py) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- // TODO: do it in one pass
-
- // translate so that the pivot is in 0,0
- setTranslate(d.mValues, -px, -py);
-
- // scale
- d.postTransform(getRotate(sinValue, cosValue));
- // translate back the pivot
- d.postTransform(getTranslate(px, py));
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetSinCos(long native_object, float sinValue, float cosValue) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- setRotate(d.mValues, sinValue, cosValue);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetSkew(long native_object, float kx, float ky,
- float px, float py) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- d.mValues = getSkew(kx, ky, px, py);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetSkew(long native_object, float kx, float ky) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- d.mValues[0] = 1;
- d.mValues[1] = kx;
- d.mValues[2] = -0;
- d.mValues[3] = ky;
- d.mValues[4] = 1;
- d.mValues[5] = 0;
- d.mValues[6] = 0;
- d.mValues[7] = 0;
- d.mValues[8] = 1;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetConcat(long native_object, long a, long b) {
- if (a == native_object) {
- nPreConcat(native_object, b);
- return;
- } else if (b == native_object) {
- nPostConcat(native_object, a);
- return;
- }
-
- Matrix_Delegate d = sManager.getDelegate(native_object);
- Matrix_Delegate a_mtx = sManager.getDelegate(a);
- Matrix_Delegate b_mtx = sManager.getDelegate(b);
- if (d != null && a_mtx != null && b_mtx != null) {
- multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPreTranslate(long native_object, float dx, float dy) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.preTransform(getTranslate(dx, dy));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPreScale(long native_object, float sx, float sy,
- float px, float py) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.preTransform(getScale(sx, sy, px, py));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPreScale(long native_object, float sx, float sy) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.preTransform(getScale(sx, sy));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPreRotate(long native_object, float degrees,
- float px, float py) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.preTransform(getRotate(degrees, px, py));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPreRotate(long native_object, float degrees) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
-
- double rad = Math.toRadians(degrees);
- float sin = (float) Math.sin(rad);
- float cos = (float) Math.cos(rad);
-
- d.preTransform(getRotate(sin, cos));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPreSkew(long native_object, float kx, float ky,
- float px, float py) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.preTransform(getSkew(kx, ky, px, py));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPreSkew(long native_object, float kx, float ky) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.preTransform(getSkew(kx, ky));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPreConcat(long native_object, long other_matrix) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- Matrix_Delegate other = sManager.getDelegate(other_matrix);
- if (d != null && other != null) {
- d.preTransform(other.mValues);
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPostTranslate(long native_object, float dx, float dy) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.postTransform(getTranslate(dx, dy));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPostScale(long native_object, float sx, float sy,
- float px, float py) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.postTransform(getScale(sx, sy, px, py));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPostScale(long native_object, float sx, float sy) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.postTransform(getScale(sx, sy));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPostRotate(long native_object, float degrees,
- float px, float py) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.postTransform(getRotate(degrees, px, py));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPostRotate(long native_object, float degrees) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.postTransform(getRotate(degrees));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPostSkew(long native_object, float kx, float ky,
- float px, float py) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.postTransform(getSkew(kx, ky, px, py));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPostSkew(long native_object, float kx, float ky) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d != null) {
- d.postTransform(getSkew(kx, ky));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nPostConcat(long native_object, long other_matrix) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- Matrix_Delegate other = sManager.getDelegate(other_matrix);
- if (d != null && other != null) {
- d.postTransform(other.mValues);
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetRectToRect(long native_object, RectF src,
- RectF dst, int stf) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
- }
-
- if (src.isEmpty()) {
- reset(d.mValues);
- return false;
- }
-
- if (dst.isEmpty()) {
- d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5]
- = d.mValues[6] = d.mValues[7] = 0;
- d.mValues[8] = 1;
- } else {
- float tx, sx = dst.width() / src.width();
- float ty, sy = dst.height() / src.height();
- boolean xLarger = false;
-
- if (stf != ScaleToFit.FILL.nativeInt) {
- if (sx > sy) {
- xLarger = true;
- sx = sy;
- } else {
- sy = sx;
- }
- }
-
- tx = dst.left - src.left * sx;
- ty = dst.top - src.top * sy;
- if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) {
- float diff;
-
- if (xLarger) {
- diff = dst.width() - src.width() * sy;
- } else {
- diff = dst.height() - src.height() * sy;
- }
-
- if (stf == ScaleToFit.CENTER.nativeInt) {
- diff = diff / 2;
- }
-
- if (xLarger) {
- tx += diff;
- } else {
- ty += diff;
- }
- }
-
- d.mValues[0] = sx;
- d.mValues[4] = sy;
- d.mValues[2] = tx;
- d.mValues[5] = ty;
- d.mValues[1] = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0;
-
- }
- // shared cleanup
- d.mValues[8] = 1;
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetPolyToPoly(long native_object, float[] src, int srcIndex,
- float[] dst, int dstIndex, int pointCount) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Matrix.setPolyToPoly is not supported.",
- null, null /*data*/);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nInvert(long native_object, long inverse) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
- }
-
- Matrix_Delegate inv_mtx = sManager.getDelegate(inverse);
- if (inv_mtx == null) {
- return false;
- }
-
- try {
- AffineTransform affineTransform = d.getAffineTransform();
- AffineTransform inverseTransform = affineTransform.createInverse();
- inv_mtx.mValues[0] = (float)inverseTransform.getScaleX();
- inv_mtx.mValues[1] = (float)inverseTransform.getShearX();
- inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX();
- inv_mtx.mValues[3] = (float)inverseTransform.getScaleX();
- inv_mtx.mValues[4] = (float)inverseTransform.getShearY();
- inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY();
-
- return true;
- } catch (NoninvertibleTransformException e) {
- return false;
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void nMapPoints(long native_object, float[] dst, int dstIndex,
- float[] src, int srcIndex, int ptCount, boolean isPts) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- if (isPts) {
- d.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
- } else {
- d.mapVectors(dst, dstIndex, src, srcIndex, ptCount);
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nMapRect(long native_object, RectF dst, RectF src) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return false;
- }
-
- return d.mapRect(dst, src);
- }
-
- @LayoutlibDelegate
- /*package*/ static float nMapRadius(long native_object, float radius) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return 0.f;
- }
-
- float[] src = new float[] { radius, 0.f, 0.f, radius };
- d.mapVectors(src, 0, src, 0, 2);
-
- float l1 = (float) Math.hypot(src[0], src[1]);
- float l2 = (float) Math.hypot(src[2], src[3]);
- return (float) Math.sqrt(l1 * l2);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nGetValues(long native_object, float[] values) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- System.arraycopy(d.mValues, 0, values, 0, MATRIX_SIZE);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetValues(long native_object, float[] values) {
- Matrix_Delegate d = sManager.getDelegate(native_object);
- if (d == null) {
- return;
- }
-
- System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nEquals(long native_a, long native_b) {
- Matrix_Delegate a = sManager.getDelegate(native_a);
- if (a == null) {
- return false;
- }
-
- Matrix_Delegate b = sManager.getDelegate(native_b);
- if (b == null) {
- return false;
- }
-
- for (int i = 0 ; i < MATRIX_SIZE ; i++) {
- if (a.mValues[i] != b.mValues[i]) {
- return false;
- }
- }
-
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static long nGetNativeFinalizer() {
- synchronized (Matrix_Delegate.class) {
- if (sFinalizer == -1) {
- sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
- }
- }
- return sFinalizer;
- }
-
- // ---- Private helper methods ----
-
- /*package*/ static AffineTransform getAffineTransform(float[] matrix) {
- // the AffineTransform constructor takes the value in a different order
- // for a matrix [ 0 1 2 ]
- // [ 3 4 5 ]
- // the order is 0, 3, 1, 4, 2, 5...
- return new AffineTransform(
- matrix[0], matrix[3], matrix[1],
- matrix[4], matrix[2], matrix[5]);
- }
-
- /**
- * Reset a matrix to the identity
- */
- private static void reset(float[] mtx) {
- for (int i = 0, k = 0; i < 3; i++) {
- for (int j = 0; j < 3; j++, k++) {
- mtx[k] = ((i==j) ? 1 : 0);
- }
- }
- }
-
- @SuppressWarnings("unused")
- private final static int kIdentity_Mask = 0;
- private final static int kTranslate_Mask = 0x01; //!< set if the matrix has translation
- private final static int kScale_Mask = 0x02; //!< set if the matrix has X or Y scale
- private final static int kAffine_Mask = 0x04; //!< set if the matrix skews or rotates
- private final static int kPerspective_Mask = 0x08; //!< set if the matrix is in perspective
- private final static int kRectStaysRect_Mask = 0x10;
- @SuppressWarnings("unused")
- private final static int kUnknown_Mask = 0x80;
-
- @SuppressWarnings("unused")
- private final static int kAllMasks = kTranslate_Mask |
- kScale_Mask |
- kAffine_Mask |
- kPerspective_Mask |
- kRectStaysRect_Mask;
-
- // these guys align with the masks, so we can compute a mask from a variable 0/1
- @SuppressWarnings("unused")
- private final static int kTranslate_Shift = 0;
- @SuppressWarnings("unused")
- private final static int kScale_Shift = 1;
- @SuppressWarnings("unused")
- private final static int kAffine_Shift = 2;
- @SuppressWarnings("unused")
- private final static int kPerspective_Shift = 3;
- private final static int kRectStaysRect_Shift = 4;
-
- private int computeTypeMask() {
- int mask = 0;
-
- if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) {
- mask |= kPerspective_Mask;
- }
-
- if (mValues[2] != 0. || mValues[5] != 0.) {
- mask |= kTranslate_Mask;
- }
-
- float m00 = mValues[0];
- float m01 = mValues[1];
- float m10 = mValues[3];
- float m11 = mValues[4];
-
- if (m01 != 0. || m10 != 0.) {
- mask |= kAffine_Mask;
- }
-
- if (m00 != 1. || m11 != 1.) {
- mask |= kScale_Mask;
- }
-
- if ((mask & kPerspective_Mask) == 0) {
- // map non-zero to 1
- int im00 = m00 != 0 ? 1 : 0;
- int im01 = m01 != 0 ? 1 : 0;
- int im10 = m10 != 0 ? 1 : 0;
- int im11 = m11 != 0 ? 1 : 0;
-
- // record if the (p)rimary and (s)econdary diagonals are all 0 or
- // all non-zero (answer is 0 or 1)
- int dp0 = (im00 | im11) ^ 1; // true if both are 0
- int dp1 = im00 & im11; // true if both are 1
- int ds0 = (im01 | im10) ^ 1; // true if both are 0
- int ds1 = im01 & im10; // true if both are 1
-
- // return 1 if primary is 1 and secondary is 0 or
- // primary is 0 and secondary is 1
- mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift;
- }
-
- return mask;
- }
-
- private Matrix_Delegate() {
- reset();
- }
-
- private Matrix_Delegate(float[] values) {
- System.arraycopy(values, 0, mValues, 0, MATRIX_SIZE);
- }
-
- /**
- * Adds the given transformation to the current Matrix
- * <p/>This in effect does this = this*matrix
- * @param matrix
- */
- private void postTransform(float[] matrix) {
- float[] tmp = new float[9];
- multiply(tmp, mValues, matrix);
- mValues = tmp;
- }
-
- /**
- * Adds the given transformation to the current Matrix
- * <p/>This in effect does this = matrix*this
- * @param matrix
- */
- private void preTransform(float[] matrix) {
- float[] tmp = new float[9];
- multiply(tmp, matrix, mValues);
- mValues = tmp;
- }
-
- /**
- * Apply this matrix to the array of 2D points specified by src, and write
- * the transformed points into the array of points specified by dst. The
- * two arrays represent their "points" as pairs of floats [x, y].
- *
- * @param dst The array of dst points (x,y pairs)
- * @param dstIndex The index of the first [x,y] pair of dst floats
- * @param src The array of src points (x,y pairs)
- * @param srcIndex The index of the first [x,y] pair of src floats
- * @param pointCount The number of points (x,y pairs) to transform
- */
-
- private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
- int pointCount) {
- final int count = pointCount * 2;
-
- float[] tmpDest = dst;
- boolean inPlace = dst == src;
- if (inPlace) {
- tmpDest = new float[dstIndex + count];
- }
-
- for (int i = 0 ; i < count ; i += 2) {
- // just in case we are doing in place, we better put this in temp vars
- float x = mValues[0] * src[i + srcIndex] +
- mValues[1] * src[i + srcIndex + 1] +
- mValues[2];
- float y = mValues[3] * src[i + srcIndex] +
- mValues[4] * src[i + srcIndex + 1] +
- mValues[5];
-
- tmpDest[i + dstIndex] = x;
- tmpDest[i + dstIndex + 1] = y;
- }
-
- if (inPlace) {
- System.arraycopy(tmpDest, dstIndex, dst, dstIndex, count);
- }
- }
-
- /**
- * Apply this matrix to the array of 2D points, and write the transformed
- * points back into the array
- *
- * @param pts The array [x0, y0, x1, y1, ...] of points to transform.
- */
-
- private void mapPoints(float[] pts) {
- mapPoints(pts, 0, pts, 0, pts.length >> 1);
- }
-
- private void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount) {
- if (hasPerspective()) {
- // transform the (0,0) point
- float[] origin = new float[] { 0.f, 0.f};
- mapPoints(origin);
-
- // translate the vector data as points
- mapPoints(dst, dstIndex, src, srcIndex, ptCount);
-
- // then substract the transformed origin.
- final int count = ptCount * 2;
- for (int i = 0 ; i < count ; i += 2) {
- dst[dstIndex + i] = dst[dstIndex + i] - origin[0];
- dst[dstIndex + i + 1] = dst[dstIndex + i + 1] - origin[1];
- }
- } else {
- // make a copy of the matrix
- Matrix_Delegate copy = new Matrix_Delegate(mValues);
-
- // remove the translation
- setTranslate(copy.mValues, 0, 0);
-
- // map the content as points.
- copy.mapPoints(dst, dstIndex, src, srcIndex, ptCount);
- }
- }
-
- /**
- * multiply two matrices and store them in a 3rd.
- * <p/>This in effect does dest = a*b
- * dest cannot be the same as a or b.
- */
- /*package*/ static void multiply(float dest[], float[] a, float[] b) {
- // first row
- dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6];
- dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7];
- dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8];
-
- // 2nd row
- dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6];
- dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7];
- dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8];
-
- // 3rd row
- dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6];
- dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7];
- dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8];
- }
-
- /**
- * Returns a matrix that represents a given translate
- * @param dx
- * @param dy
- * @return
- */
- /*package*/ static float[] getTranslate(float dx, float dy) {
- return setTranslate(new float[9], dx, dy);
- }
-
- /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) {
- dest[0] = 1;
- dest[1] = 0;
- dest[2] = dx;
- dest[3] = 0;
- dest[4] = 1;
- dest[5] = dy;
- dest[6] = 0;
- dest[7] = 0;
- dest[8] = 1;
- return dest;
- }
-
- /*package*/ static float[] getScale(float sx, float sy) {
- return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 };
- }
-
- /**
- * Returns a matrix that represents the given scale info.
- * @param sx
- * @param sy
- * @param px
- * @param py
- */
- /*package*/ static float[] getScale(float sx, float sy, float px, float py) {
- float[] tmp = new float[9];
- float[] tmp2 = new float[9];
-
- // TODO: do it in one pass
-
- // translate tmp so that the pivot is in 0,0
- setTranslate(tmp, -px, -py);
-
- // scale into tmp2
- multiply(tmp2, tmp, getScale(sx, sy));
-
- // translate back the pivot back into tmp
- multiply(tmp, tmp2, getTranslate(px, py));
-
- return tmp;
- }
-
-
- /*package*/ static float[] getRotate(float degrees) {
- double rad = Math.toRadians(degrees);
- float sin = (float)Math.sin(rad);
- float cos = (float)Math.cos(rad);
-
- return getRotate(sin, cos);
- }
-
- /*package*/ static float[] getRotate(float sin, float cos) {
- return setRotate(new float[9], sin, cos);
- }
-
- /*package*/ static float[] setRotate(float[] dest, float degrees) {
- double rad = Math.toRadians(degrees);
- float sin = (float)Math.sin(rad);
- float cos = (float)Math.cos(rad);
-
- return setRotate(dest, sin, cos);
- }
-
- /*package*/ static float[] setRotate(float[] dest, float sin, float cos) {
- dest[0] = cos;
- dest[1] = -sin;
- dest[2] = 0;
- dest[3] = sin;
- dest[4] = cos;
- dest[5] = 0;
- dest[6] = 0;
- dest[7] = 0;
- dest[8] = 1;
- return dest;
- }
-
- /*package*/ static float[] getRotate(float degrees, float px, float py) {
- float[] tmp = new float[9];
- float[] tmp2 = new float[9];
-
- // TODO: do it in one pass
-
- // translate so that the pivot is in 0,0
- setTranslate(tmp, -px, -py);
-
- // rotate into tmp2
- double rad = Math.toRadians(degrees);
- float cos = (float)Math.cos(rad);
- float sin = (float)Math.sin(rad);
- multiply(tmp2, tmp, getRotate(sin, cos));
-
- // translate back the pivot back into tmp
- multiply(tmp, tmp2, getTranslate(px, py));
-
- return tmp;
- }
-
- /*package*/ static float[] getSkew(float kx, float ky) {
- return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 };
- }
-
- /*package*/ static float[] getSkew(float kx, float ky, float px, float py) {
- float[] tmp = new float[9];
- float[] tmp2 = new float[9];
-
- // TODO: do it in one pass
-
- // translate so that the pivot is in 0,0
- setTranslate(tmp, -px, -py);
-
- // skew into tmp2
- multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 });
- // translate back the pivot back into tmp
- multiply(tmp, tmp2, getTranslate(px, py));
-
- return tmp;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.impl.GcSnapshot;
-import com.android.ninepatch.NinePatchChunk;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.drawable.NinePatchDrawable;
-
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.lang.ref.SoftReference;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Delegate implementing the native methods of android.graphics.NinePatch
- *
- * Through the layoutlib_create tool, the original native methods of NinePatch have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
- * around to map int to instance of the delegate.
- *
- */
-public final class NinePatch_Delegate {
-
- // ---- delegate manager ----
- private static final DelegateManager<NinePatch_Delegate> sManager =
- new DelegateManager<NinePatch_Delegate>(NinePatch_Delegate.class);
-
- // ---- delegate helper data ----
- /**
- * Cache map for {@link NinePatchChunk}.
- * When the chunks are created they are serialized into a byte[], and both are put
- * in the cache, using a {@link SoftReference} for the chunk. The default Java classes
- * for {@link NinePatch} and {@link NinePatchDrawable} only reference to the byte[] data, and
- * provide this for drawing.
- * Using the cache map allows us to not have to deserialize the byte[] back into a
- * {@link NinePatchChunk} every time a rendering is done.
- */
- private final static Map<byte[], SoftReference<NinePatchChunk>> sChunkCache =
- new HashMap<byte[], SoftReference<NinePatchChunk>>();
-
- // ---- delegate data ----
- private byte[] chunk;
-
-
- // ---- Public Helper methods ----
-
- /**
- * Serializes the given chunk.
- *
- * @return the serialized data for the chunk.
- */
- public static byte[] serialize(NinePatchChunk chunk) {
- // serialize the chunk to get a byte[]
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = null;
- try {
- oos = new ObjectOutputStream(baos);
- oos.writeObject(chunk);
- } catch (IOException e) {
- Bridge.getLog().error(null, "Failed to serialize NinePatchChunk.", e, null /*data*/);
- return null;
- } finally {
- if (oos != null) {
- try {
- oos.close();
- } catch (IOException ignored) {
- }
- }
- }
-
- // get the array and add it to the cache
- byte[] array = baos.toByteArray();
- sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk));
- return array;
- }
-
- /**
- * Returns a {@link NinePatchChunk} object for the given serialized representation.
- *
- * If the chunk is present in the cache then the object from the cache is returned, otherwise
- * the array is deserialized into a {@link NinePatchChunk} object.
- *
- * @param array the serialized representation of the chunk.
- * @return the NinePatchChunk or null if deserialization failed.
- */
- public static NinePatchChunk getChunk(byte[] array) {
- SoftReference<NinePatchChunk> chunkRef = sChunkCache.get(array);
- NinePatchChunk chunk = chunkRef.get();
- if (chunk == null) {
- ByteArrayInputStream bais = new ByteArrayInputStream(array);
- ObjectInputStream ois = null;
- try {
- ois = new ObjectInputStream(bais);
- chunk = (NinePatchChunk) ois.readObject();
-
- // put back the chunk in the cache
- if (chunk != null) {
- sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk));
- }
- } catch (IOException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to deserialize NinePatchChunk content.", e, null /*data*/);
- return null;
- } catch (ClassNotFoundException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to deserialize NinePatchChunk class.", e, null /*data*/);
- return null;
- } finally {
- if (ois != null) {
- try {
- ois.close();
- } catch (IOException ignored) {
- }
- }
- }
- }
-
- return chunk;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static boolean isNinePatchChunk(byte[] chunk) {
- NinePatchChunk chunkObject = getChunk(chunk);
- return chunkObject != null;
-
- }
-
- @LayoutlibDelegate
- /*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.
- NinePatch_Delegate newDelegate = new NinePatch_Delegate();
- newDelegate.chunk = chunk;
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeFinalize(long chunk) {
- sManager.removeJavaReferenceFor(chunk);
- }
-
-
- @LayoutlibDelegate
- /*package*/ static long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location) {
- return 0;
- }
-
- static byte[] getChunk(long nativeNinePatch) {
- NinePatch_Delegate delegate = sManager.getDelegate(nativeNinePatch);
- if (delegate != null) {
- return delegate.chunk;
- }
- return null;
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.PaintFlagsDrawFilter
- *
- * Through the layoutlib_create tool, the original native methods of PaintFlagsDrawFilter have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original PaintFlagsDrawFilter class.
- *
- * Because this extends {@link DrawFilter_Delegate}, there's no need to use a
- * {@link DelegateManager}, as all the DrawFilter classes will be added to the manager owned by
- * {@link DrawFilter_Delegate}.
- *
- * @see DrawFilter_Delegate
- *
- */
-public class PaintFlagsDrawFilter_Delegate extends DrawFilter_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Paint Flags Draw Filters are not supported.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeConstructor(int clearBits, int setBits) {
- PaintFlagsDrawFilter_Delegate newDelegate = new PaintFlagsDrawFilter_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.graphics.FontFamily_Delegate.FontVariant;
-import android.graphics.Paint.FontMetrics;
-import android.graphics.Paint.FontMetricsInt;
-import android.text.TextUtils;
-
-import java.awt.BasicStroke;
-import java.awt.Font;
-import java.awt.Shape;
-import java.awt.Stroke;
-import java.awt.Toolkit;
-import java.awt.geom.AffineTransform;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-
-import libcore.util.NativeAllocationRegistry_Delegate;
-
-/**
- * Delegate implementing the native methods of android.graphics.Paint
- *
- * Through the layoutlib_create tool, the original native methods of Paint have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original Paint class.
- *
- * @see DelegateManager
- *
- */
-public class Paint_Delegate {
-
- /**
- * Class associating a {@link Font} and its {@link java.awt.FontMetrics}.
- */
- /*package*/ static final class FontInfo {
- Font mFont;
- java.awt.FontMetrics mMetrics;
- }
-
- // ---- delegate manager ----
- private static final DelegateManager<Paint_Delegate> sManager =
- new DelegateManager<Paint_Delegate>(Paint_Delegate.class);
- private static long sFinalizer = -1;
-
- // ---- delegate helper data ----
-
- // This list can contain null elements.
- private List<FontInfo> mFonts;
-
- // ---- delegate data ----
- private int mFlags;
- private int mColor;
- private int mStyle;
- private int mCap;
- private int mJoin;
- private int mTextAlign;
- private Typeface_Delegate mTypeface;
- private float mStrokeWidth;
- private float mStrokeMiter;
- private float mTextSize;
- private float mTextScaleX;
- private float mTextSkewX;
- private int mHintingMode = Paint.HINTING_ON;
- private int mHyphenEdit;
- private float mLetterSpacing; // not used in actual text rendering.
- private float mWordSpacing; // 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;
-
- private int mPorterDuffMode = Xfermode.DEFAULT;
- private ColorFilter_Delegate mColorFilter;
- private Shader_Delegate mShader;
- private PathEffect_Delegate mPathEffect;
- private MaskFilter_Delegate mMaskFilter;
-
- private Locale mLocale = Locale.getDefault();
-
- // Used only to assert invariants.
- public long mNativeTypeface;
-
- // ---- Public Helper methods ----
-
- @Nullable
- public static Paint_Delegate getDelegate(long native_paint) {
- return sManager.getDelegate(native_paint);
- }
-
- /**
- * Returns the list of {@link Font} objects.
- */
- public List<FontInfo> getFonts() {
- return mFonts;
- }
-
- public boolean isAntiAliased() {
- return (mFlags & Paint.ANTI_ALIAS_FLAG) != 0;
- }
-
- public boolean isFilterBitmap() {
- return (mFlags & Paint.FILTER_BITMAP_FLAG) != 0;
- }
-
- public int getStyle() {
- return mStyle;
- }
-
- public int getColor() {
- return mColor;
- }
-
- public int getAlpha() {
- return mColor >>> 24;
- }
-
- public void setAlpha(int alpha) {
- mColor = (alpha << 24) | (mColor & 0x00FFFFFF);
- }
-
- public int getTextAlign() {
- return mTextAlign;
- }
-
- public float getStrokeWidth() {
- return mStrokeWidth;
- }
-
- /**
- * returns the value of stroke miter needed by the java api.
- */
- public float getJavaStrokeMiter() {
- return mStrokeMiter;
- }
-
- public int getJavaCap() {
- switch (Paint.sCapArray[mCap]) {
- case BUTT:
- return BasicStroke.CAP_BUTT;
- case ROUND:
- return BasicStroke.CAP_ROUND;
- default:
- case SQUARE:
- return BasicStroke.CAP_SQUARE;
- }
- }
-
- public int getJavaJoin() {
- switch (Paint.sJoinArray[mJoin]) {
- default:
- case MITER:
- return BasicStroke.JOIN_MITER;
- case ROUND:
- return BasicStroke.JOIN_ROUND;
- case BEVEL:
- return BasicStroke.JOIN_BEVEL;
- }
- }
-
- public Stroke getJavaStroke() {
- if (mPathEffect != null) {
- if (mPathEffect.isSupported()) {
- Stroke stroke = mPathEffect.getStroke(this);
- assert stroke != null;
- if (stroke != null) {
- return stroke;
- }
- } else {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_PATHEFFECT,
- mPathEffect.getSupportMessage(),
- null, null /*data*/);
- }
- }
-
- // if no custom stroke as been set, set the default one.
- return new BasicStroke(
- getStrokeWidth(),
- getJavaCap(),
- getJavaJoin(),
- getJavaStrokeMiter());
- }
-
- /**
- * Returns the {@link PorterDuff.Mode} as an int
- */
- public int getPorterDuffMode() {
- return mPorterDuffMode;
- }
-
- /**
- * Returns the {@link ColorFilter} delegate or null if none have been set
- *
- * @return the delegate or null.
- */
- public ColorFilter_Delegate getColorFilter() {
- return mColorFilter;
- }
-
- public void setColorFilter(long colorFilterPtr) {
- mColorFilter = ColorFilter_Delegate.getDelegate(colorFilterPtr);
- }
-
- public void setShader(long shaderPtr) {
- mShader = Shader_Delegate.getDelegate(shaderPtr);
- }
-
- /**
- * Returns the {@link Shader} delegate or null if none have been set
- *
- * @return the delegate or null.
- */
- public Shader_Delegate getShader() {
- return mShader;
- }
-
- /**
- * Returns the {@link MaskFilter} delegate or null if none have been set
- *
- * @return the delegate or null.
- */
- public MaskFilter_Delegate getMaskFilter() {
- return mMaskFilter;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static int nGetFlags(long nativePaint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mFlags;
- }
-
-
-
- @LayoutlibDelegate
- /*package*/ static void nSetFlags(long nativePaint, int flags) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- delegate.mFlags = flags;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetFilterBitmap(long nativePaint, boolean filter) {
- setFlag(nativePaint, Paint.FILTER_BITMAP_FLAG, filter);
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetHinting(long nativePaint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return Paint.HINTING_ON;
- }
-
- return delegate.mHintingMode;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetHinting(long nativePaint, int mode) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- delegate.mHintingMode = mode;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetAntiAlias(long nativePaint, boolean aa) {
- setFlag(nativePaint, Paint.ANTI_ALIAS_FLAG, aa);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetSubpixelText(long nativePaint,
- boolean subpixelText) {
- setFlag(nativePaint, Paint.SUBPIXEL_TEXT_FLAG, subpixelText);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetUnderlineText(long nativePaint,
- boolean underlineText) {
- setFlag(nativePaint, Paint.UNDERLINE_TEXT_FLAG, underlineText);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetStrikeThruText(long nativePaint,
- boolean strikeThruText) {
- setFlag(nativePaint, Paint.STRIKE_THRU_TEXT_FLAG, strikeThruText);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetFakeBoldText(long nativePaint,
- boolean fakeBoldText) {
- setFlag(nativePaint, Paint.FAKE_BOLD_TEXT_FLAG, fakeBoldText);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetDither(long nativePaint, boolean dither) {
- setFlag(nativePaint, Paint.DITHER_FLAG, dither);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetLinearText(long nativePaint, boolean linearText) {
- setFlag(nativePaint, Paint.LINEAR_TEXT_FLAG, linearText);
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetColor(long nativePaint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mColor;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetColor(long nativePaint, int color) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- delegate.mColor = color;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetAlpha(long nativePaint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.getAlpha();
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetAlpha(long nativePaint, int a) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- delegate.setAlpha(a);
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetStrokeWidth(long nativePaint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 1.f;
- }
-
- return delegate.mStrokeWidth;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetStrokeWidth(long nativePaint, float width) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- delegate.mStrokeWidth = width;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetStrokeMiter(long nativePaint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 1.f;
- }
-
- return delegate.mStrokeMiter;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetStrokeMiter(long nativePaint, float miter) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- delegate.mStrokeMiter = miter;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetShadowLayer(long paint, float radius, float dx, float dy,
- int color) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.setShadowLayer is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nHasShadowLayer(long paint) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.hasShadowLayer is not supported.", null, null /*data*/);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nIsElegantTextHeight(long nativePaint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- return delegate != null && delegate.mFontVariant == FontVariant.ELEGANT;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetElegantTextHeight(long nativePaint,
- boolean elegant) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- delegate.mFontVariant = elegant ? FontVariant.ELEGANT : FontVariant.COMPACT;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetTextSize(long nativePaint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 1.f;
- }
-
- return delegate.mTextSize;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetTextSize(long nativePaint, float textSize) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- if (delegate.mTextSize != textSize) {
- delegate.mTextSize = textSize;
- delegate.updateFontObject();
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetTextScaleX(long nativePaint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 1.f;
- }
-
- return delegate.mTextScaleX;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetTextScaleX(long nativePaint, float scaleX) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- if (delegate.mTextScaleX != scaleX) {
- delegate.mTextScaleX = scaleX;
- delegate.updateFontObject();
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetTextSkewX(long nativePaint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 1.f;
- }
-
- return delegate.mTextSkewX;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetTextSkewX(long nativePaint, float skewX) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- if (delegate.mTextSkewX != skewX) {
- delegate.mTextSkewX = skewX;
- delegate.updateFontObject();
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static float nAscent(long nativePaint, long nativeTypeface) {
- // get the delegate
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
-
- if (delegate.mFonts.size() > 0) {
- java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
- // Android expects negative ascent so we invert the value from Java.
- return - javaMetrics.getAscent();
- }
-
- return 0;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nDescent(long nativePaint, long nativeTypeface) {
- // get the delegate
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
-
- if (delegate.mFonts.size() > 0) {
- java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
- return javaMetrics.getDescent();
- }
-
- return 0;
-
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetFontMetrics(long nativePaint, long nativeTypeface,
- FontMetrics metrics) {
- // get the delegate
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.getFontMetrics(metrics);
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetFontMetricsInt(long nativePaint,
- long nativeTypeface, FontMetricsInt fmi) {
- // get the delegate
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
-
- if (delegate.mFonts.size() > 0) {
- java.awt.FontMetrics javaMetrics = delegate.mFonts.get(0).mMetrics;
- if (fmi != null) {
- // Android expects negative ascent so we invert the value from Java.
- fmi.top = (int)(- javaMetrics.getMaxAscent() * 1.15);
- fmi.ascent = - javaMetrics.getAscent();
- fmi.descent = javaMetrics.getDescent();
- fmi.bottom = (int)(javaMetrics.getMaxDescent() * 1.15);
- fmi.leading = javaMetrics.getLeading();
- }
-
- return javaMetrics.getHeight();
- }
-
- return 0;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, char[] text,
- int index, int count, float maxWidth, int bidiFlags, float[] measuredWidth) {
-
- // get the delegate
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
-
- int inc = count > 0 ? 1 : -1;
-
- int measureIndex = 0;
- for (int i = index; i != index + count; i += inc, measureIndex++) {
- int start, end;
- if (i < index) {
- start = i;
- end = index;
- } else {
- start = index;
- end = i;
- }
-
- // measure from start to end
- RectF bounds = delegate.measureText(text, start, end - start + 1, null, 0, bidiFlags);
- float res = bounds.right - bounds.left;
-
- if (measuredWidth != null) {
- measuredWidth[measureIndex] = res;
- }
-
- if (res > maxWidth) {
- // we should not return this char index, but since it's 0-based
- // and we need to return a count, we simply return measureIndex;
- return measureIndex;
- }
-
- }
-
- return measureIndex;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nBreakText(long nativePaint, long nativeTypeface, String text,
- boolean measureForwards,
- float maxWidth, int bidiFlags, float[] measuredWidth) {
- return nBreakText(nativePaint, nativeTypeface, text.toCharArray(), 0, text.length(),
- maxWidth, bidiFlags, measuredWidth);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nInit() {
- Paint_Delegate newDelegate = new Paint_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nInitWithPaint(long paint) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(paint);
- if (delegate == null) {
- return 0;
- }
-
- Paint_Delegate newDelegate = new Paint_Delegate(delegate);
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nReset(long native_object) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return;
- }
-
- delegate.reset();
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSet(long native_dst, long native_src) {
- // get the delegate from the native int.
- Paint_Delegate delegate_dst = sManager.getDelegate(native_dst);
- if (delegate_dst == null) {
- return;
- }
-
- // get the delegate from the native int.
- Paint_Delegate delegate_src = sManager.getDelegate(native_src);
- if (delegate_src == null) {
- return;
- }
-
- delegate_dst.set(delegate_src);
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetStyle(long native_object) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mStyle;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetStyle(long native_object, int style) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return;
- }
-
- delegate.mStyle = style;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetStrokeCap(long native_object) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mCap;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetStrokeCap(long native_object, int cap) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return;
- }
-
- delegate.mCap = cap;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetStrokeJoin(long native_object) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mJoin;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetStrokeJoin(long native_object, int join) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return;
- }
-
- delegate.mJoin = join;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nGetFillPath(long native_object, long src, long dst) {
- Paint_Delegate paint = sManager.getDelegate(native_object);
- if (paint == null) {
- return false;
- }
-
- Path_Delegate srcPath = Path_Delegate.getDelegate(src);
- if (srcPath == null) {
- return true;
- }
-
- Path_Delegate dstPath = Path_Delegate.getDelegate(dst);
- if (dstPath == null) {
- return true;
- }
-
- Stroke stroke = paint.getJavaStroke();
- Shape strokeShape = stroke.createStrokedShape(srcPath.getJavaShape());
-
- dstPath.setJavaShape(strokeShape);
-
- // FIXME figure out the return value?
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static long nSetShader(long native_object, long shader) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return shader;
- }
-
- delegate.mShader = Shader_Delegate.getDelegate(shader);
-
- return shader;
- }
-
- @LayoutlibDelegate
- /*package*/ static long nSetColorFilter(long native_object, long filter) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return filter;
- }
-
- delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);
-
- // Log warning if it's not supported.
- if (delegate.mColorFilter != null && !delegate.mColorFilter.isSupported()) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
- delegate.mColorFilter.getSupportMessage(), null, null /*data*/);
- }
-
- return filter;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetXfermode(long native_object, int xfermode) {
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return;
- }
- delegate.mPorterDuffMode = xfermode;
- }
-
- @LayoutlibDelegate
- /*package*/ static long nSetPathEffect(long native_object, long effect) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return effect;
- }
-
- delegate.mPathEffect = PathEffect_Delegate.getDelegate(effect);
-
- return effect;
- }
-
- @LayoutlibDelegate
- /*package*/ static long nSetMaskFilter(long native_object, long maskfilter) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return maskfilter;
- }
-
- delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter);
-
- // since none of those are supported, display a fidelity warning right away
- if (delegate.mMaskFilter != null && !delegate.mMaskFilter.isSupported()) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
- delegate.mMaskFilter.getSupportMessage(), null, null /*data*/);
- }
-
- return maskfilter;
- }
-
- @LayoutlibDelegate
- /*package*/ static long nSetTypeface(long native_object, long typeface) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return 0;
- }
-
- Typeface_Delegate typefaceDelegate = Typeface_Delegate.getDelegate(typeface);
- if (delegate.mTypeface != typefaceDelegate || delegate.mNativeTypeface != typeface) {
- delegate.mTypeface = Typeface_Delegate.getDelegate(typeface);
- delegate.mNativeTypeface = typeface;
- delegate.updateFontObject();
- }
- return typeface;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetTextAlign(long native_object) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mTextAlign;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetTextAlign(long native_object, int align) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return;
- }
-
- delegate.mTextAlign = align;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nSetTextLocales(long native_object, String locale) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return 0;
- }
-
- delegate.setTextLocale(locale);
- return 0;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetTextLocalesByMinikinLangListId(long paintPtr,
- int mMinikinLangListId) {
- // FIXME
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetTextAdvances(long native_object, long native_typeface,
- char[] text, int index, int count, int contextIndex, int contextCount,
- int bidiFlags, float[] advances, int advancesIndex) {
-
- if (advances != null)
- for (int i = advancesIndex; i< advancesIndex+count; i++)
- advances[i]=0;
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(native_object);
- if (delegate == null) {
- return 0.f;
- }
-
- // native_typeface is passed here since Framework's old implementation did not have the
- // typeface object associated with the Paint. Since, we follow the new framework way,
- // we store the typeface with the paint and use it directly.
- assert (native_typeface == delegate.mNativeTypeface);
-
- RectF bounds = delegate.measureText(text, index, count, advances, advancesIndex, bidiFlags);
- return bounds.right - bounds.left;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetTextAdvances(long native_object, long native_typeface,
- String text, int start, int end, int contextStart, int contextEnd,
- int bidiFlags, float[] advances, int advancesIndex) {
- // FIXME: support contextStart and contextEnd
- int count = end - start;
- char[] buffer = TemporaryBuffer.obtain(count);
- TextUtils.getChars(text, start, end, buffer, 0);
-
- return nGetTextAdvances(native_object, native_typeface, buffer, 0, count,
- contextStart, contextEnd - contextStart, bidiFlags, advances, advancesIndex);
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, long typefacePtr,
- char[] text, int contextStart, int contextLength, int flags, int offset,
- int cursorOpt) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.getTextRunCursor is not supported.", null, null /*data*/);
- return 0;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetTextRunCursor(Paint paint, long native_object, long typefacePtr,
- String text, int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.getTextRunCursor is not supported.", null, null /*data*/);
- return 0;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nGetTextPath(long native_object, long native_typeface,
- int bidiFlags, char[] text, int index, int count, float x, float y, long path) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.getTextPath is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nGetTextPath(long native_object, long native_typeface,
- int bidiFlags, String text, int start, int end, float x, float y, long path) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Paint.getTextPath is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nGetStringBounds(long nativePaint, long native_typeface,
- String text, int start, int end, int bidiFlags, Rect bounds) {
- nGetCharArrayBounds(nativePaint, native_typeface, text.toCharArray(), start,
- end - start, bidiFlags, bounds);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nGetCharArrayBounds(long nativePaint, long native_typeface,
- char[] text, int index, int count, int bidiFlags, Rect bounds) {
-
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- // assert that the typeface passed is actually the one that we had stored.
- assert (native_typeface == delegate.mNativeTypeface);
-
- delegate.measureText(text, index, count, null, 0, bidiFlags).roundOut(bounds);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nGetNativeFinalizer() {
- synchronized (Paint_Delegate.class) {
- if (sFinalizer == -1) {
- sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(
- sManager::removeJavaReferenceFor);
- }
- }
- return sFinalizer;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetLetterSpacing(long nativePaint) {
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
- return delegate.mLetterSpacing;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetLetterSpacing(long nativePaint, float letterSpacing) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
- "Paint.setLetterSpacing() not supported.", null, null);
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
- delegate.mLetterSpacing = letterSpacing;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetWordSpacing(long nativePaint) {
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
- return delegate.mWordSpacing;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetWordSpacing(long nativePaint, float wordSpacing) {
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
- delegate.mWordSpacing = wordSpacing;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetFontFeatureSettings(long nativePaint, String settings) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
- "Paint.setFontFeatureSettings() not supported.", null, null);
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetHyphenEdit(long nativePaint) {
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return 0;
- }
- return delegate.mHyphenEdit;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetHyphenEdit(long nativePaint, int hyphen) {
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
- delegate.mHyphenEdit = hyphen;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nHasGlyph(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 nGetRunAdvance(long nativePaint, long nativeTypeface,
- @NonNull char[] text, int start, int end, int contextStart, int contextEnd,
- boolean isRtl, int offset) {
- int count = end - start;
- float[] advances = new float[count];
- int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
- nGetTextAdvances(nativePaint, nativeTypeface, text, start, count,
- contextStart, contextEnd - contextStart, bidiFlags, advances, 0);
- int startOffset = offset - start; // offset from start.
- float sum = 0;
- for (int i = 0; i < startOffset; i++) {
- sum += advances[i];
- }
- return sum;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetOffsetForAdvance(long nativePaint, long nativeTypeface,
- char[] text, int start, int end, int contextStart, int contextEnd, boolean isRtl,
- float advance) {
- int count = end - start;
- float[] advances = new float[count];
- int bidiFlags = isRtl ? Paint.BIDI_FORCE_RTL : Paint.BIDI_FORCE_LTR;
- nGetTextAdvances(nativePaint, nativeTypeface, text, start, count,
- contextStart, contextEnd - contextStart, bidiFlags, advances, 0);
- float sum = 0;
- int i;
- for (i = 0; i < count && sum < advance; i++) {
- sum += advances[i];
- }
- float distanceToI = sum - advance;
- float distanceToIMinus1 = advance - (sum - advances[i]);
- return distanceToI > distanceToIMinus1 ? i : i - 1;
- }
-
- // ---- Private delegate/helper methods ----
-
- /*package*/ Paint_Delegate() {
- reset();
- }
-
- private Paint_Delegate(Paint_Delegate paint) {
- set(paint);
- }
-
- private void set(Paint_Delegate paint) {
- mFlags = paint.mFlags;
- mColor = paint.mColor;
- mStyle = paint.mStyle;
- mCap = paint.mCap;
- mJoin = paint.mJoin;
- mTextAlign = paint.mTextAlign;
-
- boolean needsFontUpdate = false;
- if (mTypeface != paint.mTypeface || mNativeTypeface != paint.mNativeTypeface) {
- mTypeface = paint.mTypeface;
- mNativeTypeface = paint.mNativeTypeface;
- needsFontUpdate = true;
- }
-
- if (mTextSize != paint.mTextSize) {
- mTextSize = paint.mTextSize;
- needsFontUpdate = true;
- }
-
- if (mTextScaleX != paint.mTextScaleX) {
- mTextScaleX = paint.mTextScaleX;
- needsFontUpdate = true;
- }
-
- if (mTextSkewX != paint.mTextSkewX) {
- mTextSkewX = paint.mTextSkewX;
- needsFontUpdate = true;
- }
-
- mStrokeWidth = paint.mStrokeWidth;
- mStrokeMiter = paint.mStrokeMiter;
- mPorterDuffMode = paint.mPorterDuffMode;
- mColorFilter = paint.mColorFilter;
- mShader = paint.mShader;
- mPathEffect = paint.mPathEffect;
- mMaskFilter = paint.mMaskFilter;
- mHintingMode = paint.mHintingMode;
-
- if (needsFontUpdate) {
- updateFontObject();
- }
- }
-
- private void reset() {
- mFlags = Paint.HIDDEN_DEFAULT_PAINT_FLAGS;
- mColor = 0xFF000000;
- mStyle = Paint.Style.FILL.nativeInt;
- mCap = Paint.Cap.BUTT.nativeInt;
- mJoin = Paint.Join.MITER.nativeInt;
- mTextAlign = 0;
- mTypeface = Typeface_Delegate.getDelegate(Typeface.sDefaults[0].native_instance);
- mNativeTypeface = 0;
- mStrokeWidth = 1.f;
- mStrokeMiter = 4.f;
- mTextSize = 20.f;
- mTextScaleX = 1.f;
- mTextSkewX = 0.f;
- mPorterDuffMode = Xfermode.DEFAULT;
- mColorFilter = null;
- mShader = null;
- mPathEffect = null;
- mMaskFilter = null;
- updateFontObject();
- mHintingMode = Paint.HINTING_ON;
- }
-
- /**
- * Update the {@link Font} object from the typeface, text size and scaling
- */
- @SuppressWarnings("deprecation")
- private void updateFontObject() {
- if (mTypeface != null) {
- // Get the fonts from the TypeFace object.
- List<Font> fonts = mTypeface.getFonts(mFontVariant);
-
- if (fonts.isEmpty()) {
- mFonts = Collections.emptyList();
- return;
- }
-
- // create new font objects as well as FontMetrics, based on the current text size
- // and skew info.
- int nFonts = fonts.size();
- ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(nFonts);
- //noinspection ForLoopReplaceableByForEach (avoid iterator instantiation)
- for (int i = 0; i < nFonts; i++) {
- Font font = fonts.get(i);
- if (font == null) {
- // If the font is null, add null to infoList. When rendering the text, if this
- // null is reached, a warning will be logged.
- infoList.add(null);
- continue;
- }
- FontInfo info = new FontInfo();
- info.mFont = font.deriveFont(mTextSize);
- if (mTextScaleX != 1.0 || mTextSkewX != 0) {
- // TODO: support skew
- info.mFont = info.mFont.deriveFont(new AffineTransform(
- mTextScaleX, mTextSkewX, 0, 1, 0, 0));
- }
- // The metrics here don't have anti-aliasing set.
- info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont);
-
- infoList.add(info);
- }
-
- mFonts = Collections.unmodifiableList(infoList);
- }
- }
-
- /*package*/ RectF measureText(char[] text, int index, int count, float[] advances,
- int advancesIndex, int bidiFlags) {
- return new BidiRenderer(null, this, text)
- .renderText(index, index + count, bidiFlags, advances, advancesIndex, false);
- }
-
- /*package*/ RectF measureText(char[] text, int index, int count, float[] advances,
- int advancesIndex, boolean isRtl) {
- return new BidiRenderer(null, this, text)
- .renderText(index, index + count, isRtl, advances, advancesIndex, false);
- }
-
- private float getFontMetrics(FontMetrics metrics) {
- if (mFonts.size() > 0) {
- java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics;
- if (metrics != null) {
- // Android expects negative ascent so we invert the value from Java.
- metrics.top = - javaMetrics.getMaxAscent();
- metrics.ascent = - javaMetrics.getAscent();
- metrics.descent = javaMetrics.getDescent();
- metrics.bottom = javaMetrics.getMaxDescent();
- metrics.leading = javaMetrics.getLeading();
- }
-
- return javaMetrics.getHeight();
- }
-
- return 0;
- }
-
- private void setTextLocale(String locale) {
- mLocale = new Locale(locale);
- }
-
- private static void setFlag(long nativePaint, int flagMask, boolean flagValue) {
- // get the delegate from the native int.
- Paint_Delegate delegate = sManager.getDelegate(nativePaint);
- if (delegate == null) {
- return;
- }
-
- if (flagValue) {
- delegate.mFlags |= flagMask;
- } else {
- delegate.mFlags &= ~flagMask;
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.Stroke;
-
-/**
- * Delegate implementing the native methods of android.graphics.PathDashPathEffect
- *
- * Through the layoutlib_create tool, the original native methods of PathDashPathEffect have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original PathDashPathEffect class.
- *
- * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager},
- * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}.
- *
- * @see PathEffect_Delegate
- *
- */
-public class PathDashPathEffect_Delegate extends PathEffect_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public Stroke getStroke(Paint_Delegate paint) {
- // FIXME
- return null;
- }
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Path Dash Path Effects are not supported in Layout Preview mode.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate(long native_path, float advance, float phase,
- int native_style) {
- PathDashPathEffect_Delegate newDelegate = new PathDashPathEffect_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.Stroke;
-
-/**
- * Delegate implementing the native methods of android.graphics.PathEffect
- *
- * Through the layoutlib_create tool, the original native methods of PathEffect have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original PathEffect class.
- *
- * This also serve as a base class for all PathEffect delegate classes.
- *
- * @see DelegateManager
- *
- */
-public abstract class PathEffect_Delegate {
-
- // ---- delegate manager ----
- protected static final DelegateManager<PathEffect_Delegate> sManager =
- new DelegateManager<PathEffect_Delegate>(PathEffect_Delegate.class);
-
- // ---- delegate helper data ----
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- public static PathEffect_Delegate getDelegate(long nativeShader) {
- return sManager.getDelegate(nativeShader);
- }
-
- public abstract Stroke getStroke(Paint_Delegate paint);
- public abstract boolean isSupported();
- public abstract String getSupportMessage();
-
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static void nativeDestructor(long native_patheffect) {
- sManager.removeJavaReferenceFor(native_patheffect);
- }
-
- // ---- Private delegate/helper methods ----
-
-}
+++ /dev/null
-/*
- * 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.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.util.CachedPathIteratorFactory;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import com.android.layoutlib.bridge.util.CachedPathIteratorFactory.CachedPathIterator;
-
-import java.awt.geom.PathIterator;
-
-/**
- * Delegate implementing the native methods of {@link android.graphics.PathMeasure}
- * <p/>
- * Through the layoutlib_create tool, the original native methods of PathMeasure have been
- * replaced by
- * calls to methods of the same name in this delegate class.
- * <p/>
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between it
- * and the original PathMeasure class.
- *
- * @see DelegateManager
- */
-public final class PathMeasure_Delegate {
-
- // ---- delegate manager ----
- private static final DelegateManager<PathMeasure_Delegate> sManager =
- new DelegateManager<PathMeasure_Delegate>(PathMeasure_Delegate.class);
-
- // ---- delegate data ----
- private CachedPathIteratorFactory mOriginalPathIterator;
-
- private long mNativePath;
-
-
- private PathMeasure_Delegate(long native_path, boolean forceClosed) {
- mNativePath = native_path;
- if (native_path != 0) {
- if (forceClosed) {
- // Copy the path and call close
- native_path = Path_Delegate.nInit(native_path);
- Path_Delegate.nClose(native_path);
- }
-
- Path_Delegate pathDelegate = Path_Delegate.getDelegate(native_path);
- mOriginalPathIterator = new CachedPathIteratorFactory(pathDelegate.getJavaShape()
- .getPathIterator(null));
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static long native_create(long native_path, boolean forceClosed) {
- return sManager.addNewDelegate(new PathMeasure_Delegate(native_path, forceClosed));
- }
-
- @LayoutlibDelegate
- /*package*/ static void native_destroy(long native_instance) {
- sManager.removeJavaReferenceFor(native_instance);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean native_getPosTan(long native_instance, float distance, float pos[],
- float tan[]) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "PathMeasure.getPostTan is not supported.", null, null);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean native_getMatrix(long native_instance, float distance, long
- native_matrix, int flags) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "PathMeasure.getMatrix is not supported.", null, null);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean native_nextContour(long native_instance) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "PathMeasure.nextContour is not supported.", null, null);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static void native_setPath(long native_instance, long native_path, boolean
- forceClosed) {
- PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance);
- assert pathMeasure != null;
-
- if (native_path != 0) {
- if (forceClosed) {
- // Copy the path and call close
- native_path = Path_Delegate.nInit(native_path);
- Path_Delegate.nClose(native_path);
- }
-
- Path_Delegate pathDelegate = Path_Delegate.getDelegate(native_path);
- pathMeasure.mOriginalPathIterator = new CachedPathIteratorFactory(pathDelegate.getJavaShape()
- .getPathIterator(null));
- }
-
- pathMeasure.mNativePath = native_path;
- }
-
- @LayoutlibDelegate
- /*package*/ static float native_getLength(long native_instance) {
- PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance);
- assert pathMeasure != null;
-
- if (pathMeasure.mOriginalPathIterator == null) {
- return 0;
- }
-
- return pathMeasure.mOriginalPathIterator.iterator().getTotalLength();
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean native_isClosed(long native_instance) {
- PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance);
- assert pathMeasure != null;
-
- Path_Delegate path = Path_Delegate.getDelegate(pathMeasure.mNativePath);
- if (path == null) {
- return false;
- }
-
- int type = 0;
- float segment[] = new float[6];
- for (PathIterator pi = path.getJavaShape().getPathIterator(null); !pi.isDone(); pi.next()) {
- type = pi.currentSegment(segment);
- }
-
- // A path is a closed path if the last element is SEG_CLOSE
- return type == PathIterator.SEG_CLOSE;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean native_getSegment(long native_instance, float startD, float stopD,
- long native_dst_path, boolean startWithMoveTo) {
- if (startD < 0) {
- startD = 0;
- }
-
- if (startD >= stopD) {
- return false;
- }
-
- PathMeasure_Delegate pathMeasure = sManager.getDelegate(native_instance);
- assert pathMeasure != null;
-
- CachedPathIterator iterator = pathMeasure.mOriginalPathIterator.iterator();
- float accLength = startD;
- boolean isZeroLength = true; // Whether the output has zero length or not
- float[] points = new float[6];
-
- iterator.jumpToSegment(accLength);
- while (!iterator.isDone() && (stopD - accLength > 0.1f)) {
- int type = iterator.currentSegment(points, stopD - accLength);
-
- if (accLength - iterator.getCurrentSegmentLength() <= stopD) {
- if (startWithMoveTo) {
- startWithMoveTo = false;
-
- // If this segment is a MOVETO, then we just use that one. If not, then we issue
- // a first moveto
- if (type != PathIterator.SEG_MOVETO) {
- float[] lastPoint = new float[2];
- iterator.getCurrentSegmentEnd(lastPoint);
- Path_Delegate.nMoveTo(native_dst_path, lastPoint[0], lastPoint[1]);
- }
- }
-
- isZeroLength = isZeroLength && iterator.getCurrentSegmentLength() > 0;
- switch (type) {
- case PathIterator.SEG_MOVETO:
- Path_Delegate.nMoveTo(native_dst_path, points[0], points[1]);
- break;
- case PathIterator.SEG_LINETO:
- Path_Delegate.nLineTo(native_dst_path, points[0], points[1]);
- break;
- case PathIterator.SEG_CLOSE:
- Path_Delegate.nClose(native_dst_path);
- break;
- case PathIterator.SEG_CUBICTO:
- Path_Delegate.nCubicTo(native_dst_path, points[0], points[1],
- points[2], points[3],
- points[4], points[5]);
- break;
- case PathIterator.SEG_QUADTO:
- Path_Delegate.nQuadTo(native_dst_path, points[0], points[1],
- points[2],
- points[3]);
- break;
- default:
- assert false;
- }
- }
-
- accLength += iterator.getCurrentSegmentLength();
- iterator.next();
- }
-
- return !isZeroLength;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.annotation.NonNull;
-import android.graphics.Path.Direction;
-import android.graphics.Path.FillType;
-
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-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;
-import java.awt.geom.RoundRectangle2D;
-import java.util.ArrayList;
-
-/**
- * Delegate implementing the native methods of android.graphics.Path
- *
- * Through the layoutlib_create tool, the original native methods of Path have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original Path class.
- *
- * @see DelegateManager
- *
- */
-public final class Path_Delegate {
-
- // ---- delegate manager ----
- private static final DelegateManager<Path_Delegate> sManager =
- new DelegateManager<Path_Delegate>(Path_Delegate.class);
-
- private static final float EPSILON = 1e-4f;
-
- // ---- delegate data ----
- private FillType mFillType = FillType.WINDING;
- private Path2D mPath = new Path2D.Double();
-
- private float mLastX = 0;
- private float mLastY = 0;
-
- // true if the path contains does not contain a curve or line.
- private boolean mCachedIsEmpty = true;
-
- // ---- Public Helper methods ----
-
- public static Path_Delegate getDelegate(long nPath) {
- return sManager.getDelegate(nPath);
- }
-
- public Path2D getJavaShape() {
- return mPath;
- }
-
- public void setJavaShape(Shape shape) {
- reset();
- mPath.append(shape, false /*connect*/);
- }
-
- public void reset() {
- mPath.reset();
- mLastX = 0;
- mLastY = 0;
- }
-
- public void setPathIterator(PathIterator iterator) {
- reset();
- mPath.append(iterator, false /*connect*/);
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nInit() {
- // create the delegate
- Path_Delegate newDelegate = new Path_Delegate();
-
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nInit(long nPath) {
- // create the delegate
- Path_Delegate newDelegate = new Path_Delegate();
-
- // get the delegate to copy, which could be null if nPath is 0
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate != null) {
- newDelegate.set(pathDelegate);
- }
-
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nReset(long nPath) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.reset();
- }
-
- @LayoutlibDelegate
- /*package*/ static void nRewind(long nPath) {
- // call out to reset since there's nothing to optimize in
- // terms of data structs.
- nReset(nPath);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSet(long native_dst, long nSrc) {
- Path_Delegate pathDstDelegate = sManager.getDelegate(native_dst);
- if (pathDstDelegate == null) {
- return;
- }
-
- Path_Delegate pathSrcDelegate = sManager.getDelegate(nSrc);
- if (pathSrcDelegate == null) {
- return;
- }
-
- pathDstDelegate.set(pathSrcDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nIsConvex(long nPath) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Path.isConvex is not supported.", null, null);
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nGetFillType(long nPath) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return 0;
- }
-
- return pathDelegate.mFillType.nativeInt;
- }
-
- @LayoutlibDelegate
- public static void nSetFillType(long nPath, int ft) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.setFillType(Path.sFillTypeArray[ft]);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nIsEmpty(long nPath) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- return pathDelegate == null || pathDelegate.isEmpty();
-
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nIsRect(long nPath, RectF rect) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return false;
- }
-
- // create an Area that can test if the path is a rect
- Area area = new Area(pathDelegate.mPath);
- if (area.isRectangular()) {
- if (rect != null) {
- pathDelegate.fillBounds(rect);
- }
-
- return true;
- }
-
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nComputeBounds(long nPath, RectF bounds) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.fillBounds(bounds);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nIncReserve(long nPath, int extraPtCount) {
- // since we use a java2D path, there's no way to pre-allocate new points,
- // so we do nothing.
- }
-
- @LayoutlibDelegate
- /*package*/ static void nMoveTo(long nPath, float x, float y) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.moveTo(x, y);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nRMoveTo(long nPath, float dx, float dy) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.rMoveTo(dx, dy);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nLineTo(long nPath, float x, float y) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.lineTo(x, y);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nRLineTo(long nPath, float dx, float dy) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.rLineTo(dx, dy);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nQuadTo(long nPath, float x1, float y1, float x2, float y2) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.quadTo(x1, y1, x2, y2);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nRQuadTo(long nPath, float dx1, float dy1, float dx2, float dy2) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.rQuadTo(dx1, dy1, dx2, dy2);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nCubicTo(long nPath, float x1, float y1,
- float x2, float y2, float x3, float y3) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.cubicTo(x1, y1, x2, y2, x3, y3);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nRCubicTo(long nPath, float x1, float y1,
- float x2, float y2, float x3, float y3) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.rCubicTo(x1, y1, x2, y2, x3, y3);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nArcTo(long nPath, float left, float top, float right,
- float bottom,
- float startAngle, float sweepAngle, boolean forceMoveTo) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.arcTo(left, top, right, bottom, startAngle, sweepAngle, forceMoveTo);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nClose(long nPath) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.close();
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAddRect(long nPath,
- float left, float top, float right, float bottom, int dir) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.addRect(left, top, right, bottom, dir);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAddOval(long nPath, float left, float top, float right,
- float bottom, int dir) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.mPath.append(new Ellipse2D.Float(
- left, top, right - left, bottom - top), false);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAddCircle(long nPath, float x, float y, float radius, int dir) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- // because x/y is the center of the circle, need to offset this by the radius
- pathDelegate.mPath.append(new Ellipse2D.Float(
- x - radius, y - radius, radius * 2, radius * 2), false);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAddArc(long nPath, float left, float top, float right,
- float bottom, float startAngle, float sweepAngle) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- // because x/y is the center of the circle, need to offset this by the radius
- pathDelegate.mPath.append(new Arc2D.Float(
- left, top, right - left, bottom - top,
- -startAngle, -sweepAngle, Arc2D.OPEN), false);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAddRoundRect(long nPath, float left, float top, float right,
- float bottom, float rx, float ry, int dir) {
-
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.mPath.append(new RoundRectangle2D.Float(
- left, top, right - left, bottom - top, rx * 2, ry * 2), false);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAddRoundRect(long nPath, float left, float top, float right,
- float bottom, float[] radii, int dir) {
-
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- float[] cornerDimensions = new float[radii.length];
- for (int i = 0; i < radii.length; i++) {
- cornerDimensions[i] = 2 * radii[i];
- }
- pathDelegate.mPath.append(new RoundRectangle(left, top, right - left, bottom - top,
- cornerDimensions), false);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAddPath(long nPath, long src, float dx, float dy) {
- addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy));
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAddPath(long nPath, long src) {
- addPath(nPath, src, null /*transform*/);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nAddPath(long nPath, long src, long matrix) {
- Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
- if (matrixDelegate == null) {
- return;
- }
-
- addPath(nPath, src, matrixDelegate.getAffineTransform());
- }
-
- @LayoutlibDelegate
- /*package*/ static void nOffset(long nPath, float dx, float dy) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.offset(dx, dy);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetLastPoint(long nPath, float dx, float dy) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- pathDelegate.mLastX = dx;
- pathDelegate.mLastY = dy;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nTransform(long nPath, long matrix,
- long dst_path) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return;
- }
-
- Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix);
- if (matrixDelegate == null) {
- return;
- }
-
- // this can be null if dst_path is 0
- Path_Delegate dstDelegate = sManager.getDelegate(dst_path);
-
- pathDelegate.transform(matrixDelegate, dstDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nTransform(long nPath, long matrix) {
- nTransform(nPath, matrix, 0);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nOp(long nPath1, long nPath2, int op, long result) {
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "Path.op() not supported", null);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nFinalize(long nPath) {
- sManager.removeJavaReferenceFor(nPath);
- }
-
- @LayoutlibDelegate
- /*package*/ static float[] nApproximate(long nPath, float error) {
- Path_Delegate pathDelegate = sManager.getDelegate(nPath);
- if (pathDelegate == null) {
- return null;
- }
- // Get a FlatteningIterator
- PathIterator iterator = pathDelegate.getJavaShape().getPathIterator(null, error);
-
- float segment[] = new float[6];
- float totalLength = 0;
- ArrayList<Point2D.Float> points = new ArrayList<Point2D.Float>();
- Point2D.Float previousPoint = null;
- while (!iterator.isDone()) {
- int type = iterator.currentSegment(segment);
- Point2D.Float currentPoint = new Point2D.Float(segment[0], segment[1]);
- // MoveTo shouldn't affect the length
- if (previousPoint != null && type != PathIterator.SEG_MOVETO) {
- totalLength += currentPoint.distance(previousPoint);
- }
- previousPoint = currentPoint;
- points.add(currentPoint);
- iterator.next();
- }
-
- int nPoints = points.size();
- float[] result = new float[nPoints * 3];
- previousPoint = null;
- for (int i = 0; i < nPoints; i++) {
- Point2D.Float point = points.get(i);
- float distance = previousPoint != null ? (float) previousPoint.distance(point) : .0f;
- result[i * 3] = distance / totalLength;
- result[i * 3 + 1] = point.x;
- result[i * 3 + 2] = point.y;
-
- totalLength += distance;
- previousPoint = point;
- }
-
- return result;
- }
-
- // ---- Private helper methods ----
-
- private void set(Path_Delegate delegate) {
- mPath.reset();
- setFillType(delegate.mFillType);
- mPath.append(delegate.mPath, false /*connect*/);
- }
-
- private void setFillType(FillType fillType) {
- mFillType = fillType;
- mPath.setWindingRule(getWindingRule(fillType));
- }
-
- /**
- * Returns the Java2D winding rules matching a given Android {@link FillType}.
- * @param type the android fill type
- * @return the matching java2d winding rule.
- */
- private static int getWindingRule(FillType type) {
- switch (type) {
- case WINDING:
- case INVERSE_WINDING:
- return GeneralPath.WIND_NON_ZERO;
- case EVEN_ODD:
- case INVERSE_EVEN_ODD:
- return GeneralPath.WIND_EVEN_ODD;
-
- default:
- assert false;
- return GeneralPath.WIND_NON_ZERO;
- }
- }
-
- @NonNull
- private static Direction getDirection(int direction) {
- for (Direction d : Direction.values()) {
- if (direction == d.nativeInt) {
- return d;
- }
- }
-
- assert false;
- return null;
- }
-
- public static void addPath(long destPath, long srcPath, AffineTransform transform) {
- Path_Delegate destPathDelegate = sManager.getDelegate(destPath);
- if (destPathDelegate == null) {
- return;
- }
-
- Path_Delegate srcPathDelegate = sManager.getDelegate(srcPath);
- if (srcPathDelegate == null) {
- return;
- }
-
- if (transform != null) {
- destPathDelegate.mPath.append(
- srcPathDelegate.mPath.getPathIterator(transform), false);
- } else {
- destPathDelegate.mPath.append(srcPathDelegate.mPath, false);
- }
- }
-
-
- /**
- * Returns whether the path already contains any points.
- * Note that this is different to
- * {@link #isEmpty} because if all elements are {@link PathIterator#SEG_MOVETO},
- * {@link #isEmpty} will return true while hasPoints will return false.
- */
- public boolean hasPoints() {
- return !mPath.getPathIterator(null).isDone();
- }
-
- /**
- * Returns whether the path is empty (contains no lines or curves).
- * @see Path#isEmpty
- */
- public boolean isEmpty() {
- if (!mCachedIsEmpty) {
- return false;
- }
-
- float[] coords = new float[6];
- mCachedIsEmpty = Boolean.TRUE;
- for (PathIterator it = mPath.getPathIterator(null); !it.isDone(); it.next()) {
- int type = it.currentSegment(coords);
- if (type != PathIterator.SEG_MOVETO) {
- // Once we know that the path is not empty, we do not need to check again unless
- // Path#reset is called.
- mCachedIsEmpty = false;
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Fills the given {@link RectF} with the path bounds.
- * @param bounds the RectF to be filled.
- */
- public void fillBounds(RectF bounds) {
- Rectangle2D rect = mPath.getBounds2D();
- bounds.left = (float)rect.getMinX();
- bounds.right = (float)rect.getMaxX();
- bounds.top = (float)rect.getMinY();
- bounds.bottom = (float)rect.getMaxY();
- }
-
- /**
- * Set the beginning of the next contour to the point (x,y).
- *
- * @param x The x-coordinate of the start of a new contour
- * @param y The y-coordinate of the start of a new contour
- */
- public void moveTo(float x, float y) {
- mPath.moveTo(mLastX = x, mLastY = y);
- }
-
- /**
- * Set the beginning of the next contour relative to the last point on the
- * previous contour. If there is no previous contour, this is treated the
- * same as moveTo().
- *
- * @param dx The amount to add to the x-coordinate of the end of the
- * previous contour, to specify the start of a new contour
- * @param dy The amount to add to the y-coordinate of the end of the
- * previous contour, to specify the start of a new contour
- */
- public void rMoveTo(float dx, float dy) {
- dx += mLastX;
- dy += mLastY;
- mPath.moveTo(mLastX = dx, mLastY = dy);
- }
-
- /**
- * Add a line from the last point to the specified point (x,y).
- * If no moveTo() call has been made for this contour, the first point is
- * automatically set to (0,0).
- *
- * @param x The x-coordinate of the end of a line
- * @param y The y-coordinate of the end of a line
- */
- public void lineTo(float x, float y) {
- if (!hasPoints()) {
- mPath.moveTo(mLastX = 0, mLastY = 0);
- }
- mPath.lineTo(mLastX = x, mLastY = y);
- }
-
- /**
- * Same as lineTo, but the coordinates are considered relative to the last
- * point on this contour. If there is no previous point, then a moveTo(0,0)
- * is inserted automatically.
- *
- * @param dx The amount to add to the x-coordinate of the previous point on
- * this contour, to specify a line
- * @param dy The amount to add to the y-coordinate of the previous point on
- * this contour, to specify a line
- */
- public void rLineTo(float dx, float dy) {
- if (!hasPoints()) {
- mPath.moveTo(mLastX = 0, mLastY = 0);
- }
-
- if (Math.abs(dx) < EPSILON && Math.abs(dy) < EPSILON) {
- // The delta is so small that this shouldn't generate a line
- return;
- }
-
- dx += mLastX;
- dy += mLastY;
- mPath.lineTo(mLastX = dx, mLastY = dy);
- }
-
- /**
- * Add a quadratic bezier from the last point, approaching control point
- * (x1,y1), and ending at (x2,y2). If no moveTo() call has been made for
- * this contour, the first point is automatically set to (0,0).
- *
- * @param x1 The x-coordinate of the control point on a quadratic curve
- * @param y1 The y-coordinate of the control point on a quadratic curve
- * @param x2 The x-coordinate of the end point on a quadratic curve
- * @param y2 The y-coordinate of the end point on a quadratic curve
- */
- public void quadTo(float x1, float y1, float x2, float y2) {
- mPath.quadTo(x1, y1, mLastX = x2, mLastY = y2);
- }
-
- /**
- * Same as quadTo, but the coordinates are considered relative to the last
- * point on this contour. If there is no previous point, then a moveTo(0,0)
- * is inserted automatically.
- *
- * @param dx1 The amount to add to the x-coordinate of the last point on
- * this contour, for the control point of a quadratic curve
- * @param dy1 The amount to add to the y-coordinate of the last point on
- * this contour, for the control point of a quadratic curve
- * @param dx2 The amount to add to the x-coordinate of the last point on
- * this contour, for the end point of a quadratic curve
- * @param dy2 The amount to add to the y-coordinate of the last point on
- * this contour, for the end point of a quadratic curve
- */
- public void rQuadTo(float dx1, float dy1, float dx2, float dy2) {
- if (!hasPoints()) {
- mPath.moveTo(mLastX = 0, mLastY = 0);
- }
- dx1 += mLastX;
- dy1 += mLastY;
- dx2 += mLastX;
- dy2 += mLastY;
- mPath.quadTo(dx1, dy1, mLastX = dx2, mLastY = dy2);
- }
-
- /**
- * Add a cubic bezier from the last point, approaching control points
- * (x1,y1) and (x2,y2), and ending at (x3,y3). If no moveTo() call has been
- * made for this contour, the first point is automatically set to (0,0).
- *
- * @param x1 The x-coordinate of the 1st control point on a cubic curve
- * @param y1 The y-coordinate of the 1st control point on a cubic curve
- * @param x2 The x-coordinate of the 2nd control point on a cubic curve
- * @param y2 The y-coordinate of the 2nd control point on a cubic curve
- * @param x3 The x-coordinate of the end point on a cubic curve
- * @param y3 The y-coordinate of the end point on a cubic curve
- */
- public void cubicTo(float x1, float y1, float x2, float y2,
- float x3, float y3) {
- if (!hasPoints()) {
- mPath.moveTo(0, 0);
- }
- mPath.curveTo(x1, y1, x2, y2, mLastX = x3, mLastY = y3);
- }
-
- /**
- * Same as cubicTo, but the coordinates are considered relative to the
- * current point on this contour. If there is no previous point, then a
- * moveTo(0,0) is inserted automatically.
- */
- public void rCubicTo(float dx1, float dy1, float dx2, float dy2,
- float dx3, float dy3) {
- if (!hasPoints()) {
- mPath.moveTo(mLastX = 0, mLastY = 0);
- }
- dx1 += mLastX;
- dy1 += mLastY;
- dx2 += mLastX;
- dy2 += mLastY;
- dx3 += mLastX;
- dy3 += mLastY;
- mPath.curveTo(dx1, dy1, dx2, dy2, mLastX = dx3, mLastY = dy3);
- }
-
- /**
- * Append the specified arc to the path as a new contour. If the start of
- * the path is different from the path's current last point, then an
- * automatic lineTo() is added to connect the current contour to the
- * start of the arc. However, if the path is empty, then we call moveTo()
- * with the first point of the arc. The sweep angle is tread mod 360.
- *
- * @param left The left of oval defining shape and size of the arc
- * @param top The top of oval defining shape and size of the arc
- * @param right The right of oval defining shape and size of the arc
- * @param bottom The bottom of oval defining shape and size of the arc
- * @param startAngle Starting angle (in degrees) where the arc begins
- * @param sweepAngle Sweep angle (in degrees) measured clockwise, treated
- * mod 360.
- * @param forceMoveTo If true, always begin a new contour with the arc
- */
- public void arcTo(float left, float top, float right, float bottom, float startAngle,
- float sweepAngle,
- boolean forceMoveTo) {
- Arc2D arc = new Arc2D.Float(left, top, right - left, bottom - top, -startAngle,
- -sweepAngle, Arc2D.OPEN);
- mPath.append(arc, true /*connect*/);
-
- resetLastPointFromPath();
- }
-
- /**
- * Close the current contour. If the current point is not equal to the
- * first point of the contour, a line segment is automatically added.
- */
- public void close() {
- mPath.closePath();
- }
-
- private void resetLastPointFromPath() {
- Point2D last = mPath.getCurrentPoint();
- mLastX = (float) last.getX();
- mLastY = (float) last.getY();
- }
-
- /**
- * Add a closed rectangle contour to the path
- *
- * @param left The left side of a rectangle to add to the path
- * @param top The top of a rectangle to add to the path
- * @param right The right side of a rectangle to add to the path
- * @param bottom The bottom of a rectangle to add to the path
- * @param dir The direction to wind the rectangle's contour
- */
- public void addRect(float left, float top, float right, float bottom,
- int dir) {
- moveTo(left, top);
-
- Direction direction = getDirection(dir);
-
- switch (direction) {
- case CW:
- lineTo(right, top);
- lineTo(right, bottom);
- lineTo(left, bottom);
- break;
- case CCW:
- lineTo(left, bottom);
- lineTo(right, bottom);
- lineTo(right, top);
- break;
- }
-
- close();
-
- resetLastPointFromPath();
- }
-
- /**
- * Offset the path by (dx,dy), returning true on success
- *
- * @param dx The amount in the X direction to offset the entire path
- * @param dy The amount in the Y direction to offset the entire path
- */
- public void offset(float dx, float dy) {
- GeneralPath newPath = new GeneralPath();
-
- PathIterator iterator = mPath.getPathIterator(new AffineTransform(0, 0, dx, 0, 0, dy));
-
- newPath.append(iterator, false /*connect*/);
- mPath = newPath;
- }
-
- /**
- * Transform the points in this path by matrix, and write the answer
- * into dst. If dst is null, then the the original path is modified.
- *
- * @param matrix The matrix to apply to the path
- * @param dst The transformed path is written here. If dst is null,
- * then the the original path is modified
- */
- public void transform(Matrix_Delegate matrix, Path_Delegate dst) {
- if (matrix.hasPerspective()) {
- assert false;
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_AFFINE,
- "android.graphics.Path#transform() only " +
- "supports affine transformations.", null, null /*data*/);
- }
-
- GeneralPath newPath = new GeneralPath();
-
- PathIterator iterator = mPath.getPathIterator(matrix.getAffineTransform());
-
- newPath.append(iterator, false /*connect*/);
-
- if (dst != null) {
- dst.mPath = newPath;
- } else {
- mPath = newPath;
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.PorterDuff.Mode;
-
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-
-import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getComposite;
-import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getPorterDuffMode;
-
-/**
- * Delegate implementing the native methods of android.graphics.PorterDuffColorFilter
- *
- * Through the layoutlib_create tool, the original native methods of PorterDuffColorFilter have
- * been replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original PorterDuffColorFilter class.
- *
- * Because this extends {@link ColorFilter_Delegate}, there's no need to use a
- * {@link DelegateManager}, as all the Shader classes will be added to the manager
- * owned by {@link ColorFilter_Delegate}.
- *
- * @see ColorFilter_Delegate
- *
- */
-public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
-
- // ---- delegate data ----
-
- private final java.awt.Color mSrcColor;
- private final Mode mMode;
-
-
- // ---- Public Helper methods ----
-
- @Override
- public boolean isSupported() {
- return true;
- }
-
- @Override
- public String getSupportMessage() {
- return "PorterDuff Color Filter is not supported for mode: " + mMode.name() + ".";
- }
-
- @Override
- public void applyFilter(Graphics2D g, int width, int height) {
- g.setComposite(getComposite(mMode, 0xFF));
- g.setColor(mSrcColor);
- g.fillRect(0, 0, width, height);
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long native_CreatePorterDuffFilter(int srcColor, int porterDuffMode) {
- PorterDuffColorFilter_Delegate newDelegate =
- new PorterDuffColorFilter_Delegate(srcColor, porterDuffMode);
- return sManager.addNewDelegate(newDelegate);
- }
-
-
- // ---- Private delegate/helper methods ----
-
- private PorterDuffColorFilter_Delegate(int srcColor, int mode) {
- mSrcColor = new java.awt.Color(srcColor, true /* hasAlpha */);
- mMode = getCompatibleMode(getPorterDuffMode(mode));
- }
-
- // For filtering the colors, the src image should contain the "color" only for pixel values
- // which are not transparent in the target image. But, we are using a simple rectangular image
- // completely filled with color. Hence some Composite rules do not apply as intended. However,
- // in such cases, they can usually be mapped to some other mode, which produces an approximately
- // equivalent result.
- private Mode getCompatibleMode(Mode mode) {
- Mode m = mode;
- // Modes that are directly supported:
- // CLEAR, DST, SRC_IN, DST_IN, DST_OUT, SRC_ATOP, DARKEN, LIGHTEN, MULTIPLY, SCREEN,
- // ADD, OVERLAY
- switch (mode) {
- // Modes that can be mapped to one of the supported modes.
- case SRC:
- m = Mode.SRC_IN;
- break;
- case SRC_OVER:
- m = Mode.SRC_ATOP;
- break;
- case DST_OVER:
- m = Mode.DST;
- break;
- case SRC_OUT:
- m = Mode.CLEAR;
- break;
- case DST_ATOP:
- m = Mode.DST_IN;
- break;
- case XOR:
- m = Mode.DST_OUT;
- break;
- }
- return m;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.Shader.TileMode;
-
-import java.awt.image.ColorModel;
-
-/**
- * Delegate implementing the native methods of android.graphics.RadialGradient
- *
- * Through the layoutlib_create tool, the original native methods of RadialGradient have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original RadialGradient class.
- *
- * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager},
- * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}.
- *
- * @see Shader_Delegate
- *
- */
-public class RadialGradient_Delegate extends Gradient_Delegate {
-
- // ---- delegate data ----
- private java.awt.Paint mJavaPaint;
-
- // ---- Public Helper methods ----
-
- @Override
- public java.awt.Paint getJavaPaint() {
- return mJavaPaint;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate1(long matrix, float x, float y, float radius,
- int colors[], float positions[], int tileMode) {
- RadialGradient_Delegate newDelegate = new RadialGradient_Delegate(matrix, x, y, radius,
- colors, positions, Shader_Delegate.getTileMode(tileMode));
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate2(long matrix, float x, float y, float radius,
- int color0, int color1, int tileMode) {
- return nativeCreate1(matrix, x, y, radius, new int[] { color0, color1 },
- null /*positions*/, tileMode);
- }
-
- // ---- Private delegate/helper methods ----
-
- /**
- * Create a shader that draws a radial gradient given the center and radius.
- *
- * @param nativeMatrix reference to the shader's native transformation matrix
- * @param x The x-coordinate of the center of the radius
- * @param y The y-coordinate of the center of the radius
- * @param radius Must be positive. The radius of the circle for this
- * gradient
- * @param colors The colors to be distributed between the center and edge of
- * the circle
- * @param positions May be NULL. The relative position of each corresponding
- * color in the colors array. If this is NULL, the the colors are
- * distributed evenly between the center and edge of the circle.
- * @param tile The Shader tiling mode
- */
- private RadialGradient_Delegate(long nativeMatrix, float x, float y, float radius,
- int colors[], float positions[], TileMode tile) {
- super(nativeMatrix, colors, positions);
- mJavaPaint = new RadialGradientPaint(x, y, radius, mColors, mPositions, tile);
- }
-
- private class RadialGradientPaint extends GradientPaint {
-
- private final float mX;
- private final float mY;
- private final float mRadius;
-
- public RadialGradientPaint(float x, float y, float radius,
- int[] colors, float[] positions, TileMode mode) {
- super(colors, positions, mode);
- mX = x;
- mY = y;
- mRadius = radius;
- }
-
- @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) {
- precomputeGradientColors();
-
- java.awt.geom.AffineTransform canvasMatrix;
- try {
- canvasMatrix = xform.createInverse();
- } catch (java.awt.geom.NoninvertibleTransformException e) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in RadialGradient", e, null /*data*/);
- canvasMatrix = new java.awt.geom.AffineTransform();
- }
-
- java.awt.geom.AffineTransform localMatrix = getLocalMatrix();
- try {
- localMatrix = localMatrix.createInverse();
- } catch (java.awt.geom.NoninvertibleTransformException e) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in RadialGradient", e, null /*data*/);
- localMatrix = new java.awt.geom.AffineTransform();
- }
-
- return new RadialGradientPaintContext(canvasMatrix, localMatrix, colorModel);
- }
-
- private class RadialGradientPaintContext implements java.awt.PaintContext {
-
- private final java.awt.geom.AffineTransform mCanvasMatrix;
- private final java.awt.geom.AffineTransform mLocalMatrix;
- private final java.awt.image.ColorModel mColorModel;
-
- public RadialGradientPaintContext(
- java.awt.geom.AffineTransform canvasMatrix,
- java.awt.geom.AffineTransform localMatrix,
- java.awt.image.ColorModel colorModel) {
- mCanvasMatrix = canvasMatrix;
- mLocalMatrix = localMatrix;
- mColorModel = colorModel.hasAlpha() ? colorModel : ColorModel.getRGBdefault();
- }
-
- @Override
- public void dispose() {
- }
-
- @Override
- public java.awt.image.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(
- mColorModel, mColorModel.createCompatibleWritableRaster(w, h),
- mColorModel.isAlphaPremultiplied(), null);
-
- int[] data = new int[w*h];
-
- // compute distance from each point to the center, and figure out the distance from
- // it.
- int index = 0;
- float[] pt1 = new float[2];
- float[] pt2 = new float[2];
- for (int iy = 0 ; iy < h ; iy++) {
- for (int ix = 0 ; ix < w ; ix++) {
- // handle the canvas transform
- pt1[0] = x + ix;
- pt1[1] = y + iy;
- mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
-
- // handle the local matrix
- pt1[0] = pt2[0] - mX;
- pt1[1] = pt2[1] - mY;
- mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
-
- float _x = pt2[0];
- float _y = pt2[1];
- float distance = (float) Math.hypot(_x, _y);
-
- data[index++] = getGradientColor(distance / mRadius);
- }
- }
-
- image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/);
-
- return image.getRaster();
- }
-
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.os.Parcel;
-
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
-import java.awt.geom.Rectangle2D;
-
-/**
- * Delegate implementing the native methods of android.graphics.Region
- *
- * Through the layoutlib_create tool, the original native methods of Region have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original Region class.
- *
- * This also serve as a base class for all Region delegate classes.
- *
- * @see DelegateManager
- *
- */
-public class Region_Delegate {
-
- // ---- delegate manager ----
- protected static final DelegateManager<Region_Delegate> sManager =
- new DelegateManager<Region_Delegate>(Region_Delegate.class);
-
- // ---- delegate helper data ----
-
- // ---- delegate data ----
- private Area mArea = new Area();
-
- // ---- Public Helper methods ----
-
- public static Region_Delegate getDelegate(long nativeShader) {
- return sManager.getDelegate(nativeShader);
- }
-
- public Area getJavaArea() {
- return mArea;
- }
-
- /**
- * Combines two {@link Shape} into another one (actually an {@link Area}), according
- * to the given {@link Region.Op}.
- *
- * If the Op is not one that combines two shapes, then this return null
- *
- * @param shape1 the firt shape to combine which can be null if there's no original clip.
- * @param shape2 the 2nd shape to combine
- * @param regionOp the operande for the combine
- * @return a new area or null.
- */
- public static Area combineShapes(Shape shape1, Shape shape2, int regionOp) {
- if (regionOp == Region.Op.DIFFERENCE.nativeInt) {
- // if shape1 is null (empty), then the result is null.
- if (shape1 == null) {
- return null;
- }
-
- // result is always a new area.
- Area result = new Area(shape1);
- result.subtract(shape2 instanceof Area ? (Area) shape2 : new Area(shape2));
- return result;
-
- } else if (regionOp == Region.Op.INTERSECT.nativeInt) {
- // if shape1 is null, then the result is simply shape2.
- if (shape1 == null) {
- return new Area(shape2);
- }
-
- // result is always a new area.
- Area result = new Area(shape1);
- result.intersect(shape2 instanceof Area ? (Area) shape2 : new Area(shape2));
- return result;
-
- } else if (regionOp == Region.Op.UNION.nativeInt) {
- // if shape1 is null, then the result is simply shape2.
- if (shape1 == null) {
- return new Area(shape2);
- }
-
- // result is always a new area.
- Area result = new Area(shape1);
- result.add(shape2 instanceof Area ? (Area) shape2 : new Area(shape2));
- return result;
-
- } else if (regionOp == Region.Op.XOR.nativeInt) {
- // if shape1 is null, then the result is simply shape2
- if (shape1 == null) {
- return new Area(shape2);
- }
-
- // result is always a new area.
- Area result = new Area(shape1);
- result.exclusiveOr(shape2 instanceof Area ? (Area) shape2 : new Area(shape2));
- return result;
-
- } else if (regionOp == Region.Op.REVERSE_DIFFERENCE.nativeInt) {
- // result is always a new area.
- Area result = new Area(shape2);
-
- if (shape1 != null) {
- result.subtract(shape1 instanceof Area ? (Area) shape1 : new Area(shape1));
- }
-
- return result;
- }
-
- return null;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static boolean isEmpty(Region thisRegion) {
- Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
- if (regionDelegate == null) {
- return true;
- }
-
- return regionDelegate.mArea.isEmpty();
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean isRect(Region thisRegion) {
- Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
- if (regionDelegate == null) {
- return true;
- }
-
- return regionDelegate.mArea.isRectangular();
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean isComplex(Region thisRegion) {
- Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
- if (regionDelegate == null) {
- return true;
- }
-
- return regionDelegate.mArea.isSingular() == false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean contains(Region thisRegion, int x, int y) {
- Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
- if (regionDelegate == null) {
- return false;
- }
-
- return regionDelegate.mArea.contains(x, y);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean quickContains(Region thisRegion,
- int left, int top, int right, int bottom) {
- Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
- if (regionDelegate == null) {
- return false;
- }
-
- return regionDelegate.mArea.isRectangular() &&
- regionDelegate.mArea.contains(left, top, right - left, bottom - top);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean quickReject(Region thisRegion,
- int left, int top, int right, int bottom) {
- Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
- if (regionDelegate == null) {
- return false;
- }
-
- return regionDelegate.mArea.isEmpty() ||
- regionDelegate.mArea.intersects(left, top, right - left, bottom - top) == false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean quickReject(Region thisRegion, Region rgn) {
- Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
- if (regionDelegate == null) {
- return false;
- }
-
- Region_Delegate targetRegionDelegate = sManager.getDelegate(rgn.mNativeRegion);
- if (targetRegionDelegate == null) {
- return false;
- }
-
- return regionDelegate.mArea.isEmpty() ||
- regionDelegate.mArea.getBounds().intersects(
- targetRegionDelegate.mArea.getBounds()) == false;
-
- }
-
- @LayoutlibDelegate
- /*package*/ static void translate(Region thisRegion, int dx, int dy, Region dst) {
- Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
- if (regionDelegate == null) {
- return;
- }
-
- Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion);
- if (targetRegionDelegate == null) {
- return;
- }
-
- if (regionDelegate.mArea.isEmpty()) {
- targetRegionDelegate.mArea = new Area();
- } else {
- targetRegionDelegate.mArea = new Area(regionDelegate.mArea);
- AffineTransform mtx = new AffineTransform();
- mtx.translate(dx, dy);
- targetRegionDelegate.mArea.transform(mtx);
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static void scale(Region thisRegion, float scale, Region dst) {
- Region_Delegate regionDelegate = sManager.getDelegate(thisRegion.mNativeRegion);
- if (regionDelegate == null) {
- return;
- }
-
- Region_Delegate targetRegionDelegate = sManager.getDelegate(dst.mNativeRegion);
- if (targetRegionDelegate == null) {
- return;
- }
-
- if (regionDelegate.mArea.isEmpty()) {
- targetRegionDelegate.mArea = new Area();
- } else {
- targetRegionDelegate.mArea = new Area(regionDelegate.mArea);
- AffineTransform mtx = new AffineTransform();
- mtx.scale(scale, scale);
- targetRegionDelegate.mArea.transform(mtx);
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static long nativeConstructor() {
- Region_Delegate newDelegate = new Region_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeDestructor(long native_region) {
- sManager.removeJavaReferenceFor(native_region);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeSetRegion(long native_dst, long native_src) {
- Region_Delegate dstRegion = sManager.getDelegate(native_dst);
- if (dstRegion == null) {
- return;
- }
-
- Region_Delegate srcRegion = sManager.getDelegate(native_src);
- if (srcRegion == null) {
- return;
- }
-
- dstRegion.mArea.reset();
- dstRegion.mArea.add(srcRegion.mArea);
-
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeSetRect(long native_dst,
- int left, int top, int right, int bottom) {
- Region_Delegate dstRegion = sManager.getDelegate(native_dst);
- if (dstRegion == null) {
- return true;
- }
-
- dstRegion.mArea = new Area(new Rectangle2D.Float(left, top, right - left, bottom - top));
- return dstRegion.mArea.getBounds().isEmpty() == false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeSetPath(long native_dst, long native_path, long native_clip) {
- Region_Delegate dstRegion = sManager.getDelegate(native_dst);
- if (dstRegion == null) {
- return true;
- }
-
- Path_Delegate path = Path_Delegate.getDelegate(native_path);
- if (path == null) {
- return true;
- }
-
- dstRegion.mArea = new Area(path.getJavaShape());
-
- Region_Delegate clip = sManager.getDelegate(native_clip);
- if (clip != null) {
- dstRegion.mArea.subtract(clip.getJavaArea());
- }
-
- return dstRegion.mArea.getBounds().isEmpty() == false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeGetBounds(long native_region, Rect rect) {
- Region_Delegate region = sManager.getDelegate(native_region);
- if (region == null) {
- return true;
- }
-
- Rectangle bounds = region.mArea.getBounds();
- if (bounds.isEmpty()) {
- rect.left = rect.top = rect.right = rect.bottom = 0;
- return false;
- }
-
- rect.left = bounds.x;
- rect.top = bounds.y;
- rect.right = bounds.x + bounds.width;
- rect.bottom = bounds.y + bounds.height;
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeGetBoundaryPath(long native_region, long native_path) {
- Region_Delegate region = sManager.getDelegate(native_region);
- if (region == null) {
- return false;
- }
-
- Path_Delegate path = Path_Delegate.getDelegate(native_path);
- if (path == null) {
- return false;
- }
-
- if (region.mArea.isEmpty()) {
- path.reset();
- return false;
- }
-
- path.setPathIterator(region.mArea.getPathIterator(new AffineTransform()));
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeOp(long native_dst,
- int left, int top, int right, int bottom, int op) {
- Region_Delegate region = sManager.getDelegate(native_dst);
- if (region == null) {
- return false;
- }
-
- region.mArea = combineShapes(region.mArea,
- new Rectangle2D.Float(left, top, right - left, bottom - top), op);
-
- assert region.mArea != null;
- if (region.mArea != null) {
- region.mArea = new Area();
- }
-
- return region.mArea.getBounds().isEmpty() == false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeOp(long native_dst, Rect rect, long native_region, int op) {
- Region_Delegate region = sManager.getDelegate(native_dst);
- if (region == null) {
- return false;
- }
-
- region.mArea = combineShapes(region.mArea,
- new Rectangle2D.Float(rect.left, rect.top, rect.width(), rect.height()), op);
-
- assert region.mArea != null;
- if (region.mArea != null) {
- region.mArea = new Area();
- }
-
- return region.mArea.getBounds().isEmpty() == false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeOp(long native_dst,
- long native_region1, long native_region2, int op) {
- Region_Delegate dstRegion = sManager.getDelegate(native_dst);
- if (dstRegion == null) {
- return true;
- }
-
- Region_Delegate region1 = sManager.getDelegate(native_region1);
- if (region1 == null) {
- return false;
- }
-
- Region_Delegate region2 = sManager.getDelegate(native_region2);
- if (region2 == null) {
- return false;
- }
-
- dstRegion.mArea = combineShapes(region1.mArea, region2.mArea, op);
-
- assert dstRegion.mArea != null;
- if (dstRegion.mArea != null) {
- dstRegion.mArea = new Area();
- }
-
- return dstRegion.mArea.getBounds().isEmpty() == false;
-
- }
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreateFromParcel(Parcel p) {
- // This is only called by Region.CREATOR (Parcelable.Creator<Region>), which is only
- // used during aidl call so really this should not be called.
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "AIDL is not suppored, and therefore Regions cannot be created from parcels.",
- null /*data*/);
- return 0;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeWriteToParcel(long native_region,
- Parcel p) {
- // This is only called when sending a region through aidl, so really this should not
- // be called.
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
- "AIDL is not suppored, and therefore Regions cannot be written to parcels.",
- null /*data*/);
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nativeEquals(long native_r1, long native_r2) {
- Region_Delegate region1 = sManager.getDelegate(native_r1);
- if (region1 == null) {
- return false;
- }
-
- Region_Delegate region2 = sManager.getDelegate(native_r2);
- if (region2 == null) {
- return false;
- }
-
- return region1.mArea.equals(region2.mArea);
- }
-
- @LayoutlibDelegate
- /*package*/ static String nativeToString(long native_region) {
- Region_Delegate region = sManager.getDelegate(native_region);
- if (region == null) {
- return "not found";
- }
-
- return region.mArea.toString();
- }
-
- // ---- Private delegate/helper methods ----
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import java.awt.geom.AffineTransform;
-import java.awt.geom.PathIterator;
-import java.awt.geom.Rectangle2D;
-import java.awt.geom.RectangularShape;
-import java.awt.geom.RoundRectangle2D;
-import java.util.EnumSet;
-import java.util.NoSuchElementException;
-
-/**
- * Defines a rectangle with rounded corners, where the sizes of the corners
- * are potentially different.
- */
-public class RoundRectangle extends RectangularShape {
- public double x;
- public double y;
- public double width;
- public double height;
- public double ulWidth;
- public double ulHeight;
- public double urWidth;
- public double urHeight;
- public double lrWidth;
- public double lrHeight;
- public double llWidth;
- public double llHeight;
-
- private enum Zone {
- CLOSE_OUTSIDE,
- CLOSE_INSIDE,
- MIDDLE,
- FAR_INSIDE,
- FAR_OUTSIDE
- }
-
- private final EnumSet<Zone> close = EnumSet.of(Zone.CLOSE_OUTSIDE, Zone.CLOSE_INSIDE);
- private final EnumSet<Zone> far = EnumSet.of(Zone.FAR_OUTSIDE, Zone.FAR_INSIDE);
-
- /**
- * @param cornerDimensions array of 8 floating-point number corresponding to the width and
- * the height of each corner in the following order: upper-left, upper-right, lower-right,
- * lower-left. It assumes for the size the same convention as {@link RoundRectangle2D}, that
- * is that the width and height of a corner correspond to the total width and height of the
- * ellipse that corner is a quarter of.
- */
- public RoundRectangle(float x, float y, float width, float height, float[] cornerDimensions) {
- assert cornerDimensions.length == 8 : "The array of corner dimensions must have eight " +
- "elements";
-
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
-
- float[] dimensions = cornerDimensions.clone();
- // If a value is negative, the corresponding corner is squared
- for (int i = 0; i < dimensions.length; i += 2) {
- if (dimensions[i] < 0 || dimensions[i + 1] < 0) {
- dimensions[i] = 0;
- dimensions[i + 1] = 0;
- }
- }
-
- double topCornerWidth = (dimensions[0] + dimensions[2]) / 2d;
- double bottomCornerWidth = (dimensions[4] + dimensions[6]) / 2d;
- double leftCornerHeight = (dimensions[1] + dimensions[7]) / 2d;
- double rightCornerHeight = (dimensions[3] + dimensions[5]) / 2d;
-
- // Rescale the corner dimensions if they are bigger than the rectangle
- double scale = Math.min(1.0, width / topCornerWidth);
- scale = Math.min(scale, width / bottomCornerWidth);
- scale = Math.min(scale, height / leftCornerHeight);
- scale = Math.min(scale, height / rightCornerHeight);
-
- this.ulWidth = dimensions[0] * scale;
- this.ulHeight = dimensions[1] * scale;
- this.urWidth = dimensions[2] * scale;
- this.urHeight = dimensions[3] * scale;
- this.lrWidth = dimensions[4] * scale;
- this.lrHeight = dimensions[5] * scale;
- this.llWidth = dimensions[6] * scale;
- this.llHeight = dimensions[7] * scale;
- }
-
- @Override
- public double getX() {
- return x;
- }
-
- @Override
- public double getY() {
- return y;
- }
-
- @Override
- public double getWidth() {
- return width;
- }
-
- @Override
- public double getHeight() {
- return height;
- }
-
- @Override
- public boolean isEmpty() {
- return (width <= 0d) || (height <= 0d);
- }
-
- @Override
- public void setFrame(double x, double y, double w, double h) {
- this.x = x;
- this.y = y;
- this.width = w;
- this.height = h;
- }
-
- @Override
- public Rectangle2D getBounds2D() {
- return new Rectangle2D.Double(x, y, width, height);
- }
-
- @Override
- public boolean contains(double x, double y) {
- if (isEmpty()) {
- return false;
- }
-
- double x0 = getX();
- double y0 = getY();
- double x1 = x0 + getWidth();
- double y1 = y0 + getHeight();
- // Check for trivial rejection - point is outside bounding rectangle
- if (x < x0 || y < y0 || x >= x1 || y >= y1) {
- return false;
- }
-
- double insideTopX0 = x0 + ulWidth / 2d;
- double insideLeftY0 = y0 + ulHeight / 2d;
- if (x < insideTopX0 && y < insideLeftY0) {
- // In the upper-left corner
- return isInsideCorner(x - insideTopX0, y - insideLeftY0, ulWidth / 2d, ulHeight / 2d);
- }
-
- double insideTopX1 = x1 - urWidth / 2d;
- double insideRightY0 = y0 + urHeight / 2d;
- if (x > insideTopX1 && y < insideRightY0) {
- // In the upper-right corner
- return isInsideCorner(x - insideTopX1, y - insideRightY0, urWidth / 2d, urHeight / 2d);
- }
-
- double insideBottomX1 = x1 - lrWidth / 2d;
- double insideRightY1 = y1 - lrHeight / 2d;
- if (x > insideBottomX1 && y > insideRightY1) {
- // In the lower-right corner
- return isInsideCorner(x - insideBottomX1, y - insideRightY1, lrWidth / 2d,
- lrHeight / 2d);
- }
-
- double insideBottomX0 = x0 + llWidth / 2d;
- double insideLeftY1 = y1 - llHeight / 2d;
- if (x < insideBottomX0 && y > insideLeftY1) {
- // In the lower-left corner
- return isInsideCorner(x - insideBottomX0, y - insideLeftY1, llWidth / 2d,
- llHeight / 2d);
- }
-
- // In the central part of the rectangle
- return true;
- }
-
- private boolean isInsideCorner(double x, double y, double width, double height) {
- double squareDist = height * height * x * x + width * width * y * y;
- return squareDist <= width * width * height * height;
- }
-
- private Zone classify(double coord, double side1, double arcSize1, double side2,
- double arcSize2) {
- if (coord < side1) {
- return Zone.CLOSE_OUTSIDE;
- } else if (coord < side1 + arcSize1) {
- return Zone.CLOSE_INSIDE;
- } else if (coord < side2 - arcSize2) {
- return Zone.MIDDLE;
- } else if (coord < side2) {
- return Zone.FAR_INSIDE;
- } else {
- return Zone.FAR_OUTSIDE;
- }
- }
-
- public boolean intersects(double x, double y, double w, double h) {
- if (isEmpty() || w <= 0 || h <= 0) {
- return false;
- }
- double x0 = getX();
- double y0 = getY();
- double x1 = x0 + getWidth();
- double y1 = y0 + getHeight();
- // Check for trivial rejection - bounding rectangles do not intersect
- if (x + w <= x0 || x >= x1 || y + h <= y0 || y >= y1) {
- return false;
- }
-
- double maxLeftCornerWidth = Math.max(ulWidth, llWidth) / 2d;
- double maxRightCornerWidth = Math.max(urWidth, lrWidth) / 2d;
- double maxUpperCornerHeight = Math.max(ulHeight, urHeight) / 2d;
- double maxLowerCornerHeight = Math.max(llHeight, lrHeight) / 2d;
- Zone x0class = classify(x, x0, maxLeftCornerWidth, x1, maxRightCornerWidth);
- Zone x1class = classify(x + w, x0, maxLeftCornerWidth, x1, maxRightCornerWidth);
- Zone y0class = classify(y, y0, maxUpperCornerHeight, y1, maxLowerCornerHeight);
- Zone y1class = classify(y + h, y0, maxUpperCornerHeight, y1, maxLowerCornerHeight);
-
- // Trivially accept if any point is inside inner rectangle
- if (x0class == Zone.MIDDLE || x1class == Zone.MIDDLE || y0class == Zone.MIDDLE || y1class == Zone.MIDDLE) {
- return true;
- }
- // Trivially accept if either edge spans inner rectangle
- if ((close.contains(x0class) && far.contains(x1class)) || (close.contains(y0class) &&
- far.contains(y1class))) {
- return true;
- }
-
- // Since neither edge spans the center, then one of the corners
- // must be in one of the rounded edges. We detect this case if
- // a [xy]0class is 3 or a [xy]1class is 1. One of those two cases
- // must be true for each direction.
- // We now find a "nearest point" to test for being inside a rounded
- // corner.
- if (x1class == Zone.CLOSE_INSIDE && y1class == Zone.CLOSE_INSIDE) {
- // Potentially in upper-left corner
- x = x + w - x0 - ulWidth / 2d;
- y = y + h - y0 - ulHeight / 2d;
- return x > 0 || y > 0 || isInsideCorner(x, y, ulWidth / 2d, ulHeight / 2d);
- }
- if (x1class == Zone.CLOSE_INSIDE) {
- // Potentially in lower-left corner
- x = x + w - x0 - llWidth / 2d;
- y = y - y1 + llHeight / 2d;
- return x > 0 || y < 0 || isInsideCorner(x, y, llWidth / 2d, llHeight / 2d);
- }
- if (y1class == Zone.CLOSE_INSIDE) {
- //Potentially in the upper-right corner
- x = x - x1 + urWidth / 2d;
- y = y + h - y0 - urHeight / 2d;
- return x < 0 || y > 0 || isInsideCorner(x, y, urWidth / 2d, urHeight / 2d);
- }
- // Potentially in the lower-right corner
- x = x - x1 + lrWidth / 2d;
- y = y - y1 + lrHeight / 2d;
- return x < 0 || y < 0 || isInsideCorner(x, y, lrWidth / 2d, lrHeight / 2d);
- }
-
- @Override
- public boolean contains(double x, double y, double w, double h) {
- if (isEmpty() || w <= 0 || h <= 0) {
- return false;
- }
- return (contains(x, y) &&
- contains(x + w, y) &&
- contains(x, y + h) &&
- contains(x + w, y + h));
- }
-
- @Override
- public PathIterator getPathIterator(final AffineTransform at) {
- return new PathIterator() {
- int index;
-
- // ArcIterator.btan(Math.PI/2)
- public static final double CtrlVal = 0.5522847498307933;
- private final double ncv = 1.0 - CtrlVal;
-
- // Coordinates of control points for Bezier curves approximating the straight lines
- // and corners of the rounded rectangle.
- private final double[][] ctrlpts = {
- {0.0, 0.0, 0.0, ulHeight},
- {0.0, 0.0, 1.0, -llHeight},
- {0.0, 0.0, 1.0, -llHeight * ncv, 0.0, ncv * llWidth, 1.0, 0.0, 0.0, llWidth,
- 1.0, 0.0},
- {1.0, -lrWidth, 1.0, 0.0},
- {1.0, -lrWidth * ncv, 1.0, 0.0, 1.0, 0.0, 1.0, -lrHeight * ncv, 1.0, 0.0, 1.0,
- -lrHeight},
- {1.0, 0.0, 0.0, urHeight},
- {1.0, 0.0, 0.0, ncv * urHeight, 1.0, -urWidth * ncv, 0.0, 0.0, 1.0, -urWidth,
- 0.0, 0.0},
- {0.0, ulWidth, 0.0, 0.0},
- {0.0, ncv * ulWidth, 0.0, 0.0, 0.0, 0.0, 0.0, ncv * ulHeight, 0.0, 0.0, 0.0,
- ulHeight},
- {}
- };
- private final int[] types = {
- SEG_MOVETO,
- SEG_LINETO, SEG_CUBICTO,
- SEG_LINETO, SEG_CUBICTO,
- SEG_LINETO, SEG_CUBICTO,
- SEG_LINETO, SEG_CUBICTO,
- SEG_CLOSE,
- };
-
- @Override
- public int getWindingRule() {
- return WIND_NON_ZERO;
- }
-
- @Override
- public boolean isDone() {
- return index >= ctrlpts.length;
- }
-
- @Override
- public void next() {
- index++;
- }
-
- @Override
- public int currentSegment(float[] coords) {
- if (isDone()) {
- throw new NoSuchElementException("roundrect iterator out of bounds");
- }
- int nc = 0;
- double ctrls[] = ctrlpts[index];
- for (int i = 0; i < ctrls.length; i += 4) {
- coords[nc++] = (float) (x + ctrls[i] * width + ctrls[i + 1] / 2d);
- coords[nc++] = (float) (y + ctrls[i + 2] * height + ctrls[i + 3] / 2d);
- }
- if (at != null) {
- at.transform(coords, 0, coords, 0, nc / 2);
- }
- return types[index];
- }
-
- @Override
- public int currentSegment(double[] coords) {
- if (isDone()) {
- throw new NoSuchElementException("roundrect iterator out of bounds");
- }
- int nc = 0;
- double ctrls[] = ctrlpts[index];
- for (int i = 0; i < ctrls.length; i += 4) {
- coords[nc++] = x + ctrls[i] * width + ctrls[i + 1] / 2d;
- coords[nc++] = y + ctrls[i + 2] * height + ctrls[i + 3] / 2d;
- }
- if (at != null) {
- at.transform(coords, 0, coords, 0, nc / 2);
- }
- return types[index];
- }
- };
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.Shader.TileMode;
-
-/**
- * Delegate implementing the native methods of android.graphics.Shader
- *
- * Through the layoutlib_create tool, the original native methods of Shader have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original Shader class.
- *
- * This also serve as a base class for all Shader delegate classes.
- *
- * @see DelegateManager
- *
- */
-public abstract class Shader_Delegate {
-
- // ---- delegate manager ----
- protected static final DelegateManager<Shader_Delegate> sManager =
- new DelegateManager<Shader_Delegate>(Shader_Delegate.class);
-
- // ---- delegate helper data ----
-
- // ---- delegate data ----
- private Matrix_Delegate mLocalMatrix = null;
-
- // ---- Public Helper methods ----
-
- public static Shader_Delegate getDelegate(long nativeShader) {
- return sManager.getDelegate(nativeShader);
- }
-
- /**
- * Returns the {@link TileMode} matching the given int.
- * @param tileMode the tile mode int value
- * @return the TileMode enum.
- */
- public static TileMode getTileMode(int tileMode) {
- for (TileMode tm : TileMode.values()) {
- if (tm.nativeInt == tileMode) {
- return tm;
- }
- }
-
- assert false;
- return TileMode.CLAMP;
- }
-
- public abstract java.awt.Paint getJavaPaint();
- public abstract boolean isSupported();
- public abstract String getSupportMessage();
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static void nativeSafeUnref(long nativeInstance) {
- sManager.removeJavaReferenceFor(nativeInstance);
- }
-
- // ---- Private delegate/helper methods ----
-
- protected Shader_Delegate(long nativeMatrix) {
- mLocalMatrix = Matrix_Delegate.getDelegate(nativeMatrix);
- }
-
- protected java.awt.geom.AffineTransform getLocalMatrix() {
- if (mLocalMatrix != null) {
- return mLocalMatrix.getAffineTransform();
- }
-
- return new java.awt.geom.AffineTransform();
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.Stroke;
-
-/**
- * Delegate implementing the native methods of android.graphics.SumPathEffect
- *
- * Through the layoutlib_create tool, the original native methods of SumPathEffect have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original SumPathEffect class.
- *
- * Because this extends {@link PathEffect_Delegate}, there's no need to use a {@link DelegateManager},
- * as all the Shader classes will be added to the manager owned by {@link PathEffect_Delegate}.
- *
- * @see PathEffect_Delegate
- *
- */
-public class SumPathEffect_Delegate extends PathEffect_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public Stroke getStroke(Paint_Delegate paint) {
- // FIXME
- return null;
- }
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Sum Path Effects are not supported in Layout Preview mode.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate(long first, long second) {
- SumPathEffect_Delegate newDelegate = new SumPathEffect_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-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;
-
-/**
- * Delegate implementing the native methods of android.graphics.SweepGradient
- *
- * Through the layoutlib_create tool, the original native methods of SweepGradient have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original SweepGradient class.
- *
- * Because this extends {@link Shader_Delegate}, there's no need to use a {@link DelegateManager},
- * as all the Shader classes will be added to the manager owned by {@link Shader_Delegate}.
- *
- * @see Shader_Delegate
- *
- */
-public class SweepGradient_Delegate extends Gradient_Delegate {
-
- // ---- delegate data ----
- private java.awt.Paint mJavaPaint;
-
- // ---- Public Helper methods ----
-
- @Override
- public java.awt.Paint getJavaPaint() {
- return mJavaPaint;
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate1(long matrix, float x, float y, int colors[], float
- positions[]) {
- SweepGradient_Delegate newDelegate = new SweepGradient_Delegate(matrix, x, y, colors,
- positions);
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate2(long matrix, float x, float y, int color0, int color1) {
- return nativeCreate1(matrix, x, y, new int[] { color0, color1 },
- null /*positions*/);
- }
-
- // ---- Private delegate/helper methods ----
-
- /**
- * A subclass of Shader that draws a sweep gradient around a center point.
- *
- * @param nativeMatrix reference to the shader's native transformation matrix
- * @param cx The x-coordinate of the center
- * @param cy The y-coordinate of the center
- * @param colors The colors to be distributed between around the center.
- * There must be at least 2 colors in the array.
- * @param positions May be NULL. The relative position of
- * each corresponding color in the colors array, beginning
- * with 0 and ending with 1.0. If the values are not
- * monotonic, the drawing may produce unexpected results.
- * If positions is NULL, then the colors are automatically
- * spaced evenly.
- */
- private SweepGradient_Delegate(long nativeMatrix, float cx, float cy,
- int colors[], float positions[]) {
- super(nativeMatrix, colors, positions);
- mJavaPaint = new SweepGradientPaint(cx, cy, mColors, mPositions);
- }
-
- private class SweepGradientPaint extends GradientPaint {
-
- private final float mCx;
- private final float mCy;
-
- public SweepGradientPaint(float cx, float cy, int[] colors,
- float[] positions) {
- super(colors, positions, null /*tileMode*/);
- mCx = cx;
- mCy = cy;
- }
-
- @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) {
- precomputeGradientColors();
-
- java.awt.geom.AffineTransform canvasMatrix;
- try {
- canvasMatrix = xform.createInverse();
- } catch (java.awt.geom.NoninvertibleTransformException e) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in SweepGradient", e, null /*data*/);
- canvasMatrix = new java.awt.geom.AffineTransform();
- }
-
- java.awt.geom.AffineTransform localMatrix = getLocalMatrix();
- try {
- localMatrix = localMatrix.createInverse();
- } catch (java.awt.geom.NoninvertibleTransformException e) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_MATRIX_INVERSE,
- "Unable to inverse matrix in SweepGradient", e, null /*data*/);
- localMatrix = new java.awt.geom.AffineTransform();
- }
-
- return new SweepGradientPaintContext(canvasMatrix, localMatrix, colorModel);
- }
-
- private class SweepGradientPaintContext implements java.awt.PaintContext {
-
- private final java.awt.geom.AffineTransform mCanvasMatrix;
- private final java.awt.geom.AffineTransform mLocalMatrix;
- private final java.awt.image.ColorModel mColorModel;
-
- public SweepGradientPaintContext(
- java.awt.geom.AffineTransform canvasMatrix,
- java.awt.geom.AffineTransform localMatrix,
- java.awt.image.ColorModel colorModel) {
- mCanvasMatrix = canvasMatrix;
- mLocalMatrix = localMatrix;
- mColorModel = colorModel;
- }
-
- @Override
- public void dispose() {
- }
-
- @Override
- public java.awt.image.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(
- mColorModel, mColorModel.createCompatibleWritableRaster(w, h),
- mColorModel.isAlphaPremultiplied(), null);
-
- int[] data = new int[w*h];
-
- // compute angle from each point to the center, and figure out the distance from
- // it.
- int index = 0;
- float[] pt1 = new float[2];
- float[] pt2 = new float[2];
- for (int iy = 0 ; iy < h ; iy++) {
- for (int ix = 0 ; ix < w ; ix++) {
- // handle the canvas transform
- pt1[0] = x + ix;
- pt1[1] = y + iy;
- mCanvasMatrix.transform(pt1, 0, pt2, 0, 1);
-
- // handle the local matrix
- pt1[0] = pt2[0] - mCx;
- pt1[1] = pt2[1] - mCy;
- mLocalMatrix.transform(pt1, 0, pt2, 0, 1);
-
- float dx = pt2[0];
- float dy = pt2[1];
-
- float angle;
- if (dx == 0) {
- angle = (float) (dy < 0 ? 3 * Math.PI / 2 : Math.PI / 2);
- } else if (dy == 0) {
- angle = (float) (dx < 0 ? Math.PI : 0);
- } else {
- angle = (float) Math.atan(dy / dx);
- if (dx > 0) {
- if (dy < 0) {
- angle += Math.PI * 2;
- }
- } else {
- angle += Math.PI;
- }
- }
-
- // convert to 0-1. value and get color
- data[index++] = getGradientColor((float) (angle / (2 * Math.PI)));
- }
- }
-
- image.setRGB(0 /*startX*/, 0 /*startY*/, w, h, data, 0 /*offset*/, w /*scansize*/);
-
- return image.getRaster();
- }
-
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import android.annotation.NonNull;
-
-/**
- * Class allowing access to package-protected methods/fields.
- */
-public class Typeface_Accessor {
- public static boolean isSystemFont(@NonNull String fontName) {
- return Typeface.sSystemFontMap.containsKey(fontName);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.annotation.NonNull;
-import android.graphics.FontFamily_Delegate.FontVariant;
-import android.graphics.fonts.FontVariationAxis;
-import android.text.FontConfig;
-
-import java.awt.Font;
-import java.io.File;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import static android.graphics.FontFamily_Delegate.getFontLocation;
-
-/**
- * Delegate implementing the native methods of android.graphics.Typeface
- *
- * Through the layoutlib_create tool, the original native methods of Typeface have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original Typeface class.
- *
- * @see DelegateManager
- *
- */
-public final class Typeface_Delegate {
-
- public static final String SYSTEM_FONTS = "/system/fonts/";
-
- // ---- delegate manager ----
- private static final DelegateManager<Typeface_Delegate> sManager =
- new DelegateManager<Typeface_Delegate>(Typeface_Delegate.class);
-
-
- // ---- delegate data ----
-
- @NonNull
- private final FontFamily_Delegate[] mFontFamilies; // the reference to FontFamily_Delegate.
- /** @see Font#getStyle() */
- private final int mStyle;
- private final int mWeight;
-
- private static long sDefaultTypeface;
-
-
- // ---- Public Helper methods ----
-
- public static Typeface_Delegate getDelegate(long nativeTypeface) {
- return sManager.getDelegate(nativeTypeface);
- }
-
- /**
- * Return a list of fonts that match the style and variant. The list is ordered according to
- * preference of fonts.
- *
- * The list may contain null when the font failed to load. If null is reached when trying to
- * render with this list of fonts, then a warning should be logged letting the user know that
- * some font failed to load.
- *
- * @param variant The variant preferred. Can only be {@link FontVariant#COMPACT} or
- * {@link FontVariant#ELEGANT}
- */
- @NonNull
- public List<Font> getFonts(FontVariant variant) {
- assert variant != FontVariant.NONE;
-
- // Calculate the required weight based on style and weight of this typeface.
- int weight = mWeight + 50 +
- ((mStyle & Font.BOLD) == 0 ? 0 : FontFamily_Delegate.BOLD_FONT_WEIGHT_DELTA);
- if (weight > 1000) {
- weight = 1000;
- } else if (weight < 100) {
- weight = 100;
- }
- final boolean isItalic = (mStyle & Font.ITALIC) != 0;
- List<Font> fonts = new ArrayList<Font>(mFontFamilies.length);
- for (int i = 0; i < mFontFamilies.length; i++) {
- FontFamily_Delegate ffd = mFontFamilies[i];
- if (ffd != null && ffd.isValid()) {
- Font font = ffd.getFont(weight, isItalic);
- if (font != null) {
- FontVariant ffdVariant = ffd.getVariant();
- if (ffdVariant == FontVariant.NONE) {
- fonts.add(font);
- continue;
- }
- // We cannot open each font and get locales supported, etc to match the fonts.
- // As a workaround, we hardcode certain assumptions like Elegant and Compact
- // always appear in pairs.
- assert i < mFontFamilies.length - 1;
- FontFamily_Delegate ffd2 = mFontFamilies[++i];
- assert ffd2 != null;
- FontVariant ffd2Variant = ffd2.getVariant();
- Font font2 = ffd2.getFont(weight, isItalic);
- assert ffd2Variant != FontVariant.NONE && ffd2Variant != ffdVariant
- && font2 != null;
- // Add the font with the matching variant to the list.
- if (variant == ffd.getVariant()) {
- fonts.add(font);
- } else {
- fonts.add(font2);
- }
- } else {
- // The FontFamily is valid but doesn't contain any matching font. This means
- // that the font failed to load. We add null to the list of fonts. Don't throw
- // the warning just yet. If this is a non-english font, we don't want to warn
- // users who are trying to render only english text.
- fonts.add(null);
- }
- }
- }
- return fonts;
- }
-
- /**
- * Clear the default typefaces when disposing bridge.
- */
- public static void resetDefaults() {
- // Sometimes this is called before the Bridge is initialized. In that case, we don't want to
- // initialize Typeface because the SDK fonts location hasn't been set.
- if (FontFamily_Delegate.getFontLocation() != null) {
- Typeface.sDefaults = null;
- }
- }
-
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static synchronized long nativeCreateFromTypeface(long native_instance, int style) {
- Typeface_Delegate delegate = sManager.getDelegate(native_instance);
- if (delegate == null) {
- delegate = sManager.getDelegate(sDefaultTypeface);
- }
- if (delegate == null) {
- return 0;
- }
-
- return sManager.addNewDelegate(new Typeface_Delegate(delegate.mFontFamilies, style,
- delegate.mWeight));
- }
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreateFromTypefaceWithExactStyle(long native_instance,
- int weight, boolean italic) {
- Typeface_Delegate delegate = sManager.getDelegate(native_instance);
- if (delegate == null) {
- delegate = sManager.getDelegate(sDefaultTypeface);
- }
- if (delegate == null) {
- return 0;
- }
-
- int style = weight >= 600 ? (italic ? Typeface.BOLD_ITALIC : Typeface.BOLD) :
- (italic ? Typeface.ITALIC : Typeface.NORMAL);
- return sManager.addNewDelegate(new Typeface_Delegate(delegate.mFontFamilies, style, weight));
- }
-
- @LayoutlibDelegate
- /*package*/ static synchronized long nativeCreateFromTypefaceWithVariation(long native_instance,
- List<FontVariationAxis> axes) {
- long newInstance = nativeCreateFromTypeface(native_instance, 0);
-
- if (newInstance != 0) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "nativeCreateFromTypefaceWithVariation is not supported", null, null);
- }
- return newInstance;
- }
-
- @LayoutlibDelegate
- /*package*/ static synchronized int[] nativeGetSupportedAxes(long native_instance) {
- // nativeCreateFromTypefaceWithVariation is not supported so we do not keep the axes
- return null;
- }
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreateWeightAlias(long native_instance, int weight) {
- Typeface_Delegate delegate = sManager.getDelegate(native_instance);
- if (delegate == null) {
- delegate = sManager.getDelegate(sDefaultTypeface);
- }
- if (delegate == null) {
- return 0;
- }
- Typeface_Delegate weightAlias =
- new Typeface_Delegate(delegate.mFontFamilies, delegate.mStyle, weight);
- return sManager.addNewDelegate(weightAlias);
- }
-
- @LayoutlibDelegate
- /*package*/ static synchronized long nativeCreateFromArray(long[] familyArray, int weight,
- int italic) {
- FontFamily_Delegate[] fontFamilies = new FontFamily_Delegate[familyArray.length];
- for (int i = 0; i < familyArray.length; i++) {
- fontFamilies[i] = FontFamily_Delegate.getDelegate(familyArray[i]);
- }
- if (weight == Typeface.RESOLVE_BY_FONT_TABLE) {
- weight = 400;
- }
- if (italic == Typeface.RESOLVE_BY_FONT_TABLE) {
- italic = 0;
- }
- int style = weight >= 600 ? (italic == 1 ? Typeface.BOLD_ITALIC : Typeface.BOLD) :
- (italic == 1 ? Typeface.ITALIC : Typeface.NORMAL);
- Typeface_Delegate delegate = new Typeface_Delegate(fontFamilies, style, weight);
- return sManager.addNewDelegate(delegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeUnref(long native_instance) {
- sManager.removeJavaReferenceFor(native_instance);
- }
-
- @LayoutlibDelegate
- /*package*/ static int nativeGetStyle(long native_instance) {
- Typeface_Delegate delegate = sManager.getDelegate(native_instance);
- if (delegate == null) {
- return 0;
- }
-
- return delegate.mStyle;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nativeSetDefault(long native_instance) {
- sDefaultTypeface = native_instance;
- }
-
- @LayoutlibDelegate
- /*package*/ static int nativeGetWeight(long native_instance) {
- Typeface_Delegate delegate = sManager.getDelegate(native_instance);
- if (delegate == null) {
- return 0;
- }
- return delegate.mWeight;
- }
-
- @LayoutlibDelegate
- /*package*/ static File getSystemFontConfigLocation() {
- return new File(getFontLocation());
- }
-
- @LayoutlibDelegate
- /*package*/ static FontFamily makeFamilyFromParsed(FontConfig.Family family,
- Map<String, ByteBuffer> bufferForPath) {
- FontFamily fontFamily = new FontFamily(family.getLanguage(), family.getVariant());
- for (FontConfig.Font font : family.getFonts()) {
- String fullPathName = "/system/fonts/" + font.getFontName();
- FontFamily_Delegate.addFont(fontFamily.mBuilderPtr, fullPathName,
- font.getWeight(), font.isItalic());
- }
- fontFamily.freeze();
- return fontFamily;
- }
-
- // ---- Private delegate/helper methods ----
-
- public Typeface_Delegate(@NonNull FontFamily_Delegate[] fontFamilies, int style, int weight) {
- mFontFamilies = fontFamilies;
- mStyle = style;
- mWeight = weight;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License") {}
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics.drawable;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.internal.view.animation.NativeInterpolatorFactoryHelper_Delegate;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
-import android.graphics.drawable.VectorDrawable_Delegate.VFullPath_Delegate;
-import android.graphics.drawable.VectorDrawable_Delegate.VGroup_Delegate;
-import android.graphics.drawable.VectorDrawable_Delegate.VNativeObject;
-import android.graphics.drawable.VectorDrawable_Delegate.VPathRenderer_Delegate;
-
-import java.util.ArrayList;
-import java.util.function.Consumer;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link
- * AnimatedVectorDrawable}
- * <p>
- * Through the layoutlib_create tool, the original methods of AnimatedVectorDrawable have been
- * replaced by calls to methods of the same name in this delegate class.
- */
-@SuppressWarnings("unused")
-public class AnimatedVectorDrawable_Delegate {
- private static DelegateManager<AnimatorSetHolder> sAnimatorSets = new
- DelegateManager<>(AnimatorSetHolder.class);
- private static DelegateManager<PropertySetter> sHolders = new
- DelegateManager<>(PropertySetter.class);
-
-
- @LayoutlibDelegate
- /*package*/ static long nCreateAnimatorSet() {
- return sAnimatorSets.addNewDelegate(new AnimatorSetHolder());
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr) {
- // TODO: implement
- }
- @LayoutlibDelegate
- /*package*/ static void nAddAnimator(long setPtr, long propertyValuesHolder,
- long nativeInterpolator, long startDelay, long duration, int repeatCount,
- int repeatMode) {
- PropertySetter holder = sHolders.getDelegate(propertyValuesHolder);
- if (holder == null || holder.getValues() == null) {
- return;
- }
-
- ObjectAnimator animator = new ObjectAnimator();
- animator.setValues(holder.getValues());
- animator.setInterpolator(
- NativeInterpolatorFactoryHelper_Delegate.getDelegate(nativeInterpolator));
- animator.setStartDelay(startDelay);
- animator.setDuration(duration);
- animator.setRepeatCount(repeatCount);
- animator.setRepeatMode(repeatMode);
- animator.setTarget(holder);
- animator.setPropertyName(holder.getValues().getPropertyName());
-
- AnimatorSetHolder set = sAnimatorSets.getDelegate(setPtr);
- assert set != null;
- set.addAnimator(animator);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nCreateGroupPropertyHolder(long nativePtr, int propertyId,
- float startValue, float endValue) {
- VGroup_Delegate group = VNativeObject.getDelegate(nativePtr);
- Consumer<Float> setter = group.getPropertySetter(propertyId);
-
- return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
- endValue));
- }
-
- @LayoutlibDelegate
- /*package*/ static long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr,
- long endValuePtr) {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "AnimatedVectorDrawable path " +
- "animations are not supported.", null, null);
- return 0;
- }
-
- @LayoutlibDelegate
- /*package*/ static long nCreatePathColorPropertyHolder(long nativePtr, int propertyId,
- int startValue, int endValue) {
- VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
- Consumer<Integer> setter = path.getIntPropertySetter(propertyId);
-
- return sHolders.addNewDelegate(IntPropertySetter.of(setter, startValue,
- endValue));
- }
-
- @LayoutlibDelegate
- /*package*/ static long nCreatePathPropertyHolder(long nativePtr, int propertyId,
- float startValue, float endValue) {
- VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr);
- Consumer<Float> setter = path.getFloatPropertySetter(propertyId);
-
- return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue,
- endValue));
- }
-
- @LayoutlibDelegate
- /*package*/ static long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue,
- float endValue) {
- VPathRenderer_Delegate renderer = VNativeObject.getDelegate(nativePtr);
-
- return sHolders.addNewDelegate(FloatPropertySetter.of(renderer::setRootAlpha,
- startValue,
- endValue));
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetPropertyHolderData(long nativePtr, float[] data, int length) {
- PropertySetter setter = sHolders.getDelegate(nativePtr);
- assert setter != null;
-
- setter.setValues(data);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetPropertyHolderData(long nativePtr, int[] data, int length) {
- PropertySetter setter = sHolders.getDelegate(nativePtr);
- assert setter != null;
-
- setter.setValues(data);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
- AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
- assert animatorSet != null;
-
- animatorSet.start();
- }
-
- @LayoutlibDelegate
- /*package*/ static void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
- AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
- assert animatorSet != null;
-
- animatorSet.reverse();
- }
-
- @LayoutlibDelegate
- /*package*/ static void nEnd(long animatorSetPtr) {
- AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
- assert animatorSet != null;
-
- animatorSet.end();
- }
-
- @LayoutlibDelegate
- /*package*/ static void nReset(long animatorSetPtr) {
- AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);
- assert animatorSet != null;
-
- animatorSet.end();
- animatorSet.start();
- }
-
- private static class AnimatorSetHolder {
- private ArrayList<Animator> mAnimators = new ArrayList<>();
- private AnimatorSet mAnimatorSet = null;
-
- private void addAnimator(@NonNull Animator animator) {
- mAnimators.add(animator);
- }
-
- private void ensureAnimatorSet() {
- if (mAnimatorSet == null) {
- mAnimatorSet = new AnimatorSet();
- mAnimatorSet.playTogether(mAnimators);
- }
- }
-
- private void start() {
- ensureAnimatorSet();
-
- mAnimatorSet.start();
- }
-
- private void end() {
- mAnimatorSet.end();
- }
-
- private void reset() {
- end();
- start();
- }
-
- private void reverse() {
- mAnimatorSet.reverse();
- }
- }
-
- /**
- * Class that allows setting a value and holds the range of values for the given property.
- *
- * @param <T> the type of the property
- */
- private static class PropertySetter<T> {
- final Consumer<T> mValueSetter;
- private PropertyValuesHolder mValues;
-
- private PropertySetter(@NonNull Consumer<T> valueSetter) {
- mValueSetter = valueSetter;
- }
-
- /**
- * Method to set an {@link Integer} value for this property. The default implementation of
- * this method doesn't do anything. This method is accessed via reflection by the
- * PropertyValuesHolder.
- */
- public void setIntValue(Integer value) {
- }
-
- /**
- * Method to set an {@link Integer} value for this property. The default implementation of
- * this method doesn't do anything. This method is accessed via reflection by the
- * PropertyValuesHolder.
- */
- public void setFloatValue(Float value) {
- }
-
- void setValues(float... values) {
- mValues = PropertyValuesHolder.ofFloat("floatValue", values);
- }
-
- @Nullable
- PropertyValuesHolder getValues() {
- return mValues;
- }
-
- void setValues(int... values) {
- mValues = PropertyValuesHolder.ofInt("intValue", values);
- }
- }
-
- private static class IntPropertySetter extends PropertySetter<Integer> {
- private IntPropertySetter(Consumer<Integer> valueSetter) {
- super(valueSetter);
- }
-
- private static PropertySetter of(Consumer<Integer> valueSetter, int... values) {
- PropertySetter setter = new IntPropertySetter(valueSetter);
- setter.setValues(values);
-
- return setter;
- }
-
- public void setIntValue(Integer value) {
- mValueSetter.accept(value);
- }
- }
-
- private static class FloatPropertySetter extends PropertySetter<Float> {
- private FloatPropertySetter(Consumer<Float> valueSetter) {
- super(valueSetter);
- }
-
- private static PropertySetter of(Consumer<Float> valueSetter, float... values) {
- PropertySetter setter = new FloatPropertySetter(valueSetter);
- setter.setValues(values);
-
- return setter;
- }
-
- public void setFloatValue(Float value) {
- mValueSetter.accept(value);
- }
-
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics.drawable;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.Canvas;
-import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
-
-public class AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate {
- @LayoutlibDelegate
- /*package*/ static boolean useLastSeenTarget(VectorDrawableAnimatorRT thisDrawableAnimator) {
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static void onDraw(VectorDrawableAnimatorRT thisDrawableAnimator, Canvas canvas) {
- // Do not attempt to record as we are not using a DisplayListCanvas
- }
-}
+++ /dev/null
-/*
- * 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.graphics.drawable;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.Path;
-import android.graphics.drawable.GradientDrawable.GradientState;
-
-import java.lang.reflect.Field;
-
-/**
- * Delegate implementing the native methods of {@link GradientDrawable}
- *
- * Through the layoutlib_create tool, the original native methods of GradientDrawable have been
- * replaced by calls to methods of the same name in this delegate class.
- */
-public class GradientDrawable_Delegate {
-
- /**
- * The ring can be built either by drawing full circles, or by drawing arcs in case the
- * circle isn't complete. LayoutLib cannot handle drawing full circles (requires path
- * subtraction). So, if we need to draw full circles, we switch to drawing 99% circle.
- */
- @LayoutlibDelegate
- /*package*/ static Path buildRing(GradientDrawable thisDrawable, GradientState st) {
- boolean useLevel = st.mUseLevelForShape;
- int level = thisDrawable.getLevel();
- // 10000 is the max level. See android.graphics.drawable.Drawable#getLevel()
- float sweep = useLevel ? (360.0f * level / 10000.0f) : 360f;
- Field mLevel = null;
- if (sweep >= 360 || sweep <= -360) {
- st.mUseLevelForShape = true;
- // Use reflection to set the value of the field to prevent setting the drawable to
- // dirty again.
- try {
- mLevel = Drawable.class.getDeclaredField("mLevel");
- mLevel.setAccessible(true);
- mLevel.setInt(thisDrawable, 9999); // set to one less than max.
- } catch (NoSuchFieldException e) {
- // The field has been removed in a recent framework change. Fall back to old
- // buggy behaviour.
- } catch (IllegalAccessException e) {
- // We've already set the field to be accessible.
- assert false;
- }
- }
- Path path = thisDrawable.buildRing_Original(st);
- st.mUseLevelForShape = useLevel;
- if (mLevel != null) {
- try {
- mLevel.setInt(thisDrawable, level);
- } catch (IllegalAccessException e) {
- assert false;
- }
- }
- return path;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics.drawable;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.annotation.NonNull;
-import android.content.res.Resources;
-import android.content.res.Resources.Theme;
-import android.content.res.TypedArray;
-import android.graphics.BaseCanvas_Delegate;
-import android.graphics.Canvas_Delegate;
-import android.graphics.Color;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Paint.Cap;
-import android.graphics.Paint.Join;
-import android.graphics.Paint_Delegate;
-import android.graphics.Path;
-import android.graphics.PathMeasure;
-import android.graphics.Path_Delegate;
-import android.graphics.Rect;
-import android.graphics.Region.Op;
-import android.util.ArrayMap;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.MathUtils;
-import android.util.PathParser_Delegate;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-import java.util.ArrayList;
-import java.util.function.Consumer;
-
-import static android.graphics.Canvas.CLIP_SAVE_FLAG;
-import static android.graphics.Canvas.MATRIX_SAVE_FLAG;
-import static android.graphics.Paint.Cap.BUTT;
-import static android.graphics.Paint.Cap.ROUND;
-import static android.graphics.Paint.Cap.SQUARE;
-import static android.graphics.Paint.Join.BEVEL;
-import static android.graphics.Paint.Join.MITER;
-import static android.graphics.Paint.Style;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link VectorDrawable}
- * <p>
- * Through the layoutlib_create tool, the original methods of VectorDrawable have been replaced by
- * calls to methods of the same name in this delegate class.
- */
-@SuppressWarnings("unused")
-public class VectorDrawable_Delegate {
- private static final String LOGTAG = VectorDrawable_Delegate.class.getSimpleName();
- private static final boolean DBG_VECTOR_DRAWABLE = false;
-
- private static final DelegateManager<VNativeObject> sPathManager =
- new DelegateManager<>(VNativeObject.class);
-
- private static long addNativeObject(VNativeObject object) {
- long ptr = sPathManager.addNewDelegate(object);
- object.setNativePtr(ptr);
-
- return ptr;
- }
-
- /**
- * Obtains styled attributes from the theme, if available, or unstyled resources if the theme is
- * null.
- */
- private static TypedArray obtainAttributes(
- Resources res, Theme theme, AttributeSet set, int[] attrs) {
- if (theme == null) {
- return res.obtainAttributes(set, attrs);
- }
- return theme.obtainStyledAttributes(set, attrs, 0, 0);
- }
-
- private static int applyAlpha(int color, float alpha) {
- int alphaBytes = Color.alpha(color);
- color &= 0x00FFFFFF;
- color |= ((int) (alphaBytes * alpha)) << 24;
- return color;
- }
-
- @LayoutlibDelegate
- static long nCreateTree(long rootGroupPtr) {
- return addNativeObject(new VPathRenderer_Delegate(rootGroupPtr));
- }
-
- @LayoutlibDelegate
- static long nCreateTreeFromCopy(long rendererToCopyPtr, long rootGroupPtr) {
- VPathRenderer_Delegate rendererToCopy = VNativeObject.getDelegate(rendererToCopyPtr);
- return addNativeObject(new VPathRenderer_Delegate(rendererToCopy,
- rootGroupPtr));
- }
-
- @LayoutlibDelegate
- static void nSetRendererViewportSize(long rendererPtr, float viewportWidth,
- float viewportHeight) {
- VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
- nativePathRenderer.mViewportWidth = viewportWidth;
- nativePathRenderer.mViewportHeight = viewportHeight;
- }
-
- @LayoutlibDelegate
- static boolean nSetRootAlpha(long rendererPtr, float alpha) {
- VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
- nativePathRenderer.setRootAlpha(alpha);
-
- return true;
- }
-
- @LayoutlibDelegate
- static float nGetRootAlpha(long rendererPtr) {
- VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
-
- return nativePathRenderer.getRootAlpha();
- }
-
- @LayoutlibDelegate
- static void nSetAllowCaching(long rendererPtr, boolean allowCaching) {
- // ignored
- }
-
- @LayoutlibDelegate
- static int nDraw(long rendererPtr, long canvasWrapperPtr,
- long colorFilterPtr, Rect bounds, boolean needsMirroring, boolean canReuseCache) {
- VPathRenderer_Delegate nativePathRenderer = VNativeObject.getDelegate(rendererPtr);
-
- Canvas_Delegate.nSave(canvasWrapperPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
- Canvas_Delegate.nTranslate(canvasWrapperPtr, bounds.left, bounds.top);
-
- if (needsMirroring) {
- Canvas_Delegate.nTranslate(canvasWrapperPtr, bounds.width(), 0);
- Canvas_Delegate.nScale(canvasWrapperPtr, -1.0f, 1.0f);
- }
-
- // At this point, canvas has been translated to the right position.
- // And we use this bound for the destination rect for the drawBitmap, so
- // we offset to (0, 0);
- bounds.offsetTo(0, 0);
- nativePathRenderer.draw(canvasWrapperPtr, colorFilterPtr, bounds.width(), bounds.height());
-
- Canvas_Delegate.nRestore(canvasWrapperPtr);
-
- return bounds.width() * bounds.height();
- }
-
- @LayoutlibDelegate
- static long nCreateFullPath() {
- return addNativeObject(new VFullPath_Delegate());
- }
-
- @LayoutlibDelegate
- static long nCreateFullPath(long nativeFullPathPtr) {
- VFullPath_Delegate original = VNativeObject.getDelegate(nativeFullPathPtr);
- return addNativeObject(new VFullPath_Delegate(original));
- }
-
- @LayoutlibDelegate
- static boolean nGetFullPathProperties(long pathPtr, byte[] propertiesData,
- int length) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
-
- ByteBuffer properties = ByteBuffer.wrap(propertiesData);
- properties.order(ByteOrder.nativeOrder());
-
- properties.putFloat(VFullPath_Delegate.STROKE_WIDTH_INDEX * 4, path.getStrokeWidth());
- properties.putInt(VFullPath_Delegate.STROKE_COLOR_INDEX * 4, path.getStrokeColor());
- properties.putFloat(VFullPath_Delegate.STROKE_ALPHA_INDEX * 4, path.getStrokeAlpha());
- properties.putInt(VFullPath_Delegate.FILL_COLOR_INDEX * 4, path.getFillColor());
- properties.putFloat(VFullPath_Delegate.FILL_ALPHA_INDEX * 4, path.getStrokeAlpha());
- properties.putFloat(VFullPath_Delegate.TRIM_PATH_START_INDEX * 4, path.getTrimPathStart());
- properties.putFloat(VFullPath_Delegate.TRIM_PATH_END_INDEX * 4, path.getTrimPathEnd());
- properties.putFloat(VFullPath_Delegate.TRIM_PATH_OFFSET_INDEX * 4,
- path.getTrimPathOffset());
- properties.putInt(VFullPath_Delegate.STROKE_LINE_CAP_INDEX * 4, path.getStrokeLineCap());
- properties.putInt(VFullPath_Delegate.STROKE_LINE_JOIN_INDEX * 4, path.getStrokeLineJoin());
- properties.putFloat(VFullPath_Delegate.STROKE_MITER_LIMIT_INDEX * 4,
- path.getStrokeMiterlimit());
- properties.putInt(VFullPath_Delegate.FILL_TYPE_INDEX * 4, path.getFillType());
-
- return true;
- }
-
- @LayoutlibDelegate
- static void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
- int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
- float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
- int strokeLineJoin, int fillType) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
-
- path.setStrokeWidth(strokeWidth);
- path.setStrokeColor(strokeColor);
- path.setStrokeAlpha(strokeAlpha);
- path.setFillColor(fillColor);
- path.setFillAlpha(fillAlpha);
- path.setTrimPathStart(trimPathStart);
- path.setTrimPathEnd(trimPathEnd);
- path.setTrimPathOffset(trimPathOffset);
- path.setStrokeMiterlimit(strokeMiterLimit);
- path.setStrokeLineCap(strokeLineCap);
- path.setStrokeLineJoin(strokeLineJoin);
- path.setFillType(fillType);
- }
-
- @LayoutlibDelegate
- static void nUpdateFullPathFillGradient(long pathPtr, long fillGradientPtr) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
-
- path.setFillGradient(fillGradientPtr);
- }
-
- @LayoutlibDelegate
- static void nUpdateFullPathStrokeGradient(long pathPtr, long strokeGradientPtr) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
-
- path.setStrokeGradient(strokeGradientPtr);
- }
-
- @LayoutlibDelegate
- static long nCreateClipPath() {
- return addNativeObject(new VClipPath_Delegate());
- }
-
- @LayoutlibDelegate
- static long nCreateClipPath(long clipPathPtr) {
- VClipPath_Delegate original = VNativeObject.getDelegate(clipPathPtr);
- return addNativeObject(new VClipPath_Delegate(original));
- }
-
- @LayoutlibDelegate
- static long nCreateGroup() {
- return addNativeObject(new VGroup_Delegate());
- }
-
- @LayoutlibDelegate
- static long nCreateGroup(long groupPtr) {
- VGroup_Delegate original = VNativeObject.getDelegate(groupPtr);
- return addNativeObject(new VGroup_Delegate(original, new ArrayMap<>()));
- }
-
- @LayoutlibDelegate
- static void nSetName(long nodePtr, String name) {
- VNativeObject group = VNativeObject.getDelegate(nodePtr);
- group.setName(name);
- }
-
- @LayoutlibDelegate
- static boolean nGetGroupProperties(long groupPtr, float[] propertiesData,
- int length) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
-
- FloatBuffer properties = FloatBuffer.wrap(propertiesData);
-
- properties.put(VGroup_Delegate.ROTATE_INDEX, group.getRotation());
- properties.put(VGroup_Delegate.PIVOT_X_INDEX, group.getPivotX());
- properties.put(VGroup_Delegate.PIVOT_Y_INDEX, group.getPivotY());
- properties.put(VGroup_Delegate.SCALE_X_INDEX, group.getScaleX());
- properties.put(VGroup_Delegate.SCALE_Y_INDEX, group.getScaleY());
- properties.put(VGroup_Delegate.TRANSLATE_X_INDEX, group.getTranslateX());
- properties.put(VGroup_Delegate.TRANSLATE_Y_INDEX, group.getTranslateY());
-
- return true;
- }
- @LayoutlibDelegate
- static void nUpdateGroupProperties(long groupPtr, float rotate, float pivotX,
- float pivotY, float scaleX, float scaleY, float translateX, float translateY) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
-
- group.setRotation(rotate);
- group.setPivotX(pivotX);
- group.setPivotY(pivotY);
- group.setScaleX(scaleX);
- group.setScaleY(scaleY);
- group.setTranslateX(translateX);
- group.setTranslateY(translateY);
- }
-
- @LayoutlibDelegate
- static void nAddChild(long groupPtr, long nodePtr) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- group.mChildren.add(VNativeObject.getDelegate(nodePtr));
- }
-
- @LayoutlibDelegate
- static void nSetPathString(long pathPtr, String pathString, int length) {
- VPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- path.setPathData(PathParser_Delegate.createNodesFromPathData(pathString));
- }
-
- /**
- * The setters and getters below for paths and groups are here temporarily, and will be removed
- * once the animation in AVD is replaced with RenderNodeAnimator, in which case the animation
- * will modify these properties in native. By then no JNI hopping would be necessary for VD
- * during animation, and these setters and getters will be obsolete.
- */
- // Setters and getters during animation.
- @LayoutlibDelegate
- static float nGetRotation(long groupPtr) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- return group.getRotation();
- }
-
- @LayoutlibDelegate
- static void nSetRotation(long groupPtr, float rotation) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- group.setRotation(rotation);
- }
-
- @LayoutlibDelegate
- static float nGetPivotX(long groupPtr) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- return group.getPivotX();
- }
-
- @LayoutlibDelegate
- static void nSetPivotX(long groupPtr, float pivotX) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- group.setPivotX(pivotX);
- }
-
- @LayoutlibDelegate
- static float nGetPivotY(long groupPtr) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- return group.getPivotY();
- }
-
- @LayoutlibDelegate
- static void nSetPivotY(long groupPtr, float pivotY) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- group.setPivotY(pivotY);
- }
-
- @LayoutlibDelegate
- static float nGetScaleX(long groupPtr) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- return group.getScaleX();
- }
-
- @LayoutlibDelegate
- static void nSetScaleX(long groupPtr, float scaleX) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- group.setScaleX(scaleX);
- }
-
- @LayoutlibDelegate
- static float nGetScaleY(long groupPtr) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- return group.getScaleY();
- }
-
- @LayoutlibDelegate
- static void nSetScaleY(long groupPtr, float scaleY) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- group.setScaleY(scaleY);
- }
-
- @LayoutlibDelegate
- static float nGetTranslateX(long groupPtr) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- return group.getTranslateX();
- }
-
- @LayoutlibDelegate
- static void nSetTranslateX(long groupPtr, float translateX) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- group.setTranslateX(translateX);
- }
-
- @LayoutlibDelegate
- static float nGetTranslateY(long groupPtr) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- return group.getTranslateY();
- }
-
- @LayoutlibDelegate
- static void nSetTranslateY(long groupPtr, float translateY) {
- VGroup_Delegate group = VNativeObject.getDelegate(groupPtr);
- group.setTranslateY(translateY);
- }
-
- @LayoutlibDelegate
- static void nSetPathData(long pathPtr, long pathDataPtr) {
- VPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- path.setPathData(PathParser_Delegate.getDelegate(pathDataPtr).getPathDataNodes());
- }
-
- @LayoutlibDelegate
- static float nGetStrokeWidth(long pathPtr) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- return path.getStrokeWidth();
- }
-
- @LayoutlibDelegate
- static void nSetStrokeWidth(long pathPtr, float width) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- path.setStrokeWidth(width);
- }
-
- @LayoutlibDelegate
- static int nGetStrokeColor(long pathPtr) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- return path.getStrokeColor();
- }
-
- @LayoutlibDelegate
- static void nSetStrokeColor(long pathPtr, int strokeColor) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- path.setStrokeColor(strokeColor);
- }
-
- @LayoutlibDelegate
- static float nGetStrokeAlpha(long pathPtr) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- return path.getStrokeAlpha();
- }
-
- @LayoutlibDelegate
- static void nSetStrokeAlpha(long pathPtr, float alpha) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- path.setStrokeAlpha(alpha);
- }
-
- @LayoutlibDelegate
- static int nGetFillColor(long pathPtr) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- return path.getFillColor();
- }
-
- @LayoutlibDelegate
- static void nSetFillColor(long pathPtr, int fillColor) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- path.setFillColor(fillColor);
- }
-
- @LayoutlibDelegate
- static float nGetFillAlpha(long pathPtr) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- return path.getFillAlpha();
- }
-
- @LayoutlibDelegate
- static void nSetFillAlpha(long pathPtr, float fillAlpha) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- path.setFillAlpha(fillAlpha);
- }
-
- @LayoutlibDelegate
- static float nGetTrimPathStart(long pathPtr) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- return path.getTrimPathStart();
- }
-
- @LayoutlibDelegate
- static void nSetTrimPathStart(long pathPtr, float trimPathStart) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- path.setTrimPathStart(trimPathStart);
- }
-
- @LayoutlibDelegate
- static float nGetTrimPathEnd(long pathPtr) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- return path.getTrimPathEnd();
- }
-
- @LayoutlibDelegate
- static void nSetTrimPathEnd(long pathPtr, float trimPathEnd) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- path.setTrimPathEnd(trimPathEnd);
- }
-
- @LayoutlibDelegate
- static float nGetTrimPathOffset(long pathPtr) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- return path.getTrimPathOffset();
- }
-
- @LayoutlibDelegate
- static void nSetTrimPathOffset(long pathPtr, float trimPathOffset) {
- VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
- path.setTrimPathOffset(trimPathOffset);
- }
-
- /**
- * Base class for all the internal Delegates that does two functions:
- * <ol>
- * <li>Serves as base class to store all the delegates in one {@link DelegateManager}
- * <li>Provides setName for all the classes. {@link VPathRenderer_Delegate} does actually
- * not need it
- * </ol>
- */
- abstract static class VNativeObject {
- long mNativePtr = 0;
-
- @NonNull
- static <T> T getDelegate(long nativePtr) {
- //noinspection unchecked
- T vNativeObject = (T) sPathManager.getDelegate(nativePtr);
-
- assert vNativeObject != null;
- return vNativeObject;
- }
-
- abstract void setName(String name);
-
- void setNativePtr(long nativePtr) {
- mNativePtr = nativePtr;
- }
-
- /**
- * Method to explicitly dispose native objects
- */
- void dispose() {
- }
- }
-
- private static class VClipPath_Delegate extends VPath_Delegate {
- private VClipPath_Delegate() {
- // Empty constructor.
- }
-
- private VClipPath_Delegate(VClipPath_Delegate copy) {
- super(copy);
- }
-
- @Override
- public boolean isClipPath() {
- return true;
- }
- }
-
- static class VFullPath_Delegate extends VPath_Delegate {
- // These constants need to be kept in sync with their values in VectorDrawable.VFullPath
- private static final int STROKE_WIDTH_INDEX = 0;
- private static final int STROKE_COLOR_INDEX = 1;
- private static final int STROKE_ALPHA_INDEX = 2;
- private static final int FILL_COLOR_INDEX = 3;
- private static final int FILL_ALPHA_INDEX = 4;
- private static final int TRIM_PATH_START_INDEX = 5;
- private static final int TRIM_PATH_END_INDEX = 6;
- private static final int TRIM_PATH_OFFSET_INDEX = 7;
- private static final int STROKE_LINE_CAP_INDEX = 8;
- private static final int STROKE_LINE_JOIN_INDEX = 9;
- private static final int STROKE_MITER_LIMIT_INDEX = 10;
- private static final int FILL_TYPE_INDEX = 11;
-
- private static final int LINECAP_BUTT = 0;
- private static final int LINECAP_ROUND = 1;
- private static final int LINECAP_SQUARE = 2;
-
- private static final int LINEJOIN_MITER = 0;
- private static final int LINEJOIN_ROUND = 1;
- private static final int LINEJOIN_BEVEL = 2;
-
- @NonNull
- public Consumer<Float> getFloatPropertySetter(int propertyIdx) {
- switch (propertyIdx) {
- case STROKE_WIDTH_INDEX:
- return this::setStrokeWidth;
- case STROKE_ALPHA_INDEX:
- return this::setStrokeAlpha;
- case FILL_ALPHA_INDEX:
- return this::setFillAlpha;
- case TRIM_PATH_START_INDEX:
- return this::setTrimPathStart;
- case TRIM_PATH_END_INDEX:
- return this::setTrimPathEnd;
- case TRIM_PATH_OFFSET_INDEX:
- return this::setTrimPathOffset;
- }
-
- assert false : ("Invalid VFullPath_Delegate property index " + propertyIdx);
- return t -> {};
- }
-
- @NonNull
- public Consumer<Integer> getIntPropertySetter(int propertyIdx) {
- switch (propertyIdx) {
- case STROKE_COLOR_INDEX:
- return this::setStrokeColor;
- case FILL_COLOR_INDEX:
- return this::setFillColor;
- }
-
- assert false : ("Invalid VFullPath_Delegate property index " + propertyIdx);
- return t -> {};
- }
-
- /////////////////////////////////////////////////////
- // Variables below need to be copied (deep copy if applicable) for mutation.
-
- int mStrokeColor = Color.TRANSPARENT;
- float mStrokeWidth = 0;
-
- int mFillColor = Color.TRANSPARENT;
- long mStrokeGradient = 0;
- long mFillGradient = 0;
- float mStrokeAlpha = 1.0f;
- float mFillAlpha = 1.0f;
- float mTrimPathStart = 0;
- float mTrimPathEnd = 1;
- float mTrimPathOffset = 0;
-
- Cap mStrokeLineCap = BUTT;
- Join mStrokeLineJoin = MITER;
- float mStrokeMiterlimit = 4;
-
- int mFillType = 0; // WINDING(0) is the default value. See Path.FillType
-
- private VFullPath_Delegate() {
- // Empty constructor.
- }
-
- private VFullPath_Delegate(VFullPath_Delegate copy) {
- super(copy);
-
- mStrokeColor = copy.mStrokeColor;
- mStrokeWidth = copy.mStrokeWidth;
- mStrokeAlpha = copy.mStrokeAlpha;
- mFillColor = copy.mFillColor;
- mFillAlpha = copy.mFillAlpha;
- mTrimPathStart = copy.mTrimPathStart;
- mTrimPathEnd = copy.mTrimPathEnd;
- mTrimPathOffset = copy.mTrimPathOffset;
-
- mStrokeLineCap = copy.mStrokeLineCap;
- mStrokeLineJoin = copy.mStrokeLineJoin;
- mStrokeMiterlimit = copy.mStrokeMiterlimit;
-
- mStrokeGradient = copy.mStrokeGradient;
- mFillGradient = copy.mFillGradient;
- mFillType = copy.mFillType;
- }
-
- private int getStrokeLineCap() {
- switch (mStrokeLineCap) {
- case BUTT:
- return LINECAP_BUTT;
- case ROUND:
- return LINECAP_ROUND;
- case SQUARE:
- return LINECAP_SQUARE;
- default:
- assert false;
- }
-
- return -1;
- }
-
- private void setStrokeLineCap(int cap) {
- switch (cap) {
- case LINECAP_BUTT:
- mStrokeLineCap = BUTT;
- break;
- case LINECAP_ROUND:
- mStrokeLineCap = ROUND;
- break;
- case LINECAP_SQUARE:
- mStrokeLineCap = SQUARE;
- break;
- default:
- assert false;
- }
- }
-
- private int getStrokeLineJoin() {
- switch (mStrokeLineJoin) {
- case MITER:
- return LINEJOIN_MITER;
- case ROUND:
- return LINEJOIN_ROUND;
- case BEVEL:
- return LINEJOIN_BEVEL;
- default:
- assert false;
- }
-
- return -1;
- }
-
- private void setStrokeLineJoin(int join) {
- switch (join) {
- case LINEJOIN_BEVEL:
- mStrokeLineJoin = BEVEL;
- break;
- case LINEJOIN_MITER:
- mStrokeLineJoin = MITER;
- break;
- case LINEJOIN_ROUND:
- mStrokeLineJoin = Join.ROUND;
- break;
- default:
- assert false;
- }
- }
-
- private int getStrokeColor() {
- return mStrokeColor;
- }
-
- private void setStrokeColor(int strokeColor) {
- mStrokeColor = strokeColor;
- }
-
- private float getStrokeWidth() {
- return mStrokeWidth;
- }
-
- private void setStrokeWidth(float strokeWidth) {
- mStrokeWidth = strokeWidth;
- }
-
- private float getStrokeAlpha() {
- return mStrokeAlpha;
- }
-
- private void setStrokeAlpha(float strokeAlpha) {
- mStrokeAlpha = strokeAlpha;
- }
-
- private int getFillColor() {
- return mFillColor;
- }
-
- private void setFillColor(int fillColor) {
- mFillColor = fillColor;
- }
-
- private float getFillAlpha() {
- return mFillAlpha;
- }
-
- private void setFillAlpha(float fillAlpha) {
- mFillAlpha = fillAlpha;
- }
-
- private float getTrimPathStart() {
- return mTrimPathStart;
- }
-
- private void setTrimPathStart(float trimPathStart) {
- mTrimPathStart = trimPathStart;
- }
-
- private float getTrimPathEnd() {
- return mTrimPathEnd;
- }
-
- private void setTrimPathEnd(float trimPathEnd) {
- mTrimPathEnd = trimPathEnd;
- }
-
- private float getTrimPathOffset() {
- return mTrimPathOffset;
- }
-
- private void setTrimPathOffset(float trimPathOffset) {
- mTrimPathOffset = trimPathOffset;
- }
-
- private void setStrokeMiterlimit(float limit) {
- mStrokeMiterlimit = limit;
- }
-
- private float getStrokeMiterlimit() {
- return mStrokeMiterlimit;
- }
-
- private void setStrokeGradient(long gradientPtr) {
- mStrokeGradient = gradientPtr;
- }
-
- private void setFillGradient(long gradientPtr) {
- mFillGradient = gradientPtr;
- }
-
- private void setFillType(int fillType) {
- mFillType = fillType;
- }
-
- private int getFillType() {
- return mFillType;
- }
- }
-
- static class VGroup_Delegate extends VNativeObject {
- // This constants need to be kept in sync with their definitions in VectorDrawable.Group
- private static final int ROTATE_INDEX = 0;
- private static final int PIVOT_X_INDEX = 1;
- private static final int PIVOT_Y_INDEX = 2;
- private static final int SCALE_X_INDEX = 3;
- private static final int SCALE_Y_INDEX = 4;
- private static final int TRANSLATE_X_INDEX = 5;
- private static final int TRANSLATE_Y_INDEX = 6;
-
- public Consumer<Float> getPropertySetter(int propertyIdx) {
- switch (propertyIdx) {
- case ROTATE_INDEX:
- return this::setRotation;
- case PIVOT_X_INDEX:
- return this::setPivotX;
- case PIVOT_Y_INDEX:
- return this::setPivotY;
- case SCALE_X_INDEX:
- return this::setScaleX;
- case SCALE_Y_INDEX:
- return this::setScaleY;
- case TRANSLATE_X_INDEX:
- return this::setTranslateX;
- case TRANSLATE_Y_INDEX:
- return this::setTranslateY;
- }
-
- assert false : ("Invalid VGroup_Delegate property index " + propertyIdx);
- return t -> {};
- }
-
- /////////////////////////////////////////////////////
- // Variables below need to be copied (deep copy if applicable) for mutation.
- final ArrayList<Object> mChildren = new ArrayList<>();
- // mStackedMatrix is only used temporarily when drawing, it combines all
- // the parents' local matrices with the current one.
- private final Matrix mStackedMatrix = new Matrix();
- // mLocalMatrix is updated based on the update of transformation information,
- // either parsed from the XML or by animation.
- private final Matrix mLocalMatrix = new Matrix();
- private float mRotate = 0;
- private float mPivotX = 0;
- private float mPivotY = 0;
- private float mScaleX = 1;
- private float mScaleY = 1;
- private float mTranslateX = 0;
- private float mTranslateY = 0;
- private int mChangingConfigurations;
- private String mGroupName = null;
-
- private VGroup_Delegate(VGroup_Delegate copy, ArrayMap<String, Object> targetsMap) {
- mRotate = copy.mRotate;
- mPivotX = copy.mPivotX;
- mPivotY = copy.mPivotY;
- mScaleX = copy.mScaleX;
- mScaleY = copy.mScaleY;
- mTranslateX = copy.mTranslateX;
- mTranslateY = copy.mTranslateY;
- mGroupName = copy.mGroupName;
- mChangingConfigurations = copy.mChangingConfigurations;
- if (mGroupName != null) {
- targetsMap.put(mGroupName, this);
- }
-
- mLocalMatrix.set(copy.mLocalMatrix);
- }
-
- private VGroup_Delegate() {
- }
-
- private void updateLocalMatrix() {
- // The order we apply is the same as the
- // RenderNode.cpp::applyViewPropertyTransforms().
- mLocalMatrix.reset();
- mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
- mLocalMatrix.postScale(mScaleX, mScaleY);
- mLocalMatrix.postRotate(mRotate, 0, 0);
- mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
- }
-
- /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
- private float getRotation() {
- return mRotate;
- }
-
- private void setRotation(float rotation) {
- if (rotation != mRotate) {
- mRotate = rotation;
- updateLocalMatrix();
- }
- }
-
- private float getPivotX() {
- return mPivotX;
- }
-
- private void setPivotX(float pivotX) {
- if (pivotX != mPivotX) {
- mPivotX = pivotX;
- updateLocalMatrix();
- }
- }
-
- private float getPivotY() {
- return mPivotY;
- }
-
- private void setPivotY(float pivotY) {
- if (pivotY != mPivotY) {
- mPivotY = pivotY;
- updateLocalMatrix();
- }
- }
-
- private float getScaleX() {
- return mScaleX;
- }
-
- private void setScaleX(float scaleX) {
- if (scaleX != mScaleX) {
- mScaleX = scaleX;
- updateLocalMatrix();
- }
- }
-
- private float getScaleY() {
- return mScaleY;
- }
-
- private void setScaleY(float scaleY) {
- if (scaleY != mScaleY) {
- mScaleY = scaleY;
- updateLocalMatrix();
- }
- }
-
- private float getTranslateX() {
- return mTranslateX;
- }
-
- private void setTranslateX(float translateX) {
- if (translateX != mTranslateX) {
- mTranslateX = translateX;
- updateLocalMatrix();
- }
- }
-
- private float getTranslateY() {
- return mTranslateY;
- }
-
- private void setTranslateY(float translateY) {
- if (translateY != mTranslateY) {
- mTranslateY = translateY;
- updateLocalMatrix();
- }
- }
-
- @Override
- public void setName(String name) {
- mGroupName = name;
- }
-
- @Override
- protected void dispose() {
- mChildren.stream().filter(child -> child instanceof VNativeObject).forEach(child
- -> {
- VNativeObject nativeObject = (VNativeObject) child;
- if (nativeObject.mNativePtr != 0) {
- sPathManager.removeJavaReferenceFor(nativeObject.mNativePtr);
- nativeObject.mNativePtr = 0;
- }
- nativeObject.dispose();
- });
- mChildren.clear();
- }
-
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
- }
- }
-
- public static class VPath_Delegate extends VNativeObject {
- protected PathParser_Delegate.PathDataNode[] mNodes = null;
- String mPathName;
- int mChangingConfigurations;
-
- public VPath_Delegate() {
- // Empty constructor.
- }
-
- public VPath_Delegate(VPath_Delegate copy) {
- mPathName = copy.mPathName;
- mChangingConfigurations = copy.mChangingConfigurations;
- mNodes = copy.mNodes != null ? PathParser_Delegate.deepCopyNodes(copy.mNodes) : null;
- }
-
- public void toPath(Path path) {
- path.reset();
- if (mNodes != null) {
- PathParser_Delegate.PathDataNode.nodesToPath(mNodes,
- Path_Delegate.getDelegate(path.mNativePath));
- }
- }
-
- @Override
- public void setName(String name) {
- mPathName = name;
- }
-
- public boolean isClipPath() {
- return false;
- }
-
- private void setPathData(PathParser_Delegate.PathDataNode[] nodes) {
- if (!PathParser_Delegate.canMorph(mNodes, nodes)) {
- // This should not happen in the middle of animation.
- mNodes = PathParser_Delegate.deepCopyNodes(nodes);
- } else {
- PathParser_Delegate.updateNodes(mNodes, nodes);
- }
- }
-
- @Override
- void dispose() {
- mNodes = null;
- }
- }
-
- static class VPathRenderer_Delegate extends VNativeObject {
- /* Right now the internal data structure is organized as a tree.
- * Each node can be a group node, or a path.
- * A group node can have groups or paths as children, but a path node has
- * no children.
- * One example can be:
- * Root Group
- * / | \
- * Group Path Group
- * / \ |
- * Path Path Path
- *
- */
- // Variables that only used temporarily inside the draw() call, so there
- // is no need for deep copying.
- private final Path mPath;
- private final Path mRenderPath;
- private final Matrix mFinalPathMatrix = new Matrix();
- private final long mRootGroupPtr;
- private float mViewportWidth = 0;
- private float mViewportHeight = 0;
- private float mRootAlpha = 1.0f;
- private Paint mStrokePaint;
- private Paint mFillPaint;
- private PathMeasure mPathMeasure;
-
- private VPathRenderer_Delegate(long rootGroupPtr) {
- mRootGroupPtr = rootGroupPtr;
- mPath = new Path();
- mRenderPath = new Path();
- }
-
- private VPathRenderer_Delegate(VPathRenderer_Delegate rendererToCopy,
- long rootGroupPtr) {
- this(rootGroupPtr);
- mViewportWidth = rendererToCopy.mViewportWidth;
- mViewportHeight = rendererToCopy.mViewportHeight;
- mRootAlpha = rendererToCopy.mRootAlpha;
- }
-
- private float getRootAlpha() {
- return mRootAlpha;
- }
-
- void setRootAlpha(float alpha) {
- mRootAlpha = alpha;
- }
-
- private void drawGroupTree(VGroup_Delegate currentGroup, Matrix currentMatrix,
- long canvasPtr, int w, int h, long filterPtr) {
- // Calculate current group's matrix by preConcat the parent's and
- // and the current one on the top of the stack.
- // Basically the Mfinal = Mviewport * M0 * M1 * M2;
- // Mi the local matrix at level i of the group tree.
- currentGroup.mStackedMatrix.set(currentMatrix);
- currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
-
- // Save the current clip information, which is local to this group.
- Canvas_Delegate.nSave(canvasPtr, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
- // Draw the group tree in the same order as the XML file.
- for (int i = 0; i < currentGroup.mChildren.size(); i++) {
- Object child = currentGroup.mChildren.get(i);
- if (child instanceof VGroup_Delegate) {
- VGroup_Delegate childGroup = (VGroup_Delegate) child;
- drawGroupTree(childGroup, currentGroup.mStackedMatrix,
- canvasPtr, w, h, filterPtr);
- } else if (child instanceof VPath_Delegate) {
- VPath_Delegate childPath = (VPath_Delegate) child;
- drawPath(currentGroup, childPath, canvasPtr, w, h, filterPtr);
- }
- }
- Canvas_Delegate.nRestore(canvasPtr);
- }
-
- public void draw(long canvasPtr, long filterPtr, int w, int h) {
- // Traverse the tree in pre-order to draw.
- drawGroupTree(VNativeObject.getDelegate(mRootGroupPtr), Matrix.IDENTITY_MATRIX, canvasPtr, w, h, filterPtr);
- }
-
- private void drawPath(VGroup_Delegate VGroup, VPath_Delegate VPath, long canvasPtr,
- int w,
- int h,
- long filterPtr) {
- final float scaleX = w / mViewportWidth;
- final float scaleY = h / mViewportHeight;
- final float minScale = Math.min(scaleX, scaleY);
- final Matrix groupStackedMatrix = VGroup.mStackedMatrix;
-
- mFinalPathMatrix.set(groupStackedMatrix);
- mFinalPathMatrix.postScale(scaleX, scaleY);
-
- final float matrixScale = getMatrixScale(groupStackedMatrix);
- if (matrixScale == 0) {
- // When either x or y is scaled to 0, we don't need to draw anything.
- return;
- }
- VPath.toPath(mPath);
- final Path path = mPath;
-
- mRenderPath.reset();
-
- if (VPath.isClipPath()) {
- mRenderPath.addPath(path, mFinalPathMatrix);
- Canvas_Delegate.nClipPath(canvasPtr, mRenderPath.mNativePath, Op
- .INTERSECT.nativeInt);
- } else {
- VFullPath_Delegate fullPath = (VFullPath_Delegate) VPath;
- if (fullPath.mTrimPathStart != 0.0f || fullPath.mTrimPathEnd != 1.0f) {
- float start = (fullPath.mTrimPathStart + fullPath.mTrimPathOffset) % 1.0f;
- float end = (fullPath.mTrimPathEnd + fullPath.mTrimPathOffset) % 1.0f;
-
- if (mPathMeasure == null) {
- mPathMeasure = new PathMeasure();
- }
- mPathMeasure.setPath(mPath, false);
-
- float len = mPathMeasure.getLength();
- start = start * len;
- end = end * len;
- path.reset();
- if (start > end) {
- mPathMeasure.getSegment(start, len, path, true);
- mPathMeasure.getSegment(0f, end, path, true);
- } else {
- mPathMeasure.getSegment(start, end, path, true);
- }
- path.rLineTo(0, 0); // fix bug in measure
- }
- mRenderPath.addPath(path, mFinalPathMatrix);
-
- if (fullPath.mFillColor != Color.TRANSPARENT) {
- if (mFillPaint == null) {
- mFillPaint = new Paint();
- mFillPaint.setStyle(Style.FILL);
- mFillPaint.setAntiAlias(true);
- }
-
- final Paint fillPaint = mFillPaint;
- fillPaint.setColor(applyAlpha(applyAlpha(fullPath.mFillColor, fullPath
- .mFillAlpha), getRootAlpha()));
- Paint_Delegate fillPaintDelegate = Paint_Delegate.getDelegate(fillPaint
- .getNativeInstance());
- // mFillPaint can not be null at this point so we will have a delegate
- assert fillPaintDelegate != null;
- fillPaintDelegate.setColorFilter(filterPtr);
- fillPaintDelegate.setShader(fullPath.mFillGradient);
- Path_Delegate.nSetFillType(mRenderPath.mNativePath, fullPath.mFillType);
- BaseCanvas_Delegate.nDrawPath(canvasPtr, mRenderPath.mNativePath, fillPaint
- .getNativeInstance());
- }
-
- if (fullPath.mStrokeColor != Color.TRANSPARENT) {
- if (mStrokePaint == null) {
- mStrokePaint = new Paint();
- mStrokePaint.setStyle(Style.STROKE);
- mStrokePaint.setAntiAlias(true);
- }
-
- final Paint strokePaint = mStrokePaint;
- if (fullPath.mStrokeLineJoin != null) {
- strokePaint.setStrokeJoin(fullPath.mStrokeLineJoin);
- }
-
- if (fullPath.mStrokeLineCap != null) {
- strokePaint.setStrokeCap(fullPath.mStrokeLineCap);
- }
-
- strokePaint.setStrokeMiter(fullPath.mStrokeMiterlimit);
- strokePaint.setColor(applyAlpha(applyAlpha(fullPath.mStrokeColor, fullPath
- .mStrokeAlpha), getRootAlpha()));
- Paint_Delegate strokePaintDelegate = Paint_Delegate.getDelegate(strokePaint
- .getNativeInstance());
- // mStrokePaint can not be null at this point so we will have a delegate
- assert strokePaintDelegate != null;
- strokePaintDelegate.setColorFilter(filterPtr);
- final float finalStrokeScale = minScale * matrixScale;
- strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
- strokePaintDelegate.setShader(fullPath.mStrokeGradient);
- BaseCanvas_Delegate.nDrawPath(canvasPtr, mRenderPath.mNativePath, strokePaint
- .getNativeInstance());
- }
- }
- }
-
- private float getMatrixScale(Matrix groupStackedMatrix) {
- // Given unit vectors A = (0, 1) and B = (1, 0).
- // After matrix mapping, we got A' and B'. Let theta = the angel b/t A' and B'.
- // Therefore, the final scale we want is min(|A'| * sin(theta), |B'| * sin(theta)),
- // which is (|A'| * |B'| * sin(theta)) / max (|A'|, |B'|);
- // If max (|A'|, |B'|) = 0, that means either x or y has a scale of 0.
- //
- // For non-skew case, which is most of the cases, matrix scale is computing exactly the
- // scale on x and y axis, and take the minimal of these two.
- // For skew case, an unit square will mapped to a parallelogram. And this function will
- // return the minimal height of the 2 bases.
- float[] unitVectors = new float[]{0, 1, 1, 0};
- groupStackedMatrix.mapVectors(unitVectors);
- float scaleX = MathUtils.mag(unitVectors[0], unitVectors[1]);
- float scaleY = MathUtils.mag(unitVectors[2], unitVectors[3]);
- float crossProduct = MathUtils.cross(unitVectors[0], unitVectors[1],
- unitVectors[2], unitVectors[3]);
- float maxScale = MathUtils.max(scaleX, scaleY);
-
- float matrixScale = 0;
- if (maxScale > 0) {
- matrixScale = MathUtils.abs(crossProduct) / maxScale;
- }
- if (DBG_VECTOR_DRAWABLE) {
- Log.d(LOGTAG, "Scale x " + scaleX + " y " + scaleY + " final " + matrixScale);
- }
- return matrixScale;
- }
-
- @Override
- public void setName(String name) {
- }
-
- @Override
- protected void finalize() throws Throwable {
- // The mRootGroupPtr is not explicitly freed by anything in the VectorDrawable so we
- // need to free it here.
- VNativeObject nativeObject = sPathManager.getDelegate(mRootGroupPtr);
- sPathManager.removeJavaReferenceFor(mRootGroupPtr);
- assert nativeObject != null;
- nativeObject.dispose();
-
- super.finalize();
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.RenderAction;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Delegate overriding selected methods of android.os.HandlerThread
- *
- * Through the layoutlib_create tool, selected methods of Handler have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- *
- */
-public class HandlerThread_Delegate {
-
- private static Map<BridgeContext, List<HandlerThread>> sThreads =
- new HashMap<BridgeContext, List<HandlerThread>>();
-
- public static void cleanUp(BridgeContext context) {
- List<HandlerThread> list = sThreads.get(context);
- if (list != null) {
- for (HandlerThread thread : list) {
- thread.quit();
- }
-
- list.clear();
- sThreads.remove(context);
- }
- }
-
- // -------- Delegate methods
-
- @LayoutlibDelegate
- /*package*/ static void run(HandlerThread theThread) {
- // record the thread so that it can be quit() on clean up.
- BridgeContext context = RenderAction.getCurrentContext();
- List<HandlerThread> list = sThreads.get(context);
- if (list == null) {
- list = new ArrayList<HandlerThread>();
- sThreads.put(context, list);
- }
-
- list.add(theThread);
-
- // ---- START DEFAULT IMPLEMENTATION.
-
- theThread.mTid = Process.myTid();
- Looper.prepare();
- synchronized (theThread) {
- theThread.mLooper = Looper.myLooper();
- theThread.notifyAll();
- }
- Process.setThreadPriority(theThread.mPriority);
- theThread.onLooperPrepared();
- Looper.loop();
- theThread.mTid = -1;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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.os;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-
-/**
- * Delegate overriding selected methods of android.os.Handler
- *
- * Through the layoutlib_create tool, selected methods of Handler have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- *
- */
-public class Handler_Delegate {
-
- // -------- Delegate methods
-
- @LayoutlibDelegate
- /*package*/ static boolean sendMessageAtTime(Handler handler, Message msg, long uptimeMillis) {
- // get the callback
- IHandlerCallback callback = sCallbacks.get();
- if (callback != null) {
- callback.sendMessageAtTime(handler, msg, uptimeMillis);
- }
- return true;
- }
-
- // -------- Delegate implementation
-
- public interface IHandlerCallback {
- void sendMessageAtTime(Handler handler, Message msg, long uptimeMillis);
- }
-
- private final static ThreadLocal<IHandlerCallback> sCallbacks =
- new ThreadLocal<IHandlerCallback>();
-
- public static void setCallback(IHandlerCallback callback) {
- sCallbacks.set(callback);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.os;
-
-import java.lang.reflect.Field;
-
-/**
- * Class allowing access to package-protected methods/fields.
- */
-public class Looper_Accessor {
-
- public static void cleanupThread() {
- // clean up the looper
- Looper.sThreadLocal.remove();
- try {
- Field sMainLooper = Looper.class.getDeclaredField("sMainLooper");
- sMainLooper.setAccessible(true);
- sMainLooper.set(null, null);
- } catch (SecurityException e) {
- catchReflectionException();
- } catch (IllegalArgumentException e) {
- catchReflectionException();
- } catch (NoSuchFieldException e) {
- catchReflectionException();
- } catch (IllegalAccessException e) {
- catchReflectionException();
- }
-
- }
-
- private static void catchReflectionException() {
- assert(false);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2009 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.os;
-
-import java.util.Map;
-
-public final class ServiceManager {
-
- /**
- * Returns a reference to a service with the given name.
- *
- * @param name the name of the service to get
- * @return a reference to the service, or <code>null</code> if the service doesn't exist
- */
- public static IBinder getService(String name) {
- return null;
- }
-
- /**
- * Is not supposed to return null, but that is fine for layoutlib.
- */
- public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
- throw new ServiceNotFoundException(name);
- }
-
- /**
- * Place a new @a service called @a name into the service
- * manager.
- *
- * @param name the name of the new service
- * @param service the service object
- */
- public static void addService(String name, IBinder service) {
- // pass
- }
-
- /**
- * Retrieve an existing service called @a name from the
- * service manager. Non-blocking.
- */
- public static IBinder checkService(String name) {
- return null;
- }
-
- /**
- * Return a list of all currently running services.
- * @return an array of all currently running services, or <code>null</code> in
- * case of an exception
- */
- public static String[] listServices() {
- // actual implementation returns null sometimes, so it's ok
- // to return null instead of an empty list.
- return null;
- }
-
- /**
- * This is only intended to be called when the process is first being brought
- * up and bound by the activity manager. There is only one thread in the process
- * at that time, so no locking is done.
- *
- * @param cache the cache of service references
- * @hide
- */
- public static void initServiceCache(Map<String, IBinder> cache) {
- // pass
- }
-
- /**
- * Exception thrown when no service published for given name. This might be
- * thrown early during boot before certain services have published
- * themselves.
- *
- * @hide
- */
- public static class ServiceNotFoundException extends Exception {
- // identical to the original implementation
- public ServiceNotFoundException(String name) {
- super("No service published for: " + name);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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.os;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-import com.android.tools.layoutlib.java.System_Delegate;
-
-/**
- * Delegate implementing the native methods of android.os.SystemClock
- *
- * Through the layoutlib_create tool, the original native methods of SystemClock have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
- * around to map int to instance of the delegate.
- *
- */
-public class SystemClock_Delegate {
- /**
- * Returns milliseconds since boot, not counting time spent in deep sleep.
- * <b>Note:</b> This value may get reset occasionally (before it would
- * otherwise wrap around).
- *
- * @return milliseconds of non-sleep uptime since boot.
- */
- @LayoutlibDelegate
- /*package*/ static long uptimeMillis() {
- return System_Delegate.currentTimeMillis() - System_Delegate.bootTimeMillis();
- }
-
- /**
- * Returns milliseconds since boot, including time spent in sleep.
- *
- * @return elapsed milliseconds since boot.
- */
- @LayoutlibDelegate
- /*package*/ static long elapsedRealtime() {
- return System_Delegate.currentTimeMillis() - System_Delegate.bootTimeMillis();
- }
-
- /**
- * Returns nanoseconds since boot, including time spent in sleep.
- *
- * @return elapsed nanoseconds since boot.
- */
- @LayoutlibDelegate
- /*package*/ static long elapsedRealtimeNanos() {
- return System_Delegate.nanoTime() - System_Delegate.bootTime();
- }
-
- /**
- * Returns milliseconds running in the current thread.
- *
- * @return elapsed milliseconds in the thread
- */
- @LayoutlibDelegate
- /*package*/ static long currentThreadTimeMillis() {
- return System_Delegate.currentTimeMillis();
- }
-
- /**
- * Returns microseconds running in the current thread.
- *
- * @return elapsed microseconds in the thread
- *
- * @hide
- */
- @LayoutlibDelegate
- /*package*/ static long currentThreadTimeMicro() {
- return System_Delegate.currentTimeMillis() * 1000;
- }
-
- /**
- * Returns current wall time in microseconds.
- *
- * @return elapsed microseconds in wall time
- *
- * @hide
- */
- @LayoutlibDelegate
- /*package*/ static long currentTimeMicro() {
- return elapsedRealtime() * 1000;
- }
-}
+++ /dev/null
-/*
- * 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.os;
-
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.util.Map;
-
-/**
- * Delegate implementing the native methods of android.os.SystemProperties
- *
- * Through the layoutlib_create tool, the original native methods of SystemProperties have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
- * around to map int to instance of the delegate.
- */
-public class SystemProperties_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static String native_get(String key) {
- return native_get(key, "");
- }
-
- @LayoutlibDelegate
- /*package*/ static String native_get(String key, String def) {
- Map<String, String> properties = Bridge.getPlatformProperties();
- String value = properties.get(key);
- if (value != null) {
- return value;
- }
-
- return def;
- }
- @LayoutlibDelegate
- /*package*/ static int native_get_int(String key, int def) {
- Map<String, String> properties = Bridge.getPlatformProperties();
- String value = properties.get(key);
- if (value != null) {
- return Integer.decode(value);
- }
-
- return def;
- }
-
- @LayoutlibDelegate
- /*package*/ static long native_get_long(String key, long def) {
- Map<String, String> properties = Bridge.getPlatformProperties();
- String value = properties.get(key);
- if (value != null) {
- return Long.decode(value);
- }
-
- return def;
- }
-
- /**
- * Values 'n', 'no', '0', 'false' or 'off' are considered false.
- * Values 'y', 'yes', '1', 'true' or 'on' are considered true.
- */
- @LayoutlibDelegate
- /*package*/ static boolean native_get_boolean(String key, boolean def) {
- Map<String, String> properties = Bridge.getPlatformProperties();
- String value = properties.get(key);
-
- if ("n".equals(value) || "no".equals(value) || "0".equals(value) || "false".equals(value)
- || "off".equals(value)) {
- return false;
- }
- //noinspection SimplifiableIfStatement
- if ("y".equals(value) || "yes".equals(value) || "1".equals(value) || "true".equals(value)
- || "on".equals(value)) {
- return true;
- }
-
- return def;
- }
-
- @LayoutlibDelegate
- /*package*/ static void native_set(String key, String def) {
- Map<String, String> properties = Bridge.getPlatformProperties();
- properties.put(key, def);
- }
-
- @LayoutlibDelegate
- /*package*/ static void native_add_change_callback() {
- // pass.
- }
-
- @LayoutlibDelegate
- /*package*/ static void native_report_sysprop_change() {
- // pass.
- }
-}
+++ /dev/null
-/*
- * 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.preference;
-
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.InflateException;
-
-public class BridgePreferenceInflater extends PreferenceInflater {
-
- public BridgePreferenceInflater(Context context, PreferenceManager preferenceManager) {
- super(context, preferenceManager);
- }
-
- @Override
- protected Preference onCreateItem(String name, AttributeSet attrs)
- throws ClassNotFoundException {
- Object viewKey = null;
- BridgeContext bc = null;
-
- Context context = getContext();
- if (context instanceof BridgeContext) {
- bc = (BridgeContext) context;
- }
- if (attrs instanceof BridgeXmlBlockParser) {
- viewKey = ((BridgeXmlBlockParser) attrs).getViewCookie();
- }
-
- Preference preference = null;
- try {
- preference = super.onCreateItem(name, attrs);
- } catch (ClassNotFoundException | InflateException exception) {
- // name is probably not a valid preference type
- if ("SwitchPreferenceCompat".equals(name)) {
- preference = super.onCreateItem("SwitchPreference", attrs);
- }
- }
-
- if (viewKey != null && bc != null) {
- bc.addCookie(preference, viewKey);
- }
- return preference;
- }
-}
+++ /dev/null
-/*
- * 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.preference;
-
-import com.android.internal.R;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ListView;
-
-/**
- * Delegate that provides implementation for native methods in {@link Preference}
- * <p/>
- * Through the layoutlib_create tool, selected methods of Preference have been replaced by calls to
- * methods of the same name in this delegate class.
- */
-public class Preference_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static View getView(Preference pref, View convertView, ViewGroup parent) {
- Context context = pref.getContext();
- BridgeContext bc = context instanceof BridgeContext ? ((BridgeContext) context) : null;
- convertView = pref.getView_Original(convertView, parent);
- if (bc != null) {
- Object cookie = bc.getCookie(pref);
- if (cookie != null) {
- bc.addViewKey(convertView, cookie);
- }
- }
- return convertView;
- }
-
- /**
- * Inflates the parser and returns the ListView containing the Preferences.
- */
- public static View inflatePreference(Context context, XmlPullParser parser, ViewGroup root) {
- PreferenceManager pm = new PreferenceManager(context);
- PreferenceInflater inflater = new BridgePreferenceInflater(context, pm);
- PreferenceScreen ps = (PreferenceScreen) inflater.inflate(parser, null, true);
- pm.setPreferences(ps);
- ListView preferenceView = createContainerView(context, root);
- ps.bind(preferenceView);
- return preferenceView;
- }
-
- private static ListView createContainerView(Context context, ViewGroup root) {
- TypedArray a = context.obtainStyledAttributes(null, R.styleable.PreferenceFragment,
- R.attr.preferenceFragmentStyle, 0);
- int mLayoutResId = a.getResourceId(R.styleable.PreferenceFragment_layout,
- R.layout.preference_list_fragment);
- a.recycle();
-
- LayoutInflater inflater =
- (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(mLayoutResId, root, true);
-
- return (ListView) root.findViewById(android.R.id.list);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.icu.text.Bidi;
-
-/**
- * Delegate used to provide new implementation for the native methods of {@link AndroidBidi}
- *
- * Through the layoutlib_create tool, the original methods of AndroidBidi have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-public class AndroidBidi_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static int runBidi(int dir, char[] chars, byte[] charInfo, int count,
- boolean haveInfo) {
-
- switch (dir) {
- case 0: // Layout.DIR_REQUEST_LTR
- dir = Bidi.LTR;
- break;
- case 1: // Layout.DIR_REQUEST_RTL
- dir = Bidi.RTL;
- break;
- case -1: // Layout.DIR_REQUEST_DEFAULT_RTL
- dir = Bidi.LEVEL_DEFAULT_RTL;
- break;
- case -2: // Layout.DIR_REQUEST_DEFAULT_LTR
- dir = Bidi.LEVEL_DEFAULT_LTR;
- break;
- default:
- // Invalid code. Log error, assume LEVEL_DEFAULT_LTR and continue.
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Invalid direction flag", null);
- dir = Bidi.LEVEL_DEFAULT_LTR;
- }
- Bidi bidi = new Bidi(chars, 0, null, 0, count, dir);
- if (charInfo != null) {
- for (int i = 0; i < count; ++i)
- charInfo[i] = bidi.getLevelAt(i);
- }
- return bidi.getParaLevel();
- }
-}
+++ /dev/null
-/*
- * 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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;
-import java.nio.ByteBuffer;
-
-/**
- * Delegate that overrides implementation for certain methods in {@link android.text.Hyphenator}
- * <p/>
- * Through the layoutlib_create tool, selected methods of Hyphenator have been replaced
- * by calls to methods of the same name in this delegate class.
- */
-public class Hyphenator_Delegate {
-
- private static final DelegateManager<Hyphenator_Delegate> sDelegateManager = new
- DelegateManager<Hyphenator_Delegate>(Hyphenator_Delegate.class);
-
- @LayoutlibDelegate
- /*package*/ static File getSystemHyphenatorLocation() {
- // FIXME
- return null;
- }
-
- /*package*/ @SuppressWarnings("UnusedParameters") // TODO implement this.
- static long loadHyphenator(ByteBuffer buffer, int offset, int minPrefix, int minSuffix) {
- return sDelegateManager.addNewDelegate(new Hyphenator_Delegate());
- }
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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;
- }
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
-
+++ /dev/null
-package android.text;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-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.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.swing.text.Segment;
-
-/**
- * Delegate that provides implementation for native 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 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(ByteBuffer buf, int offset, int minPrefix,
- int minSuffix) {
- return Hyphenator_Delegate.loadHyphenator(buf, offset, minPrefix, minSuffix);
- }
-
- @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, boolean isJustified) {
- // TODO: implement justified alignment
- 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:
- assert false : "Unknown break strategy: " + builder.mBreakStrategy;
- builder.mLineBreaker = new GreedyLineBreaker(primitives, builder.mLineWidth,
- builder.mTabStopCalculator);
- }
- builder.mLineBreaker.computeBreaks(recycle);
- return recycle.breaks.length;
- }
-
- /**
- * Compute metadata each character - things which help in deciding if it's possible to break
- * at a point or not.
- */
- @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]));
- }
- }
- // final break at end of everything
- primitives.add(
- PrimitiveType.PENALTY.getNewPrimitive(length, 0, -PrimitiveType.PENALTY_INFINITY));
- return primitives;
- }
-
- 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;
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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 android.text.format;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.content.Context;
-
-
-/**
- * Delegate used to provide new implementation for the native methods of {@link DateFormat}
- *
- * Through the layoutlib_create tool, the original methods of DateFormat have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-public class DateFormat_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static boolean is24HourFormat(Context context) {
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean is24HourFormat(Context context, int userHandle) {
- return false;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import com.android.ide.common.rendering.api.AttrResourceValue;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.internal.util.XmlUtils;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.BridgeConstants;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.ResourceHelper;
-import com.android.resources.ResourceType;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.annotation.NonNull;
-
-import java.util.Map;
-import java.util.function.Function;
-
-/**
- * A correct implementation of the {@link AttributeSet} interface on top of a XmlPullParser
- */
-public class BridgeXmlPullAttributes extends XmlPullAttributes {
-
- private final BridgeContext mContext;
- private final boolean mPlatformFile;
- private final Function<String, Map<String, Integer>> mFrameworkEnumValueSupplier;
- private final Function<String, Map<String, Integer>> mProjectEnumValueSupplier;
-
- // VisibleForTesting
- BridgeXmlPullAttributes(@NonNull XmlPullParser parser, @NonNull BridgeContext context,
- boolean platformFile,
- @NonNull Function<String, Map<String, Integer>> frameworkEnumValueSupplier,
- @NonNull Function<String, Map<String, Integer>> projectEnumValueSupplier) {
- super(parser);
- mContext = context;
- mPlatformFile = platformFile;
- mFrameworkEnumValueSupplier = frameworkEnumValueSupplier;
- mProjectEnumValueSupplier = projectEnumValueSupplier;
- }
-
- public BridgeXmlPullAttributes(@NonNull XmlPullParser parser, @NonNull BridgeContext context,
- boolean platformFile) {
- this(parser, context, platformFile, Bridge::getEnumValues, attrName -> {
- // get the styleable matching the resolved name
- RenderResources res = context.getRenderResources();
- ResourceValue attr = res.getProjectResource(ResourceType.ATTR, attrName);
- return attr instanceof AttrResourceValue ?
- ((AttrResourceValue) attr).getAttributeValues() : null;
- });
- }
-
- /*
- * (non-Javadoc)
- * @see android.util.XmlPullAttributes#getAttributeNameResource(int)
- *
- * This methods must return com.android.internal.R.attr.<name> matching
- * the name of the attribute.
- * It returns 0 if it doesn't find anything.
- */
- @Override
- public int getAttributeNameResource(int index) {
- // get the attribute name.
- String name = getAttributeName(index);
-
- // get the attribute namespace
- String ns = mParser.getAttributeNamespace(index);
-
- if (BridgeConstants.NS_RESOURCES.equals(ns)) {
- return Bridge.getResourceId(ResourceType.ATTR, name);
-
- }
-
- // this is not an attribute in the android namespace, we query the customviewloader, if
- // the namespaces match.
- if (mContext.getLayoutlibCallback().getNamespace().equals(ns)) {
- Integer v = mContext.getLayoutlibCallback().getResourceId(ResourceType.ATTR, name);
- if (v != null) {
- return v;
- }
- }
-
- return 0;
- }
-
- @Override
- public int getAttributeListValue(String namespace, String attribute,
- String[] options, int defaultValue) {
- String value = getAttributeValue(namespace, attribute);
- if (value != null) {
- ResourceValue r = getResourceValue(value);
-
- if (r != null) {
- value = r.getValue();
- }
-
- return XmlUtils.convertValueToList(value, options, defaultValue);
- }
-
- return defaultValue;
- }
-
- @Override
- public boolean getAttributeBooleanValue(String namespace, String attribute,
- boolean defaultValue) {
- String value = getAttributeValue(namespace, attribute);
- if (value != null) {
- ResourceValue r = getResourceValue(value);
-
- if (r != null) {
- value = r.getValue();
- }
-
- return XmlUtils.convertValueToBoolean(value, defaultValue);
- }
-
- return defaultValue;
- }
-
- @Override
- public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
- String value = getAttributeValue(namespace, attribute);
-
- return resolveResourceValue(value, defaultValue);
- }
-
- @Override
- public int getAttributeIntValue(String namespace, String attribute, int defaultValue) {
- String value = getAttributeValue(namespace, attribute);
- if (value == null) {
- return defaultValue;
- }
-
- ResourceValue r = getResourceValue(value);
-
- if (r != null) {
- value = r.getValue();
- }
-
- if (value.charAt(0) == '#') {
- return ResourceHelper.getColor(value);
- }
-
- try {
- return XmlUtils.convertValueToInt(value, defaultValue);
- } catch (NumberFormatException e) {
- // This is probably an enum
- Map<String, Integer> enumValues = BridgeConstants.NS_RESOURCES.equals(namespace) ?
- mFrameworkEnumValueSupplier.apply(attribute) :
- mProjectEnumValueSupplier.apply(attribute);
-
- Integer enumValue = enumValues != null ? enumValues.get(value) : null;
- if (enumValue != null) {
- return enumValue;
- }
-
- // We weren't able to find the enum int value
- throw e;
- }
- }
-
- @Override
- public int getAttributeUnsignedIntValue(String namespace, String attribute,
- int defaultValue) {
- String value = getAttributeValue(namespace, attribute);
- if (value != null) {
- ResourceValue r = getResourceValue(value);
-
- if (r != null) {
- value = r.getValue();
- }
-
- return XmlUtils.convertValueToUnsignedInt(value, defaultValue);
- }
-
- return defaultValue;
- }
-
- @Override
- public float getAttributeFloatValue(String namespace, String attribute,
- float defaultValue) {
- String s = getAttributeValue(namespace, attribute);
- if (s != null) {
- ResourceValue r = getResourceValue(s);
-
- if (r != null) {
- s = r.getValue();
- }
-
- return Float.parseFloat(s);
- }
-
- return defaultValue;
- }
-
- @Override
- public int getAttributeListValue(int index,
- String[] options, int defaultValue) {
- return XmlUtils.convertValueToList(
- getAttributeValue(index), options, defaultValue);
- }
-
- @Override
- public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
- String value = getAttributeValue(index);
- if (value != null) {
- ResourceValue r = getResourceValue(value);
-
- if (r != null) {
- value = r.getValue();
- }
-
- return XmlUtils.convertValueToBoolean(value, defaultValue);
- }
-
- return defaultValue;
- }
-
- @Override
- public int getAttributeResourceValue(int index, int defaultValue) {
- String value = getAttributeValue(index);
-
- return resolveResourceValue(value, defaultValue);
- }
-
- @Override
- public int getAttributeIntValue(int index, int defaultValue) {
- return getAttributeIntValue(mParser.getAttributeNamespace(index),
- getAttributeName(index)
- , defaultValue);
- }
-
- @Override
- public int getAttributeUnsignedIntValue(int index, int defaultValue) {
- String value = getAttributeValue(index);
- if (value != null) {
- ResourceValue r = getResourceValue(value);
-
- if (r != null) {
- value = r.getValue();
- }
-
- return XmlUtils.convertValueToUnsignedInt(value, defaultValue);
- }
-
- return defaultValue;
- }
-
- @Override
- public float getAttributeFloatValue(int index, float defaultValue) {
- String s = getAttributeValue(index);
- if (s != null) {
- ResourceValue r = getResourceValue(s);
-
- if (r != null) {
- s = r.getValue();
- }
-
- return Float.parseFloat(s);
- }
-
- return defaultValue;
- }
-
- // -- private helper methods
-
- /**
- * Returns a resolved {@link ResourceValue} from a given value.
- */
- private ResourceValue getResourceValue(String value) {
- // now look for this particular value
- RenderResources resources = mContext.getRenderResources();
- return resources.resolveResValue(resources.findResValue(value, mPlatformFile));
- }
-
- /**
- * Resolves and return a value to its associated integer.
- */
- private int resolveResourceValue(String value, int defaultValue) {
- ResourceValue resource = getResourceValue(value);
- if (resource != null) {
- Integer id = null;
- if (mPlatformFile || resource.isFramework()) {
- id = Bridge.getResourceId(resource.getResourceType(), resource.getName());
- } else {
- id = mContext.getLayoutlibCallback().getResourceId(
- resource.getResourceType(), resource.getName());
- }
-
- if (id != null) {
- return id;
- }
- }
-
- return defaultValue;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-class Log_Delegate {
- // to replicate prefix visible when using 'adb logcat'
- private static char priorityChar(int priority) {
- switch (priority) {
- case Log.VERBOSE:
- return 'V';
- case Log.DEBUG:
- return 'D';
- case Log.INFO:
- return 'I';
- case Log.WARN:
- return 'W';
- case Log.ERROR:
- return 'E';
- case Log.ASSERT:
- return 'A';
- default:
- return '?';
- }
- }
-
- @LayoutlibDelegate
- static int println_native(int bufID, int priority, String tag, String msgs) {
- String prefix = priorityChar(priority) + "/" + tag + ": ";
- for (String msg: msgs.split("\n")) {
- System.out.println(prefix + msg);
- }
- return 0;
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * BEGIN LAYOUTLIB CHANGE
- * This is a custom version that doesn't use the non standard LinkedHashMap#eldest.
- * END LAYOUTLIB CHANGE
- *
- * A cache that holds strong references to a limited number of values. Each time
- * a value is accessed, it is moved to the head of a queue. When a value is
- * added to a full cache, the value at the end of that queue is evicted and may
- * become eligible for garbage collection.
- *
- * <p>If your cached values hold resources that need to be explicitly released,
- * override {@link #entryRemoved}.
- *
- * <p>If a cache miss should be computed on demand for the corresponding keys,
- * override {@link #create}. This simplifies the calling code, allowing it to
- * assume a value will always be returned, even when there's a cache miss.
- *
- * <p>By default, the cache size is measured in the number of entries. Override
- * {@link #sizeOf} to size the cache in different units. For example, this cache
- * is limited to 4MiB of bitmaps:
- * <pre> {@code
- * int cacheSize = 4 * 1024 * 1024; // 4MiB
- * LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) {
- * protected int sizeOf(String key, Bitmap value) {
- * return value.getByteCount();
- * }
- * }}</pre>
- *
- * <p>This class is thread-safe. Perform multiple cache operations atomically by
- * synchronizing on the cache: <pre> {@code
- * synchronized (cache) {
- * if (cache.get(key) == null) {
- * cache.put(key, value);
- * }
- * }}</pre>
- *
- * <p>This class does not allow null to be used as a key or value. A return
- * value of null from {@link #get}, {@link #put} or {@link #remove} is
- * unambiguous: the key was not in the cache.
- *
- * <p>This class appeared in Android 3.1 (Honeycomb MR1); it's available as part
- * of <a href="http://developer.android.com/sdk/compatibility-library.html">Android's
- * Support Package</a> for earlier releases.
- */
-public class LruCache<K, V> {
- private final LinkedHashMap<K, V> map;
-
- /** Size of this cache in units. Not necessarily the number of elements. */
- private int size;
- private int maxSize;
-
- private int putCount;
- private int createCount;
- private int evictionCount;
- private int hitCount;
- private int missCount;
-
- /**
- * @param maxSize for caches that do not override {@link #sizeOf}, this is
- * the maximum number of entries in the cache. For all other caches,
- * this is the maximum sum of the sizes of the entries in this cache.
- */
- public LruCache(int maxSize) {
- if (maxSize <= 0) {
- throw new IllegalArgumentException("maxSize <= 0");
- }
- this.maxSize = maxSize;
- this.map = new LinkedHashMap<K, V>(0, 0.75f, true);
- }
-
- /**
- * Sets the size of the cache.
- * @param maxSize The new maximum size.
- *
- * @hide
- */
- public void resize(int maxSize) {
- if (maxSize <= 0) {
- throw new IllegalArgumentException("maxSize <= 0");
- }
-
- synchronized (this) {
- this.maxSize = maxSize;
- }
- trimToSize(maxSize);
- }
-
- /**
- * Returns the value for {@code key} if it exists in the cache or can be
- * created by {@code #create}. If a value was returned, it is moved to the
- * head of the queue. This returns null if a value is not cached and cannot
- * be created.
- */
- public final V get(K key) {
- if (key == null) {
- throw new NullPointerException("key == null");
- }
-
- V mapValue;
- synchronized (this) {
- mapValue = map.get(key);
- if (mapValue != null) {
- hitCount++;
- return mapValue;
- }
- missCount++;
- }
-
- /*
- * Attempt to create a value. This may take a long time, and the map
- * may be different when create() returns. If a conflicting value was
- * added to the map while create() was working, we leave that value in
- * the map and release the created value.
- */
-
- V createdValue = create(key);
- if (createdValue == null) {
- return null;
- }
-
- synchronized (this) {
- createCount++;
- mapValue = map.put(key, createdValue);
-
- if (mapValue != null) {
- // There was a conflict so undo that last put
- map.put(key, mapValue);
- } else {
- size += safeSizeOf(key, createdValue);
- }
- }
-
- if (mapValue != null) {
- entryRemoved(false, key, createdValue, mapValue);
- return mapValue;
- } else {
- trimToSize(maxSize);
- return createdValue;
- }
- }
-
- /**
- * Caches {@code value} for {@code key}. The value is moved to the head of
- * the queue.
- *
- * @return the previous value mapped by {@code key}.
- */
- public final V put(K key, V value) {
- if (key == null || value == null) {
- throw new NullPointerException("key == null || value == null");
- }
-
- V previous;
- synchronized (this) {
- putCount++;
- size += safeSizeOf(key, value);
- previous = map.put(key, value);
- if (previous != null) {
- size -= safeSizeOf(key, previous);
- }
- }
-
- if (previous != null) {
- entryRemoved(false, key, previous, value);
- }
-
- trimToSize(maxSize);
- return previous;
- }
-
- /**
- * @param maxSize the maximum size of the cache before returning. May be -1
- * to evict even 0-sized elements.
- */
- private void trimToSize(int maxSize) {
- while (true) {
- K key;
- V value;
- synchronized (this) {
- if (size < 0 || (map.isEmpty() && size != 0)) {
- throw new IllegalStateException(getClass().getName()
- + ".sizeOf() is reporting inconsistent results!");
- }
-
- if (size <= maxSize) {
- break;
- }
-
- // BEGIN LAYOUTLIB CHANGE
- // get the last item in the linked list.
- // This is not efficient, the goal here is to minimize the changes
- // compared to the platform version.
- Map.Entry<K, V> toEvict = null;
- for (Map.Entry<K, V> entry : map.entrySet()) {
- toEvict = entry;
- }
- // END LAYOUTLIB CHANGE
-
- if (toEvict == null) {
- break;
- }
-
- key = toEvict.getKey();
- value = toEvict.getValue();
- map.remove(key);
- size -= safeSizeOf(key, value);
- evictionCount++;
- }
-
- entryRemoved(true, key, value, null);
- }
- }
-
- /**
- * Removes the entry for {@code key} if it exists.
- *
- * @return the previous value mapped by {@code key}.
- */
- public final V remove(K key) {
- if (key == null) {
- throw new NullPointerException("key == null");
- }
-
- V previous;
- synchronized (this) {
- previous = map.remove(key);
- if (previous != null) {
- size -= safeSizeOf(key, previous);
- }
- }
-
- if (previous != null) {
- entryRemoved(false, key, previous, null);
- }
-
- return previous;
- }
-
- /**
- * Called for entries that have been evicted or removed. This method is
- * invoked when a value is evicted to make space, removed by a call to
- * {@link #remove}, or replaced by a call to {@link #put}. The default
- * implementation does nothing.
- *
- * <p>The method is called without synchronization: other threads may
- * access the cache while this method is executing.
- *
- * @param evicted true if the entry is being removed to make space, false
- * if the removal was caused by a {@link #put} or {@link #remove}.
- * @param newValue the new value for {@code key}, if it exists. If non-null,
- * this removal was caused by a {@link #put}. Otherwise it was caused by
- * an eviction or a {@link #remove}.
- */
- protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}
-
- /**
- * Called after a cache miss to compute a value for the corresponding key.
- * Returns the computed value or null if no value can be computed. The
- * default implementation returns null.
- *
- * <p>The method is called without synchronization: other threads may
- * access the cache while this method is executing.
- *
- * <p>If a value for {@code key} exists in the cache when this method
- * returns, the created value will be released with {@link #entryRemoved}
- * and discarded. This can occur when multiple threads request the same key
- * at the same time (causing multiple values to be created), or when one
- * thread calls {@link #put} while another is creating a value for the same
- * key.
- */
- protected V create(K key) {
- return null;
- }
-
- private int safeSizeOf(K key, V value) {
- int result = sizeOf(key, value);
- if (result < 0) {
- throw new IllegalStateException("Negative size: " + key + "=" + value);
- }
- return result;
- }
-
- /**
- * Returns the size of the entry for {@code key} and {@code value} in
- * user-defined units. The default implementation returns 1 so that size
- * is the number of entries and max size is the maximum number of entries.
- *
- * <p>An entry's size must not change while it is in the cache.
- */
- protected int sizeOf(K key, V value) {
- return 1;
- }
-
- /**
- * Clear the cache, calling {@link #entryRemoved} on each removed entry.
- */
- public final void evictAll() {
- trimToSize(-1); // -1 will evict 0-sized elements
- }
-
- /**
- * For caches that do not override {@link #sizeOf}, this returns the number
- * of entries in the cache. For all other caches, this returns the sum of
- * the sizes of the entries in this cache.
- */
- public synchronized final int size() {
- return size;
- }
-
- /**
- * For caches that do not override {@link #sizeOf}, this returns the maximum
- * number of entries in the cache. For all other caches, this returns the
- * maximum sum of the sizes of the entries in this cache.
- */
- public synchronized final int maxSize() {
- return maxSize;
- }
-
- /**
- * Returns the number of times {@link #get} returned a value that was
- * already present in the cache.
- */
- public synchronized final int hitCount() {
- return hitCount;
- }
-
- /**
- * Returns the number of times {@link #get} returned null or required a new
- * value to be created.
- */
- public synchronized final int missCount() {
- return missCount;
- }
-
- /**
- * Returns the number of times {@link #create(Object)} returned a value.
- */
- public synchronized final int createCount() {
- return createCount;
- }
-
- /**
- * Returns the number of times {@link #put} was called.
- */
- public synchronized final int putCount() {
- return putCount;
- }
-
- /**
- * Returns the number of values that have been evicted.
- */
- public synchronized final int evictionCount() {
- return evictionCount;
- }
-
- /**
- * Returns a copy of the current contents of the cache, ordered from least
- * recently accessed to most recently accessed.
- */
- public synchronized final Map<K, V> snapshot() {
- return new LinkedHashMap<K, V>(map);
- }
-
- @Override public synchronized final String toString() {
- int accesses = hitCount + missCount;
- int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;
- return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",
- maxSize, hitCount, missCount, hitPercent);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.annotation.NonNull;
-import android.graphics.Path_Delegate;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Delegate that provides implementation for native methods in {@link android.util.PathParser}
- * <p/>
- * Through the layoutlib_create tool, selected methods of PathParser have been replaced by calls to
- * methods of the same name in this delegate class.
- *
- * Most of the code has been taken from the implementation in
- * {@code tools/base/sdk-common/src/main/java/com/android/ide/common/vectordrawable/PathParser.java}
- * revision be6fe89a3b686db5a75e7e692a148699973957f3
- */
-public class PathParser_Delegate {
-
- private static final Logger LOGGER = Logger.getLogger("PathParser");
-
- // ---- Builder delegate manager ----
- private static final DelegateManager<PathParser_Delegate> sManager =
- new DelegateManager<PathParser_Delegate>(PathParser_Delegate.class);
-
- // ---- delegate data ----
- @NonNull
- private PathDataNode[] mPathDataNodes;
-
- public static PathParser_Delegate getDelegate(long nativePtr) {
- return sManager.getDelegate(nativePtr);
- }
-
- private PathParser_Delegate(@NonNull PathDataNode[] nodes) {
- mPathDataNodes = nodes;
- }
-
- public PathDataNode[] getPathDataNodes() {
- return mPathDataNodes;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nParseStringForPath(long pathPtr, @NonNull String pathString, int
- stringLength) {
- Path_Delegate path_delegate = Path_Delegate.getDelegate(pathPtr);
- if (path_delegate == null) {
- return;
- }
- assert pathString.length() == stringLength;
- PathDataNode.nodesToPath(createNodesFromPathData(pathString), path_delegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static void nCreatePathFromPathData(long outPathPtr, long pathData) {
- Path_Delegate path_delegate = Path_Delegate.getDelegate(outPathPtr);
- PathParser_Delegate source = sManager.getDelegate(outPathPtr);
- if (source == null || path_delegate == null) {
- return;
- }
- PathDataNode.nodesToPath(source.mPathDataNodes, path_delegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nCreateEmptyPathData() {
- PathParser_Delegate newDelegate = new PathParser_Delegate(new PathDataNode[0]);
- return sManager.addNewDelegate(newDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nCreatePathData(long nativePtr) {
- PathParser_Delegate source = sManager.getDelegate(nativePtr);
- if (source == null) {
- return 0;
- }
- PathParser_Delegate dest = new PathParser_Delegate(deepCopyNodes(source.mPathDataNodes));
- return sManager.addNewDelegate(dest);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nCreatePathDataFromString(@NonNull String pathString,
- int stringLength) {
- assert pathString.length() == stringLength : "Inconsistent path string length.";
- PathDataNode[] nodes = createNodesFromPathData(pathString);
- PathParser_Delegate delegate = new PathParser_Delegate(nodes);
- return sManager.addNewDelegate(delegate);
-
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nInterpolatePathData(long outDataPtr, long fromDataPtr,
- long toDataPtr, float fraction) {
- PathParser_Delegate out = sManager.getDelegate(outDataPtr);
- PathParser_Delegate from = sManager.getDelegate(fromDataPtr);
- PathParser_Delegate to = sManager.getDelegate(toDataPtr);
- if (out == null || from == null || to == null) {
- return false;
- }
- int length = from.mPathDataNodes.length;
- if (length != to.mPathDataNodes.length) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Cannot interpolate path data with different lengths (from " + length + " to " +
- to.mPathDataNodes.length + ").", null);
- return false;
- }
- if (out.mPathDataNodes.length != length) {
- out.mPathDataNodes = new PathDataNode[length];
- }
- for (int i = 0; i < length; i++) {
- if (out.mPathDataNodes[i] == null) {
- out.mPathDataNodes[i] = new PathDataNode(from.mPathDataNodes[i]);
- }
- out.mPathDataNodes[i].interpolatePathDataNode(from.mPathDataNodes[i],
- to.mPathDataNodes[i], fraction);
- }
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static void nFinalize(long nativePtr) {
- sManager.removeJavaReferenceFor(nativePtr);
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nCanMorph(long fromDataPtr, long toDataPtr) {
- PathParser_Delegate fromPath = PathParser_Delegate.getDelegate(fromDataPtr);
- PathParser_Delegate toPath = PathParser_Delegate.getDelegate(toDataPtr);
- if (fromPath == null || toPath == null || fromPath.getPathDataNodes() == null || toPath
- .getPathDataNodes() == null) {
- return true;
- }
- return PathParser_Delegate.canMorph(fromPath.getPathDataNodes(), toPath.getPathDataNodes());
- }
-
- @LayoutlibDelegate
- /*package*/ static void nSetPathData(long outDataPtr, long fromDataPtr) {
- PathParser_Delegate out = sManager.getDelegate(outDataPtr);
- PathParser_Delegate from = sManager.getDelegate(fromDataPtr);
- if (from == null || out == null) {
- return;
- }
- out.mPathDataNodes = deepCopyNodes(from.mPathDataNodes);
- }
-
- /**
- * @param pathData The string representing a path, the same as "d" string in svg file.
- *
- * @return an array of the PathDataNode.
- */
- @NonNull
- public static PathDataNode[] createNodesFromPathData(@NonNull String pathData) {
- int start = 0;
- int end = 1;
-
- ArrayList<PathDataNode> list = new ArrayList<PathDataNode>();
- while (end < pathData.length()) {
- end = nextStart(pathData, end);
- String s = pathData.substring(start, end).trim();
- if (s.length() > 0) {
- float[] val = getFloats(s);
- addNode(list, s.charAt(0), val);
- }
-
- start = end;
- end++;
- }
- if ((end - start) == 1 && start < pathData.length()) {
- addNode(list, pathData.charAt(start), new float[0]);
- }
- return list.toArray(new PathDataNode[list.size()]);
- }
-
- /**
- * @param source The array of PathDataNode to be duplicated.
- *
- * @return a deep copy of the <code>source</code>.
- */
- @NonNull
- public static PathDataNode[] deepCopyNodes(@NonNull PathDataNode[] source) {
- PathDataNode[] copy = new PathDataNode[source.length];
- for (int i = 0; i < source.length; i++) {
- copy[i] = new PathDataNode(source[i]);
- }
- return copy;
- }
-
- /**
- * @param nodesFrom The source path represented in an array of PathDataNode
- * @param nodesTo The target path represented in an array of PathDataNode
- * @return whether the <code>nodesFrom</code> can morph into <code>nodesTo</code>
- */
- public static boolean canMorph(PathDataNode[] nodesFrom, PathDataNode[] nodesTo) {
- if (nodesFrom == null || nodesTo == null) {
- return false;
- }
-
- if (nodesFrom.length != nodesTo.length) {
- return false;
- }
-
- for (int i = 0; i < nodesFrom.length; i ++) {
- if (nodesFrom[i].mType != nodesTo[i].mType
- || nodesFrom[i].mParams.length != nodesTo[i].mParams.length) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Update the target's data to match the source.
- * Before calling this, make sure canMorph(target, source) is true.
- *
- * @param target The target path represented in an array of PathDataNode
- * @param source The source path represented in an array of PathDataNode
- */
- public static void updateNodes(PathDataNode[] target, PathDataNode[] source) {
- for (int i = 0; i < source.length; i ++) {
- target[i].mType = source[i].mType;
- for (int j = 0; j < source[i].mParams.length; j ++) {
- target[i].mParams[j] = source[i].mParams[j];
- }
- }
- }
-
- private static int nextStart(@NonNull String s, int end) {
- char c;
-
- while (end < s.length()) {
- c = s.charAt(end);
- // Note that 'e' or 'E' are not valid path commands, but could be
- // used for floating point numbers' scientific notation.
- // Therefore, when searching for next command, we should ignore 'e'
- // and 'E'.
- if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0))
- && c != 'e' && c != 'E') {
- return end;
- }
- end++;
- }
- return end;
- }
-
- /**
- * Calculate the position of the next comma or space or negative sign
- *
- * @param s the string to search
- * @param start the position to start searching
- * @param result the result of the extraction, including the position of the the starting
- * position of next number, whether it is ending with a '-'.
- */
- private static void extract(@NonNull String s, int start, @NonNull ExtractFloatResult result) {
- // Now looking for ' ', ',', '.' or '-' from the start.
- int currentIndex = start;
- boolean foundSeparator = false;
- result.mEndWithNegOrDot = false;
- boolean secondDot = false;
- boolean isExponential = false;
- for (; currentIndex < s.length(); currentIndex++) {
- boolean isPrevExponential = isExponential;
- isExponential = false;
- char currentChar = s.charAt(currentIndex);
- switch (currentChar) {
- case ' ':
- case ',':
- foundSeparator = true;
- break;
- case '-':
- // The negative sign following a 'e' or 'E' is not a separator.
- if (currentIndex != start && !isPrevExponential) {
- foundSeparator = true;
- result.mEndWithNegOrDot = true;
- }
- break;
- case '.':
- if (!secondDot) {
- secondDot = true;
- } else {
- // This is the second dot, and it is considered as a separator.
- foundSeparator = true;
- result.mEndWithNegOrDot = true;
- }
- break;
- case 'e':
- case 'E':
- isExponential = true;
- break;
- }
- if (foundSeparator) {
- break;
- }
- }
- // When there is nothing found, then we put the end position to the end
- // of the string.
- result.mEndPosition = currentIndex;
- }
-
- /**
- * Parse the floats in the string. This is an optimized version of
- * parseFloat(s.split(",|\\s"));
- *
- * @param s the string containing a command and list of floats
- *
- * @return array of floats
- */
- @NonNull
- private static float[] getFloats(@NonNull String s) {
- if (s.charAt(0) == 'z' || s.charAt(0) == 'Z') {
- return new float[0];
- }
- try {
- float[] results = new float[s.length()];
- int count = 0;
- int startPosition = 1;
- int endPosition;
-
- ExtractFloatResult result = new ExtractFloatResult();
- int totalLength = s.length();
-
- // The startPosition should always be the first character of the
- // current number, and endPosition is the character after the current
- // number.
- while (startPosition < totalLength) {
- extract(s, startPosition, result);
- endPosition = result.mEndPosition;
-
- if (startPosition < endPosition) {
- results[count++] = Float.parseFloat(
- s.substring(startPosition, endPosition));
- }
-
- if (result.mEndWithNegOrDot) {
- // Keep the '-' or '.' sign with next number.
- startPosition = endPosition;
- } else {
- startPosition = endPosition + 1;
- }
- }
- return Arrays.copyOf(results, count);
- } catch (NumberFormatException e) {
- assert false : "error in parsing \"" + s + "\"" + e;
- return new float[0];
- }
- }
-
-
- private static void addNode(@NonNull ArrayList<PathDataNode> list, char cmd,
- @NonNull float[] val) {
- list.add(new PathDataNode(cmd, val));
- }
-
- private static class ExtractFloatResult {
- // We need to return the position of the next separator and whether the
- // next float starts with a '-' or a '.'.
- private int mEndPosition;
- private boolean mEndWithNegOrDot;
- }
-
- /**
- * Each PathDataNode represents one command in the "d" attribute of the svg file. An array of
- * PathDataNode can represent the whole "d" attribute.
- */
- public static class PathDataNode {
- private char mType;
- @NonNull
- private float[] mParams;
-
- private PathDataNode(char type, @NonNull float[] params) {
- mType = type;
- mParams = params;
- }
-
- public char getType() {
- return mType;
- }
-
- @NonNull
- public float[] getParams() {
- return mParams;
- }
-
- private PathDataNode(@NonNull PathDataNode n) {
- mType = n.mType;
- mParams = Arrays.copyOf(n.mParams, n.mParams.length);
- }
-
- /**
- * Convert an array of PathDataNode to Path. Reset the passed path as needed before
- * calling this method.
- *
- * @param node The source array of PathDataNode.
- * @param path The target Path object.
- */
- public static void nodesToPath(@NonNull PathDataNode[] node, @NonNull Path_Delegate path) {
- float[] current = new float[6];
- char previousCommand = 'm';
- //noinspection ForLoopReplaceableByForEach
- for (int i = 0; i < node.length; i++) {
- addCommand(path, current, previousCommand, node[i].mType, node[i].mParams);
- previousCommand = node[i].mType;
- }
- }
-
- /**
- * The current PathDataNode will be interpolated between the <code>nodeFrom</code> and
- * <code>nodeTo</code> according to the <code>fraction</code>.
- *
- * @param nodeFrom The start value as a PathDataNode.
- * @param nodeTo The end value as a PathDataNode
- * @param fraction The fraction to interpolate.
- */
- private void interpolatePathDataNode(@NonNull PathDataNode nodeFrom,
- @NonNull PathDataNode nodeTo, float fraction) {
- for (int i = 0; i < nodeFrom.mParams.length; i++) {
- mParams[i] = nodeFrom.mParams[i] * (1 - fraction)
- + nodeTo.mParams[i] * fraction;
- }
- }
-
- @SuppressWarnings("PointlessArithmeticExpression")
- private static void addCommand(@NonNull Path_Delegate path, float[] current,
- char previousCmd, char cmd, @NonNull float[] val) {
-
- int incr = 2;
- float currentX = current[0];
- float currentY = current[1];
- float ctrlPointX = current[2];
- float ctrlPointY = current[3];
- float currentSegmentStartX = current[4];
- float currentSegmentStartY = current[5];
- float reflectiveCtrlPointX;
- float reflectiveCtrlPointY;
-
- switch (cmd) {
- case 'z':
- case 'Z':
- path.close();
- // Path is closed here, but we need to move the pen to the
- // closed position. So we cache the segment's starting position,
- // and restore it here.
- currentX = currentSegmentStartX;
- currentY = currentSegmentStartY;
- ctrlPointX = currentSegmentStartX;
- ctrlPointY = currentSegmentStartY;
- path.moveTo(currentX, currentY);
- break;
- case 'm':
- case 'M':
- case 'l':
- case 'L':
- case 't':
- case 'T':
- incr = 2;
- break;
- case 'h':
- case 'H':
- case 'v':
- case 'V':
- incr = 1;
- break;
- case 'c':
- case 'C':
- incr = 6;
- break;
- case 's':
- case 'S':
- case 'q':
- case 'Q':
- incr = 4;
- break;
- case 'a':
- case 'A':
- incr = 7;
- break;
- }
-
- for (int k = 0; k < val.length; k += incr) {
- switch (cmd) {
- case 'm': // moveto - Start a new sub-path (relative)
- currentX += val[k + 0];
- currentY += val[k + 1];
-
- if (k > 0) {
- // According to the spec, if a moveto is followed by multiple
- // pairs of coordinates, the subsequent pairs are treated as
- // implicit lineto commands.
- path.rLineTo(val[k + 0], val[k + 1]);
- } else {
- path.rMoveTo(val[k + 0], val[k + 1]);
- currentSegmentStartX = currentX;
- currentSegmentStartY = currentY;
- }
- break;
- case 'M': // moveto - Start a new sub-path
- currentX = val[k + 0];
- currentY = val[k + 1];
-
- if (k > 0) {
- // According to the spec, if a moveto is followed by multiple
- // pairs of coordinates, the subsequent pairs are treated as
- // implicit lineto commands.
- path.lineTo(val[k + 0], val[k + 1]);
- } else {
- path.moveTo(val[k + 0], val[k + 1]);
- currentSegmentStartX = currentX;
- currentSegmentStartY = currentY;
- }
- break;
- case 'l': // lineto - Draw a line from the current point (relative)
- path.rLineTo(val[k + 0], val[k + 1]);
- currentX += val[k + 0];
- currentY += val[k + 1];
- break;
- case 'L': // lineto - Draw a line from the current point
- path.lineTo(val[k + 0], val[k + 1]);
- currentX = val[k + 0];
- currentY = val[k + 1];
- break;
- case 'h': // horizontal lineto - Draws a horizontal line (relative)
- path.rLineTo(val[k + 0], 0);
- currentX += val[k + 0];
- break;
- case 'H': // horizontal lineto - Draws a horizontal line
- path.lineTo(val[k + 0], currentY);
- currentX = val[k + 0];
- break;
- case 'v': // vertical lineto - Draws a vertical line from the current point (r)
- path.rLineTo(0, val[k + 0]);
- currentY += val[k + 0];
- break;
- case 'V': // vertical lineto - Draws a vertical line from the current point
- path.lineTo(currentX, val[k + 0]);
- currentY = val[k + 0];
- break;
- case 'c': // curveto - Draws a cubic Bézier curve (relative)
- path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
- val[k + 4], val[k + 5]);
-
- ctrlPointX = currentX + val[k + 2];
- ctrlPointY = currentY + val[k + 3];
- currentX += val[k + 4];
- currentY += val[k + 5];
-
- break;
- case 'C': // curveto - Draws a cubic Bézier curve
- path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
- val[k + 4], val[k + 5]);
- currentX = val[k + 4];
- currentY = val[k + 5];
- ctrlPointX = val[k + 2];
- ctrlPointY = val[k + 3];
- break;
- case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
- reflectiveCtrlPointX = 0;
- reflectiveCtrlPointY = 0;
- if (previousCmd == 'c' || previousCmd == 's'
- || previousCmd == 'C' || previousCmd == 'S') {
- reflectiveCtrlPointX = currentX - ctrlPointX;
- reflectiveCtrlPointY = currentY - ctrlPointY;
- }
- path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
- val[k + 0], val[k + 1],
- val[k + 2], val[k + 3]);
-
- ctrlPointX = currentX + val[k + 0];
- ctrlPointY = currentY + val[k + 1];
- currentX += val[k + 2];
- currentY += val[k + 3];
- break;
- case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
- reflectiveCtrlPointX = currentX;
- reflectiveCtrlPointY = currentY;
- if (previousCmd == 'c' || previousCmd == 's'
- || previousCmd == 'C' || previousCmd == 'S') {
- reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
- reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
- }
- path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
- val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
- ctrlPointX = val[k + 0];
- ctrlPointY = val[k + 1];
- currentX = val[k + 2];
- currentY = val[k + 3];
- break;
- case 'q': // Draws a quadratic Bézier (relative)
- path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
- ctrlPointX = currentX + val[k + 0];
- ctrlPointY = currentY + val[k + 1];
- currentX += val[k + 2];
- currentY += val[k + 3];
- break;
- case 'Q': // Draws a quadratic Bézier
- path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
- ctrlPointX = val[k + 0];
- ctrlPointY = val[k + 1];
- currentX = val[k + 2];
- currentY = val[k + 3];
- break;
- case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
- reflectiveCtrlPointX = 0;
- reflectiveCtrlPointY = 0;
- if (previousCmd == 'q' || previousCmd == 't'
- || previousCmd == 'Q' || previousCmd == 'T') {
- reflectiveCtrlPointX = currentX - ctrlPointX;
- reflectiveCtrlPointY = currentY - ctrlPointY;
- }
- path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
- val[k + 0], val[k + 1]);
- ctrlPointX = currentX + reflectiveCtrlPointX;
- ctrlPointY = currentY + reflectiveCtrlPointY;
- currentX += val[k + 0];
- currentY += val[k + 1];
- break;
- case 'T': // Draws a quadratic Bézier curve (reflective control point)
- reflectiveCtrlPointX = currentX;
- reflectiveCtrlPointY = currentY;
- if (previousCmd == 'q' || previousCmd == 't'
- || previousCmd == 'Q' || previousCmd == 'T') {
- reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
- reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
- }
- path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
- val[k + 0], val[k + 1]);
- ctrlPointX = reflectiveCtrlPointX;
- ctrlPointY = reflectiveCtrlPointY;
- currentX = val[k + 0];
- currentY = val[k + 1];
- break;
- case 'a': // Draws an elliptical arc
- // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
- drawArc(path,
- currentX,
- currentY,
- val[k + 5] + currentX,
- val[k + 6] + currentY,
- val[k + 0],
- val[k + 1],
- val[k + 2],
- val[k + 3] != 0,
- val[k + 4] != 0);
- currentX += val[k + 5];
- currentY += val[k + 6];
- ctrlPointX = currentX;
- ctrlPointY = currentY;
- break;
- case 'A': // Draws an elliptical arc
- drawArc(path,
- currentX,
- currentY,
- val[k + 5],
- val[k + 6],
- val[k + 0],
- val[k + 1],
- val[k + 2],
- val[k + 3] != 0,
- val[k + 4] != 0);
- currentX = val[k + 5];
- currentY = val[k + 6];
- ctrlPointX = currentX;
- ctrlPointY = currentY;
- break;
- }
- previousCmd = cmd;
- }
- current[0] = currentX;
- current[1] = currentY;
- current[2] = ctrlPointX;
- current[3] = ctrlPointY;
- current[4] = currentSegmentStartX;
- current[5] = currentSegmentStartY;
- }
-
- private static void drawArc(@NonNull Path_Delegate p, float x0, float y0, float x1,
- float y1, float a, float b, float theta, boolean isMoreThanHalf,
- boolean isPositiveArc) {
-
- LOGGER.log(Level.FINE, "(" + x0 + "," + y0 + ")-(" + x1 + "," + y1
- + ") {" + a + " " + b + "}");
- /* Convert rotation angle from degrees to radians */
- double thetaD = theta * Math.PI / 180.0f;
- /* Pre-compute rotation matrix entries */
- double cosTheta = Math.cos(thetaD);
- double sinTheta = Math.sin(thetaD);
- /* Transform (x0, y0) and (x1, y1) into unit space */
- /* using (inverse) rotation, followed by (inverse) scale */
- double x0p = (x0 * cosTheta + y0 * sinTheta) / a;
- double y0p = (-x0 * sinTheta + y0 * cosTheta) / b;
- double x1p = (x1 * cosTheta + y1 * sinTheta) / a;
- double y1p = (-x1 * sinTheta + y1 * cosTheta) / b;
- LOGGER.log(Level.FINE, "unit space (" + x0p + "," + y0p + ")-(" + x1p
- + "," + y1p + ")");
- /* Compute differences and averages */
- double dx = x0p - x1p;
- double dy = y0p - y1p;
- double xm = (x0p + x1p) / 2;
- double ym = (y0p + y1p) / 2;
- /* Solve for intersecting unit circles */
- double dsq = dx * dx + dy * dy;
- if (dsq == 0.0) {
- LOGGER.log(Level.FINE, " Points are coincident");
- return; /* Points are coincident */
- }
- double disc = 1.0 / dsq - 1.0 / 4.0;
- if (disc < 0.0) {
- LOGGER.log(Level.FINE, "Points are too far apart " + dsq);
- float adjust = (float) (Math.sqrt(dsq) / 1.99999);
- drawArc(p, x0, y0, x1, y1, a * adjust, b * adjust, theta,
- isMoreThanHalf, isPositiveArc);
- return; /* Points are too far apart */
- }
- double s = Math.sqrt(disc);
- double sdx = s * dx;
- double sdy = s * dy;
- double cx;
- double cy;
- if (isMoreThanHalf == isPositiveArc) {
- cx = xm - sdy;
- cy = ym + sdx;
- } else {
- cx = xm + sdy;
- cy = ym - sdx;
- }
-
- double eta0 = Math.atan2((y0p - cy), (x0p - cx));
- LOGGER.log(Level.FINE, "eta0 = Math.atan2( " + (y0p - cy) + " , "
- + (x0p - cx) + ") = " + Math.toDegrees(eta0));
-
- double eta1 = Math.atan2((y1p - cy), (x1p - cx));
- LOGGER.log(Level.FINE, "eta1 = Math.atan2( " + (y1p - cy) + " , "
- + (x1p - cx) + ") = " + Math.toDegrees(eta1));
- double sweep = (eta1 - eta0);
- if (isPositiveArc != (sweep >= 0)) {
- if (sweep > 0) {
- sweep -= 2 * Math.PI;
- } else {
- sweep += 2 * Math.PI;
- }
- }
-
- cx *= a;
- cy *= b;
- double tcx = cx;
- cx = cx * cosTheta - cy * sinTheta;
- cy = tcx * sinTheta + cy * cosTheta;
- LOGGER.log(
- Level.FINE,
- "cx, cy, a, b, x0, y0, thetaD, eta0, sweep = " + cx + " , "
- + cy + " , " + a + " , " + b + " , " + x0 + " , " + y0
- + " , " + Math.toDegrees(thetaD) + " , "
- + Math.toDegrees(eta0) + " , " + Math.toDegrees(sweep));
-
- arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep);
- }
-
- /**
- * Converts an arc to cubic Bezier segments and records them in p.
- *
- * @param p The target for the cubic Bezier segments
- * @param cx The x coordinate center of the ellipse
- * @param cy The y coordinate center of the ellipse
- * @param a The radius of the ellipse in the horizontal direction
- * @param b The radius of the ellipse in the vertical direction
- * @param e1x E(eta1) x coordinate of the starting point of the arc
- * @param e1y E(eta2) y coordinate of the starting point of the arc
- * @param theta The angle that the ellipse bounding rectangle makes with the horizontal
- * plane
- * @param start The start angle of the arc on the ellipse
- * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse
- */
- private static void arcToBezier(@NonNull Path_Delegate p, double cx, double cy, double a,
- double b, double e1x, double e1y, double theta, double start,
- double sweep) {
- // Taken from equations at:
- // http://spaceroots.org/documents/ellipse/node8.html
- // and http://www.spaceroots.org/documents/ellipse/node22.html
- // Maximum of 45 degrees per cubic Bezier segment
- int numSegments = (int) Math.ceil(Math.abs(sweep * 4 / Math.PI));
-
-
- double eta1 = start;
- double cosTheta = Math.cos(theta);
- double sinTheta = Math.sin(theta);
- double cosEta1 = Math.cos(eta1);
- double sinEta1 = Math.sin(eta1);
- double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1);
- double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1);
-
- double anglePerSegment = sweep / numSegments;
- for (int i = 0; i < numSegments; i++) {
- double eta2 = eta1 + anglePerSegment;
- double sinEta2 = Math.sin(eta2);
- double cosEta2 = Math.cos(eta2);
- double e2x = cx + (a * cosTheta * cosEta2)
- - (b * sinTheta * sinEta2);
- double e2y = cy + (a * sinTheta * cosEta2)
- + (b * cosTheta * sinEta2);
- double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2;
- double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2;
- double tanDiff2 = Math.tan((eta2 - eta1) / 2);
- double alpha = Math.sin(eta2 - eta1)
- * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3;
- double q1x = e1x + alpha * ep1x;
- double q1y = e1y + alpha * ep1y;
- double q2x = e2x - alpha * ep2x;
- double q2y = e2y - alpha * ep2y;
-
- p.cubicTo((float) q1x,
- (float) q1y,
- (float) q2x,
- (float) q2y,
- (float) e2x,
- (float) e2y);
- eta1 = eta2;
- e1x = e2x;
- e1y = e2y;
- ep1x = ep2x;
- ep1y = ep2y;
- }
- }
- }
-}
+++ /dev/null
-/*
- * 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.util;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.impl.ParserFactory;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-/**
- * Delegate overriding some methods of android.util.Xml
- *
- * Through the layoutlib_create tool, the original methods of Xml have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
- * around to map int to instance of the delegate.
- */
-public class Xml_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static XmlPullParser newPullParser() {
- try {
- return ParserFactory.instantiateParser(null);
- } catch (XmlPullParserException e) {
- throw new AssertionError();
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import com.android.layoutlib.bridge.android.BridgeWindow;
-import com.android.layoutlib.bridge.android.BridgeWindowSession;
-
-import android.content.Context;
-import android.os.Handler;
-import android.view.View.AttachInfo;
-
-/**
- * Class allowing access to package-protected methods/fields.
- */
-public class AttachInfo_Accessor {
-
- public static void setAttachInfo(View view) {
- Context context = view.getContext();
- WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- ViewRootImpl root = new ViewRootImpl(context, display);
- AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
- display, root, new Handler(), null, context);
- info.mHasWindowFocus = true;
- info.mWindowVisibility = View.VISIBLE;
- info.mInTouchMode = false; // this is so that we can display selections.
- info.mHardwareAccelerated = false;
- view.dispatchAttachedToWindow(info, 0);
- }
-
- public static void dispatchOnPreDraw(View view) {
- view.mAttachInfo.mTreeObserver.dispatchOnPreDraw();
- }
-
- public static void detachFromWindow(View view) {
- if (view != null) {
- view.dispatchDetachedFromWindow();
- }
- }
-
- public static ViewRootImpl getRootView(View view) {
- return view.mAttachInfo != null ? view.mAttachInfo.mViewRootImpl : null;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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.view;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.MergeCookie;
-import com.android.ide.common.rendering.api.ResourceReference;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.BridgeConstants;
-import com.android.layoutlib.bridge.MockView;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.android.support.DrawerLayoutUtil;
-import com.android.layoutlib.bridge.android.support.RecyclerViewUtil;
-import com.android.layoutlib.bridge.impl.ParserFactory;
-import com.android.layoutlib.bridge.util.ReflectionUtils;
-import com.android.resources.ResourceType;
-import com.android.util.Pair;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.annotation.NonNull;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.drawable.Animatable;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-import android.widget.NumberPicker;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import static com.android.SdkConstants.AUTO_COMPLETE_TEXT_VIEW;
-import static com.android.SdkConstants.BUTTON;
-import static com.android.SdkConstants.CHECKED_TEXT_VIEW;
-import static com.android.SdkConstants.CHECK_BOX;
-import static com.android.SdkConstants.EDIT_TEXT;
-import static com.android.SdkConstants.IMAGE_BUTTON;
-import static com.android.SdkConstants.IMAGE_VIEW;
-import static com.android.SdkConstants.MULTI_AUTO_COMPLETE_TEXT_VIEW;
-import static com.android.SdkConstants.RADIO_BUTTON;
-import static com.android.SdkConstants.SEEK_BAR;
-import static com.android.SdkConstants.SPINNER;
-import static com.android.SdkConstants.TEXT_VIEW;
-import static com.android.layoutlib.bridge.android.BridgeContext.getBaseContext;
-
-/**
- * Custom implementation of {@link LayoutInflater} to handle custom views.
- */
-public final class BridgeInflater extends LayoutInflater {
-
- private final LayoutlibCallback mLayoutlibCallback;
- /**
- * If true, the inflater will try to replace the framework widgets with the AppCompat versions.
- * Ideally, this should be based on the activity being an AppCompat activity but since that is
- * not trivial to check from layoutlib, we currently base the decision on the current theme
- * being an AppCompat theme.
- */
- private boolean mLoadAppCompatViews;
- /**
- * This set contains the framework views that have an AppCompat version but failed to load.
- * This might happen because not all widgets are contained in all versions of the support
- * library.
- * This will help us to avoid trying to load the AppCompat version multiple times if it
- * doesn't exist.
- */
- private Set<String> mFailedAppCompatViews = new HashSet<>();
- private boolean mIsInMerge = false;
- private ResourceReference mResourceReference;
- private Map<View, String> mOpenDrawerLayouts;
-
- // Keep in sync with the same value in LayoutInflater.
- private static final int[] ATTRS_THEME = new int[] {com.android.internal.R.attr.theme };
-
- private static final String APPCOMPAT_WIDGET_PREFIX = "android.support.v7.widget.AppCompat";
- /** List of platform widgets that have an AppCompat version */
- private static final Set<String> APPCOMPAT_VIEWS = Collections.unmodifiableSet(
- new HashSet<>(
- Arrays.asList(TEXT_VIEW, IMAGE_VIEW, BUTTON, EDIT_TEXT, SPINNER,
- IMAGE_BUTTON, CHECK_BOX, RADIO_BUTTON, CHECKED_TEXT_VIEW,
- AUTO_COMPLETE_TEXT_VIEW, MULTI_AUTO_COMPLETE_TEXT_VIEW, "RatingBar",
- SEEK_BAR)));
-
- /**
- * List of class prefixes which are tried first by default.
- * <p/>
- * This should match the list in com.android.internal.policy.impl.PhoneLayoutInflater.
- */
- private static final String[] sClassPrefixList = {
- "android.widget.",
- "android.webkit.",
- "android.app."
- };
-
- public static String[] getClassPrefixList() {
- return sClassPrefixList;
- }
-
- private BridgeInflater(LayoutInflater original, Context newContext) {
- super(original, newContext);
- newContext = getBaseContext(newContext);
- if (newContext instanceof BridgeContext) {
- mLayoutlibCallback = ((BridgeContext) newContext).getLayoutlibCallback();
- mLoadAppCompatViews = ((BridgeContext) newContext).isAppCompatTheme();
- } else {
- mLayoutlibCallback = null;
- mLoadAppCompatViews = false;
- }
- }
-
- /**
- * Instantiate a new BridgeInflater with an {@link LayoutlibCallback} object.
- *
- * @param context The Android application context.
- * @param layoutlibCallback the {@link LayoutlibCallback} object.
- */
- public BridgeInflater(BridgeContext context, LayoutlibCallback layoutlibCallback) {
- super(context);
- mLayoutlibCallback = layoutlibCallback;
- mConstructorArgs[0] = context;
- mLoadAppCompatViews = context.isAppCompatTheme();
- }
-
- @Override
- public View onCreateView(String name, AttributeSet attrs) throws ClassNotFoundException {
- View view = null;
-
- try {
- if (mLoadAppCompatViews
- && APPCOMPAT_VIEWS.contains(name)
- && !mFailedAppCompatViews.contains(name)) {
- // We are using an AppCompat theme so try to load the appcompat views
- view = loadCustomView(APPCOMPAT_WIDGET_PREFIX + name, attrs, true);
-
- if (view == null) {
- mFailedAppCompatViews.add(name); // Do not try this one anymore
- }
- }
-
- if (view == null) {
- // First try to find a class using the default Android prefixes
- for (String prefix : sClassPrefixList) {
- try {
- view = createView(name, prefix, attrs);
- if (view != null) {
- break;
- }
- } catch (ClassNotFoundException e) {
- // Ignore. We'll try again using the base class below.
- }
- }
-
- // Next try using the parent loader. This will most likely only work for
- // fully-qualified class names.
- try {
- if (view == null) {
- view = super.onCreateView(name, attrs);
- }
- } catch (ClassNotFoundException e) {
- // Ignore. We'll try again using the custom view loader below.
- }
- }
-
- // Finally try again using the custom view loader
- if (view == null) {
- view = loadCustomView(name, attrs);
- }
- } catch (InflateException e) {
- // Don't catch the InflateException below as that results in hiding the real cause.
- throw e;
- } catch (Exception e) {
- // Wrap the real exception in a ClassNotFoundException, so that the calling method
- // can deal with it.
- throw new ClassNotFoundException("onCreateView", e);
- }
-
- setupViewInContext(view, attrs);
-
- return view;
- }
-
- @Override
- public View createViewFromTag(View parent, String name, Context context, AttributeSet attrs,
- boolean ignoreThemeAttr) {
- View view = null;
- if (name.equals("view")) {
- // This is usually done by the superclass but this allows us catching the error and
- // reporting something useful.
- name = attrs.getAttributeValue(null, "class");
-
- if (name == null) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to inflate view tag without " +
- "class attribute", null);
- // We weren't able to resolve the view so we just pass a mock View to be able to
- // continue rendering.
- view = new MockView(context, attrs);
- ((MockView) view).setText("view");
- }
- }
-
- try {
- if (view == null) {
- view = super.createViewFromTag(parent, name, context, attrs, ignoreThemeAttr);
- }
- } catch (InflateException e) {
- // Creation of ContextThemeWrapper code is same as in the super method.
- // Apply a theme wrapper, if allowed and one is specified.
- if (!ignoreThemeAttr) {
- final TypedArray ta = context.obtainStyledAttributes(attrs, ATTRS_THEME);
- final int themeResId = ta.getResourceId(0, 0);
- if (themeResId != 0) {
- context = new ContextThemeWrapper(context, themeResId);
- }
- ta.recycle();
- }
- if (!(e.getCause() instanceof ClassNotFoundException)) {
- // There is some unknown inflation exception in inflating a View that was found.
- view = new MockView(context, attrs);
- ((MockView) view).setText(name);
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, e.getMessage(), e, null);
- } else {
- final Object lastContext = mConstructorArgs[0];
- mConstructorArgs[0] = context;
- // try to load the class from using the custom view loader
- try {
- view = loadCustomView(name, attrs);
- } catch (Exception e2) {
- // Wrap the real exception in an InflateException so that the calling
- // method can deal with it.
- InflateException exception = new InflateException();
- if (!e2.getClass().equals(ClassNotFoundException.class)) {
- exception.initCause(e2);
- } else {
- exception.initCause(e);
- }
- throw exception;
- } finally {
- mConstructorArgs[0] = lastContext;
- }
- }
- }
-
- setupViewInContext(view, attrs);
-
- return view;
- }
-
- @Override
- public View inflate(int resource, ViewGroup root) {
- Context context = getContext();
- context = getBaseContext(context);
- if (context instanceof BridgeContext) {
- BridgeContext bridgeContext = (BridgeContext)context;
-
- ResourceValue value = null;
-
- @SuppressWarnings("deprecation")
- Pair<ResourceType, String> layoutInfo = Bridge.resolveResourceId(resource);
- if (layoutInfo != null) {
- value = bridgeContext.getRenderResources().getFrameworkResource(
- ResourceType.LAYOUT, layoutInfo.getSecond());
- } else {
- layoutInfo = mLayoutlibCallback.resolveResourceId(resource);
-
- if (layoutInfo != null) {
- value = bridgeContext.getRenderResources().getProjectResource(
- ResourceType.LAYOUT, layoutInfo.getSecond());
- }
- }
-
- if (value != null) {
- File f = new File(value.getValue());
- if (f.isFile()) {
- try {
- XmlPullParser parser = ParserFactory.create(f, true);
-
- BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(
- parser, bridgeContext, value.isFramework());
-
- return inflate(bridgeParser, root);
- } catch (Exception e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + f.getAbsolutePath(), e, null);
-
- return null;
- }
- }
- }
- }
- return null;
- }
-
- /**
- * Instantiates the given view name and returns the instance. If the view doesn't exist, a
- * MockView or null might be returned.
- * @param name the custom view name
- * @param attrs the {@link AttributeSet} to be passed to the view constructor
- * @param silent if true, errors while loading the view won't be reported and, if the view
- * doesn't exist, null will be returned.
- */
- private View loadCustomView(String name, AttributeSet attrs, boolean silent) throws Exception {
- if (mLayoutlibCallback != null) {
- // first get the classname in case it's not the node name
- if (name.equals("view")) {
- name = attrs.getAttributeValue(null, "class");
- if (name == null) {
- return null;
- }
- }
-
- mConstructorArgs[1] = attrs;
-
- Object customView = silent ?
- mLayoutlibCallback.loadClass(name, mConstructorSignature, mConstructorArgs)
- : mLayoutlibCallback.loadView(name, mConstructorSignature, mConstructorArgs);
-
- if (customView instanceof View) {
- return (View)customView;
- }
- }
-
- return null;
- }
-
- private View loadCustomView(String name, AttributeSet attrs) throws Exception {
- return loadCustomView(name, attrs, false);
- }
-
- private void setupViewInContext(View view, AttributeSet attrs) {
- Context context = getContext();
- context = getBaseContext(context);
- if (context instanceof BridgeContext) {
- BridgeContext bc = (BridgeContext) context;
- // get the view key
- Object viewKey = getViewKeyFromParser(attrs, bc, mResourceReference, mIsInMerge);
- if (viewKey != null) {
- bc.addViewKey(view, viewKey);
- }
- String scrollPosX = attrs.getAttributeValue(BridgeConstants.NS_RESOURCES, "scrollX");
- if (scrollPosX != null && scrollPosX.endsWith("px")) {
- int value = Integer.parseInt(scrollPosX.substring(0, scrollPosX.length() - 2));
- bc.setScrollXPos(view, value);
- }
- String scrollPosY = attrs.getAttributeValue(BridgeConstants.NS_RESOURCES, "scrollY");
- if (scrollPosY != null && scrollPosY.endsWith("px")) {
- int value = Integer.parseInt(scrollPosY.substring(0, scrollPosY.length() - 2));
- bc.setScrollYPos(view, value);
- }
- if (ReflectionUtils.isInstanceOf(view, RecyclerViewUtil.CN_RECYCLER_VIEW)) {
- Integer resourceId = null;
- String attrVal = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI,
- BridgeConstants.ATTR_LIST_ITEM);
- if (attrVal != null && !attrVal.isEmpty()) {
- ResourceValue resValue = bc.getRenderResources().findResValue(attrVal, false);
- if (resValue.isFramework()) {
- resourceId = Bridge.getResourceId(resValue.getResourceType(),
- resValue.getName());
- } else {
- resourceId = mLayoutlibCallback.getResourceId(resValue.getResourceType(),
- resValue.getName());
- }
- }
- if (resourceId == null) {
- resourceId = 0;
- }
- RecyclerViewUtil.setAdapter(view, bc, mLayoutlibCallback, resourceId);
- } else if (ReflectionUtils.isInstanceOf(view, DrawerLayoutUtil.CN_DRAWER_LAYOUT)) {
- String attrVal = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI,
- BridgeConstants.ATTR_OPEN_DRAWER);
- if (attrVal != null) {
- getDrawerLayoutMap().put(view, attrVal);
- }
- }
- else if (view instanceof NumberPicker) {
- NumberPicker numberPicker = (NumberPicker) view;
- String minValue = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI, "minValue");
- if (minValue != null) {
- numberPicker.setMinValue(Integer.parseInt(minValue));
- }
- String maxValue = attrs.getAttributeValue(BridgeConstants.NS_TOOLS_URI, "maxValue");
- if (maxValue != null) {
- numberPicker.setMaxValue(Integer.parseInt(maxValue));
- }
- }
- else if (view instanceof ImageView) {
- ImageView img = (ImageView) view;
- Drawable drawable = img.getDrawable();
- if (drawable instanceof Animatable) {
- if (!((Animatable) drawable).isRunning()) {
- ((Animatable) drawable).start();
- }
- }
- }
-
- }
- }
-
- public void setIsInMerge(boolean isInMerge) {
- mIsInMerge = isInMerge;
- }
-
- public void setResourceReference(ResourceReference reference) {
- mResourceReference = reference;
- }
-
- @Override
- public LayoutInflater cloneInContext(Context newContext) {
- return new BridgeInflater(this, newContext);
- }
-
- /*package*/ static Object getViewKeyFromParser(AttributeSet attrs, BridgeContext bc,
- ResourceReference resourceReference, boolean isInMerge) {
-
- if (!(attrs instanceof BridgeXmlBlockParser)) {
- return null;
- }
- BridgeXmlBlockParser parser = ((BridgeXmlBlockParser) attrs);
-
- // get the view key
- Object viewKey = parser.getViewCookie();
-
- if (viewKey == null) {
- int currentDepth = parser.getDepth();
-
- // test whether we are in an included file or in a adapter binding view.
- BridgeXmlBlockParser previousParser = bc.getPreviousParser();
- if (previousParser != null) {
- // looks like we are inside an embedded layout.
- // only apply the cookie of the calling node (<include>) if we are at the
- // top level of the embedded layout. If there is a merge tag, then
- // skip it and look for the 2nd level
- int testDepth = isInMerge ? 2 : 1;
- if (currentDepth == testDepth) {
- viewKey = previousParser.getViewCookie();
- // if we are in a merge, wrap the cookie in a MergeCookie.
- if (viewKey != null && isInMerge) {
- viewKey = new MergeCookie(viewKey);
- }
- }
- } else if (resourceReference != null && currentDepth == 1) {
- // else if there's a resource reference, this means we are in an adapter
- // binding case. Set the resource ref as the view cookie only for the top
- // level view.
- viewKey = resourceReference;
- }
- }
-
- return viewKey;
- }
-
- public void postInflateProcess(View view) {
- if (mOpenDrawerLayouts != null) {
- String gravity = mOpenDrawerLayouts.get(view);
- if (gravity != null) {
- DrawerLayoutUtil.openDrawer(view, gravity);
- }
- mOpenDrawerLayouts.remove(view);
- }
- }
-
- @NonNull
- private Map<View, String> getDrawerLayoutMap() {
- if (mOpenDrawerLayouts == null) {
- mOpenDrawerLayouts = new HashMap<View, String>(4);
- }
- return mOpenDrawerLayouts;
- }
-
- public void onDoneInflation() {
- if (mOpenDrawerLayouts != null) {
- mOpenDrawerLayouts.clear();
- }
- }
-}
+++ /dev/null
-/*
- * 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 android.view;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-import com.android.tools.layoutlib.java.System_Delegate;
-
-import java.lang.reflect.Field;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link Choreographer}
- *
- * Through the layoutlib_create tool, the original methods of Choreographer have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- */
-public class Choreographer_Delegate {
- static final AtomicReference<Choreographer> mInstance = new AtomicReference<Choreographer>();
-
- @LayoutlibDelegate
- public static Choreographer getInstance() {
- if (mInstance.get() == null) {
- mInstance.compareAndSet(null, Choreographer.getInstance_Original());
- }
-
- return mInstance.get();
- }
-
- @LayoutlibDelegate
- public static float getRefreshRate() {
- return 60.f;
- }
-
- @LayoutlibDelegate
- static void scheduleVsyncLocked(Choreographer thisChoreographer) {
- // do nothing
- }
-
- public static void doFrame(long frameTimeNanos) {
- Choreographer thisChoreographer = Choreographer.getInstance();
-
- thisChoreographer.mLastFrameTimeNanos = frameTimeNanos - thisChoreographer
- .getFrameIntervalNanos();
- thisChoreographer.mFrameInfo.markInputHandlingStart();
- thisChoreographer.doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
-
- thisChoreographer.mFrameInfo.markAnimationsStart();
- thisChoreographer.doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
-
- thisChoreographer.mFrameInfo.markPerformTraversalsStart();
- thisChoreographer.doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
-
- thisChoreographer.doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
- }
-
- public static void dispose() {
- try {
- Field threadInstanceField = Choreographer.class.getDeclaredField("sThreadInstance");
- threadInstanceField.setAccessible(true);
- @SuppressWarnings("unchecked") ThreadLocal<Choreographer> threadInstance =
- (ThreadLocal<Choreographer>) threadInstanceField.get(null);
- threadInstance.remove();
- } catch (ReflectiveOperationException e) {
- assert false;
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Unable to clear Choreographer memory.", e, null);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link Display}
- *
- * Through the layoutlib_create tool, the original methods of Display have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-public class Display_Delegate {
-
- @LayoutlibDelegate
- static void updateDisplayInfoLocked(Display theDisplay) {
- // do nothing
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate used to provide new implementation of a select few methods of
- * {@link HandlerActionQueue}
- *
- * Through the layoutlib_create tool, the original methods of ViewRootImpl.RunQueue have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- */
-public class HandlerActionQueue_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static void postDelayed(HandlerActionQueue thisQueue, Runnable action, long
- delayMillis) {
- // The actual HandlerActionQueue is never run and therefore never cleared. This method
- // avoids runnables to be added to the RunQueue so they do not leak resources.
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.IRemoteCallback;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.util.DisplayMetrics;
-
-import com.android.internal.app.IAssistScreenshotReceiver;
-import com.android.internal.os.IResultReceiver;
-import com.android.internal.policy.IKeyguardDismissCallback;
-import com.android.internal.policy.IShortcutService;
-import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethodClient;
-
-/**
- * Basic implementation of {@link IWindowManager} so that {@link Display} (and
- * {@link Display_Delegate}) can return a valid instance.
- */
-public class IWindowManagerImpl implements IWindowManager {
-
- private final Configuration mConfig;
- private final DisplayMetrics mMetrics;
- private final int mRotation;
- private final boolean mHasNavigationBar;
-
- public IWindowManagerImpl(Configuration config, DisplayMetrics metrics, int rotation,
- boolean hasNavigationBar) {
- mConfig = config;
- mMetrics = metrics;
- mRotation = rotation;
- mHasNavigationBar = hasNavigationBar;
- }
-
- // custom API.
-
- public DisplayMetrics getMetrics() {
- return mMetrics;
- }
-
- // ---- implementation of IWindowManager that we care about ----
-
- @Override
- public int getDefaultDisplayRotation() throws RemoteException {
- return mRotation;
- }
-
- @Override
- public boolean hasNavigationBar() {
- return mHasNavigationBar;
- }
-
- // ---- unused implementation of IWindowManager ----
-
- @Override
- public void addWindowToken(IBinder arg0, int arg1, int arg2) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void clearForcedDisplaySize(int displayId) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void clearForcedDisplayDensityForUser(int displayId, int userId) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void setOverscan(int displayId, int left, int top, int right, int bottom)
- throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void closeSystemDialogs(String arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void startFreezingScreen(int exitAnim, int enterAnim) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void stopFreezingScreen() {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void disableKeyguard(IBinder arg0, String arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void executeAppTransition() throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void exitKeyguardSecurely(IOnKeyguardExitResult arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void freezeRotation(int arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public float getAnimationScale(int arg0) throws RemoteException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public float[] getAnimationScales() throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public int getPendingAppTransition() throws RemoteException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public boolean inKeyguardRestrictedInputMode() throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean inputMethodClientHasFocus(IInputMethodClient arg0) throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean isKeyguardLocked() throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean isKeyguardSecure() throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean isViewServerRunning() throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public IWindowSession openSession(IWindowSessionCallback argn1, IInputMethodClient arg0,
- IInputContext arg1) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void overridePendingAppTransition(String arg0, int arg1, int arg2,
- IRemoteCallback startedCallback) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
- int startHeight) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @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
- }
-
- @Override
- public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
- int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
- boolean scaleUp) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void overridePendingAppTransitionInPlace(String packageName, int anim) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void overridePendingAppTransitionMultiThumbFuture(
- IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback startedCallback,
- boolean scaleUp) throws RemoteException {
-
- }
-
- @Override
- public void overridePendingAppTransitionMultiThumb(AppTransitionAnimationSpec[] specs,
- IRemoteCallback callback0, IRemoteCallback callback1, boolean scaleUp) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void prepareAppTransition(int arg0, boolean arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void reenableKeyguard(IBinder arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeWindowToken(IBinder arg0, int arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean requestAssistScreenshot(IAssistScreenshotReceiver receiver)
- throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void setAnimationScale(int arg0, float arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setAnimationScales(float[] arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public float getCurrentAnimatorScale() throws RemoteException {
- return 0;
- }
-
- @Override
- public void setEventDispatching(boolean arg0) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void setFocusedApp(IBinder arg0, boolean arg1) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void getInitialDisplaySize(int displayId, Point size) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void getBaseDisplaySize(int displayId, Point size) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void setForcedDisplaySize(int displayId, int arg0, int arg1) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public int getInitialDisplayDensity(int displayId) {
- return -1;
- }
-
- @Override
- public int getBaseDisplayDensity(int displayId) {
- return -1;
- }
-
- @Override
- public void setForcedDisplayDensityForUser(int displayId, int density, int userId)
- throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void setForcedDisplayScalingMode(int displayId, int mode) {
- }
-
- @Override
- public void setInTouchMode(boolean arg0) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public int[] setNewDisplayOverrideConfiguration(Configuration arg0, int displayId)
- throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void setScreenCaptureDisabled(int userId, boolean disabled) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void updateRotation(boolean arg0, boolean arg1) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void setStrictModeVisualIndicatorPreference(String arg0) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void showStrictModeViolation(boolean arg0) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public boolean startViewServer(int arg0) throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void statusBarVisibilityChanged(int arg0) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void setRecentsVisibility(boolean visible) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void setPipVisibility(boolean visible) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public boolean stopViewServer() throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void thawRotation() throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public Configuration updateOrientationFromAppTokens(Configuration arg0, IBinder arg1, int arg2)
- throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public int watchRotation(IRotationWatcher arg0, int arg1) throws RemoteException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public void removeRotationWatcher(IRotationWatcher arg0) throws RemoteException {
- }
-
- @Override
- public IBinder asBinder() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public int getPreferredOptionsPanelGravity() throws RemoteException {
- return Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
- }
-
- @Override
- public void dismissKeyguard(IKeyguardDismissCallback callback) throws RemoteException {
- }
-
- @Override
- public void setSwitchingUser(boolean switching) throws RemoteException {
- }
-
- @Override
- public void lockNow(Bundle options) {
- // TODO Auto-generated method stub
- }
-
- @Override
- public boolean isSafeModeEnabled() {
- return false;
- }
-
- @Override
- public boolean isRotationFrozen() throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void enableScreenIfNeeded() throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public boolean clearWindowContentFrameStats(IBinder token) throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public WindowContentFrameStats getWindowContentFrameStats(IBinder token)
- throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public int getDockedStackSide() throws RemoteException {
- return 0;
- }
-
- @Override
- public void setDockedStackResizing(boolean resizing) throws RemoteException {
- }
-
- @Override
- public void endProlongedAnimations() {
- }
-
- @Override
- public void registerDockedStackListener(IDockedStackListener listener) throws RemoteException {
- }
-
- @Override
- public void registerPinnedStackListener(int displayId, IPinnedStackListener listener) throws RemoteException {
- }
-
- @Override
- public void setResizeDimLayer(boolean visible, int targetStackId, float alpha)
- throws RemoteException {
- }
-
- @Override
- public void setDockedStackDividerTouchRegion(Rect touchableRegion) throws RemoteException {
- }
-
- @Override
- public void requestAppKeyboardShortcuts(
- IResultReceiver receiver, int deviceId) throws RemoteException {
- }
-
- @Override
- public void getStableInsets(int displayId, Rect outInsets) throws RemoteException {
- }
-
- @Override
- public void registerShortcutKey(long shortcutCode, IShortcutService service)
- throws RemoteException {}
-
- @Override
- public void createInputConsumer(String name, InputChannel inputChannel)
- throws RemoteException {}
-
- @Override
- public boolean destroyInputConsumer(String name) throws RemoteException {
- return false;
- }
-
- @Override
- public Bitmap screenshotWallpaper() throws RemoteException {
- return null;
- }
-
- @Override
- public void enableSurfaceTrace(ParcelFileDescriptor fd) throws RemoteException {
- }
-
- @Override
- public void disableSurfaceTrace() throws RemoteException {
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-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;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link LayoutInflater}
- *
- * Through the layoutlib_create tool, the original methods of LayoutInflater have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-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;
-
- /**
- * Recursive method used to descend down the xml hierarchy and instantiate
- * views, instantiate their children, and then call onFinishInflate().
- *
- * This implementation just records the merge status before calling the default implementation.
- */
- @LayoutlibDelegate
- /* package */ static void rInflate(LayoutInflater thisInflater, XmlPullParser parser,
- View parent, Context context, AttributeSet attrs, boolean finishInflate)
- throws XmlPullParserException, IOException {
-
- if (finishInflate == false) {
- // this is a merge rInflate!
- if (thisInflater instanceof BridgeInflater) {
- ((BridgeInflater) thisInflater).setIsInMerge(true);
- }
- }
-
- // ---- START DEFAULT IMPLEMENTATION.
-
- thisInflater.rInflate_Original(parser, parent, context, attrs, finishInflate);
-
- // ---- END DEFAULT IMPLEMENTATION.
-
- if (finishInflate == false) {
- // this is a merge rInflate!
- if (thisInflater instanceof BridgeInflater) {
- ((BridgeInflater) thisInflater).setIsInMerge(false);
- }
- }
- }
-
- @LayoutlibDelegate
- public static void parseInclude(LayoutInflater thisInflater, XmlPullParser parser,
- Context context, View parent, AttributeSet attrs)
- throws XmlPullParserException, IOException {
- int type;
-
- if (parent instanceof ViewGroup) {
- // 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, ATTR_LAYOUT);
- if (value == null || value.length() <= 0) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, "You must specify a layout in the"
- + " include tag: <include layout=\"@layout/layoutID\" />", null);
- LayoutInflater.consumeChildElements(parser);
- return;
- }
-
- // 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) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, "You must specify a layout in the"
- + " include tag: <include layout=\"@layout/layoutID\" />", null);
- } else {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, "You must specify a valid layout "
- + "reference. The layout ID " + value + " is not valid.", null);
- }
- } else {
- final XmlResourceParser childParser =
- thisInflater.getContext().getResources().getLayout(layout);
-
- try {
- final AttributeSet childAttrs = Xml.asAttributeSet(childParser);
-
- while ((type = childParser.next()) != XmlPullParser.START_TAG &&
- type != XmlPullParser.END_DOCUMENT) {
- // Empty.
- }
-
- if (type != XmlPullParser.START_TAG) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- childParser.getPositionDescription() + ": No start tag found!",
- null);
- LayoutInflater.consumeChildElements(parser);
- return;
- }
-
- final String childName = childParser.getName();
-
- if (TAG_MERGE.equals(childName)) {
- // Inflate all children.
- thisInflater.rInflate(childParser, parent, context, childAttrs, false);
- } else {
- final View view = thisInflater.createViewFromTag(parent, childName,
- 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.
- // During a layoutparams generation, a runtime exception is thrown
- // if either layout_width or layout_height is missing. We catch
- // this exception and set localParams accordingly: true means we
- // successfully loaded layout params from the <include /> tag,
- // false means we need to rely on the included layout params.
- ViewGroup.LayoutParams params = null;
- try {
- // ---- START CHANGES
- sIsInInclude = true;
- // ---- 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) {
- params = group.generateLayoutParams(childAttrs);
- }
- view.setLayoutParams(params);
-
- // Inflate all children.
- thisInflater.rInflateChildren(childParser, view, childAttrs, true);
-
- if (id != View.NO_ID) {
- view.setId(id);
- }
-
- switch (visibility) {
- case 0:
- view.setVisibility(View.VISIBLE);
- break;
- case 1:
- view.setVisibility(View.INVISIBLE);
- break;
- case 2:
- view.setVisibility(View.GONE);
- break;
- }
-
- group.addView(view);
- }
- } finally {
- childParser.close();
- }
- }
- } else {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "<include /> can only be used inside of a ViewGroup",
- null);
- }
-
- LayoutInflater.consumeChildElements(parser);
- }
-}
+++ /dev/null
-/*
- * 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.view;
-
-import android.content.Context;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.ViewInfo;
-import com.android.internal.view.menu.BridgeMenuItemImpl;
-import com.android.internal.view.menu.MenuView;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.util.AttributeSet;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link MenuInflater}
- * <p/>
- * Through the layoutlib_create tool, the original methods of MenuInflater have been
- * replaced by calls to methods of the same name in this delegate class.
- * <p/>
- * The main purpose of the class is to get the view key from the menu xml parser and add it to
- * the menu item. The view key is used by the IDE to match the individual view elements to the
- * corresponding xml tag in the menu/layout file.
- * <p/>
- * For Menus, the views may be reused and the {@link MenuItem} is a better object to hold the
- * view key than the {@link MenuView.ItemView}. At the time of computation of the rest of {@link
- * ViewInfo}, we check the corresponding view key in the menu item for the view and add it
- */
-public class MenuInflater_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static void registerMenu(MenuInflater thisInflater, MenuItem menuItem,
- AttributeSet attrs) {
- if (menuItem instanceof BridgeMenuItemImpl) {
- Context context = thisInflater.getContext();
- context = BridgeContext.getBaseContext(context);
- if (context instanceof BridgeContext) {
- Object viewKey = BridgeInflater.getViewKeyFromParser(
- attrs, ((BridgeContext) context), null, false);
- ((BridgeMenuItemImpl) menuItem).setViewCookie(viewKey);
- return;
- }
- }
- // This means that Bridge did not take over the instantiation of some object properly.
- // This is most likely a bug in the LayoutLib code.
- Bridge.getLog().warning(LayoutLog.TAG_BROKEN,
- "Action Bar Menu rendering may be incorrect.", null);
-
- }
-
- @LayoutlibDelegate
- /*package*/ static void registerMenu(MenuInflater thisInflater, SubMenu subMenu,
- AttributeSet parser) {
- registerMenu(thisInflater, subMenu.getItem(), parser);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-public class PointerIcon_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static void loadResource(PointerIcon icon, Context context, Resources resources,
- int resourceId) {
- // HACK: This bypasses the problem of having an enum resolved as a resourceId.
- // PointerIcon would not be displayed by layoutlib anyway, so we always return the null
- // icon.
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2015, 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.annotation.NonNull;
-import android.graphics.Canvas;
-import android.graphics.LinearGradient;
-import android.graphics.Outline;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.Path;
-import android.graphics.Path.FillType;
-import android.graphics.RadialGradient;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Shader.TileMode;
-
-import com.android.layoutlib.bridge.impl.ResourceHelper;
-import com.android.layoutlib.bridge.shadowutil.SpotShadow;
-import com.android.layoutlib.bridge.shadowutil.ShadowBuffer;
-
-public class RectShadowPainter {
-
- private static final float SIMPLE_SHADOW_ELEVATION_THRESHOLD = 16f;
- private static final int SIMPLE_SHADOW_START_COLOR = ResourceHelper.getColor("#37000000");
- private static final int SIMPLE_SHADOW_END_COLOR = ResourceHelper.getColor("#03000000");
- private static final float PERPENDICULAR_ANGLE = 90f;
-
- private static final float SHADOW_STRENGTH = 0.1f;
- private static final int LIGHT_POINTS = 8;
-
- private static final int QUADRANT_DIVIDED_COUNT = 8;
-
- private static final int RAY_TRACING_RAYS = 180;
- private static final int RAY_TRACING_LAYERS = 10;
-
- public static void paintShadow(@NonNull Outline viewOutline, float elevation,
- @NonNull Canvas canvas) {
- Rect outline = new Rect();
- if (!viewOutline.getRect(outline)) {
- assert false : "Outline is not a rect shadow";
- return;
- }
-
- if (elevation <= 0) {
- // If elevation is 0, we don't need to paint the shadow
- return;
- }
-
- Rect originCanvasRect = canvas.getClipBounds();
- int saved = modifyCanvas(canvas);
- if (saved == -1) {
- return;
- }
- try {
- float radius = viewOutline.getRadius();
- if (radius <= 0) {
- // We can not paint a shadow with radius 0
- return;
- }
-
- if (elevation <= SIMPLE_SHADOW_ELEVATION_THRESHOLD) {
- // When elevation is not high, the shadow is very similar to a small outline of
- // View. For the performance reason, we draw the shadow in simple way.
- simpleRectangleShadow(canvas, outline, radius, elevation);
- } else {
- // view's absolute position in this canvas.
- int viewLeft = -originCanvasRect.left + outline.left;
- int viewTop = -originCanvasRect.top + outline.top;
- int viewRight = viewLeft + outline.width();
- int viewBottom = viewTop + outline.height();
-
- float[][] rectangleCoordinators =
- generateRectangleCoordinates(viewLeft, viewTop, viewRight, viewBottom,
- radius, elevation);
-
- // TODO: get these values from resources.
- float lightPosX = canvas.getWidth() / 2;
- float lightPosY = 0;
- float lightHeight = 1800;
- float lightSize = 200;
-
- paintGeometricShadow(rectangleCoordinators, lightPosX, lightPosY, lightHeight,
- lightSize, canvas);
- }
- } finally {
- canvas.restoreToCount(saved);
- }
- }
-
- private static int modifyCanvas(@NonNull Canvas canvas) {
- Rect rect = canvas.getClipBounds();
- canvas.translate(rect.left, rect.top);
- return canvas.save();
- }
-
- private static void simpleRectangleShadow(@NonNull Canvas canvas, @NonNull Rect outline,
- float radius, float elevation) {
- float shadowSize = elevation / 2;
-
- Paint cornerPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
- cornerPaint.setStyle(Style.FILL);
- Paint edgePaint = new Paint(cornerPaint);
- edgePaint.setAntiAlias(false);
- float outerArcRadius = radius + shadowSize;
- int[] colors = {SIMPLE_SHADOW_START_COLOR, SIMPLE_SHADOW_START_COLOR,
- SIMPLE_SHADOW_END_COLOR};
- cornerPaint.setShader(new RadialGradient(0, 0, outerArcRadius, colors,
- new float[]{0f, radius / outerArcRadius, 1f}, TileMode.CLAMP));
- edgePaint.setShader(new LinearGradient(0, 0, -shadowSize, 0, SIMPLE_SHADOW_START_COLOR,
- SIMPLE_SHADOW_END_COLOR,
- TileMode.CLAMP));
- Path path = new Path();
- path.setFillType(FillType.EVEN_ODD);
- // A rectangle bounding the complete shadow.
- RectF shadowRect = new RectF(outline);
- shadowRect.inset(-shadowSize, -shadowSize);
- // A rectangle with edges corresponding to the straight edges of the outline.
- RectF inset = new RectF(outline);
- inset.inset(radius, radius);
- // A rectangle used to represent the edge shadow.
- RectF edgeShadowRect = new RectF();
-
-
- // left and right sides.
- edgeShadowRect.set(-shadowSize, 0f, 0f, inset.height());
- // Left shadow
- drawSideShadow(canvas, edgePaint, edgeShadowRect, outline.left, inset.top, 0);
- // Right shadow
- drawSideShadow(canvas, edgePaint, edgeShadowRect, outline.right, inset.bottom, 2);
- // Top shadow
- edgeShadowRect.set(-shadowSize, 0, 0, inset.width());
- drawSideShadow(canvas, edgePaint, edgeShadowRect, inset.right, outline.top, 1);
- // bottom shadow. This needs an inset so that blank doesn't appear when the content is
- // moved up.
- edgeShadowRect.set(-shadowSize, 0, shadowSize / 2f, inset.width());
- edgePaint.setShader(
- new LinearGradient(edgeShadowRect.right, 0, edgeShadowRect.left, 0, colors,
- new float[]{0f, 1 / 3f, 1f}, TileMode.CLAMP));
- drawSideShadow(canvas, edgePaint, edgeShadowRect, inset.left, outline.bottom, 3);
-
- // Draw corners.
- drawCorner(canvas, cornerPaint, path, inset.right, inset.bottom, outerArcRadius, 0);
- drawCorner(canvas, cornerPaint, path, inset.left, inset.bottom, outerArcRadius, 1);
- drawCorner(canvas, cornerPaint, path, inset.left, inset.top, outerArcRadius, 2);
- drawCorner(canvas, cornerPaint, path, inset.right, inset.top, outerArcRadius, 3);
- }
-
- private static void drawSideShadow(@NonNull Canvas canvas, @NonNull Paint edgePaint,
- @NonNull RectF shadowRect, float dx, float dy, int rotations) {
- if ((int) shadowRect.left >= (int) shadowRect.right ||
- (int) shadowRect.top >= (int) shadowRect.bottom) {
- // Rect is empty, no need to draw shadow
- return;
- }
- int saved = canvas.save();
- canvas.translate(dx, dy);
- canvas.rotate(rotations * PERPENDICULAR_ANGLE);
- canvas.drawRect(shadowRect, edgePaint);
- canvas.restoreToCount(saved);
- }
-
- /**
- * @param canvas Canvas to draw the rectangle on.
- * @param paint Paint to use when drawing the corner.
- * @param path A path to reuse. Prevents allocating memory for each path.
- * @param x Center of circle, which this corner is a part of.
- * @param y Center of circle, which this corner is a part of.
- * @param radius radius of the arc
- * @param rotations number of quarter rotations before starting to paint the arc.
- */
- private static void drawCorner(@NonNull Canvas canvas, @NonNull Paint paint, @NonNull Path path,
- float x, float y, float radius, int rotations) {
- int saved = canvas.save();
- canvas.translate(x, y);
- path.reset();
- path.arcTo(-radius, -radius, radius, radius, rotations * PERPENDICULAR_ANGLE,
- PERPENDICULAR_ANGLE, false);
- path.lineTo(0, 0);
- path.close();
- canvas.drawPath(path, paint);
- canvas.restoreToCount(saved);
- }
-
- @NonNull
- private static float[][] generateRectangleCoordinates(float left, float top, float right,
- float bottom, float radius, float elevation) {
- left = left + radius;
- top = top + radius;
- right = right - radius;
- bottom = bottom - radius;
-
- final double RADIANS_STEP = 2 * Math.PI / 4 / QUADRANT_DIVIDED_COUNT;
-
- float[][] ret = new float[QUADRANT_DIVIDED_COUNT * 4][3];
-
- int points = 0;
- // left-bottom points
- for (int i = 0; i < QUADRANT_DIVIDED_COUNT; i++) {
- ret[points][0] = (float) (left - radius + radius * Math.cos(RADIANS_STEP * i));
- ret[points][1] = (float) (bottom + radius - radius * Math.cos(RADIANS_STEP * i));
- ret[points][2] = elevation;
- points++;
- }
- // left-top points
- for (int i = 0; i < QUADRANT_DIVIDED_COUNT; i++) {
- ret[points][0] = (float) (left + radius - radius * Math.cos(RADIANS_STEP * i));
- ret[points][1] = (float) (top + radius - radius * Math.cos(RADIANS_STEP * i));
- ret[points][2] = elevation;
- points++;
- }
- // right-top points
- for (int i = 0; i < QUADRANT_DIVIDED_COUNT; i++) {
- ret[points][0] = (float) (right + radius - radius * Math.cos(RADIANS_STEP * i));
- ret[points][1] = (float) (top + radius + radius * Math.cos(RADIANS_STEP * i));
- ret[points][2] = elevation;
- points++;
- }
- // right-bottom point
- for (int i = 0; i < QUADRANT_DIVIDED_COUNT; i++) {
- ret[points][0] = (float) (right - radius + radius * Math.cos(RADIANS_STEP * i));
- ret[points][1] = (float) (bottom - radius + radius * Math.cos(RADIANS_STEP * i));
- ret[points][2] = elevation;
- points++;
- }
-
- return ret;
- }
-
- private static void paintGeometricShadow(@NonNull float[][] coordinates, float lightPosX,
- float lightPosY, float lightHeight, float lightSize, Canvas canvas) {
- if (canvas == null || canvas.getWidth() == 0 || canvas.getHeight() == 0) {
- return;
- }
-
- // The polygon of shadow (same as the original item)
- float[] shadowPoly = new float[coordinates.length * 3];
- for (int i = 0; i < coordinates.length; i++) {
- shadowPoly[i * 3 + 0] = coordinates[i][0];
- shadowPoly[i * 3 + 1] = coordinates[i][1];
- shadowPoly[i * 3 + 2] = coordinates[i][2];
- }
-
- // TODO: calculate the ambient shadow and mix with Spot shadow.
-
- // Calculate the shadow of SpotLight
- float[] light = SpotShadow.calculateLight(lightSize, LIGHT_POINTS, lightPosX,
- lightPosY, lightHeight);
-
- int stripSize = 3 * SpotShadow.getStripSize(RAY_TRACING_RAYS, RAY_TRACING_LAYERS);
- if (stripSize < 9) {
- return;
- }
- float[] strip = new float[stripSize];
- SpotShadow.calcShadow(light, LIGHT_POINTS, shadowPoly, coordinates.length, RAY_TRACING_RAYS,
- RAY_TRACING_LAYERS, 1f, strip);
-
- ShadowBuffer buff = new ShadowBuffer(canvas.getWidth(), canvas.getHeight());
- buff.generateTriangles(strip, SHADOW_STRENGTH);
- buff.draw(canvas);
- }
-}
+++ /dev/null
-/*
- * 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.view;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.Matrix;
-
-import libcore.util.NativeAllocationRegistry_Delegate;
-
-/**
- * Delegate implementing the native methods of {@link RenderNode}
- * <p/>
- * Through the layoutlib_create tool, some native methods of RenderNode have been replaced by calls
- * to methods of the same name in this delegate class.
- *
- * @see DelegateManager
- */
-public class RenderNode_Delegate {
-
-
- // ---- delegate manager ----
- private static final DelegateManager<RenderNode_Delegate> sManager =
- new DelegateManager<RenderNode_Delegate>(RenderNode_Delegate.class);
- private static long sFinalizer = -1;
-
- private float mLift;
- private float mTranslationX;
- private float mTranslationY;
- private float mTranslationZ;
- private float mRotation;
- private float mScaleX = 1;
- private float mScaleY = 1;
- private float mPivotX;
- private float mPivotY;
- private boolean mPivotExplicitlySet;
- private int mLeft;
- private int mRight;
- private int mTop;
- private int mBottom;
- @SuppressWarnings("UnusedDeclaration")
- private String mName;
-
- @LayoutlibDelegate
- /*package*/ static long nCreate(String name) {
- RenderNode_Delegate renderNodeDelegate = new RenderNode_Delegate();
- renderNodeDelegate.mName = name;
- return sManager.addNewDelegate(renderNodeDelegate);
- }
-
- @LayoutlibDelegate
- /*package*/ static long nGetNativeFinalizer() {
- synchronized (RenderNode_Delegate.class) {
- if (sFinalizer == -1) {
- sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
- }
- }
- return sFinalizer;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetElevation(long renderNode, float lift) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mLift != lift) {
- delegate.mLift = lift;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetElevation(long renderNode) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- return delegate.mLift;
- }
- return 0f;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetTranslationX(long renderNode, float translationX) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mTranslationX != translationX) {
- delegate.mTranslationX = translationX;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetTranslationX(long renderNode) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- return delegate.mTranslationX;
- }
- return 0f;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetTranslationY(long renderNode, float translationY) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mTranslationY != translationY) {
- delegate.mTranslationY = translationY;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetTranslationY(long renderNode) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- return delegate.mTranslationY;
- }
- return 0f;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetTranslationZ(long renderNode, float translationZ) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mTranslationZ != translationZ) {
- delegate.mTranslationZ = translationZ;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetTranslationZ(long renderNode) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- return delegate.mTranslationZ;
- }
- return 0f;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetRotation(long renderNode, float rotation) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mRotation != rotation) {
- delegate.mRotation = rotation;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetRotation(long renderNode) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- return delegate.mRotation;
- }
- return 0f;
- }
-
- @LayoutlibDelegate
- /*package*/ static void getMatrix(RenderNode renderNode, Matrix outMatrix) {
- outMatrix.reset();
- if (renderNode != null) {
- float rotation = renderNode.getRotation();
- float translationX = renderNode.getTranslationX();
- float translationY = renderNode.getTranslationY();
- float pivotX = renderNode.getPivotX();
- float pivotY = renderNode.getPivotY();
- float scaleX = renderNode.getScaleX();
- float scaleY = renderNode.getScaleY();
-
- outMatrix.setTranslate(translationX, translationY);
- outMatrix.preRotate(rotation, pivotX, pivotY);
- outMatrix.preScale(scaleX, scaleY, pivotX, pivotY);
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetLeft(long renderNode, int left) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mLeft != left) {
- delegate.mLeft = left;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetTop(long renderNode, int top) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mTop != top) {
- delegate.mTop = top;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetRight(long renderNode, int right) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mRight != right) {
- delegate.mRight = right;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetBottom(long renderNode, int bottom) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mBottom != bottom) {
- delegate.mBottom = bottom;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetLeftTopRightBottom(long renderNode, int left, int top, int right,
- int bottom) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && (delegate.mLeft != left || delegate.mTop != top || delegate
- .mRight != right || delegate.mBottom != bottom)) {
- delegate.mLeft = left;
- delegate.mTop = top;
- delegate.mRight = right;
- delegate.mBottom = bottom;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nIsPivotExplicitlySet(long renderNode) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- return delegate != null && delegate.mPivotExplicitlySet;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetPivotX(long renderNode, float pivotX) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- delegate.mPivotX = pivotX;
- delegate.mPivotExplicitlySet = true;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetPivotX(long renderNode) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- if (delegate.mPivotExplicitlySet) {
- return delegate.mPivotX;
- } else {
- return (delegate.mRight - delegate.mLeft) / 2.0f;
- }
- }
- return 0f;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetPivotY(long renderNode, float pivotY) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- delegate.mPivotY = pivotY;
- delegate.mPivotExplicitlySet = true;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetPivotY(long renderNode) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- if (delegate.mPivotExplicitlySet) {
- return delegate.mPivotY;
- } else {
- return (delegate.mBottom - delegate.mTop) / 2.0f;
- }
- }
- return 0f;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetScaleX(long renderNode, float scaleX) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mScaleX != scaleX) {
- delegate.mScaleX = scaleX;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetScaleX(long renderNode) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- return delegate.mScaleX;
- }
- return 0f;
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean nSetScaleY(long renderNode, float scaleY) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null && delegate.mScaleY != scaleY) {
- delegate.mScaleY = scaleY;
- return true;
- }
- return false;
- }
-
- @LayoutlibDelegate
- /*package*/ static float nGetScaleY(long renderNode) {
- RenderNode_Delegate delegate = sManager.getDelegate(renderNode);
- if (delegate != null) {
- return delegate.mScaleY;
- }
- return 0f;
- }
-}
+++ /dev/null
-/*
- * 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.view;
-
-import android.annotation.NonNull;
-
-import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.image.BufferedImage;
-import java.awt.image.DataBufferInt;
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.imageio.ImageIO;
-
-public class ShadowPainter {
-
- /**
- * Adds a drop shadow to a semi-transparent image (of an arbitrary shape) and returns it as a
- * new image. This method attempts to mimic the same visual characteristics as the rectangular
- * shadow painting methods in this class, {@link #createRectangularDropShadow(java.awt.image.BufferedImage)}
- * and {@link #createSmallRectangularDropShadow(java.awt.image.BufferedImage)}.
- * <p/>
- * If shadowSize is less or equals to 1, no shadow will be painted and the source image will be
- * returned instead.
- *
- * @param source the source image
- * @param shadowSize the size of the shadow, normally {@link #SHADOW_SIZE or {@link
- * #SMALL_SHADOW_SIZE}}
- *
- * @return an image with the shadow painted in or the source image if shadowSize <= 1
- */
- @NonNull
- public static BufferedImage createDropShadow(BufferedImage source, int shadowSize) {
- shadowSize /= 2; // make shadow size have the same meaning as in the other shadow paint methods in this class
-
- return createDropShadow(source, shadowSize, 0.7f, 0);
- }
-
- /**
- * Creates a drop shadow of a given image and returns a new image which shows the input image on
- * top of its drop shadow.
- * <p/>
- * <b>NOTE: If the shape is rectangular and opaque, consider using {@link
- * #drawRectangleShadow(Graphics2D, int, int, int, int)} instead.</b>
- *
- * @param source the source image to be shadowed
- * @param shadowSize the size of the shadow in pixels
- * @param shadowOpacity the opacity of the shadow, with 0=transparent and 1=opaque
- * @param shadowRgb the RGB int to use for the shadow color
- *
- * @return a new image with the source image on top of its shadow when shadowSize > 0 or the
- * source image otherwise
- */
- @SuppressWarnings({"SuspiciousNameCombination", "UnnecessaryLocalVariable"}) // Imported code
- public static BufferedImage createDropShadow(BufferedImage source, int shadowSize,
- float shadowOpacity, int shadowRgb) {
- if (shadowSize <= 0) {
- return source;
- }
-
- // This code is based on
- // http://www.jroller.com/gfx/entry/non_rectangular_shadow
-
- BufferedImage image;
- int width = source.getWidth();
- int height = source.getHeight();
- image = new BufferedImage(width + SHADOW_SIZE, height + SHADOW_SIZE,
- BufferedImage.TYPE_INT_ARGB);
-
- Graphics2D g2 = image.createGraphics();
- g2.drawImage(image, shadowSize, shadowSize, null);
-
- int dstWidth = image.getWidth();
- int dstHeight = image.getHeight();
-
- int left = (shadowSize - 1) >> 1;
- int right = shadowSize - left;
- int xStart = left;
- int xStop = dstWidth - right;
- int yStart = left;
- int yStop = dstHeight - right;
-
- shadowRgb &= 0x00FFFFFF;
-
- int[] aHistory = new int[shadowSize];
- int historyIdx;
-
- int aSum;
-
- int[] dataBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
- int lastPixelOffset = right * dstWidth;
- float sumDivider = shadowOpacity / shadowSize;
-
- // horizontal pass
- for (int y = 0, bufferOffset = 0; y < dstHeight; y++, bufferOffset = y * dstWidth) {
- aSum = 0;
- historyIdx = 0;
- for (int x = 0; x < shadowSize; x++, bufferOffset++) {
- int a = dataBuffer[bufferOffset] >>> 24;
- aHistory[x] = a;
- aSum += a;
- }
-
- bufferOffset -= right;
-
- for (int x = xStart; x < xStop; x++, bufferOffset++) {
- int a = (int) (aSum * sumDivider);
- dataBuffer[bufferOffset] = a << 24 | shadowRgb;
-
- // subtract the oldest pixel from the sum
- aSum -= aHistory[historyIdx];
-
- // get the latest pixel
- a = dataBuffer[bufferOffset + right] >>> 24;
- aHistory[historyIdx] = a;
- aSum += a;
-
- if (++historyIdx >= shadowSize) {
- historyIdx -= shadowSize;
- }
- }
- }
- // vertical pass
- for (int x = 0, bufferOffset = 0; x < dstWidth; x++, bufferOffset = x) {
- aSum = 0;
- historyIdx = 0;
- for (int y = 0; y < shadowSize; y++, bufferOffset += dstWidth) {
- int a = dataBuffer[bufferOffset] >>> 24;
- aHistory[y] = a;
- aSum += a;
- }
-
- bufferOffset -= lastPixelOffset;
-
- for (int y = yStart; y < yStop; y++, bufferOffset += dstWidth) {
- int a = (int) (aSum * sumDivider);
- dataBuffer[bufferOffset] = a << 24 | shadowRgb;
-
- // subtract the oldest pixel from the sum
- aSum -= aHistory[historyIdx];
-
- // get the latest pixel
- a = dataBuffer[bufferOffset + lastPixelOffset] >>> 24;
- aHistory[historyIdx] = a;
- aSum += a;
-
- if (++historyIdx >= shadowSize) {
- historyIdx -= shadowSize;
- }
- }
- }
-
- g2.drawImage(source, null, 0, 0);
- g2.dispose();
-
- return image;
- }
-
- /**
- * Draws a rectangular drop shadow (of size {@link #SHADOW_SIZE} by {@link #SHADOW_SIZE} around
- * the given source and returns a new image with both combined
- *
- * @param source the source image
- *
- * @return the source image with a drop shadow on the bottom and right
- */
- @SuppressWarnings("UnusedDeclaration")
- public static BufferedImage createRectangularDropShadow(BufferedImage source) {
- int type = source.getType();
- if (type == BufferedImage.TYPE_CUSTOM) {
- type = BufferedImage.TYPE_INT_ARGB;
- }
-
- int width = source.getWidth();
- int height = source.getHeight();
- BufferedImage image;
- image = new BufferedImage(width + SHADOW_SIZE, height + SHADOW_SIZE, type);
- Graphics2D g = image.createGraphics();
- g.drawImage(source, 0, 0, null);
- drawRectangleShadow(image, 0, 0, width, height);
- g.dispose();
-
- return image;
- }
-
- /**
- * Draws a small rectangular drop shadow (of size {@link #SMALL_SHADOW_SIZE} by {@link
- * #SMALL_SHADOW_SIZE} around the given source and returns a new image with both combined
- *
- * @param source the source image
- *
- * @return the source image with a drop shadow on the bottom and right
- */
- @SuppressWarnings("UnusedDeclaration")
- public static BufferedImage createSmallRectangularDropShadow(BufferedImage source) {
- int type = source.getType();
- if (type == BufferedImage.TYPE_CUSTOM) {
- type = BufferedImage.TYPE_INT_ARGB;
- }
-
- int width = source.getWidth();
- int height = source.getHeight();
-
- BufferedImage image;
- image = new BufferedImage(width + SMALL_SHADOW_SIZE, height + SMALL_SHADOW_SIZE, type);
-
- Graphics2D g = image.createGraphics();
- g.drawImage(source, 0, 0, null);
- drawSmallRectangleShadow(image, 0, 0, width, height);
- g.dispose();
-
- return image;
- }
-
- /**
- * Draws a drop shadow for the given rectangle into the given context. It will not draw anything
- * if the rectangle is smaller than a minimum determined by the assets used to draw the shadow
- * graphics. The size of the shadow is {@link #SHADOW_SIZE}.
- *
- * @param image the image to draw the shadow into
- * @param x the left coordinate of the left hand side of the rectangle
- * @param y the top coordinate of the top of the rectangle
- * @param width the width of the rectangle
- * @param height the height of the rectangle
- */
- public static void drawRectangleShadow(BufferedImage image,
- int x, int y, int width, int height) {
- Graphics2D gc = image.createGraphics();
- try {
- drawRectangleShadow(gc, x, y, width, height);
- } finally {
- gc.dispose();
- }
- }
-
- /**
- * Draws a small drop shadow for the given rectangle into the given context. It will not draw
- * anything if the rectangle is smaller than a minimum determined by the assets used to draw the
- * shadow graphics. The size of the shadow is {@link #SMALL_SHADOW_SIZE}.
- *
- * @param image the image to draw the shadow into
- * @param x the left coordinate of the left hand side of the rectangle
- * @param y the top coordinate of the top of the rectangle
- * @param width the width of the rectangle
- * @param height the height of the rectangle
- */
- public static void drawSmallRectangleShadow(BufferedImage image,
- int x, int y, int width, int height) {
- Graphics2D gc = image.createGraphics();
- try {
- drawSmallRectangleShadow(gc, x, y, width, height);
- } finally {
- gc.dispose();
- }
- }
-
- /**
- * The width and height of the drop shadow painted by
- * {@link #drawRectangleShadow(Graphics2D, int, int, int, int)}
- */
- public static final int SHADOW_SIZE = 20; // DO NOT EDIT. This corresponds to bitmap graphics
-
- /**
- * The width and height of the drop shadow painted by
- * {@link #drawSmallRectangleShadow(Graphics2D, int, int, int, int)}
- */
- public static final int SMALL_SHADOW_SIZE = 10; // DO NOT EDIT. Corresponds to bitmap graphics
-
- /**
- * Draws a drop shadow for the given rectangle into the given context. It will not draw anything
- * if the rectangle is smaller than a minimum determined by the assets used to draw the shadow
- * graphics.
- *
- * @param gc the graphics context to draw into
- * @param x the left coordinate of the left hand side of the rectangle
- * @param y the top coordinate of the top of the rectangle
- * @param width the width of the rectangle
- * @param height the height of the rectangle
- */
- public static void drawRectangleShadow(Graphics2D gc, int x, int y, int width, int height) {
- assert ShadowBottomLeft != null;
- assert ShadowBottomRight.getWidth(null) == SHADOW_SIZE;
- assert ShadowBottomRight.getHeight(null) == SHADOW_SIZE;
-
- int blWidth = ShadowBottomLeft.getWidth(null);
- int trHeight = ShadowTopRight.getHeight(null);
- if (width < blWidth) {
- return;
- }
- if (height < trHeight) {
- return;
- }
-
- gc.drawImage(ShadowBottomLeft, x - ShadowBottomLeft.getWidth(null), y + height, null);
- gc.drawImage(ShadowBottomRight, x + width, y + height, null);
- gc.drawImage(ShadowTopRight, x + width, y, null);
- gc.drawImage(ShadowTopLeft, x - ShadowTopLeft.getWidth(null), y, null);
- gc.drawImage(ShadowBottom,
- x, y + height, x + width, y + height + ShadowBottom.getHeight(null),
- 0, 0, ShadowBottom.getWidth(null), ShadowBottom.getHeight(null), null);
- gc.drawImage(ShadowRight,
- x + width, y + ShadowTopRight.getHeight(null), x + width + ShadowRight.getWidth(null), y + height,
- 0, 0, ShadowRight.getWidth(null), ShadowRight.getHeight(null), null);
- gc.drawImage(ShadowLeft,
- x - ShadowLeft.getWidth(null), y + ShadowTopLeft.getHeight(null), x, y + height,
- 0, 0, ShadowLeft.getWidth(null), ShadowLeft.getHeight(null), null);
- }
-
- /**
- * Draws a small drop shadow for the given rectangle into the given context. It will not draw
- * anything if the rectangle is smaller than a minimum determined by the assets used to draw the
- * shadow graphics.
- * <p/>
- *
- * @param gc the graphics context to draw into
- * @param x the left coordinate of the left hand side of the rectangle
- * @param y the top coordinate of the top of the rectangle
- * @param width the width of the rectangle
- * @param height the height of the rectangle
- */
- public static void drawSmallRectangleShadow(Graphics2D gc, int x, int y, int width,
- int height) {
- assert Shadow2BottomLeft != null;
- assert Shadow2TopRight != null;
- assert Shadow2BottomRight.getWidth(null) == SMALL_SHADOW_SIZE;
- assert Shadow2BottomRight.getHeight(null) == SMALL_SHADOW_SIZE;
-
- int blWidth = Shadow2BottomLeft.getWidth(null);
- int trHeight = Shadow2TopRight.getHeight(null);
- if (width < blWidth) {
- return;
- }
- if (height < trHeight) {
- return;
- }
-
- gc.drawImage(Shadow2BottomLeft, x - Shadow2BottomLeft.getWidth(null), y + height, null);
- gc.drawImage(Shadow2BottomRight, x + width, y + height, null);
- gc.drawImage(Shadow2TopRight, x + width, y, null);
- gc.drawImage(Shadow2TopLeft, x - Shadow2TopLeft.getWidth(null), y, null);
- gc.drawImage(Shadow2Bottom,
- x, y + height, x + width, y + height + Shadow2Bottom.getHeight(null),
- 0, 0, Shadow2Bottom.getWidth(null), Shadow2Bottom.getHeight(null), null);
- gc.drawImage(Shadow2Right,
- x + width, y + Shadow2TopRight.getHeight(null), x + width + Shadow2Right.getWidth(null), y + height,
- 0, 0, Shadow2Right.getWidth(null), Shadow2Right.getHeight(null), null);
- gc.drawImage(Shadow2Left,
- x - Shadow2Left.getWidth(null), y + Shadow2TopLeft.getHeight(null), x, y + height,
- 0, 0, Shadow2Left.getWidth(null), Shadow2Left.getHeight(null), null);
- }
-
- private static Image loadIcon(String name) {
- InputStream inputStream = ShadowPainter.class.getResourceAsStream(name);
- if (inputStream == null) {
- throw new RuntimeException("Unable to load image for shadow: " + name);
- }
- try {
- return ImageIO.read(inputStream);
- } catch (IOException e) {
- throw new RuntimeException("Unable to load image for shadow:" + name, e);
- } finally {
- try {
- inputStream.close();
- } catch (IOException e) {
- // ignore.
- }
- }
- }
-
- // Shadow graphics. This was generated by creating a drop shadow in
- // Gimp, using the parameters x offset=10, y offset=10, blur radius=10,
- // (for the small drop shadows x offset=10, y offset=10, blur radius=10)
- // color=black, and opacity=51. These values attempt to make a shadow
- // that is legible both for dark and light themes, on top of the
- // canvas background (rgb(150,150,150). Darker shadows would tend to
- // blend into the foreground for a dark holo screen, and lighter shadows
- // would be hard to spot on the canvas background. If you make adjustments,
- // make sure to check the shadow with both dark and light themes.
- //
- // After making the graphics, I cut out the top right, bottom left
- // and bottom right corners as 20x20 images, and these are reproduced by
- // painting them in the corresponding places in the target graphics context.
- // I then grabbed a single horizontal gradient line from the middle of the
- // right edge,and a single vertical gradient line from the bottom. These
- // are then painted scaled/stretched in the target to fill the gaps between
- // the three corner images.
- //
- // Filenames: bl=bottom left, b=bottom, br=bottom right, r=right, tr=top right
-
- // Normal Drop Shadow
- private static final Image ShadowBottom = loadIcon("/icons/shadow-b.png");
- private static final Image ShadowBottomLeft = loadIcon("/icons/shadow-bl.png");
- private static final Image ShadowBottomRight = loadIcon("/icons/shadow-br.png");
- private static final Image ShadowRight = loadIcon("/icons/shadow-r.png");
- private static final Image ShadowTopRight = loadIcon("/icons/shadow-tr.png");
- private static final Image ShadowTopLeft = loadIcon("/icons/shadow-tl.png");
- private static final Image ShadowLeft = loadIcon("/icons/shadow-l.png");
-
- // Small Drop Shadow
- private static final Image Shadow2Bottom = loadIcon("/icons/shadow2-b.png");
- private static final Image Shadow2BottomLeft = loadIcon("/icons/shadow2-bl.png");
- private static final Image Shadow2BottomRight = loadIcon("/icons/shadow2-br.png");
- private static final Image Shadow2Right = loadIcon("/icons/shadow2-r.png");
- private static final Image Shadow2TopRight = loadIcon("/icons/shadow2-tr.png");
- private static final Image Shadow2TopLeft = loadIcon("/icons/shadow2-tl.png");
- private static final Image Shadow2Left = loadIcon("/icons/shadow2-l.png");
-}
+++ /dev/null
-/*
- * Copyright (C) 2006 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.view;
-
-import com.android.layoutlib.bridge.MockView;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.util.AttributeSet;
-
-/**
- * Mock version of the SurfaceView.
- * Only non override public methods from the real SurfaceView have been added in there.
- * Methods that take an unknown class as parameter or as return object, have been removed for now.
- *
- * TODO: generate automatically.
- *
- */
-public class SurfaceView extends MockView {
-
- public SurfaceView(Context context) {
- this(context, null);
- }
-
- public SurfaceView(Context context, AttributeSet attrs) {
- this(context, attrs , 0);
- }
-
- public SurfaceView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- public boolean gatherTransparentRegion(Region region) {
- return false;
- }
-
- public void setZOrderMediaOverlay(boolean isMediaOverlay) {
- }
-
- public void setZOrderOnTop(boolean onTop) {
- }
-
- public void setSecure(boolean isSecure) {
- }
-
- public SurfaceHolder getHolder() {
- return mSurfaceHolder;
- }
-
- private SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
-
- @Override
- public boolean isCreating() {
- return false;
- }
-
- @Override
- public void addCallback(Callback callback) {
- }
-
- @Override
- public void removeCallback(Callback callback) {
- }
-
- @Override
- public void setFixedSize(int width, int height) {
- }
-
- @Override
- public void setSizeFromLayout() {
- }
-
- @Override
- public void setFormat(int format) {
- }
-
- @Override
- public void setType(int type) {
- }
-
- @Override
- public void setKeepScreenOn(boolean screenOn) {
- }
-
- @Override
- public Canvas lockCanvas() {
- return null;
- }
-
- @Override
- public Canvas lockCanvas(Rect dirty) {
- return null;
- }
-
- @Override
- public void unlockCanvasAndPost(Canvas canvas) {
- }
-
- @Override
- public Surface getSurface() {
- return null;
- }
-
- @Override
- public Rect getSurfaceFrame() {
- return null;
- }
- };
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-/**
- * Class allowing access to package-protected methods/fields.
- */
-public class ViewConfiguration_Accessor {
-
- public static void clearConfigurations() {
- // clear the stored ViewConfiguration since the map is per density and not per context.
- ViewConfiguration.sConfigurations.clear();
- }
-
-}
+++ /dev/null
-/*
- * 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.view;
-
-import com.android.resources.Density;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap_Delegate;
-import android.graphics.Canvas;
-import android.graphics.Outline;
-import android.graphics.Path_Delegate;
-import android.graphics.Rect;
-import android.graphics.Region.Op;
-import android.view.animation.Transformation;
-
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link ViewGroup}
- * <p/>
- * Through the layoutlib_create tool, the original methods of ViewGroup have been replaced by calls
- * to methods of the same name in this delegate class.
- */
-public class ViewGroup_Delegate {
-
- /**
- * Overrides the original drawChild call in ViewGroup to draw the shadow.
- */
- @LayoutlibDelegate
- /*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();
- if (outlineProvider != null) {
- Outline outline = child.mAttachInfo.mTmpOutline;
- 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);
- canvas.restoreToCount(restoreTo);
- }
- }
- }
- return thisVG.drawChild_Original(canvas, child, drawingTime);
- }
-
- private static void drawShadow(ViewGroup parent, Canvas canvas, View child,
- Outline outline) {
- float elevation = getElevation(child, parent);
- if(outline.mMode == Outline.MODE_ROUND_RECT && outline.mRect != null) {
- RectShadowPainter.paintShadow(outline, elevation, canvas);
- return;
- }
- BufferedImage shadow = null;
- if (outline.mPath != null) {
- shadow = getPathShadow(outline, canvas, elevation);
- }
- if (shadow == null) {
- return;
- }
- Bitmap bitmap = Bitmap_Delegate.createBitmap(shadow, false,
- Density.getEnum(canvas.getDensity()));
- Rect clipBounds = canvas.getClipBounds();
- Rect newBounds = new Rect(clipBounds);
- newBounds.inset((int)-elevation, (int)-elevation);
- canvas.clipRect(newBounds, Op.REPLACE);
- canvas.drawBitmap(bitmap, 0, 0, null);
- canvas.clipRect(clipBounds, Op.REPLACE);
- }
-
- private static float getElevation(View child, ViewGroup parent) {
- return child.getZ() - parent.getZ();
- }
-
- private static BufferedImage getPathShadow(Outline outline, Canvas canvas, float elevation) {
- Rect clipBounds = canvas.getClipBounds();
- if (clipBounds.isEmpty()) {
- return null;
- }
- BufferedImage image = new BufferedImage(clipBounds.width(), clipBounds.height(),
- BufferedImage.TYPE_INT_ARGB);
- Graphics2D graphics = image.createGraphics();
- graphics.draw(Path_Delegate.getDelegate(outline.mPath.mNativePath).getJavaShape());
- graphics.dispose();
- return ShadowPainter.createDropShadow(image, (int) elevation);
- }
-
- // Copied from android.view.View#draw(Canvas, ViewGroup, long) and removed code paths
- // which were never taken. Ideally, we should hook up the shadow code in the same method so
- // that we don't have to transform the canvas twice.
- private static int transformCanvas(ViewGroup thisVG, Canvas canvas, View child) {
- final int restoreTo = canvas.save();
- final boolean childHasIdentityMatrix = child.hasIdentityMatrix();
- int flags = thisVG.mGroupFlags;
- Transformation transformToApply = null;
- boolean concatMatrix = false;
- if ((flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
- final Transformation t = thisVG.getChildTransformation();
- final boolean hasTransform = thisVG.getChildStaticTransformation(child, t);
- if (hasTransform) {
- final int transformType = t.getTransformationType();
- transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
- concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
- }
- }
- concatMatrix |= childHasIdentityMatrix;
-
- child.computeScroll();
- int sx = child.mScrollX;
- int sy = child.mScrollY;
-
- canvas.translate(child.mLeft - sx, child.mTop - sy);
- float alpha = child.getAlpha() * child.getTransitionAlpha();
-
- if (transformToApply != null || alpha < 1 || !childHasIdentityMatrix) {
- if (transformToApply != null || !childHasIdentityMatrix) {
- int transX = -sx;
- int transY = -sy;
-
- if (transformToApply != null) {
- if (concatMatrix) {
- // Undo the scroll translation, apply the transformation matrix,
- // then redo the scroll translate to get the correct result.
- canvas.translate(-transX, -transY);
- canvas.concat(transformToApply.getMatrix());
- canvas.translate(transX, transY);
- }
- if (!childHasIdentityMatrix) {
- canvas.translate(-transX, -transY);
- canvas.concat(child.getMatrix());
- canvas.translate(transX, transY);
- }
- }
-
- }
- }
- return restoreTo;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-/**
- * Accessor to allow layoutlib to call {@link ViewRootImpl#dispatchApplyInsets} directly.
- */
-public class ViewRootImpl_Accessor {
- public static void dispatchApplyInsets(ViewRootImpl viewRoot, View host) {
- viewRoot.dispatchApplyInsets(host);
- }
-}
+++ /dev/null
-/*
- * 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 android.view;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link ViewRootImpl}
- *
- * Through the layoutlib_create tool, the original methods of ViewRootImpl have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-public class ViewRootImpl_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static boolean isInTouchMode() {
- return false; // this allows displaying selection.
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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.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}
- *
- * Through the layoutlib_create tool, the original methods of View have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-public class View_Delegate {
-
- @LayoutlibDelegate
- /*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;
- }
-}
+++ /dev/null
-/*
- * 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.view;
-
-import android.annotation.Nullable;
-import android.view.ActionMode.Callback;
-import android.view.WindowManager.LayoutParams;
-import android.view.accessibility.AccessibilityEvent;
-
-import java.util.List;
-
-/**
- * An empty implementation of {@link Window.Callback} that always returns null/false.
- */
-public class WindowCallback implements Window.Callback {
- @Override
- public boolean dispatchKeyEvent(KeyEvent event) {
- return false;
- }
-
- @Override
- public boolean dispatchKeyShortcutEvent(KeyEvent event) {
- return false;
- }
-
- @Override
- public boolean dispatchTouchEvent(MotionEvent event) {
- return false;
- }
-
- @Override
- public boolean dispatchTrackballEvent(MotionEvent event) {
- return false;
- }
-
- @Override
- public boolean dispatchGenericMotionEvent(MotionEvent event) {
- return false;
- }
-
- @Override
- public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- return false;
- }
-
- @Override
- public View onCreatePanelView(int featureId) {
- return null;
- }
-
- @Override
- public boolean onCreatePanelMenu(int featureId, Menu menu) {
- return false;
- }
-
- @Override
- public boolean onPreparePanel(int featureId, View view, Menu menu) {
- return false;
- }
-
- @Override
- public boolean onMenuOpened(int featureId, Menu menu) {
- return false;
- }
-
- @Override
- public boolean onMenuItemSelected(int featureId, MenuItem item) {
- return false;
- }
-
- @Override
- public void onWindowAttributesChanged(LayoutParams attrs) {
-
- }
-
- @Override
- public void onContentChanged() {
-
- }
-
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
-
- }
-
- @Override
- public void onAttachedToWindow() {
-
- }
-
- @Override
- public void onDetachedFromWindow() {
-
- }
-
- @Override
- public void onPanelClosed(int featureId, Menu menu) {
-
- }
-
- @Override
- public boolean onSearchRequested(SearchEvent searchEvent) {
- return onSearchRequested();
- }
-
- @Override
- public boolean onSearchRequested() {
- return false;
- }
-
- @Override
- public ActionMode onWindowStartingActionMode(Callback callback) {
- return null;
- }
-
- @Override
- public ActionMode onWindowStartingActionMode(Callback callback, int type) {
- return null;
- }
-
- @Override
- public void onActionModeStarted(ActionMode mode) {
-
- }
-
- @Override
- public void onActionModeFinished(ActionMode mode) {
-
- }
-}
+++ /dev/null
-/*
- * 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 android.view;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate used to provide new implementation of a select few methods of
- * {@link WindowManagerGlobal}
- *
- * Through the layoutlib_create tool, the original methods of WindowManagerGlobal have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- */
-public class WindowManagerGlobal_Delegate {
-
- private static IWindowManager sService;
-
- @LayoutlibDelegate
- public static IWindowManager getWindowManagerService() {
- return sService;
- }
-
- // ---- internal implementation stuff ----
-
- public static void setWindowManagerService(IWindowManager service) {
- sService = service;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2009 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.view.accessibility;
-
-import android.accessibilityservice.AccessibilityServiceInfo;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.pm.ServiceInfo;
-import android.os.Handler;
-import android.view.IWindow;
-import android.view.View;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * System level service that serves as an event dispatch for {@link AccessibilityEvent}s.
- * Such events are generated when something notable happens in the user interface,
- * for example an {@link android.app.Activity} starts, the focus or selection of a
- * {@link android.view.View} changes etc. Parties interested in handling accessibility
- * events implement and register an accessibility service which extends
- * {@code android.accessibilityservice.AccessibilityService}.
- *
- * @see AccessibilityEvent
- * @see android.content.Context#getSystemService
- */
-@SuppressWarnings("UnusedDeclaration")
-public final class AccessibilityManager {
-
- private static AccessibilityManager sInstance = new AccessibilityManager(null, null, 0);
-
-
- /**
- * Listener for the accessibility state.
- */
- public interface AccessibilityStateChangeListener {
-
- /**
- * Called back on change in the accessibility state.
- *
- * @param enabled Whether accessibility is enabled.
- */
- public void onAccessibilityStateChanged(boolean enabled);
- }
-
- /**
- * Listener for the system touch exploration state. To listen for changes to
- * the touch exploration state on the device, implement this interface and
- * register it with the system by calling
- * {@link #addTouchExplorationStateChangeListener}.
- */
- public interface TouchExplorationStateChangeListener {
-
- /**
- * Called when the touch exploration enabled state changes.
- *
- * @param enabled Whether touch exploration is enabled.
- */
- public void onTouchExplorationStateChanged(boolean enabled);
- }
-
- /**
- * Listener for the system high text contrast state. To listen for changes to
- * the high text contrast state on the device, implement this interface and
- * register it with the system by calling
- * {@link #addHighTextContrastStateChangeListener}.
- */
- public interface HighTextContrastChangeListener {
-
- /**
- * Called when the high text contrast enabled state changes.
- *
- * @param enabled Whether high text contrast is enabled.
- */
- public void onHighTextContrastStateChanged(boolean enabled);
- }
-
- private final IAccessibilityManagerClient.Stub mClient =
- new IAccessibilityManagerClient.Stub() {
- public void setState(int state) {
- }
-
- public void notifyServicesStateChanged() {
- }
-
- public void setRelevantEventTypes(int eventTypes) {
- }
- };
-
- /**
- * Get an AccessibilityManager instance (create one if necessary).
- *
- */
- public static AccessibilityManager getInstance(Context context) {
- return sInstance;
- }
-
- /**
- * Create an instance.
- *
- * @param context A {@link Context}.
- */
- public AccessibilityManager(Context context, IAccessibilityManager service, int userId) {
- }
-
- public IAccessibilityManagerClient getClient() {
- return mClient;
- }
-
- /**
- * Returns if the {@link AccessibilityManager} is enabled.
- *
- * @return True if this {@link AccessibilityManager} is enabled, false otherwise.
- */
- public boolean isEnabled() {
- return false;
- }
-
- /**
- * Returns if the touch exploration in the system is enabled.
- *
- * @return True if touch exploration is enabled, false otherwise.
- */
- public boolean isTouchExplorationEnabled() {
- return true;
- }
-
- /**
- * Returns if the high text contrast in the system is enabled.
- * <p>
- * <strong>Note:</strong> You need to query this only if you application is
- * doing its own rendering and does not rely on the platform rendering pipeline.
- * </p>
- *
- */
- public boolean isHighTextContrastEnabled() {
- return false;
- }
-
- /**
- * Sends an {@link AccessibilityEvent}.
- */
- public void sendAccessibilityEvent(AccessibilityEvent event) {
- }
-
- /**
- * Requests interruption of the accessibility feedback from all accessibility services.
- */
- public void interrupt() {
- }
-
- /**
- * Returns the {@link ServiceInfo}s of the installed accessibility services.
- *
- * @return An unmodifiable list with {@link ServiceInfo}s.
- */
- @Deprecated
- public List<ServiceInfo> getAccessibilityServiceList() {
- return Collections.emptyList();
- }
-
- public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
- return Collections.emptyList();
- }
-
- /**
- * Returns the {@link AccessibilityServiceInfo}s of the enabled accessibility services
- * for a given feedback type.
- *
- * @param feedbackTypeFlags The feedback type flags.
- * @return An unmodifiable list with {@link AccessibilityServiceInfo}s.
- *
- * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE
- * @see AccessibilityServiceInfo#FEEDBACK_GENERIC
- * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC
- * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN
- * @see AccessibilityServiceInfo#FEEDBACK_VISUAL
- */
- public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(
- int feedbackTypeFlags) {
- return Collections.emptyList();
- }
-
- /**
- * Registers an {@link AccessibilityStateChangeListener} for changes in
- * the global accessibility state of the system.
- *
- * @param listener The listener.
- * @return True if successfully registered.
- */
- public boolean addAccessibilityStateChangeListener(
- AccessibilityStateChangeListener listener) {
- return true;
- }
-
- /**
- * Registers an {@link AccessibilityStateChangeListener} for changes in
- * the global accessibility state of the system. If the listener has already been registered,
- * the handler used to call it back is updated.
- *
- * @param listener The listener.
- * @param handler The handler on which the listener should be called back, or {@code null}
- * for a callback on the process's main handler.
- */
- public void addAccessibilityStateChangeListener(
- @NonNull AccessibilityStateChangeListener listener, @Nullable Handler handler) {}
-
- public boolean removeAccessibilityStateChangeListener(
- AccessibilityStateChangeListener listener) {
- return true;
- }
-
- /**
- * Registers a {@link TouchExplorationStateChangeListener} for changes in
- * the global touch exploration state of the system.
- *
- * @param listener The listener.
- * @return True if successfully registered.
- */
- public boolean addTouchExplorationStateChangeListener(
- @NonNull TouchExplorationStateChangeListener listener) {
- return true;
- }
-
- /**
- * Registers an {@link TouchExplorationStateChangeListener} for changes in
- * the global touch exploration state of the system. If the listener has already been
- * registered, the handler used to call it back is updated.
- *
- * @param listener The listener.
- * @param handler The handler on which the listener should be called back, or {@code null}
- * for a callback on the process's main handler.
- */
- public void addTouchExplorationStateChangeListener(
- @NonNull TouchExplorationStateChangeListener listener, @Nullable Handler handler) {}
-
- /**
- * Unregisters a {@link TouchExplorationStateChangeListener}.
- *
- * @param listener The listener.
- * @return True if successfully unregistered.
- */
- public boolean removeTouchExplorationStateChangeListener(
- @NonNull TouchExplorationStateChangeListener listener) {
- return true;
- }
-
- /**
- * Registers a {@link HighTextContrastChangeListener} for changes in
- * the global high text contrast state of the system.
- *
- * @param listener The listener.
- *
- * @hide
- */
- public void addHighTextContrastStateChangeListener(
- @NonNull HighTextContrastChangeListener listener, @Nullable Handler handler) {}
-
- /**
- * Unregisters a {@link HighTextContrastChangeListener}.
- *
- * @param listener The listener.
- *
- * @hide
- */
- public void removeHighTextContrastStateChangeListener(
- @NonNull HighTextContrastChangeListener listener) {}
-
- /**
- * Sets the current state and notifies listeners, if necessary.
- *
- * @param stateFlags The state flags.
- */
- private void setStateLocked(int stateFlags) {
- }
-
- public int addAccessibilityInteractionConnection(IWindow windowToken,
- IAccessibilityInteractionConnection connection) {
- return View.NO_ID;
- }
-
- public void removeAccessibilityInteractionConnection(IWindow windowToken) {
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.inputmethod;
-
-/**
- * Class allowing access to package-protected methods/fields.
- */
-public class InputMethodManager_Accessor {
-
- public static void resetInstance() {
- InputMethodManager.sInstance = null;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.inputmethod;
-
-import com.android.layoutlib.bridge.android.BridgeIInputMethodManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.content.Context;
-import android.os.Looper;
-
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link InputMethodManager}
- *
- * Through the layoutlib_create tool, the original methods of InputMethodManager have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-public class InputMethodManager_Delegate {
-
- // ---- Overridden methods ----
-
- @LayoutlibDelegate
- /*package*/ static InputMethodManager getInstance() {
- synchronized (InputMethodManager.class) {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm == null) {
- imm = new InputMethodManager(
- new BridgeIInputMethodManager(), Looper.getMainLooper());
- InputMethodManager.sInstance = imm;
- }
- return imm;
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view.textservice;
-
-import android.os.Bundle;
-import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
-
-import java.util.Locale;
-
-/**
- * A stub class of TextServicesManager for Layout-Lib.
- */
-public final class TextServicesManager {
- private static final TextServicesManager sInstance = new TextServicesManager();
- private static final SpellCheckerInfo[] EMPTY_SPELL_CHECKER_INFO = new SpellCheckerInfo[0];
-
- /**
- * Retrieve the global TextServicesManager instance, creating it if it doesn't already exist.
- * @hide
- */
- public static TextServicesManager getInstance() {
- return sInstance;
- }
-
- public SpellCheckerSession newSpellCheckerSession(Bundle bundle, Locale locale,
- SpellCheckerSessionListener listener, boolean referToSpellCheckerLanguageSettings) {
- return null;
- }
-
- /**
- * @hide
- */
- public SpellCheckerInfo[] getEnabledSpellCheckers() {
- return EMPTY_SPELL_CHECKER_INFO;
- }
-
- /**
- * @hide
- */
- public SpellCheckerInfo getCurrentSpellChecker() {
- return null;
- }
-
- /**
- * @hide
- */
- public SpellCheckerSubtype getCurrentSpellCheckerSubtype(
- boolean allowImplicitlySelectedSubtype) {
- return null;
- }
-
- /**
- * @hide
- */
- public boolean isSpellCheckerEnabled() {
- return false;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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.webkit;
-
-import com.android.layoutlib.bridge.MockView;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Picture;
-import android.os.Bundle;
-import android.os.Message;
-import android.util.AttributeSet;
-import android.view.View;
-
-/**
- * Mock version of the WebView.
- * Only non override public methods from the real WebView have been added in there.
- * Methods that take an unknown class as parameter or as return object, have been removed for now.
- *
- * TODO: generate automatically.
- *
- */
-public class WebView extends MockView {
-
- /**
- * Construct a new WebView with a Context object.
- * @param context A Context object used to access application assets.
- */
- public WebView(Context context) {
- this(context, null);
- }
-
- /**
- * Construct a new WebView with layout parameters.
- * @param context A Context object used to access application assets.
- * @param attrs An AttributeSet passed to our parent.
- */
- public WebView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.webViewStyle);
- }
-
- /**
- * Construct a new WebView with layout parameters and a default style.
- * @param context A Context object used to access application assets.
- * @param attrs An AttributeSet passed to our parent.
- * @param defStyle The default style resource ID.
- */
- public WebView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- // START FAKE PUBLIC METHODS
-
- public void setHorizontalScrollbarOverlay(boolean overlay) {
- }
-
- public void setVerticalScrollbarOverlay(boolean overlay) {
- }
-
- public boolean overlayHorizontalScrollbar() {
- return false;
- }
-
- public boolean overlayVerticalScrollbar() {
- return false;
- }
-
- public void savePassword(String host, String username, String password) {
- }
-
- public void setHttpAuthUsernamePassword(String host, String realm,
- String username, String password) {
- }
-
- public String[] getHttpAuthUsernamePassword(String host, String realm) {
- return null;
- }
-
- public void destroy() {
- }
-
- public static void enablePlatformNotifications() {
- }
-
- public static void disablePlatformNotifications() {
- }
-
- public void loadUrl(String url) {
- }
-
- public void loadData(String data, String mimeType, String encoding) {
- }
-
- public void loadDataWithBaseURL(String baseUrl, String data,
- String mimeType, String encoding, String failUrl) {
- }
-
- public void stopLoading() {
- }
-
- public void reload() {
- }
-
- public boolean canGoBack() {
- return false;
- }
-
- public void goBack() {
- }
-
- public boolean canGoForward() {
- return false;
- }
-
- public void goForward() {
- }
-
- public boolean canGoBackOrForward(int steps) {
- return false;
- }
-
- public void goBackOrForward(int steps) {
- }
-
- public boolean pageUp(boolean top) {
- return false;
- }
-
- public boolean pageDown(boolean bottom) {
- return false;
- }
-
- public void clearView() {
- }
-
- public Picture capturePicture() {
- return null;
- }
-
- public float getScale() {
- return 0;
- }
-
- public void setInitialScale(int scaleInPercent) {
- }
-
- public void invokeZoomPicker() {
- }
-
- public void requestFocusNodeHref(Message hrefMsg) {
- }
-
- public void requestImageRef(Message msg) {
- }
-
- public String getUrl() {
- return null;
- }
-
- public String getTitle() {
- return null;
- }
-
- public Bitmap getFavicon() {
- return null;
- }
-
- public int getProgress() {
- return 0;
- }
-
- public int getContentHeight() {
- return 0;
- }
-
- public void pauseTimers() {
- }
-
- public void resumeTimers() {
- }
-
- public void clearCache() {
- }
-
- public void clearFormData() {
- }
-
- public void clearHistory() {
- }
-
- public void clearSslPreferences() {
- }
-
- public static String findAddress(String addr) {
- return null;
- }
-
- public void documentHasImages(Message response) {
- }
-
- public void setWebViewClient(WebViewClient client) {
- }
-
- public void setDownloadListener(DownloadListener listener) {
- }
-
- public void setWebChromeClient(WebChromeClient client) {
- }
-
- public void addJavascriptInterface(Object obj, String interfaceName) {
- }
-
- public View getZoomControls() {
- return null;
- }
-
- public boolean zoomIn() {
- return false;
- }
-
- public boolean zoomOut() {
- return false;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.widget;
-
-import android.content.Context;
-
-/**
- * To access non public members of classes in {@link Toolbar}
- */
-public class Toolbar_Accessor {
- public static ActionMenuPresenter getActionMenuPresenter(Toolbar toolbar) {
- return toolbar.getOuterActionMenuPresenter();
- }
-
- public static Context getPopupContext(Toolbar toolbar) {
- return toolbar.getPopupContext();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.util.LongSparseLongArray;
-
-/**
- * Delegate used to provide new implementation the native methods of {@link VirtualRefBasePtr}
- *
- * Through the layoutlib_create tool, the original native methods of VirtualRefBasePtr have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- */
-@SuppressWarnings("unused")
-public class VirtualRefBasePtr_Delegate {
- private static final DelegateManager<Object> sManager = new DelegateManager<>(Object.class);
- private static final LongSparseLongArray sRefCount = new LongSparseLongArray();
-
- @LayoutlibDelegate
- /*package*/ static synchronized void nIncStrong(long ptr) {
- long counter = sRefCount.get(ptr);
- sRefCount.put(ptr, ++counter);
- }
-
- @LayoutlibDelegate
- /*package*/ static synchronized void nDecStrong(long ptr) {
- long counter = sRefCount.get(ptr);
-
- if (counter > 1) {
- sRefCount.put(ptr, --counter);
- } else {
- sRefCount.delete(ptr);
- sManager.removeJavaReferenceFor(ptr);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link XmlUtils}
- *
- * Through the layoutlib_create tool, the original methods of XmlUtils have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-public class XmlUtils_Delegate {
-
- @LayoutlibDelegate
- /*package*/ static final int convertValueToInt(CharSequence charSeq, int defaultValue) {
- if (null == charSeq)
- return defaultValue;
-
- String nm = charSeq.toString();
-
- // This code is copied from the original implementation. The issue is that
- // The Dalvik libraries are able to handle Integer.parse("XXXXXXXX", 16) where XXXXXXX
- // is > 80000000 but the Java VM cannot.
-
- int sign = 1;
- int index = 0;
- int len = nm.length();
- int base = 10;
-
- if ('-' == nm.charAt(0)) {
- sign = -1;
- index++;
- }
-
- if ('0' == nm.charAt(index)) {
- // Quick check for a zero by itself
- if (index == (len - 1))
- return 0;
-
- char c = nm.charAt(index + 1);
-
- if ('x' == c || 'X' == c) {
- index += 2;
- base = 16;
- } else {
- index++;
- base = 8;
- }
- }
- else if ('#' == nm.charAt(index)) {
- index++;
- base = 16;
- }
-
- return ((int)Long.parseLong(nm.substring(index), base)) * sign;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.view.animation;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.graphics.Path;
-import android.util.MathUtils;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.AccelerateInterpolator;
-import android.view.animation.AnticipateInterpolator;
-import android.view.animation.AnticipateOvershootInterpolator;
-import android.view.animation.BaseInterpolator;
-import android.view.animation.BounceInterpolator;
-import android.view.animation.CycleInterpolator;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-import android.view.animation.OvershootInterpolator;
-import android.view.animation.PathInterpolator;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link
- * NativeInterpolatorFactoryHelper}
- * <p>
- * Through the layoutlib_create tool, the original methods of NativeInterpolatorFactoryHelper have
- * been replaced by calls to methods of the same name in this delegate class.
- */
-@SuppressWarnings("unused")
-public class NativeInterpolatorFactoryHelper_Delegate {
- private static final DelegateManager<Interpolator> sManager = new DelegateManager<>
- (Interpolator.class);
-
- public static Interpolator getDelegate(long nativePtr) {
- return sManager.getDelegate(nativePtr);
- }
-
- @LayoutlibDelegate
- /*package*/ static long createAccelerateDecelerateInterpolator() {
- return sManager.addNewDelegate(new AccelerateDecelerateInterpolator());
- }
-
- @LayoutlibDelegate
- /*package*/ static long createAccelerateInterpolator(float factor) {
- return sManager.addNewDelegate(new AccelerateInterpolator(factor));
- }
-
- @LayoutlibDelegate
- /*package*/ static long createAnticipateInterpolator(float tension) {
- return sManager.addNewDelegate(new AnticipateInterpolator(tension));
- }
-
- @LayoutlibDelegate
- /*package*/ static long createAnticipateOvershootInterpolator(float tension) {
- return sManager.addNewDelegate(new AnticipateOvershootInterpolator(tension));
- }
-
- @LayoutlibDelegate
- /*package*/ static long createBounceInterpolator() {
- return sManager.addNewDelegate(new BounceInterpolator());
- }
-
- @LayoutlibDelegate
- /*package*/ static long createCycleInterpolator(float cycles) {
- return sManager.addNewDelegate(new CycleInterpolator(cycles));
- }
-
- @LayoutlibDelegate
- /*package*/ static long createDecelerateInterpolator(float factor) {
- return sManager.addNewDelegate(new DecelerateInterpolator(factor));
- }
-
- @LayoutlibDelegate
- /*package*/ static long createLinearInterpolator() {
- return sManager.addNewDelegate(new LinearInterpolator());
- }
-
- @LayoutlibDelegate
- /*package*/ static long createOvershootInterpolator(float tension) {
- return sManager.addNewDelegate(new OvershootInterpolator(tension));
- }
-
- @LayoutlibDelegate
- /*package*/ static long createPathInterpolator(float[] x, float[] y) {
- Path path = new Path();
- path.moveTo(x[0], y[0]);
- for (int i = 1; i < x.length; i++) {
- path.lineTo(x[i], y[i]);
- }
- return sManager.addNewDelegate(new PathInterpolator(path));
- }
-
- private static class LutInterpolator extends BaseInterpolator {
- private final float[] mValues;
- private final int mSize;
-
- private LutInterpolator(float[] values) {
- mValues = values;
- mSize = mValues.length;
- }
-
- @Override
- public float getInterpolation(float input) {
- float lutpos = input * (mSize - 1);
- if (lutpos >= (mSize - 1)) {
- return mValues[mSize - 1];
- }
-
- int ipart = (int) lutpos;
- float weight = lutpos - ipart;
-
- int i1 = ipart;
- int i2 = Math.min(i1 + 1, mSize - 1);
-
- assert i1 >= 0 && i2 >= 0 : "Negatives in the interpolation";
-
- return MathUtils.lerp(mValues[i1], mValues[i2], weight);
- }
- }
-
- @LayoutlibDelegate
- /*package*/ static long createLutInterpolator(float[] values) {
- return sManager.addNewDelegate(new LutInterpolator(values));
- }
-}
+++ /dev/null
-/*
- * 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 com.android.internal.view.menu;
-
-import com.android.layoutlib.bridge.android.BridgeContext;
-
-import android.content.Context;
-import android.view.View;
-
-/**
- * An extension of the {@link MenuItemImpl} to store the view cookie also.
- */
-public class BridgeMenuItemImpl extends MenuItemImpl {
-
- /**
- * An object returned by the IDE that helps mapping each View to the corresponding XML tag in
- * the layout. For Menus, we store this cookie here and attach it to the corresponding view
- * at the time of rendering.
- */
- private Object viewCookie;
- private BridgeContext mContext;
-
- /**
- * Instantiates this menu item.
- */
- BridgeMenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
- CharSequence title, int showAsAction) {
- super(menu, group, id, categoryOrder, ordering, title, showAsAction);
- Context context = menu.getContext();
- context = BridgeContext.getBaseContext(context);
- if (context instanceof BridgeContext) {
- mContext = ((BridgeContext) context);
- }
- }
-
- public Object getViewCookie() {
- return viewCookie;
- }
-
- public void setViewCookie(Object viewCookie) {
- // If the menu item has an associated action provider view,
- // directly set the cookie in the view to cookie map stored in BridgeContext.
- View actionView = getActionView();
- if (actionView != null && mContext != null) {
- mContext.addViewKey(actionView, viewCookie);
- // We don't need to add the view cookie to the this item now. But there's no harm in
- // storing it, in case we need it in the future.
- }
- this.viewCookie = viewCookie;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.internal.view.menu;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate used to provide new implementation of a select few methods of {@link MenuBuilder}
- * <p/>
- * Through the layoutlib_create tool, the original methods of {@code MenuBuilder} have been
- * replaced by calls to methods of the same name in this delegate class.
- */
-public class MenuBuilder_Delegate {
- /**
- * The method overrides the instantiation of the {@link MenuItemImpl} with an instance of
- * {@link BridgeMenuItemImpl} so that view cookies may be stored.
- */
- @LayoutlibDelegate
- /*package*/ static MenuItemImpl createNewMenuItem(MenuBuilder thisMenu, int group, int id,
- int categoryOrder, int ordering, CharSequence title, int defaultShowAsAction) {
- return new BridgeMenuItemImpl(thisMenu, group, id, categoryOrder, ordering, title,
- defaultShowAsAction);
- }
-}
+++ /dev/null
-/*
- * 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 com.android.internal.widget;
-
-import android.widget.ActionMenuPresenter;
-
-/**
- * To access non public members of AbsActionBarView
- */
-public class ActionBarAccessor {
-
- /**
- * Returns the {@link ActionMenuPresenter} associated with the {@link AbsActionBarView}
- */
- public static ActionMenuPresenter getActionMenuPresenter(AbsActionBarView view) {
- return view.mActionMenuPresenter;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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;
-
-import com.android.ide.common.rendering.api.Capability;
-import com.android.ide.common.rendering.api.DrawableParams;
-import com.android.ide.common.rendering.api.Features;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.RenderSession;
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.Result.Status;
-import com.android.ide.common.rendering.api.SessionParams;
-import com.android.layoutlib.bridge.android.RenderParamsFlags;
-import com.android.layoutlib.bridge.impl.RenderDrawable;
-import com.android.layoutlib.bridge.impl.RenderSessionImpl;
-import com.android.layoutlib.bridge.util.DynamicIdMap;
-import com.android.ninepatch.NinePatchChunk;
-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 android.annotation.NonNull;
-import android.content.res.BridgeAssetManager;
-import android.graphics.Bitmap;
-import android.graphics.FontFamily_Delegate;
-import android.graphics.Typeface;
-import android.graphics.Typeface_Delegate;
-import android.icu.util.ULocale;
-import android.os.Looper;
-import android.os.Looper_Accessor;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-
-import java.io.File;
-import java.lang.ref.SoftReference;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
-import java.util.EnumMap;
-import java.util.EnumSet;
-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;
-
-/**
- * Main entry point of the LayoutLib Bridge.
- * <p/>To use this bridge, simply instantiate an object of type {@link Bridge} and call
- * {@link #createSession(SessionParams)}
- */
-public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
-
- private static final String ICU_LOCALE_DIRECTION_RTL = "right-to-left";
-
- public static class StaticMethodNotImplementedException extends RuntimeException {
- private static final long serialVersionUID = 1L;
-
- public StaticMethodNotImplementedException(String msg) {
- super(msg);
- }
- }
-
- /**
- * Lock to ensure only one rendering/inflating happens at a time.
- * This is due to some singleton in the Android framework.
- */
- private final static ReentrantLock sLock = new ReentrantLock();
-
- /**
- * Maps from id to resource type/name. This is for com.android.internal.R
- */
- @SuppressWarnings("deprecation")
- private final static Map<Integer, Pair<ResourceType, String>> sRMap = new HashMap<>();
-
- /**
- * Reverse map compared to sRMap, resource type -> (resource name -> id).
- * This is for com.android.internal.R.
- */
- private final static Map<ResourceType, Map<String, Integer>> sRevRMap = new EnumMap<>(ResourceType.class);
-
- // framework resources are defined as 0x01XX#### where XX is the resource type (layout,
- // drawable, etc...). Using FF as the type allows for 255 resource types before we get a
- // collision which should be fine.
- private final static int DYNAMIC_ID_SEED_START = 0x01ff0000;
- private final static DynamicIdMap sDynamicIds = new DynamicIdMap(DYNAMIC_ID_SEED_START);
-
- private final static Map<Object, Map<String, SoftReference<Bitmap>>> sProjectBitmapCache =
- new HashMap<>();
- private final static Map<Object, Map<String, SoftReference<NinePatchChunk>>> sProject9PatchCache =
-
- new HashMap<>();
-
- private final static Map<String, SoftReference<Bitmap>> sFrameworkBitmapCache = new HashMap<>();
- private final static Map<String, SoftReference<NinePatchChunk>> sFramework9PatchCache =
- new HashMap<>();
-
- private static Map<String, Map<String, Integer>> sEnumValueMap;
- private static Map<String, String> sPlatformProperties;
-
- /**
- * A default log than prints to stdout/stderr.
- */
- private final static LayoutLog sDefaultLog = new LayoutLog() {
- @Override
- public void error(String tag, String message, Object data) {
- System.err.println(message);
- }
-
- @Override
- public void error(String tag, String message, Throwable throwable, Object data) {
- System.err.println(message);
- }
-
- @Override
- public void warning(String tag, String message, Object data) {
- System.out.println(message);
- }
- };
-
- /**
- * Current log.
- */
- private static LayoutLog sCurrentLog = sDefaultLog;
-
- private static final int LAST_SUPPORTED_FEATURE = Features.THEME_PREVIEW_NAVIGATION_BAR;
-
- @Override
- public int getApiLevel() {
- return com.android.ide.common.rendering.api.Bridge.API_CURRENT;
- }
-
- @SuppressWarnings("deprecation")
- @Override
- @Deprecated
- public EnumSet<Capability> getCapabilities() {
- // The Capability class is deprecated and frozen. All Capabilities enumerated there are
- // supported by this version of LayoutLibrary. So, it's safe to use EnumSet.allOf()
- return EnumSet.allOf(Capability.class);
- }
-
- @Override
- public boolean supports(int feature) {
- return feature <= LAST_SUPPORTED_FEATURE;
- }
-
- @Override
- public boolean init(Map<String,String> platformProperties,
- File fontLocation,
- Map<String, Map<String, Integer>> enumValueMap,
- LayoutLog log) {
- sPlatformProperties = platformProperties;
- sEnumValueMap = enumValueMap;
-
- BridgeAssetManager.initSystem();
-
- // When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener
- // on static (native) methods which prints the signature on the console and
- // throws an exception.
- // This is useful when testing the rendering in ADT to identify static native
- // methods that are ignored -- layoutlib_create makes them returns 0/false/null
- // which is generally OK yet might be a problem, so this is how you'd find out.
- //
- // Currently layoutlib_create only overrides static native method.
- // Static non-natives are not overridden and thus do not get here.
- final String debug = System.getenv("DEBUG_LAYOUT");
- if (debug != null && !debug.equals("0") && !debug.equals("false")) {
-
- OverrideMethod.setDefaultListener(new MethodAdapter() {
- @Override
- public void onInvokeV(String signature, boolean isNative, Object caller) {
- sDefaultLog.error(null, "Missing Stub: " + signature +
- (isNative ? " (native)" : ""), null /*data*/);
-
- if (debug.equalsIgnoreCase("throw")) {
- // Throwing this exception doesn't seem that useful. It breaks
- // the layout editor yet doesn't display anything meaningful to the
- // user. Having the error in the console is just as useful. We'll
- // throw it only if the environment variable is "throw" or "THROW".
- throw new StaticMethodNotImplementedException(signature);
- }
- }
- });
- }
-
- // load the fonts.
- FontFamily_Delegate.setFontLocation(fontLocation.getAbsolutePath());
- MemoryMappedFile_Delegate.setDataDir(fontLocation.getAbsoluteFile().getParentFile());
-
- // now parse com.android.internal.R (and only this one as android.R is a subset of
- // the internal version), and put the content in the maps.
- try {
- Class<?> r = com.android.internal.R.class;
- // Parse the styleable class first, since it may contribute to attr values.
- parseStyleable();
-
- for (Class<?> inner : r.getDeclaredClasses()) {
- if (inner == com.android.internal.R.styleable.class) {
- // Already handled the styleable case. Not skipping attr, as there may be attrs
- // that are not referenced from styleables.
- continue;
- }
- String resTypeName = inner.getSimpleName();
- ResourceType resType = ResourceType.getEnum(resTypeName);
- if (resType != null) {
- Map<String, Integer> fullMap = null;
- switch (resType) {
- case ATTR:
- fullMap = sRevRMap.get(ResourceType.ATTR);
- break;
- case STRING:
- case STYLE:
- // Slightly less than thousand entries in each.
- fullMap = new HashMap<>(1280);
- // no break.
- default:
- if (fullMap == null) {
- fullMap = new HashMap<>();
- }
- sRevRMap.put(resType, fullMap);
- }
-
- for (Field f : inner.getDeclaredFields()) {
- // only process static final fields. Since the final attribute may have
- // been altered by layoutlib_create, we only check static
- if (!isValidRField(f)) {
- continue;
- }
- Class<?> type = f.getType();
- if (!type.isArray()) {
- Integer value = (Integer) f.get(null);
- //noinspection deprecation
- sRMap.put(value, Pair.of(resType, f.getName()));
- fullMap.put(f.getName(), value);
- }
- }
- }
- }
- } catch (Exception throwable) {
- if (log != null) {
- log.error(LayoutLog.TAG_BROKEN,
- "Failed to load com.android.internal.R from the layout library jar",
- throwable, null);
- }
- return false;
- }
-
- return true;
- }
-
- /**
- * Tests if the field is pubic, static and one of int or int[].
- */
- private static boolean isValidRField(Field field) {
- int modifiers = field.getModifiers();
- boolean isAcceptable = Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers);
- Class<?> type = field.getType();
- return isAcceptable && type == int.class ||
- (type.isArray() && type.getComponentType() == int.class);
-
- }
-
- private static void parseStyleable() throws Exception {
- // R.attr doesn't contain all the needed values. There are too many resources in the
- // framework for all to be in the R class. Only the ones specified manually in
- // res/values/symbols.xml are put in R class. Since, we need to create a map of all attr
- // values, we try and find them from the styleables.
-
- // There were 1500 elements in this map at M timeframe.
- Map<String, Integer> revRAttrMap = new HashMap<>(2048);
- sRevRMap.put(ResourceType.ATTR, revRAttrMap);
- // There were 2000 elements in this map at M timeframe.
- Map<String, Integer> revRStyleableMap = new HashMap<>(3072);
- sRevRMap.put(ResourceType.STYLEABLE, revRStyleableMap);
- Class<?> c = com.android.internal.R.styleable.class;
- Field[] fields = c.getDeclaredFields();
- // Sort the fields to bring all arrays to the beginning, so that indices into the array are
- // able to refer back to the arrays (i.e. no forward references).
- Arrays.sort(fields, (o1, o2) -> {
- if (o1 == o2) {
- return 0;
- }
- Class<?> t1 = o1.getType();
- Class<?> t2 = o2.getType();
- if (t1.isArray() && !t2.isArray()) {
- return -1;
- } else if (t2.isArray() && !t1.isArray()) {
- return 1;
- }
- return o1.getName().compareTo(o2.getName());
- });
- Map<String, int[]> styleables = new HashMap<>();
- for (Field field : fields) {
- if (!isValidRField(field)) {
- // Only consider public static fields that are int or int[].
- // Don't check the final flag as it may have been modified by layoutlib_create.
- continue;
- }
- String name = field.getName();
- if (field.getType().isArray()) {
- int[] styleableValue = (int[]) field.get(null);
- styleables.put(name, styleableValue);
- continue;
- }
- // Not an array.
- String arrayName = name;
- int[] arrayValue = null;
- int index;
- while ((index = arrayName.lastIndexOf('_')) >= 0) {
- // Find the name of the corresponding styleable.
- // Search in reverse order so that attrs like LinearLayout_Layout_layout_gravity
- // are mapped to LinearLayout_Layout and not to LinearLayout.
- arrayName = arrayName.substring(0, index);
- arrayValue = styleables.get(arrayName);
- if (arrayValue != null) {
- break;
- }
- }
- index = (Integer) field.get(null);
- if (arrayValue != null) {
- String attrName = name.substring(arrayName.length() + 1);
- int attrValue = arrayValue[index];
- //noinspection deprecation
- sRMap.put(attrValue, Pair.of(ResourceType.ATTR, attrName));
- revRAttrMap.put(attrName, attrValue);
- }
- //noinspection deprecation
- sRMap.put(index, Pair.of(ResourceType.STYLEABLE, name));
- revRStyleableMap.put(name, index);
- }
- }
-
- @Override
- public boolean dispose() {
- BridgeAssetManager.clearSystem();
-
- // dispose of the default typeface.
- Typeface_Delegate.resetDefaults();
- Typeface.sDynamicTypefaceCache.evictAll();
-
- return true;
- }
-
- /**
- * Starts a layout session by inflating and rendering it. The method returns a
- * {@link RenderSession} on which further actions can be taken.
- * <p/>
- * If {@link SessionParams} includes the {@link RenderParamsFlags#FLAG_DO_NOT_RENDER_ON_CREATE},
- * this method will only inflate the layout but will NOT render it.
- * @param params the {@link SessionParams} object with all the information necessary to create
- * the scene.
- * @return a new {@link RenderSession} object that contains the result of the layout.
- * @since 5
- */
- @Override
- public RenderSession createSession(SessionParams params) {
- try {
- Result lastResult;
- RenderSessionImpl scene = new RenderSessionImpl(params);
- try {
- prepareThread();
- lastResult = scene.init(params.getTimeout());
- if (lastResult.isSuccess()) {
- lastResult = scene.inflate();
-
- boolean doNotRenderOnCreate = Boolean.TRUE.equals(
- params.getFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE));
- if (lastResult.isSuccess() && !doNotRenderOnCreate) {
- lastResult = scene.render(true /*freshRender*/);
- }
- }
- } finally {
- scene.release();
- cleanupThread();
- }
-
- return new BridgeRenderSession(scene, lastResult);
- } catch (Throwable t) {
- // get the real cause of the exception.
- Throwable t2 = t;
- while (t2.getCause() != null) {
- t2 = t.getCause();
- }
- return new BridgeRenderSession(null,
- ERROR_UNKNOWN.createResult(t2.getMessage(), t));
- }
- }
-
- @Override
- public Result renderDrawable(DrawableParams params) {
- try {
- Result lastResult;
- RenderDrawable action = new RenderDrawable(params);
- try {
- prepareThread();
- lastResult = action.init(params.getTimeout());
- if (lastResult.isSuccess()) {
- lastResult = action.render();
- }
- } finally {
- action.release();
- cleanupThread();
- }
-
- return lastResult;
- } catch (Throwable t) {
- // get the real cause of the exception.
- Throwable t2 = t;
- while (t2.getCause() != null) {
- t2 = t.getCause();
- }
- return ERROR_UNKNOWN.createResult(t2.getMessage(), t);
- }
- }
-
- @Override
- public void clearCaches(Object projectKey) {
- if (projectKey != null) {
- sProjectBitmapCache.remove(projectKey);
- sProject9PatchCache.remove(projectKey);
- }
- }
-
- @Override
- public Result getViewParent(Object viewObject) {
- if (viewObject instanceof View) {
- return Status.SUCCESS.createResult(((View)viewObject).getParent());
- }
-
- throw new IllegalArgumentException("viewObject is not a View");
- }
-
- @Override
- public Result getViewIndex(Object viewObject) {
- if (viewObject instanceof View) {
- View view = (View) viewObject;
- ViewParent parentView = view.getParent();
-
- if (parentView instanceof ViewGroup) {
- Status.SUCCESS.createResult(((ViewGroup) parentView).indexOfChild(view));
- }
-
- return Status.SUCCESS.createResult();
- }
-
- throw new IllegalArgumentException("viewObject is not a View");
- }
-
- @Override
- public boolean isRtl(String locale) {
- return isLocaleRtl(locale);
- }
-
- public static boolean isLocaleRtl(String locale) {
- if (locale == null) {
- locale = "";
- }
- ULocale uLocale = new ULocale(locale);
- return uLocale.getCharacterOrientation().equals(ICU_LOCALE_DIRECTION_RTL);
- }
-
- /**
- * Returns the lock for the bridge
- */
- public static ReentrantLock getLock() {
- return sLock;
- }
-
- /**
- * Prepares the current thread for rendering.
- *
- * Note that while this can be called several time, the first call to {@link #cleanupThread()}
- * will do the clean-up, and make the thread unable to do further scene actions.
- */
- public synchronized static void prepareThread() {
- // we need to make sure the Looper has been initialized for this thread.
- // this is required for View that creates Handler objects.
- if (Looper.myLooper() == null) {
- Looper.prepareMainLooper();
- }
- }
-
- /**
- * Cleans up thread-specific data. After this, the thread cannot be used for scene actions.
- * <p>
- * Note that it doesn't matter how many times {@link #prepareThread()} was called, a single
- * call to this will prevent the thread from doing further scene actions
- */
- public synchronized static void cleanupThread() {
- // clean up the looper
- Looper_Accessor.cleanupThread();
- }
-
- public static LayoutLog getLog() {
- return sCurrentLog;
- }
-
- public static void setLog(LayoutLog log) {
- // check only the thread currently owning the lock can do this.
- if (!sLock.isHeldByCurrentThread()) {
- throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
- }
-
- if (log != null) {
- sCurrentLog = log;
- } else {
- sCurrentLog = sDefaultLog;
- }
- }
-
- /**
- * Returns details of a framework resource from its integer value.
- * @param value the integer value
- * @return a Pair containing the resource type and name, or null if the id
- * does not match any resource.
- */
- @SuppressWarnings("deprecation")
- public static Pair<ResourceType, String> resolveResourceId(int value) {
- Pair<ResourceType, String> pair = sRMap.get(value);
- if (pair == null) {
- pair = sDynamicIds.resolveId(value);
- }
- return pair;
- }
-
- /**
- * Returns the integer id of a framework resource, from a given resource type and resource name.
- * <p/>
- * If no resource is found, it creates a dynamic id for the resource.
- *
- * @param type the type of the resource
- * @param name the name of the resource.
- *
- * @return an {@link Integer} containing the resource id.
- */
- @NonNull
- public static Integer getResourceId(ResourceType type, String name) {
- Map<String, Integer> map = sRevRMap.get(type);
- Integer value = null;
- if (map != null) {
- value = map.get(name);
- }
-
- return value == null ? sDynamicIds.getId(type, name) : value;
-
- }
-
- /**
- * Returns the list of possible enums for a given attribute name.
- */
- public static Map<String, Integer> getEnumValues(String attributeName) {
- if (sEnumValueMap != null) {
- return sEnumValueMap.get(attributeName);
- }
-
- return null;
- }
-
- /**
- * Returns the platform build properties.
- */
- public static Map<String, String> getPlatformProperties() {
- return sPlatformProperties;
- }
-
- /**
- * Returns the bitmap for a specific path, from a specific project cache, or from the
- * framework cache.
- * @param value the path of the bitmap
- * @param projectKey the key of the project, or null to query the framework cache.
- * @return the cached Bitmap or null if not found.
- */
- public static Bitmap getCachedBitmap(String value, Object projectKey) {
- if (projectKey != null) {
- Map<String, SoftReference<Bitmap>> map = sProjectBitmapCache.get(projectKey);
- if (map != null) {
- SoftReference<Bitmap> ref = map.get(value);
- if (ref != null) {
- return ref.get();
- }
- }
- } else {
- SoftReference<Bitmap> ref = sFrameworkBitmapCache.get(value);
- if (ref != null) {
- return ref.get();
- }
- }
-
- return null;
- }
-
- /**
- * Sets a bitmap in a project cache or in the framework cache.
- * @param value the path of the bitmap
- * @param bmp the Bitmap object
- * @param projectKey the key of the project, or null to put the bitmap in the framework cache.
- */
- public static void setCachedBitmap(String value, Bitmap bmp, Object projectKey) {
- if (projectKey != null) {
- Map<String, SoftReference<Bitmap>> map =
- sProjectBitmapCache.computeIfAbsent(projectKey, k -> new HashMap<>());
-
- map.put(value, new SoftReference<>(bmp));
- } else {
- sFrameworkBitmapCache.put(value, new SoftReference<>(bmp));
- }
- }
-
- /**
- * Returns the 9 patch chunk for a specific path, from a specific project cache, or from the
- * framework cache.
- * @param value the path of the 9 patch
- * @param projectKey the key of the project, or null to query the framework cache.
- * @return the cached 9 patch or null if not found.
- */
- public static NinePatchChunk getCached9Patch(String value, Object projectKey) {
- if (projectKey != null) {
- Map<String, SoftReference<NinePatchChunk>> map = sProject9PatchCache.get(projectKey);
-
- if (map != null) {
- SoftReference<NinePatchChunk> ref = map.get(value);
- if (ref != null) {
- return ref.get();
- }
- }
- } else {
- SoftReference<NinePatchChunk> ref = sFramework9PatchCache.get(value);
- if (ref != null) {
- return ref.get();
- }
- }
-
- return null;
- }
-
- /**
- * Sets a 9 patch chunk in a project cache or in the framework cache.
- * @param value the path of the 9 patch
- * @param ninePatch the 9 patch object
- * @param projectKey the key of the project, or null to put the bitmap in the framework cache.
- */
- public static void setCached9Patch(String value, NinePatchChunk ninePatch, Object projectKey) {
- if (projectKey != null) {
- Map<String, SoftReference<NinePatchChunk>> map =
- sProject9PatchCache.computeIfAbsent(projectKey, k -> new HashMap<>());
-
- map.put(value, new SoftReference<>(ninePatch));
- } else {
- sFramework9PatchCache.put(value, new SoftReference<>(ninePatch));
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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;
-
-/**
- * Constant definition class.<br>
- * <br>
- * Most constants have a prefix defining the content.
- * <ul>
- * <li><code>WS_</code> Workspace path constant. Those are absolute paths,
- * from the project root.</li>
- * <li><code>OS_</code> OS path constant. These paths are different depending on the platform.</li>
- * <li><code>FN_</code> File name constant.</li>
- * <li><code>FD_</code> Folder name constant.</li>
- * <li><code>EXT_</code> File extension constant. This does NOT include a dot.</li>
- * <li><code>DOT_</code> File extension constant. This start with a dot.</li>
- * <li><code>RE_</code> Regexp constant.</li>
- * <li><code>NS_</code> Namespace constant.</li>
- * <li><code>CLASS_</code> Fully qualified class name.</li>
- * </ul>
- *
- */
-public class BridgeConstants {
-
- /** Namespace for the resource XML */
- public final static String NS_RESOURCES = "http://schemas.android.com/apk/res/android";
-
- /** App auto namespace */
- public final static String NS_APP_RES_AUTO = "http://schemas.android.com/apk/res-auto";
- public final static String NS_TOOLS_URI = "http://schemas.android.com/tools";
-
- public final static String R = "com.android.internal.R";
-
-
- public final static String MATCH_PARENT = "match_parent";
- public final static String FILL_PARENT = "fill_parent";
- public final static String WRAP_CONTENT = "wrap_content";
-
- // Should be kept in sync with LayoutMetadata.KEY_LV_ITEM in tools/adt/idea
- /** Attribute in the tools namespace used to specify layout manager for RecyclerView. */
- @SuppressWarnings("SpellCheckingInspection")
- public static final String ATTR_LIST_ITEM = "listitem";
- public static final String ATTR_OPEN_DRAWER = "openDrawer";
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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;
-
-import com.android.ide.common.rendering.api.IAnimationListener;
-import com.android.ide.common.rendering.api.ILayoutPullParser;
-import com.android.ide.common.rendering.api.RenderParams;
-import com.android.ide.common.rendering.api.RenderSession;
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.ViewInfo;
-import com.android.layoutlib.bridge.impl.RenderSessionImpl;
-import com.android.tools.layoutlib.java.System_Delegate;
-import com.android.util.PropertiesMap;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.view.View;
-import android.view.ViewGroup;
-
-import java.awt.image.BufferedImage;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * An implementation of {@link RenderSession}.
- *
- * This is a pretty basic class that does almost nothing. All of the work is done in
- * {@link RenderSessionImpl}.
- *
- */
-public class BridgeRenderSession extends RenderSession {
-
- @Nullable
- private final RenderSessionImpl mSession;
- @NonNull
- private Result mLastResult;
-
- @Override
- public Result getResult() {
- return mLastResult;
- }
-
- @Override
- public BufferedImage getImage() {
- return mSession != null ? mSession.getImage() :
- new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
- }
-
- @Override
- public boolean isAlphaChannelImage() {
- return mSession != null && mSession.isAlphaChannelImage();
- }
-
- @Override
- public List<ViewInfo> getRootViews() {
- return mSession != null ? mSession.getViewInfos() : Collections.emptyList();
- }
-
- @Override
- public List<ViewInfo> getSystemRootViews() {
- return mSession != null ? mSession.getSystemViewInfos() : Collections.emptyList();
- }
-
- @Override
- public Map<Object, PropertiesMap> getDefaultProperties() {
- return mSession != null ? mSession.getDefaultProperties() : Collections.emptyMap();
- }
-
- @Override
- public Result measure(long timeout) {
- if (mSession != null) {
- try {
- Bridge.prepareThread();
- mLastResult = mSession.acquire(timeout);
- if (mLastResult.isSuccess()) {
- mSession.invalidateRenderingSize();
- mLastResult = mSession.measure();
- }
- } finally {
- mSession.release();
- Bridge.cleanupThread();
- }
- }
-
- return mLastResult;
- }
-
- @Override
- public Result render(long timeout, boolean forceMeasure) {
- if (mSession != null) {
- try {
- Bridge.prepareThread();
- mLastResult = mSession.acquire(timeout);
- if (mLastResult.isSuccess()) {
- if (forceMeasure) {
- mSession.invalidateRenderingSize();
- }
- mLastResult = mSession.render(false /*freshRender*/);
- }
- } finally {
- mSession.release();
- Bridge.cleanupThread();
- }
- }
-
- return mLastResult;
- }
-
- @Override
- public Result animate(Object targetObject, String animationName,
- boolean isFrameworkAnimation, IAnimationListener listener) {
- if (mSession != null) {
- try {
- Bridge.prepareThread();
- mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
- if (mLastResult.isSuccess()) {
- mLastResult = mSession.animate(targetObject, animationName, isFrameworkAnimation,
- listener);
- }
- } finally {
- mSession.release();
- Bridge.cleanupThread();
- }
- }
-
- return mLastResult;
- }
-
- @Override
- public Result insertChild(Object parentView, ILayoutPullParser childXml, int index,
- IAnimationListener listener) {
- if (!(parentView instanceof ViewGroup)) {
- throw new IllegalArgumentException("parentView is not a ViewGroup");
- }
-
- if (mSession != null) {
- try {
- Bridge.prepareThread();
- mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
- if (mLastResult.isSuccess()) {
- mLastResult =
- mSession.insertChild((ViewGroup) parentView, childXml, index, listener);
- }
- } finally {
- mSession.release();
- Bridge.cleanupThread();
- }
- }
-
- return mLastResult;
- }
-
-
- @Override
- public Result moveChild(Object parentView, Object childView, int index,
- Map<String, String> layoutParams, IAnimationListener listener) {
- if (!(parentView instanceof ViewGroup)) {
- throw new IllegalArgumentException("parentView is not a ViewGroup");
- }
- if (!(childView instanceof View)) {
- throw new IllegalArgumentException("childView is not a View");
- }
-
- if (mSession != null) {
- try {
- Bridge.prepareThread();
- mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
- if (mLastResult.isSuccess()) {
- mLastResult = mSession.moveChild((ViewGroup) parentView, (View) childView, index,
- layoutParams, listener);
- }
- } finally {
- mSession.release();
- Bridge.cleanupThread();
- }
- }
-
- return mLastResult;
- }
-
- @Override
- public Result removeChild(Object childView, IAnimationListener listener) {
- if (!(childView instanceof View)) {
- throw new IllegalArgumentException("childView is not a View");
- }
-
- if (mSession != null) {
- try {
- Bridge.prepareThread();
- mLastResult = mSession.acquire(RenderParams.DEFAULT_TIMEOUT);
- if (mLastResult.isSuccess()) {
- mLastResult = mSession.removeChild((View) childView, listener);
- }
- } finally {
- mSession.release();
- Bridge.cleanupThread();
- }
- }
-
- return mLastResult;
- }
-
- @Override
- public void setSystemTimeNanos(long nanos) {
- System_Delegate.setNanosTime(nanos);
- }
-
- @Override
- public void setSystemBootTimeNanos(long nanos) {
- System_Delegate.setBootTimeNanos(nanos);
- }
-
- @Override
- public void setElapsedFrameTimeNanos(long nanos) {
- if (mSession != null) {
- mSession.setElapsedFrameTimeNanos(nanos);
- }
- }
-
- @Override
- public void dispose() {
- if (mSession != null) {
- mSession.dispose();
- }
- }
-
- /*package*/ BridgeRenderSession(@Nullable RenderSessionImpl scene, @NonNull Result lastResult) {
- mSession = scene;
- if (scene != null) {
- mSession.setScene(this);
- }
- mLastResult = lastResult;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-/**
- * Base class for mocked views.
- * <p/>
- * FrameLayout with a single TextView. Doesn't allow adding any other views to itself.
- */
-public class MockView extends FrameLayout {
-
- private final TextView mView;
-
- public MockView(Context context) {
- this(context, null);
- }
-
- public MockView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public MockView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public MockView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mView = new TextView(context, attrs);
- mView.setTextColor(0xFF000000);
- setGravity(Gravity.CENTER);
- setText(getClass().getSimpleName());
- addView(mView);
- setBackgroundColor(0xFF7F7F7F);
- }
-
- // Only allow adding one TextView.
- @Override
- public void addView(View child) {
- if (child == mView) {
- super.addView(child);
- }
- }
-
- @Override
- public void addView(View child, int index) {
- if (child == mView) {
- super.addView(child, index);
- }
- }
-
- @Override
- public void addView(View child, int width, int height) {
- if (child == mView) {
- super.addView(child, width, height);
- }
- }
-
- @Override
- public void addView(View child, ViewGroup.LayoutParams params) {
- if (child == mView) {
- super.addView(child, params);
- }
- }
-
- @Override
- public void addView(View child, int index, ViewGroup.LayoutParams params) {
- if (child == mView) {
- super.addView(child, index, params);
- }
- }
-
- // The following methods are called by the IDE via reflection, and should be considered part
- // of the API.
- // Historically, MockView used to be a textView and had these methods. Now, we simply delegate
- // them to the contained textView.
-
- public void setText(CharSequence text) {
- mView.setText(text);
- }
-
- @SuppressWarnings("WeakerAccess") // This method is used from Studio
- public void setGravity(int gravity) {
- mView.setGravity(gravity);
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.android;
-
-import com.android.layoutlib.bridge.impl.RenderAction;
-
-import android.icu.util.ULocale;
-
-import java.util.Locale;
-
-/**
- * This class provides an alternate implementation for {@code java.util.Locale#toLanguageTag}
- * which is only available after Java 6.
- *
- * The create tool re-writes references to the above mentioned method to this one. Hence it's
- * imperative that this class is not deleted unless the create tool is modified.
- */
-@SuppressWarnings("UnusedDeclaration")
-public class AndroidLocale {
-
- public static String toLanguageTag(Locale locale) {
- return ULocale.forLocale(locale).toLanguageTag();
- }
-
- public static String adjustLanguageCode(String languageCode) {
- String adjusted = languageCode.toLowerCase(Locale.US);
- // Map new language codes to the obsolete language
- // codes so the correct resource bundles will be used.
- if (languageCode.equals("he")) {
- adjusted = "iw";
- } else if (languageCode.equals("id")) {
- adjusted = "in";
- } else if (languageCode.equals("yi")) {
- adjusted = "ji";
- }
-
- return adjusted;
- }
-
- public static Locale forLanguageTag(String tag) {
- return ULocale.forLanguageTag(tag).toLocale();
- }
-
- 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();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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.content.ContentProviderOperation;
-import android.content.ContentProviderResult;
-import android.content.ContentValues;
-import android.content.IContentProvider;
-import android.content.OperationApplicationException;
-import android.content.res.AssetFileDescriptor;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.ICancellationSignal;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-
-/**
- * Mock implementation of {@link IContentProvider}.
- *
- * TODO: never return null when the method is not supposed to. Return fake data instead.
- */
-public final class BridgeContentProvider implements IContentProvider {
- @Override
- public ContentProviderResult[] applyBatch(String callingPackage,
- ArrayList<ContentProviderOperation> arg0)
- throws RemoteException, OperationApplicationException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public int bulkInsert(String callingPackage, Uri arg0, ContentValues[] arg1)
- throws RemoteException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public Bundle call(String callingPackage, String arg0, String arg1, Bundle arg2)
- throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public int delete(String callingPackage, Uri arg0, String arg1, String[] arg2)
- throws RemoteException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public String getType(Uri arg0) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Uri insert(String callingPackage, Uri arg0, ContentValues arg1) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public AssetFileDescriptor openAssetFile(
- String callingPackage, Uri arg0, String arg1, ICancellationSignal signal)
- throws RemoteException, FileNotFoundException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public ParcelFileDescriptor openFile(
- String callingPackage, Uri arg0, String arg1, ICancellationSignal signal, IBinder token)
- throws RemoteException, FileNotFoundException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public Cursor query(String callingPackage, Uri arg0, String[] arg1,
- Bundle arg3, ICancellationSignal arg4) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public int update(String callingPackage, Uri arg0, ContentValues arg1, String arg2,
- String[] arg3) throws RemoteException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public IBinder asBinder() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public String[] getStreamTypes(Uri arg0, String arg1) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public AssetFileDescriptor openTypedAssetFile(String callingPackage, Uri arg0, String arg1,
- Bundle arg2, ICancellationSignal signal) throws RemoteException, FileNotFoundException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public ICancellationSignal createCancellationSignal() throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
-
- @Override
- public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException {
- return null;
- }
-
- @Override
- public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException {
- return null;
- }
-
- @Override
- public boolean refresh(String callingPkg, Uri url, Bundle args,
- ICancellationSignal cancellationSignal) throws RemoteException {
- return false;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2009 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.content.ContentResolver;
-import android.content.Context;
-import android.content.IContentProvider;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Bundle;
-
-/**
- * A mock content resolver for the LayoutLib Bridge.
- * <p/>
- * It won't serve any actual data but it's good enough for all
- * the widgets which expect to have a content resolver available via
- * {@link BridgeContext#getContentResolver()}.
- */
-public class BridgeContentResolver extends ContentResolver {
-
- private BridgeContentProvider mProvider = null;
-
- public BridgeContentResolver(Context context) {
- super(context);
- }
-
- @Override
- public IContentProvider acquireProvider(Context c, String name) {
- if (mProvider == null) {
- mProvider = new BridgeContentProvider();
- }
-
- return mProvider;
- }
-
- @Override
- public IContentProvider acquireExistingProvider(Context c, String name) {
- if (mProvider == null) {
- mProvider = new BridgeContentProvider();
- }
-
- return mProvider;
- }
-
- @Override
- public boolean releaseProvider(IContentProvider icp) {
- // ignore
- return false;
- }
-
- @Override
- protected IContentProvider acquireUnstableProvider(Context c, String name) {
- return acquireProvider(c, name);
- }
-
- @Override
- public boolean releaseUnstableProvider(IContentProvider icp) {
- return releaseProvider(icp);
- }
-
- /** @hide */
- @Override
- public void unstableProviderDied(IContentProvider icp) {
- }
-
- /**
- * Stub for the layoutlib bridge content resolver.
- */
- @Override
- public void registerContentObserver(Uri uri, boolean notifyForDescendents,
- ContentObserver observer) {
- // pass
- }
-
- /**
- * Stub for the layoutlib bridge content resolver.
- */
- @Override
- public void unregisterContentObserver(ContentObserver observer) {
- // pass
- }
-
- /**
- * Stub for the layoutlib bridge content resolver.
- */
- @Override
- public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
- // pass
- }
-
- /**
- * Stub for the layoutlib bridge content resolver.
- */
- @Override
- public void startSync(Uri uri, Bundle extras) {
- // pass
- }
-
- /**
- * Stub for the layoutlib bridge content resolver.
- */
- @Override
- public void cancelSync(Uri uri) {
- // pass
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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 com.android.SdkConstants;
-import com.android.ide.common.rendering.api.AssetRepository;
-import com.android.ide.common.rendering.api.ILayoutPullParser;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceReference;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.StyleResourceValue;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.BridgeConstants;
-import com.android.layoutlib.bridge.android.view.WindowManagerImpl;
-import com.android.layoutlib.bridge.impl.ParserFactory;
-import com.android.layoutlib.bridge.impl.Stack;
-import com.android.resources.ResourceType;
-import com.android.util.Pair;
-import com.android.util.PropertiesMap;
-import com.android.util.PropertiesMap.Property;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Notification;
-import android.app.SystemServiceRegistry_Accessor;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.IntentSender;
-import android.content.ServiceConnection;
-import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.AssetManager;
-import android.content.res.BridgeAssetManager;
-import android.content.res.BridgeTypedArray;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.Resources.Theme;
-import android.content.res.Resources_Delegate;
-import android.database.DatabaseErrorHandler;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteDatabase.CursorFactory;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
-import android.hardware.display.DisplayManager;
-import android.net.Uri;
-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;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.os.ShellCallback;
-import android.os.UserHandle;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-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;
-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;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-
-import static android.os._Original_Build.VERSION_CODES.JELLY_BEAN_MR1;
-import static com.android.layoutlib.bridge.android.RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE;
-
-/**
- * Custom implementation of Context/Activity to handle non compiled resources.
- */
-@SuppressWarnings("deprecation") // For use of Pair.
-public class BridgeContext extends Context {
- private static final String PREFIX_THEME_APPCOMPAT = "Theme.AppCompat";
-
- private static final Map<String, ResourceValue> FRAMEWORK_PATCHED_VALUES = new HashMap<>(2);
- private static final Map<String, ResourceValue> FRAMEWORK_REPLACE_VALUES = new HashMap<>(3);
-
- static {
- FRAMEWORK_PATCHED_VALUES.put("animateFirstView", new ResourceValue(
- ResourceType.BOOL, "animateFirstView", "false", false));
- FRAMEWORK_PATCHED_VALUES.put("animateLayoutChanges",
- new ResourceValue(ResourceType.BOOL, "animateLayoutChanges", "false", false));
-
-
- FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionItemLayout",
- new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionItemLayout",
- "text_edit_suggestion_item", true));
- FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionContainerLayout",
- new ResourceValue(ResourceType.LAYOUT, "textEditSuggestionContainerLayout",
- "text_edit_suggestion_container", true));
- FRAMEWORK_REPLACE_VALUES.put("textEditSuggestionHighlightStyle",
- new ResourceValue(ResourceType.STYLE, "textEditSuggestionHighlightStyle",
- "TextAppearance.Holo.SuggestionHighlight", true));
-
- }
-
- /** The map adds cookies to each view so that IDE can link xml tags to views. */
- private final HashMap<View, Object> mViewKeyMap = new HashMap<>();
- /**
- * In some cases, when inflating an xml, some objects are created. Then later, the objects are
- * converted to views. This map stores the mapping from objects to cookies which can then be
- * used to populate the mViewKeyMap.
- */
- private final HashMap<Object, Object> mViewKeyHelpMap = new HashMap<>();
- private final BridgeAssetManager mAssets;
- private Resources mSystemResources;
- private final Object mProjectKey;
- private final DisplayMetrics mMetrics;
- private final RenderResources mRenderResources;
- private final Configuration mConfig;
- private final ApplicationInfo mApplicationInfo;
- private final LayoutlibCallback mLayoutlibCallback;
- private final WindowManager mWindowManager;
- private final DisplayManager mDisplayManager;
- private final HashMap<View, Integer> mScrollYPos = new HashMap<>();
- private final HashMap<View, Integer> mScrollXPos = new HashMap<>();
-
- private Resources.Theme mTheme;
-
- private final Map<Object, PropertiesMap> mDefaultPropMaps = new IdentityHashMap<>();
-
- // maps for dynamically generated id representing style objects (StyleResourceValue)
- @Nullable
- private Map<Integer, StyleResourceValue> mDynamicIdToStyleMap;
- private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap;
- private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
-
- // cache for TypedArray generated from StyleResourceValue object
- private TypedArrayCache mTypedArrayCache;
- private BridgeInflater mBridgeInflater;
-
- private BridgeContentResolver mContentResolver;
-
- private final Stack<BridgeXmlBlockParser> mParserStack = new Stack<>();
- private SharedPreferences mSharedPreferences;
- private ClassLoader mClassLoader;
- private IBinder mBinder;
- private PackageManager mPackageManager;
- private Boolean mIsThemeAppCompat;
-
- /**
- * Some applications that target both pre API 17 and post API 17, set the newer attrs to
- * reference the older ones. For example, android:paddingStart will resolve to
- * android:paddingLeft. This way the apps need to only define paddingLeft at any other place.
- * This a map from value to attribute name. Warning for missing references shouldn't be logged
- * if value and attr name pair is the same as an entry in this map.
- */
- private static Map<String, String> RTL_ATTRS = new HashMap<>(10);
-
- static {
- RTL_ATTRS.put("?android:attr/paddingLeft", "paddingStart");
- RTL_ATTRS.put("?android:attr/paddingRight", "paddingEnd");
- RTL_ATTRS.put("?android:attr/layout_marginLeft", "layout_marginStart");
- RTL_ATTRS.put("?android:attr/layout_marginRight", "layout_marginEnd");
- RTL_ATTRS.put("?android:attr/layout_toLeftOf", "layout_toStartOf");
- RTL_ATTRS.put("?android:attr/layout_toRightOf", "layout_toEndOf");
- RTL_ATTRS.put("?android:attr/layout_alignParentLeft", "layout_alignParentStart");
- RTL_ATTRS.put("?android:attr/layout_alignParentRight", "layout_alignParentEnd");
- RTL_ATTRS.put("?android:attr/drawableLeft", "drawableStart");
- RTL_ATTRS.put("?android:attr/drawableRight", "drawableEnd");
- }
-
- /**
- * @param projectKey An Object identifying the project. This is used for the cache mechanism.
- * @param metrics the {@link DisplayMetrics}.
- * @param renderResources the configured resources (both framework and projects) for this
- * render.
- * @param config the Configuration object for this render.
- * @param targetSdkVersion the targetSdkVersion of the application.
- */
- public BridgeContext(Object projectKey, DisplayMetrics metrics,
- RenderResources renderResources,
- AssetRepository assets,
- LayoutlibCallback layoutlibCallback,
- Configuration config,
- int targetSdkVersion,
- boolean hasRtlSupport) {
- mProjectKey = projectKey;
- mMetrics = metrics;
- mLayoutlibCallback = layoutlibCallback;
-
- mRenderResources = renderResources;
- mConfig = config;
- AssetManager systemAssetManager = AssetManager.getSystem();
- if (systemAssetManager instanceof BridgeAssetManager) {
- mAssets = (BridgeAssetManager) systemAssetManager;
- } else {
- throw new AssertionError("Creating BridgeContext without initializing Bridge");
- }
- mAssets.setAssetRepository(assets);
-
- mApplicationInfo = new ApplicationInfo();
- mApplicationInfo.targetSdkVersion = targetSdkVersion;
- if (hasRtlSupport) {
- mApplicationInfo.flags = mApplicationInfo.flags | ApplicationInfo.FLAG_SUPPORTS_RTL;
- }
-
- mWindowManager = new WindowManagerImpl(mMetrics);
- mDisplayManager = new DisplayManager(this);
- }
-
- /**
- * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its
- * {@link DisplayMetrics}, {@link Configuration}, and {@link LayoutlibCallback}.
- *
- * @see #disposeResources()
- */
- public void initResources() {
- AssetManager assetManager = AssetManager.getSystem();
-
- mSystemResources = Resources_Delegate.initSystem(
- this,
- assetManager,
- mMetrics,
- mConfig,
- mLayoutlibCallback);
- mTheme = mSystemResources.newTheme();
- }
-
- /**
- * Disposes the {@link Resources} singleton.
- */
- public void disposeResources() {
- Resources_Delegate.disposeSystem();
- }
-
- public void setBridgeInflater(BridgeInflater inflater) {
- mBridgeInflater = inflater;
- }
-
- public void addViewKey(View view, Object viewKey) {
- mViewKeyMap.put(view, viewKey);
- }
-
- public Object getViewKey(View view) {
- return mViewKeyMap.get(view);
- }
-
- public void addCookie(Object o, Object cookie) {
- mViewKeyHelpMap.put(o, cookie);
- }
-
- public Object getCookie(Object o) {
- return mViewKeyHelpMap.get(o);
- }
-
- public Object getProjectKey() {
- return mProjectKey;
- }
-
- public DisplayMetrics getMetrics() {
- return mMetrics;
- }
-
- public LayoutlibCallback getLayoutlibCallback() {
- return mLayoutlibCallback;
- }
-
- public RenderResources getRenderResources() {
- return mRenderResources;
- }
-
- public Map<Object, PropertiesMap> getDefaultProperties() {
- return mDefaultPropMaps;
- }
-
- public Configuration getConfiguration() {
- return mConfig;
- }
-
- /**
- * Adds a parser to the stack.
- * @param parser the parser to add.
- */
- public void pushParser(BridgeXmlBlockParser parser) {
- if (ParserFactory.LOG_PARSER) {
- System.out.println("PUSH " + parser.getParser().toString());
- }
- mParserStack.push(parser);
- }
-
- /**
- * Removes the parser at the top of the stack
- */
- public void popParser() {
- BridgeXmlBlockParser parser = mParserStack.pop();
- if (ParserFactory.LOG_PARSER) {
- System.out.println("POPD " + parser.getParser().toString());
- }
- }
-
- /**
- * Returns the current parser at the top the of the stack.
- * @return a parser or null.
- */
- private BridgeXmlBlockParser getCurrentParser() {
- return mParserStack.peek();
- }
-
- /**
- * Returns the previous parser.
- * @return a parser or null if there isn't any previous parser
- */
- public BridgeXmlBlockParser getPreviousParser() {
- if (mParserStack.size() < 2) {
- return null;
- }
- return mParserStack.get(mParserStack.size() - 2);
- }
-
- public boolean resolveThemeAttribute(int resId, TypedValue outValue, boolean resolveRefs) {
- Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(resId);
- boolean isFrameworkRes = true;
- if (resourceInfo == null) {
- resourceInfo = mLayoutlibCallback.resolveResourceId(resId);
- isFrameworkRes = false;
- }
-
- if (resourceInfo == null) {
- return false;
- }
-
- ResourceValue value = mRenderResources.findItemInTheme(resourceInfo.getSecond(),
- isFrameworkRes);
- if (resolveRefs) {
- value = mRenderResources.resolveResValue(value);
- }
-
- if (value == null) {
- // unable to find the attribute.
- return false;
- }
-
- // check if this is a style resource
- if (value instanceof StyleResourceValue) {
- // get the id that will represent this style.
- outValue.resourceId = getDynamicIdByStyle((StyleResourceValue) value);
- return true;
- }
-
- String stringValue = value.getValue();
- if (!stringValue.isEmpty()) {
- if (stringValue.charAt(0) == '#') {
- outValue.type = TypedValue.TYPE_INT_COLOR_ARGB8;
- outValue.data = Color.parseColor(value.getValue());
- }
- else if (stringValue.charAt(0) == '@') {
- outValue.type = TypedValue.TYPE_REFERENCE;
- }
-
- }
-
- int a;
- // if this is a framework value.
- if (value.isFramework()) {
- // look for idName in the android R classes.
- // use 0 a default res value as it's not a valid id value.
- a = getFrameworkResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/);
- } else {
- // look for idName in the project R class.
- // use 0 a default res value as it's not a valid id value.
- a = getProjectResourceValue(value.getResourceType(), value.getName(), 0 /*defValue*/);
- }
-
- if (a != 0) {
- outValue.resourceId = a;
- return true;
- }
-
- // If the value is not a valid reference, fallback to pass the value as a string.
- outValue.string = stringValue;
- return true;
- }
-
-
- public ResourceReference resolveId(int id) {
- // first get the String related to this id in the framework
- Pair<ResourceType, String> resourceInfo = Bridge.resolveResourceId(id);
-
- if (resourceInfo != null) {
- return new ResourceReference(resourceInfo.getSecond(), true);
- }
-
- // didn't find a match in the framework? look in the project.
- if (mLayoutlibCallback != null) {
- resourceInfo = mLayoutlibCallback.resolveResourceId(id);
-
- if (resourceInfo != null) {
- return new ResourceReference(resourceInfo.getSecond(), false);
- }
- }
-
- // The base value for R.style is 0x01030000 and the custom style is 0x02030000.
- // So, if the second byte is 03, it's probably a style.
- if ((id >> 16 & 0xFF) == 0x03) {
- return getStyleByDynamicId(id);
- }
- return null;
- }
-
- public Pair<View, Boolean> inflateView(ResourceReference resource, ViewGroup parent,
- @SuppressWarnings("SameParameterValue") boolean attachToRoot,
- boolean skipCallbackParser) {
- boolean isPlatformLayout = resource.isFramework();
-
- if (!isPlatformLayout && !skipCallbackParser) {
- // check if the project callback can provide us with a custom parser.
- ILayoutPullParser parser = getParser(resource);
-
- if (parser != null) {
- BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser,
- this, resource.isFramework());
- try {
- pushParser(blockParser);
- return Pair.of(
- mBridgeInflater.inflate(blockParser, parent, attachToRoot),
- Boolean.TRUE);
- } finally {
- popParser();
- }
- }
- }
-
- ResourceValue resValue;
- if (resource instanceof ResourceValue) {
- resValue = (ResourceValue) resource;
- } else {
- if (isPlatformLayout) {
- resValue = mRenderResources.getFrameworkResource(ResourceType.LAYOUT,
- resource.getName());
- } else {
- resValue = mRenderResources.getProjectResource(ResourceType.LAYOUT,
- resource.getName());
- }
- }
-
- if (resValue != null) {
-
- File xml = new File(resValue.getValue());
- if (xml.isFile()) {
- // we need to create a pull parser around the layout XML file, and then
- // give that to our XmlBlockParser
- try {
- XmlPullParser parser = ParserFactory.create(xml, true);
-
- // set the resource ref to have correct view cookies
- mBridgeInflater.setResourceReference(resource);
-
- BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(parser,
- this, resource.isFramework());
- try {
- pushParser(blockParser);
- return Pair.of(
- mBridgeInflater.inflate(blockParser, parent, attachToRoot),
- Boolean.FALSE);
- } finally {
- popParser();
- }
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + xml, e, null /*data*/);
- // we'll return null below.
- } catch (FileNotFoundException e) {
- // this shouldn't happen since we check above.
- } finally {
- mBridgeInflater.setResourceReference(null);
- }
- } else {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- String.format("File %s is missing!", xml), null);
- }
- } else {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- String.format("Layout %s%s does not exist.", isPlatformLayout ? "android:" : "",
- resource.getName()), null);
- }
-
- return Pair.of(null, Boolean.FALSE);
- }
-
- /**
- * Returns whether the current selected theme is based on AppCompat
- */
- public boolean isAppCompatTheme() {
- // If a cached value exists, return it.
- if (mIsThemeAppCompat != null) {
- return mIsThemeAppCompat;
- }
- // Ideally, we should check if the corresponding activity extends
- // android.support.v7.app.ActionBarActivity, and not care about the theme name at all.
- StyleResourceValue defaultTheme = mRenderResources.getDefaultTheme();
- // We can't simply check for parent using resources.themeIsParentOf() since the
- // inheritance structure isn't really what one would expect. The first common parent
- // between Theme.AppCompat.Light and Theme.AppCompat is Theme.Material (for v21).
- boolean isThemeAppCompat = false;
- for (int i = 0; i < 50; i++) {
- if (defaultTheme == null) {
- break;
- }
- // for loop ensures that we don't run into cyclic theme inheritance.
- if (defaultTheme.getName().startsWith(PREFIX_THEME_APPCOMPAT)) {
- isThemeAppCompat = true;
- break;
- }
- defaultTheme = mRenderResources.getParent(defaultTheme);
- }
- mIsThemeAppCompat = isThemeAppCompat;
- return isThemeAppCompat;
- }
-
- @SuppressWarnings("deprecation")
- private ILayoutPullParser getParser(ResourceReference resource) {
- ILayoutPullParser parser;
- if (resource instanceof ResourceValue) {
- parser = mLayoutlibCallback.getParser((ResourceValue) resource);
- } else {
- parser = mLayoutlibCallback.getParser(resource.getName());
- }
- return parser;
- }
-
- // ------------ Context methods
-
- @Override
- public Resources getResources() {
- return mSystemResources;
- }
-
- @Override
- public Theme getTheme() {
- return mTheme;
- }
-
- @Override
- public ClassLoader getClassLoader() {
- // The documentation for this method states that it should return a class loader one can
- // use to retrieve classes in this package. However, when called by LayoutInflater, we do
- // not want the class loader to return app's custom views.
- // This is so that the IDE can instantiate the custom views and also generate proper error
- // messages in case of failure. This also enables the IDE to fallback to MockView in case
- // there's an exception thrown when trying to inflate the custom view.
- // To work around this issue, LayoutInflater is modified via LayoutLib Create tool to
- // replace invocations of this method to a new method: getFrameworkClassLoader(). Also,
- // the method is injected into Context. The implementation of getFrameworkClassLoader() is:
- // "return getClass().getClassLoader();". This means that when LayoutInflater asks for
- // the context ClassLoader, it gets only LayoutLib's ClassLoader which doesn't have
- // access to the apps's custom views.
- // This method can now return the right ClassLoader, which CustomViews can use to do the
- // right thing.
- if (mClassLoader == null) {
- mClassLoader = new ClassLoader(getClass().getClassLoader()) {
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- for (String prefix : BridgeInflater.getClassPrefixList()) {
- if (name.startsWith(prefix)) {
- // These are framework classes and should not be loaded from the app.
- throw new ClassNotFoundException(name + " not found");
- }
- }
- return BridgeContext.this.mLayoutlibCallback.findClass(name);
- }
- };
- }
- return mClassLoader;
- }
-
- @Override
- public Object getSystemService(String service) {
- if (LAYOUT_INFLATER_SERVICE.equals(service)) {
- return mBridgeInflater;
- }
-
- if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) {
- // we need to return a valid service to avoid NPE
- return TextServicesManager.getInstance();
- }
-
- if (WINDOW_SERVICE.equals(service)) {
- return mWindowManager;
- }
-
- // needed by SearchView
- if (INPUT_METHOD_SERVICE.equals(service)) {
- return null;
- }
-
- if (POWER_SERVICE.equals(service)) {
- return new PowerManager(this, new BridgePowerManager(), new Handler());
- }
-
- if (DISPLAY_SERVICE.equals(service)) {
- return mDisplayManager;
- }
-
- if (ACCESSIBILITY_SERVICE.equals(service)) {
- return AccessibilityManager.getInstance(this);
- }
-
- if (AUTOFILL_MANAGER_SERVICE.equals(service)) {
- return null;
- }
-
- if (AUDIO_SERVICE.equals(service)) {
- return null;
- }
-
- assert false : "Unsupported Service: " + service;
- return null;
- }
-
- @Override
- public String getSystemServiceName(Class<?> serviceClass) {
- return SystemServiceRegistry_Accessor.getSystemServiceName(serviceClass);
- }
-
- @Override
- public final BridgeTypedArray obtainStyledAttributes(int[] attrs) {
- return obtainStyledAttributes(0, attrs);
- }
-
- @Override
- public final BridgeTypedArray obtainStyledAttributes(int resId, int[] attrs)
- throws Resources.NotFoundException {
- StyleResourceValue style = null;
- // get the StyleResourceValue based on the resId;
- if (resId != 0) {
- style = getStyleByDynamicId(resId);
-
- if (style == null) {
- // In some cases, style may not be a dynamic id, so we do a full search.
- ResourceReference ref = resolveId(resId);
- if (ref != null) {
- style = mRenderResources.getStyle(ref.getName(), ref.isFramework());
- }
- }
-
- if (style == null) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
- "Failed to find style with " + resId, null);
- return null;
- }
- }
-
- if (mTypedArrayCache == null) {
- mTypedArrayCache = new TypedArrayCache();
- }
-
- List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes();
-
- Pair<BridgeTypedArray, PropertiesMap> typeArrayAndPropertiesPair =
- mTypedArrayCache.get(attrs, currentThemes, resId);
-
- if (typeArrayAndPropertiesPair == null) {
- typeArrayAndPropertiesPair = createStyleBasedTypedArray(style, attrs);
- mTypedArrayCache.put(attrs, currentThemes, resId, typeArrayAndPropertiesPair);
- }
- // Add value to defaultPropsMap if needed
- if (typeArrayAndPropertiesPair.getSecond() != null) {
- BridgeXmlBlockParser parser = getCurrentParser();
- Object key = parser != null ? parser.getViewCookie() : null;
- if (key != null) {
- PropertiesMap defaultPropMap = mDefaultPropMaps.get(key);
- if (defaultPropMap == null) {
- defaultPropMap = typeArrayAndPropertiesPair.getSecond();
- mDefaultPropMaps.put(key, defaultPropMap);
- } else {
- defaultPropMap.putAll(typeArrayAndPropertiesPair.getSecond());
- }
- }
- }
- return typeArrayAndPropertiesPair.getFirst();
- }
-
- @Override
- public final BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) {
- return obtainStyledAttributes(set, attrs, 0, 0);
- }
-
- @Override
- public BridgeTypedArray obtainStyledAttributes(AttributeSet set, int[] attrs,
- int defStyleAttr, int defStyleRes) {
-
- PropertiesMap defaultPropMap = null;
- boolean isPlatformFile = true;
-
- // Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
- if (set instanceof BridgeXmlBlockParser) {
- BridgeXmlBlockParser parser;
- parser = (BridgeXmlBlockParser)set;
-
- isPlatformFile = parser.isPlatformFile();
-
- Object key = parser.getViewCookie();
- if (key != null) {
- defaultPropMap = mDefaultPropMaps.computeIfAbsent(key, k -> new PropertiesMap());
- }
-
- } else if (set instanceof BridgeLayoutParamsMapAttributes) {
- // this is only for temp layout params generated dynamically, so this is never
- // platform content.
- isPlatformFile = false;
- } else if (set != null) { // null parser is ok
- // really this should not be happening since its instantiated in Bridge
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Parser is not a BridgeXmlBlockParser!", null);
- return null;
- }
-
- List<Pair<String, Boolean>> attributeList = searchAttrs(attrs);
-
- BridgeTypedArray ta =
- Resources_Delegate.newTypeArray(mSystemResources, attrs.length, isPlatformFile);
-
- // look for a custom style.
- String customStyle = null;
- if (set != null) {
- customStyle = set.getAttributeValue(null, "style");
- }
-
- StyleResourceValue customStyleValues = null;
- if (customStyle != null) {
- ResourceValue item = mRenderResources.findResValue(customStyle,
- isPlatformFile /*forceFrameworkOnly*/);
-
- // resolve it in case it links to something else
- item = mRenderResources.resolveResValue(item);
-
- if (item instanceof StyleResourceValue) {
- customStyleValues = (StyleResourceValue)item;
- }
- }
-
- // resolve the defStyleAttr value into a IStyleResourceValue
- StyleResourceValue defStyleValues = null;
-
- if (defStyleAttr != 0) {
- // get the name from the int.
- Pair<String, Boolean> defStyleAttribute = searchAttr(defStyleAttr);
-
- if (defStyleAttribute == null) {
- // This should be rare. Happens trying to map R.style.foo to @style/foo fails.
- // This will happen if the user explicitly used a non existing int value for
- // defStyleAttr or there's something wrong with the project structure/build.
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
- "Failed to find the style corresponding to the id " + defStyleAttr, null);
- } else {
- String defStyleName = defStyleAttribute.getFirst();
-
- // look for the style in the current theme, and its parent:
- ResourceValue item = mRenderResources.findItemInTheme(defStyleName,
- defStyleAttribute.getSecond());
-
- if (item != null) {
- // item is a reference to a style entry. Search for it.
- item = mRenderResources.findResValue(item.getValue(), item.isFramework());
- item = mRenderResources.resolveResValue(item);
- if (item instanceof StyleResourceValue) {
- defStyleValues = (StyleResourceValue) item;
- }
- if (defaultPropMap != null) {
- if (defStyleAttribute.getSecond()) {
- defStyleName = "android:" + defStyleName;
- }
- defaultPropMap.put("style", new Property(defStyleName, item.getValue()));
- }
- } else {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
- String.format(
- "Failed to find style '%s' in current theme",
- defStyleAttribute.getFirst()),
- null);
- }
- }
- } else if (defStyleRes != 0) {
- StyleResourceValue item = getStyleByDynamicId(defStyleRes);
- if (item != null) {
- defStyleValues = item;
- } else {
- boolean isFrameworkRes = true;
- Pair<ResourceType, String> value = Bridge.resolveResourceId(defStyleRes);
- if (value == null) {
- value = mLayoutlibCallback.resolveResourceId(defStyleRes);
- isFrameworkRes = false;
- }
-
- if (value != null) {
- if ((value.getFirst() == ResourceType.STYLE)) {
- // look for the style in all resources:
- item = mRenderResources.getStyle(value.getSecond(), isFrameworkRes);
- if (item != null) {
- if (defaultPropMap != null) {
- String name = item.getName();
- defaultPropMap.put("style", new Property(name, name));
- }
-
- defStyleValues = item;
- } else {
- Bridge.getLog().error(null,
- String.format(
- "Style with id 0x%x (resolved to '%s') does not exist.",
- defStyleRes, value.getSecond()),
- null);
- }
- } else {
- Bridge.getLog().error(null,
- String.format(
- "Resource id 0x%x is not of type STYLE (instead %s)",
- defStyleRes, value.getFirst().toString()),
- null);
- }
- } else {
- Bridge.getLog().error(null,
- String.format(
- "Failed to find style with id 0x%x in current theme",
- defStyleRes),
- null);
- }
- }
- }
-
- String appNamespace = mLayoutlibCallback.getNamespace();
-
- if (attributeList != null) {
- for (int index = 0 ; index < attributeList.size() ; index++) {
- Pair<String, Boolean> attribute = attributeList.get(index);
-
- if (attribute == null) {
- continue;
- }
-
- String attrName = attribute.getFirst();
- boolean frameworkAttr = attribute.getSecond();
- String value = null;
- if (set != null) {
- value = set.getAttributeValue(
- frameworkAttr ? BridgeConstants.NS_RESOURCES : appNamespace,
- attrName);
-
- // if this is an app attribute, and the first get fails, try with the
- // new res-auto namespace as well
- if (!frameworkAttr && value == null) {
- value = set.getAttributeValue(BridgeConstants.NS_APP_RES_AUTO, attrName);
- }
- }
-
- // Calculate the default value from the Theme in two cases:
- // - If defaultPropMap is not null, get the default value to add it to the list
- // of default values of properties.
- // - If value is null, it means that the attribute is not directly set as an
- // attribute in the XML so try to get the default value.
- ResourceValue defaultValue = null;
- if (defaultPropMap != null || value == null) {
- // look for the value in the custom style first (and its parent if needed)
- if (customStyleValues != null) {
- defaultValue = mRenderResources.findItemInStyle(customStyleValues, attrName,
- frameworkAttr);
- }
-
- // then look for the value in the default Style (and its parent if needed)
- if (defaultValue == null && defStyleValues != null) {
- defaultValue = mRenderResources.findItemInStyle(defStyleValues, attrName,
- frameworkAttr);
- }
-
- // if the item is not present in the defStyle, we look in the main theme (and
- // its parent themes)
- if (defaultValue == null) {
- defaultValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
- }
-
- // if we found a value, we make sure this doesn't reference another value.
- // So we resolve it.
- if (defaultValue != null) {
- String preResolve = defaultValue.getValue();
- defaultValue = mRenderResources.resolveResValue(defaultValue);
-
- if (defaultPropMap != null) {
- defaultPropMap.put(
- frameworkAttr ? SdkConstants.PREFIX_ANDROID + attrName :
- attrName, new Property(preResolve, defaultValue.getValue()));
- }
- }
- }
- // Done calculating the defaultValue
-
- // if there's no direct value for this attribute in the XML, we look for default
- // values in the widget defStyle, and then in the theme.
- if (value == null) {
- if (frameworkAttr) {
- // For some framework values, layoutlib patches the actual value in the
- // theme when it helps to improve the final preview. In most cases
- // we just disable animations.
- ResourceValue patchedValue = FRAMEWORK_PATCHED_VALUES.get(attrName);
- if (patchedValue != null) {
- defaultValue = patchedValue;
- }
- }
-
- // if we found a value, we make sure this doesn't reference another value.
- // So we resolve it.
- if (defaultValue != null) {
- // If the value is a reference to another theme attribute that doesn't
- // exist, we should log a warning and omit it.
- String val = defaultValue.getValue();
- if (val != null && val.startsWith(SdkConstants.PREFIX_THEME_REF)) {
- // Because we always use the latest framework code, some resources might
- // fail to resolve when using old themes (they haven't been backported).
- // Since this is an artifact caused by us using always the latest
- // code, we check for some of those values and replace them here.
- defaultValue = FRAMEWORK_REPLACE_VALUES.get(attrName);
-
- if (defaultValue == null &&
- (getApplicationInfo().targetSdkVersion < JELLY_BEAN_MR1 ||
- !attrName.equals(RTL_ATTRS.get(val)))) {
- // Only log a warning if the referenced value isn't one of the RTL
- // attributes, or the app targets old API.
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE_THEME_ATTR,
- String.format("Failed to find '%s' in current theme.", val),
- val);
- }
- }
- }
-
- ta.bridgeSetValue(index, attrName, frameworkAttr, defaultValue);
- } else {
- // there is a value in the XML, but we need to resolve it in case it's
- // referencing another resource or a theme value.
- ta.bridgeSetValue(index, attrName, frameworkAttr,
- mRenderResources.resolveValue(null, attrName, value, isPlatformFile));
- }
- }
- }
-
- ta.sealArray();
-
- return ta;
- }
-
- @Override
- public Looper getMainLooper() {
- return Looper.myLooper();
- }
-
-
- @Override
- public String getPackageName() {
- if (mApplicationInfo.packageName == null) {
- mApplicationInfo.packageName = mLayoutlibCallback.getFlag(FLAG_KEY_APPLICATION_PACKAGE);
- }
- return mApplicationInfo.packageName;
- }
-
- @Override
- public PackageManager getPackageManager() {
- if (mPackageManager == null) {
- mPackageManager = new BridgePackageManager();
- }
- return mPackageManager;
- }
-
- // ------------- private new methods
-
- /**
- * Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the
- * values found in the given style. If no style is specified, the default theme, along with the
- * styles applied to it are used.
- *
- * @see #obtainStyledAttributes(int, int[])
- */
- private Pair<BridgeTypedArray, PropertiesMap> createStyleBasedTypedArray(
- @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
- List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
-
- BridgeTypedArray ta =
- Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
-
- PropertiesMap defaultPropMap = new PropertiesMap();
- // for each attribute, get its name so that we can search it in the style
- for (int i = 0; i < attrs.length; i++) {
- Pair<String, Boolean> attribute = attributes.get(i);
-
- if (attribute != null) {
- // look for the value in the given style
- ResourceValue resValue;
- String attrName = attribute.getFirst();
- boolean frameworkAttr = attribute.getSecond();
- if (style != null) {
- resValue = mRenderResources.findItemInStyle(style, attrName, frameworkAttr);
- } else {
- resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
- }
-
- if (resValue != null) {
- // Add it to defaultPropMap before resolving
- String preResolve = resValue.getValue();
- // resolve it to make sure there are no references left.
- resValue = mRenderResources.resolveResValue(resValue);
- ta.bridgeSetValue(i, attrName, frameworkAttr, resValue);
- defaultPropMap.put(
- frameworkAttr ? SdkConstants.ANDROID_PREFIX + attrName : attrName,
- new Property(preResolve, resValue.getValue()));
- }
- }
- }
-
- ta.sealArray();
-
- return Pair.of(ta, defaultPropMap);
- }
-
- /**
- * The input int[] attrs is a list of attributes. The returns a list of information about
- * each attributes. The information is (name, isFramework)
- * <p/>
- *
- * @param attrs An attribute array reference given to obtainStyledAttributes.
- * @return List of attribute information.
- */
- private List<Pair<String, Boolean>> searchAttrs(int[] attrs) {
- List<Pair<String, Boolean>> results = new ArrayList<>(attrs.length);
-
- // for each attribute, get its name so that we can search it in the style
- for (int attr : attrs) {
- Pair<ResourceType, String> resolvedResource = Bridge.resolveResourceId(attr);
- boolean isFramework = false;
- if (resolvedResource != null) {
- isFramework = true;
- } else {
- resolvedResource = mLayoutlibCallback.resolveResourceId(attr);
- }
-
- if (resolvedResource != null) {
- results.add(Pair.of(resolvedResource.getSecond(), isFramework));
- } else {
- results.add(null);
- }
- }
-
- return results;
- }
-
- /**
- * Searches for the attribute referenced by its internal id.
- *
- * @param attr An attribute reference given to obtainStyledAttributes such as defStyle.
- * @return A (name, isFramework) pair describing the attribute if found. Returns null
- * if nothing is found.
- */
- private Pair<String, Boolean> searchAttr(int attr) {
- Pair<ResourceType, String> info = Bridge.resolveResourceId(attr);
- if (info != null) {
- return Pair.of(info.getSecond(), Boolean.TRUE);
- }
-
- info = mLayoutlibCallback.resolveResourceId(attr);
- if (info != null) {
- return Pair.of(info.getSecond(), Boolean.FALSE);
- }
-
- return null;
- }
-
- public int getDynamicIdByStyle(StyleResourceValue resValue) {
- if (mDynamicIdToStyleMap == null) {
- // create the maps.
- mDynamicIdToStyleMap = new HashMap<>();
- mStyleToDynamicIdMap = new HashMap<>();
- }
-
- // look for an existing id
- Integer id = mStyleToDynamicIdMap.get(resValue);
-
- if (id == null) {
- // generate a new id
- id = ++mDynamicIdGenerator;
-
- // and add it to the maps.
- mDynamicIdToStyleMap.put(id, resValue);
- mStyleToDynamicIdMap.put(resValue, id);
- }
-
- return id;
- }
-
- private StyleResourceValue getStyleByDynamicId(int i) {
- if (mDynamicIdToStyleMap != null) {
- return mDynamicIdToStyleMap.get(i);
- }
-
- return null;
- }
-
- public int getFrameworkResourceValue(ResourceType resType, String resName, int defValue) {
- if (getRenderResources().getFrameworkResource(resType, resName) != null) {
- // Bridge.getResourceId creates a new resource id if an existing one isn't found. So,
- // we check for the existence of the resource before calling it.
- return Bridge.getResourceId(resType, resName);
- }
-
- return defValue;
- }
-
- public int getProjectResourceValue(ResourceType resType, String resName, int defValue) {
- // getResourceId creates a new resource id if an existing resource id isn't found. So, we
- // check for the existence of the resource before calling it.
- if (getRenderResources().getProjectResource(resType, resName) != null) {
- if (mLayoutlibCallback != null) {
- Integer value = mLayoutlibCallback.getResourceId(resType, resName);
- if (value != null) {
- return value;
- }
- }
- }
-
- return defValue;
- }
-
- public static Context getBaseContext(Context context) {
- while (context instanceof ContextWrapper) {
- context = ((ContextWrapper) context).getBaseContext();
- }
- 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;
- }
-
- @Override
- public void shellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ShellCallback shellCallback, ResultReceiver resultReceiver) {
- }
- };
- }
- return mBinder;
- }
-
- //------------ NOT OVERRIDEN --------------------
-
- @Override
- public boolean bindService(Intent arg0, ServiceConnection arg1, int arg2) {
- // pass
- return false;
- }
-
- @Override
- public int checkCallingOrSelfPermission(String arg0) {
- // pass
- return 0;
- }
-
- @Override
- public int checkCallingOrSelfUriPermission(Uri arg0, int arg1) {
- // pass
- return 0;
- }
-
- @Override
- public int checkCallingPermission(String arg0) {
- // pass
- return 0;
- }
-
- @Override
- public int checkCallingUriPermission(Uri arg0, int arg1) {
- // pass
- return 0;
- }
-
- @Override
- public int checkPermission(String arg0, int arg1, int arg2) {
- // pass
- return 0;
- }
-
- @Override
- public int checkSelfPermission(String arg0) {
- // pass
- return 0;
- }
-
- @Override
- public int checkPermission(String arg0, int arg1, int arg2, IBinder arg3) {
- // pass
- return 0;
- }
-
- @Override
- public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3) {
- // pass
- return 0;
- }
-
- @Override
- public int checkUriPermission(Uri arg0, int arg1, int arg2, int arg3, IBinder arg4) {
- // pass
- return 0;
- }
-
- @Override
- public int checkUriPermission(Uri arg0, String arg1, String arg2, int arg3,
- int arg4, int arg5) {
- // pass
- return 0;
- }
-
- @Override
- public void clearWallpaper() {
- // pass
-
- }
-
- @Override
- public Context createPackageContext(String arg0, int arg1) {
- // pass
- return null;
- }
-
- @Override
- public Context createPackageContextAsUser(String arg0, int arg1, UserHandle user) {
- // pass
- return null;
- }
-
- @Override
- public Context createConfigurationContext(Configuration overrideConfiguration) {
- // pass
- return null;
- }
-
- @Override
- public Context createDisplayContext(Display display) {
- // pass
- return null;
- }
-
- @Override
- public Context createContextForSplit(String splitName) {
- // pass
- return null;
- }
-
- @Override
- public String[] databaseList() {
- // pass
- return null;
- }
-
- @Override
- public Context createApplicationContext(ApplicationInfo application, int flags)
- throws PackageManager.NameNotFoundException {
- return null;
- }
-
- @Override
- public boolean moveDatabaseFrom(Context sourceContext, String name) {
- // pass
- return false;
- }
-
- @Override
- public boolean deleteDatabase(String arg0) {
- // pass
- return false;
- }
-
- @Override
- public boolean deleteFile(String arg0) {
- // pass
- return false;
- }
-
- @Override
- public void enforceCallingOrSelfPermission(String arg0, String arg1) {
- // pass
-
- }
-
- @Override
- public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1,
- String arg2) {
- // pass
-
- }
-
- @Override
- public void enforceCallingPermission(String arg0, String arg1) {
- // pass
-
- }
-
- @Override
- public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) {
- // pass
-
- }
-
- @Override
- public void enforcePermission(String arg0, int arg1, int arg2, String arg3) {
- // pass
-
- }
-
- @Override
- public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3,
- String arg4) {
- // pass
-
- }
-
- @Override
- public void enforceUriPermission(Uri arg0, String arg1, String arg2,
- int arg3, int arg4, int arg5, String arg6) {
- // pass
-
- }
-
- @Override
- public String[] fileList() {
- // pass
- return null;
- }
-
- @Override
- public BridgeAssetManager getAssets() {
- return mAssets;
- }
-
- @Override
- public File getCacheDir() {
- // pass
- return null;
- }
-
- @Override
- public File getCodeCacheDir() {
- // pass
- return null;
- }
-
- @Override
- public File getExternalCacheDir() {
- // pass
- return null;
- }
-
- @Override
- public File getPreloadsFileCache() {
- // pass
- return null;
- }
-
- @Override
- public ContentResolver getContentResolver() {
- if (mContentResolver == null) {
- mContentResolver = new BridgeContentResolver(this);
- }
- return mContentResolver;
- }
-
- @Override
- public File getDatabasePath(String arg0) {
- // pass
- return null;
- }
-
- @Override
- public File getDir(String arg0, int arg1) {
- // pass
- return null;
- }
-
- @Override
- public File getFileStreamPath(String arg0) {
- // pass
- return null;
- }
-
- @Override
- public File getSharedPreferencesPath(String name) {
- // pass
- return null;
- }
-
- @Override
- public File getDataDir() {
- // pass
- return null;
- }
-
- @Override
- public File getFilesDir() {
- // pass
- return null;
- }
-
- @Override
- public File getNoBackupFilesDir() {
- // pass
- return null;
- }
-
- @Override
- public File getExternalFilesDir(String type) {
- // pass
- return null;
- }
-
- @Override
- public String getPackageCodePath() {
- // pass
- return null;
- }
-
- @Override
- public String getBasePackageName() {
- // pass
- return null;
- }
-
- @Override
- public String getOpPackageName() {
- // pass
- return null;
- }
-
- @Override
- public ApplicationInfo getApplicationInfo() {
- return mApplicationInfo;
- }
-
- @Override
- public String getPackageResourcePath() {
- // pass
- return null;
- }
-
- @Override
- public SharedPreferences getSharedPreferences(String arg0, int arg1) {
- if (mSharedPreferences == null) {
- mSharedPreferences = new BridgeSharedPreferences();
- }
- return mSharedPreferences;
- }
-
- @Override
- public SharedPreferences getSharedPreferences(File arg0, int arg1) {
- if (mSharedPreferences == null) {
- mSharedPreferences = new BridgeSharedPreferences();
- }
- return mSharedPreferences;
- }
-
- @Override
- public boolean moveSharedPreferencesFrom(Context sourceContext, String name) {
- // pass
- return false;
- }
-
- @Override
- public boolean deleteSharedPreferences(String name) {
- // pass
- return false;
- }
-
- @Override
- public Drawable getWallpaper() {
- // pass
- return null;
- }
-
- @Override
- public int getWallpaperDesiredMinimumWidth() {
- return -1;
- }
-
- @Override
- public int getWallpaperDesiredMinimumHeight() {
- return -1;
- }
-
- @Override
- public void grantUriPermission(String arg0, Uri arg1, int arg2) {
- // pass
-
- }
-
- @Override
- public FileInputStream openFileInput(String arg0) throws FileNotFoundException {
- // pass
- return null;
- }
-
- @Override
- public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException {
- // pass
- return null;
- }
-
- @Override
- public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) {
- // pass
- return null;
- }
-
- @Override
- public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1,
- CursorFactory arg2, DatabaseErrorHandler arg3) {
- // pass
- return null;
- }
-
- @Override
- public Drawable peekWallpaper() {
- // pass
- return null;
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1) {
- // pass
- return null;
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1, int arg2) {
- // pass
- return null;
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1,
- String arg2, Handler arg3) {
- // pass
- return null;
- }
-
- @Override
- public Intent registerReceiver(BroadcastReceiver arg0, IntentFilter arg1,
- String arg2, Handler arg3, int arg4) {
- // pass
- return null;
- }
-
- @Override
- public Intent registerReceiverAsUser(BroadcastReceiver arg0, UserHandle arg0p5,
- IntentFilter arg1, String arg2, Handler arg3) {
- // pass
- return null;
- }
-
- @Override
- public void removeStickyBroadcast(Intent arg0) {
- // pass
-
- }
-
- @Override
- public void revokeUriPermission(Uri arg0, int arg1) {
- // pass
-
- }
-
- @Override
- public void revokeUriPermission(String arg0, Uri arg1, int arg2) {
- // pass
-
- }
-
- @Override
- public void sendBroadcast(Intent arg0) {
- // pass
-
- }
-
- @Override
- public void sendBroadcast(Intent arg0, String arg1) {
- // pass
-
- }
-
- @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
- }
-
- @Override
- public void sendOrderedBroadcast(Intent arg0, String arg1) {
- // pass
-
- }
-
- @Override
- public void sendOrderedBroadcast(Intent arg0, String arg1,
- BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
- Bundle arg6) {
- // pass
-
- }
-
- @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) {
- // pass
- }
-
- @Override
- public void sendBroadcastAsUser(Intent intent, UserHandle user) {
- // pass
- }
-
- @Override
- public void sendBroadcastAsUser(Intent intent, UserHandle user,
- String receiverPermission) {
- // pass
- }
-
- @Override
- public void sendBroadcastAsUser(Intent intent, UserHandle user,
- String receiverPermission, Bundle options) {
- // 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,
- int initialCode, String initialData, Bundle initialExtras) {
- // pass
- }
-
- @Override
- public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
- String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
- Handler scheduler,
- int initialCode, String initialData, Bundle initialExtras) {
- // pass
- }
-
- @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
-
- }
-
- @Override
- public void sendStickyOrderedBroadcast(Intent intent,
- BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData,
- Bundle initialExtras) {
- // pass
- }
-
- @Override
- public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
- // pass
- }
-
- @Override
- public void sendStickyBroadcastAsUser(Intent intent, UserHandle user, Bundle options) {
- // pass
- }
-
- @Override
- public void sendStickyOrderedBroadcastAsUser(Intent intent,
- UserHandle user, BroadcastReceiver resultReceiver,
- Handler scheduler, int initialCode, String initialData,
- Bundle initialExtras) {
- // pass
- }
-
- @Override
- public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
- // pass
- }
-
- @Override
- public void setTheme(int arg0) {
- // pass
-
- }
-
- @Override
- public void setWallpaper(Bitmap arg0) throws IOException {
- // pass
-
- }
-
- @Override
- public void setWallpaper(InputStream arg0) throws IOException {
- // pass
-
- }
-
- @Override
- public void startActivity(Intent arg0) {
- // pass
- }
-
- @Override
- public void startActivity(Intent arg0, Bundle arg1) {
- // pass
- }
-
- @Override
- public void startIntentSender(IntentSender intent,
- Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)
- throws IntentSender.SendIntentException {
- // pass
- }
-
- @Override
- public void startIntentSender(IntentSender intent,
- Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags,
- Bundle options) throws IntentSender.SendIntentException {
- // pass
- }
-
- @Override
- public boolean startInstrumentation(ComponentName arg0, String arg1,
- Bundle arg2) {
- // pass
- return false;
- }
-
- @Override
- public ComponentName startService(Intent arg0) {
- // pass
- return null;
- }
-
- @Override
- public ComponentName startForegroundService(Intent service) {
- // pass
- return null;
- }
-
- @Override
- public ComponentName startForegroundServiceAsUser(Intent service, UserHandle user) {
- // pass
- return null;
- }
-
- @Override
- public boolean stopService(Intent arg0) {
- // pass
- return false;
- }
-
- @Override
- public ComponentName startServiceAsUser(Intent arg0, UserHandle arg1) {
- // pass
- return null;
- }
-
- @Override
- public boolean stopServiceAsUser(Intent arg0, UserHandle arg1) {
- // pass
- return false;
- }
-
- @Override
- public void unbindService(ServiceConnection arg0) {
- // pass
-
- }
-
- @Override
- public void unregisterReceiver(BroadcastReceiver arg0) {
- // pass
-
- }
-
- @Override
- public Context getApplicationContext() {
- return this;
- }
-
- @Override
- public void startActivities(Intent[] arg0) {
- // pass
-
- }
-
- @Override
- public void startActivities(Intent[] arg0, Bundle arg1) {
- // pass
-
- }
-
- @Override
- public boolean isRestricted() {
- return false;
- }
-
- @Override
- public File getObbDir() {
- Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED, "OBB not supported", null);
- return null;
- }
-
- @Override
- public DisplayAdjustments getDisplayAdjustments(int displayId) {
- // pass
- return null;
- }
-
- @Override
- public Display getDisplay() {
- // pass
- return null;
- }
-
- @Override
- public void updateDisplay(int displayId) {
- // pass
- }
-
- @Override
- public int getUserId() {
- return 0; // not used
- }
-
- @Override
- public File[] getExternalFilesDirs(String type) {
- // pass
- return new File[0];
- }
-
- @Override
- public File[] getObbDirs() {
- // pass
- return new File[0];
- }
-
- @Override
- public File[] getExternalCacheDirs() {
- // pass
- return new File[0];
- }
-
- @Override
- public File[] getExternalMediaDirs() {
- // pass
- return new File[0];
- }
-
- public void setScrollYPos(@NonNull View view, int scrollPos) {
- mScrollYPos.put(view, scrollPos);
- }
-
- public int getScrollYPos(@NonNull View view) {
- Integer pos = mScrollYPos.get(view);
- return pos != null ? pos : 0;
- }
-
- public void setScrollXPos(@NonNull View view, int scrollPos) {
- mScrollXPos.put(view, scrollPos);
- }
-
- public int getScrollXPos(@NonNull View view) {
- Integer pos = mScrollXPos.get(view);
- return pos != null ? pos : 0;
- }
-
- @Override
- public Context createDeviceProtectedStorageContext() {
- // pass
- return null;
- }
-
- @Override
- public Context createCredentialProtectedStorageContext() {
- // pass
- return null;
- }
-
- @Override
- public boolean isDeviceProtectedStorage() {
- return false;
- }
-
- @Override
- public boolean isCredentialProtectedStorage() {
- return false;
- }
-
- /**
- * The cached value depends on
- * <ol>
- * <li>{@code int[]}: the attributes for which TypedArray is created </li>
- * <li>{@code List<StyleResourceValue>}: the themes set on the context at the time of
- * creation of the TypedArray</li>
- * <li>{@code Integer}: the default style used at the time of creation</li>
- * </ol>
- *
- * The class is created by using nested maps resolving one dependency at a time.
- * <p/>
- * The final value of the nested maps is a pair of the typed array and a map of properties
- * that should be added to {@link #mDefaultPropMaps}, if needed.
- */
- private static class TypedArrayCache {
-
- private Map<int[],
- Map<List<StyleResourceValue>,
- Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>> mCache;
-
- private TypedArrayCache() {
- mCache = new IdentityHashMap<>();
- }
-
- public Pair<BridgeTypedArray, PropertiesMap> get(int[] attrs,
- List<StyleResourceValue> themes, int resId) {
- Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
- cacheFromThemes = mCache.get(attrs);
- if (cacheFromThemes != null) {
- Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
- cacheFromThemes.get(themes);
- if (cacheFromResId != null) {
- return cacheFromResId.get(resId);
- }
- }
- return null;
- }
-
- public void put(int[] attrs, List<StyleResourceValue> themes, int resId,
- Pair<BridgeTypedArray, PropertiesMap> value) {
- Map<List<StyleResourceValue>, Map<Integer, Pair<BridgeTypedArray, PropertiesMap>>>
- cacheFromThemes = mCache.computeIfAbsent(attrs, k -> new HashMap<>());
- Map<Integer, Pair<BridgeTypedArray, PropertiesMap>> cacheFromResId =
- cacheFromThemes.computeIfAbsent(themes, k -> new HashMap<>());
- cacheFromResId.put(resId, value);
- }
-
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.android;
-
-import com.android.internal.inputmethod.IInputContentUriToken;
-import com.android.internal.view.IInputContext;
-import com.android.internal.view.IInputMethodClient;
-import com.android.internal.view.IInputMethodManager;
-import com.android.internal.view.InputBindResult;
-
-import android.net.Uri;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.text.style.SuggestionSpan;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodSubtype;
-
-import java.util.List;
-
-/**
- * Basic implementation of IInputMethodManager that does nothing.
- *
- */
-public class BridgeIInputMethodManager implements IInputMethodManager {
-
- @Override
- public void addClient(IInputMethodClient arg0, IInputContext arg1, int arg2, int arg3)
- throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void finishInput(IInputMethodClient arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public InputMethodSubtype getCurrentInputMethodSubtype() throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public List<InputMethodInfo> getEnabledInputMethodList() throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String arg0,
- boolean arg1) throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public List<InputMethodInfo> getInputMethodList() throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public InputMethodSubtype getLastInputMethodSubtype() throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public List getShortcutInputMethodsAndSubtypes() throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void hideMySoftInput(IBinder arg0, int arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean hideSoftInput(IInputMethodClient arg0, int arg1, ResultReceiver arg2)
- throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean notifySuggestionPicked(SuggestionSpan arg0, String arg1, int arg2)
- throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void registerSuggestionSpansForNotification(SuggestionSpan[] arg0)
- throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void removeClient(IInputMethodClient arg0) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setAdditionalInputMethodSubtypes(String arg0, InputMethodSubtype[] arg1)
- throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public boolean setCurrentInputMethodSubtype(InputMethodSubtype arg0) throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void setImeWindowStatus(IBinder arg0, IBinder arg1, int arg2, int arg3)
- throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void setInputMethod(IBinder arg0, String arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void setInputMethodAndSubtype(IBinder arg0, String arg1, InputMethodSubtype arg2)
- throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean setInputMethodEnabled(String arg0, boolean arg1) throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public void showInputMethodAndSubtypeEnablerFromClient(IInputMethodClient arg0, String arg1)
- throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void showInputMethodPickerFromClient(IInputMethodClient arg0,
- int arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void showMySoftInput(IBinder arg0, int arg1) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean showSoftInput(IInputMethodClient arg0, int arg1, ResultReceiver arg2)
- throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean switchToLastInputMethod(IBinder arg0) throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean switchToNextInputMethod(IBinder arg0, boolean arg1) throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean shouldOfferSwitchingToNextInputMethod(IBinder arg0) throws RemoteException {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public int getInputMethodWindowVisibleHeight() throws RemoteException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public void notifyUserAction(int sequenceNumber) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public void updateStatusIcon(IBinder arg0, String arg1, int arg2) throws RemoteException {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void clearLastInputMethodWindowForTransition(IBinder arg0) throws RemoteException {
- // TODO Auto-generated method stub
- }
-
- @Override
- public InputBindResult startInputOrWindowGainedFocus(
- /* @InputMethodClient.StartInputReason */ int startInputReason,
- IInputMethodClient client, IBinder windowToken, int controlFlags,
- /* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode,
- int windowFlags, EditorInfo attribute, IInputContext inputContext,
- /* @InputConnectionInspector.MissingMethodFlags */ int missingMethodFlags)
- throws RemoteException {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public IBinder asBinder() {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public IInputContentUriToken createInputContentUriToken(IBinder token, Uri contentUri,
- String packageName) {
- // TODO Auto-generated method stub
- return null;
- }
-
- @Override
- public void reportFullscreenMode(IBinder token, boolean fullscreen) {
- // TODO Auto-generated method stub
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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 com.android.layoutlib.bridge.BridgeConstants;
-
-import android.util.AttributeSet;
-
-import java.util.Map;
-
-/**
- * An implementation of the {@link AttributeSet} interface on top of a map of attribute in the form
- * of (name, value).
- *
- * This is meant to be called only from {@link BridgeContext#obtainStyledAttributes(AttributeSet, int[], int, int)}
- * in the case of LayoutParams and therefore isn't a full implementation.
- */
-public class BridgeLayoutParamsMapAttributes implements AttributeSet {
-
- private final Map<String, String> mAttributes;
-
- public BridgeLayoutParamsMapAttributes(Map<String, String> attributes) {
- mAttributes = attributes;
- }
-
- @Override
- public String getAttributeValue(String namespace, String name) {
- if (BridgeConstants.NS_RESOURCES.equals(namespace)) {
- return mAttributes.get(name);
- }
-
- return null;
- }
-
- // ---- the following methods are not called from
- // BridgeContext#obtainStyledAttributes(AttributeSet, int[], int, int)
- // Should they ever be called, we'll just implement them on a need basis.
-
- @Override
- public int getAttributeCount() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getAttributeName(int index) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getAttributeValue(int index) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getPositionDescription() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getAttributeNameResource(int index) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getAttributeListValue(String namespace, String attribute,
- String[] options, int defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean getAttributeBooleanValue(String namespace, String attribute,
- boolean defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getAttributeResourceValue(String namespace, String attribute,
- int defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getAttributeIntValue(String namespace, String attribute,
- int defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getAttributeUnsignedIntValue(String namespace, String attribute,
- int defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public float getAttributeFloatValue(String namespace, String attribute,
- float defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getAttributeListValue(int index,
- String[] options, int defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getAttributeResourceValue(int index, int defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getAttributeIntValue(int index, int defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getAttributeUnsignedIntValue(int index, int defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public float getAttributeFloatValue(int index, float defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getIdAttribute() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getClassAttribute() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getIdAttributeResourceValue(int defaultValue) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getStyleAttribute() {
- throw new UnsupportedOperationException();
- }
-}
+++ /dev/null
-/*
- * 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.annotation.NonNull;
-import android.annotation.Nullable;
-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.ChangedPackages;
-import android.content.pm.InstantAppInfo;
-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.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.SharedLibraryInfo;
-import android.content.pm.VerifierDeviceIdentity;
-import android.content.pm.VersionedPackage;
-import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
-import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
-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 PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
- throws NameNotFoundException {
- return null;
- }
-
- @Override
- public PackageInfo getPackageInfo(VersionedPackage versionedPackage,
- @PackageInfoFlags int flags) throws NameNotFoundException {
- return null;
- }
-
- @Override
- public List<SharedLibraryInfo> getSharedLibraries(@InstallFlags int flags) {
- return null;
- }
-
- @Override
- public List<SharedLibraryInfo> getSharedLibrariesAsUser(@InstallFlags int flags,
- int userId) {
- 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[] getPackageGids(String packageName, int flags) throws NameNotFoundException {
- return new int[0];
- }
-
- @Override
- public int getPackageUid(String packageName, int flags) throws NameNotFoundException {
- return 0;
- }
-
- @Override
- public int getPackageUidAsUser(String packageName, int userHandle) throws NameNotFoundException {
- return 0;
- }
-
- @Override
- public int getPackageUidAsUser(String packageName, int flags, int userHandle) throws NameNotFoundException {
- return 0;
- }
-
- @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 boolean isPermissionReviewModeEnabled() {
- return false;
- }
-
- @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 ApplicationInfo getApplicationInfoAsUser(String packageName, int flags, int userId)
- 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> getInstalledPackagesAsUser(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 List<ApplicationInfo> getInstalledApplicationsAsUser(int flags, int userId) {
- return null;
- }
-
- @Override
- public List<InstantAppInfo> getInstantApps() {
- return null;
- }
-
- @Override
- public Drawable getInstantAppIcon(String packageName) {
- assert false : "Unsupported operation";
- return new ColorDrawable();
- }
-
- @Override
- public byte[] getInstantAppCookie() {
- return new byte[0];
- }
-
- @Override
- public boolean isInstantApp() {
- return false;
- }
-
- @Override
- public boolean isInstantApp(String packageName) {
- return false;
- }
-
- @Override
- public int getInstantAppCookieMaxBytes() {
- return 0;
- }
-
- @Override
- public int getInstantAppCookieMaxSize() {
- return 0;
- }
-
- @Override
- public void clearInstantAppCookie() {;
-
- }
-
- @Override
- public void updateInstantAppCookie(@Nullable byte[] cookie) {
-
- }
-
- @Override
- public boolean setInstantAppCookie(@NonNull byte[] cookie) {
- return false;
- }
-
- @Override
- public String[] getSystemSharedLibraryNames() {
- return new String[0];
- }
-
- @Override
- public String getServicesSystemSharedLibraryPackageName() {
- return null;
- }
-
- @Override
- public @NonNull String getSharedSystemSharedLibraryPackageName() {
- return null;
- }
-
- @Override
- public FeatureInfo[] getSystemAvailableFeatures() {
- return new FeatureInfo[0];
- }
-
- @Override
- public boolean hasSystemFeature(String name) {
- return false;
- }
-
- @Override
- public boolean hasSystemFeature(String name, int version) {
- 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> queryBroadcastReceiversAsUser(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 Drawable getUserBadgeForDensityNoBackground(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 installPackage(Uri packageURI, PackageInstallObserver observer, int flags,
- String installerPackageName) {
- }
-
- @Override
- public int installExistingPackage(String packageName) throws NameNotFoundException {
- return 0;
- }
-
- @Override
- public int installExistingPackageAsUser(String packageName, int userId)
- throws NameNotFoundException {
- return 0;
- }
-
- @Override
- public void verifyPendingInstall(int id, int verificationCode) {
- }
-
- @Override
- public void extendVerificationTimeout(int id, int verificationCodeAtTimeout,
- long millisecondsToDelay) {
- }
-
- @Override
- public void verifyIntentFilter(int verificationId, int verificationCode,
- List<String> outFailedDomains) {
- }
-
- @Override
- public int getIntentVerificationStatusAsUser(String packageName, int userId) {
- return 0;
- }
-
- @Override
- public boolean updateIntentVerificationStatusAsUser(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 getDefaultBrowserPackageNameAsUser(int userId) {
- return null;
- }
-
- @Override
- public boolean setDefaultBrowserPackageNameAsUser(String packageName, int userId) {
- return false;
- }
-
- @Override
- public void setInstallerPackageName(String targetPackage, String installerPackageName) {
- }
-
- @Override
- public void setUpdateAvailable(String packageName, boolean updateAvailable) {
- }
-
- @Override
- public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
- }
-
- @Override
- public void deletePackageAsUser(String packageName, IPackageDeleteObserver observer, int flags,
- int userId) {
- }
-
- @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 deleteApplicationCacheFilesAsUser(String packageName, int userId,
- 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 getPackageSizeInfoAsUser(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 void flushPackageRestrictionsAsUser(int userId) {
- }
-
- @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 String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
- int userId) {
- return new String[]{};
- }
-
- @Override
- public boolean isPackageSuspendedForUser(String packageName, int userId) {
- return false;
- }
-
- @Override
- public void setApplicationCategoryHint(String packageName, int categoryHint) {
- }
-
- @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 ChangedPackages getChangedPackages(int sequenceNumber) {
- 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;
- }
-
- @Override
- public int getInstallReason(String packageName, UserHandle user) {
- return INSTALL_REASON_UNKNOWN;
- }
-
- @Override
- public boolean canRequestPackageInstalls() {
- return false;
- }
-
- @Override
- public ComponentName getInstantAppResolverSettingsComponent() {
- return null;
- }
-
- @Override
- public ComponentName getInstantAppInstallerComponent() {
- return null;
- }
-
- @Override
- public String getInstantAppAndroidId(String packageName, UserHandle user) {
- return null;
- }
-
- @Override
- public void registerDexModule(String dexModulePath,
- @Nullable DexModuleRegisterCallback callback) {
- callback.onDexModuleRegistered(dexModulePath, false, null);
- }
-}
+++ /dev/null
-/*
- * 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.layoutlib.bridge.android;
-
-import android.os.IBinder;
-import android.os.IPowerManager;
-import android.os.PowerManager;
-import android.os.PowerSaveState;
-import android.os.RemoteException;
-import android.os.WorkSource;
-
-/**
- * Fake implementation of IPowerManager.
- *
- */
-public class BridgePowerManager implements IPowerManager {
-
- @Override
- public boolean isInteractive() throws RemoteException {
- return true;
- }
-
- @Override
- public boolean isPowerSaveMode() throws RemoteException {
- return false;
- }
-
- @Override
- public boolean setPowerSaveMode(boolean mode) throws RemoteException {
- return false;
- }
-
- public PowerSaveState getPowerSaveState(int serviceType) {
- return null;
- }
-
- @Override
- public IBinder asBinder() {
- // pass for now.
- return null;
- }
-
- @Override
- public void acquireWakeLock(IBinder arg0, int arg1, String arg2, String arg2_5, WorkSource arg3, String arg4)
- throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void acquireWakeLockWithUid(IBinder arg0, int arg1, String arg2, String arg2_5, int arg3)
- throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void powerHint(int hintId, int data) {
- // pass for now.
- }
-
- @Override
- public void crash(String arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void goToSleep(long arg0, int arg1, int arg2) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void nap(long arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void reboot(boolean confirm, String reason, boolean wait) {
- // pass for now.
- }
-
- @Override
- public void rebootSafeMode(boolean confirm, boolean wait) {
- // pass for now.
- }
-
- @Override
- public void shutdown(boolean confirm, String reason, boolean wait) {
- // pass for now.
- }
-
- @Override
- public void releaseWakeLock(IBinder arg0, int arg1) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void updateWakeLockUids(IBinder arg0, int[] arg1) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void setAttentionLight(boolean arg0, int arg1) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void setTemporaryScreenBrightnessSettingOverride(int arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void setStayOnSetting(int arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void updateWakeLockWorkSource(IBinder arg0, WorkSource arg1, String arg2) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public boolean isWakeLockLevelSupported(int level) throws RemoteException {
- // pass for now.
- return true;
- }
-
- @Override
- public void userActivity(long time, int event, int flags) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void wakeUp(long time, String reason, String opPackageName) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void boostScreenBrightness(long time) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public boolean isDeviceIdleMode() throws RemoteException {
- return false;
- }
-
- @Override
- public boolean isLightDeviceIdleMode() throws RemoteException {
- return false;
- }
-
- @Override
- public boolean isScreenBrightnessBoosted() throws RemoteException {
- return false;
- }
-
- @Override
- public int getLastShutdownReason() {
- return PowerManager.SHUTDOWN_REASON_UNKNOWN;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.android;
-
-import android.content.SharedPreferences;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * An empty shared preferences implementation which doesn't store anything. It always returns
- * null, 0 or false.
- */
-public class BridgeSharedPreferences implements SharedPreferences {
- private Editor mEditor;
-
- @Override
- public Map<String, ?> getAll() {
- return null;
- }
-
- @Override
- public String getString(String key, String defValue) {
- return null;
- }
-
- @Override
- public Set<String> getStringSet(String key, Set<String> defValues) {
- return null;
- }
-
- @Override
- public int getInt(String key, int defValue) {
- return 0;
- }
-
- @Override
- public long getLong(String key, long defValue) {
- return 0;
- }
-
- @Override
- public float getFloat(String key, float defValue) {
- return 0;
- }
-
- @Override
- public boolean getBoolean(String key, boolean defValue) {
- return false;
- }
-
- @Override
- public boolean contains(String key) {
- return false;
- }
-
- @Override
- public Editor edit() {
- if (mEditor != null) {
- return mEditor;
- }
- mEditor = new Editor() {
- @Override
- public Editor putString(String key, String value) {
- return null;
- }
-
- @Override
- public Editor putStringSet(String key, Set<String> values) {
- return null;
- }
-
- @Override
- public Editor putInt(String key, int value) {
- return null;
- }
-
- @Override
- public Editor putLong(String key, long value) {
- return null;
- }
-
- @Override
- public Editor putFloat(String key, float value) {
- return null;
- }
-
- @Override
- public Editor putBoolean(String key, boolean value) {
- return null;
- }
-
- @Override
- public Editor remove(String key) {
- return null;
- }
-
- @Override
- public Editor clear() {
- return null;
- }
-
- @Override
- public boolean commit() {
- return false;
- }
-
- @Override
- public void apply() {
- }
- };
- return mEditor;
- }
-
- @Override
- public void registerOnSharedPreferenceChangeListener(
- OnSharedPreferenceChangeListener listener) {
- }
-
- @Override
- public void unregisterOnSharedPreferenceChangeListener(
- OnSharedPreferenceChangeListener listener) {
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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 com.android.internal.os.IResultReceiver;
-
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.util.MergedConfiguration;
-import android.view.DragEvent;
-import android.view.IWindow;
-
-/**
- * Implementation of {@link IWindow} to pass to the AttachInfo.
- */
-public final class BridgeWindow implements IWindow {
-
- @Override
- public void dispatchAppVisibility(boolean arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void dispatchGetNewSurface() throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void executeCommand(String arg0, String arg1, ParcelFileDescriptor arg2)
- throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void resized(Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5, Rect rect6,
- boolean b, MergedConfiguration mergedConfig, Rect rect7, boolean b2, boolean b3, int i0)
- throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void moved(int arg0, int arg1) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void windowFocusChanged(boolean arg0, boolean arg1) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
- boolean sync) {
- // pass for now.
- }
-
- @Override
- public void dispatchWallpaperCommand(String action, int x, int y,
- int z, Bundle extras, boolean sync) {
- // pass for now.
- }
-
- @Override
- public void closeSystemDialogs(String reason) {
- // pass for now.
- }
-
- @Override
- public void dispatchDragEvent(DragEvent event) {
- // pass for now.
- }
-
- @Override
- public void updatePointerIcon(float x, float y) {
- // pass for now
- }
-
- @Override
- public void dispatchSystemUiVisibilityChanged(int seq, int globalUi,
- int localValue, int localChanges) {
- // pass for now.
- }
-
- @Override
- public void dispatchWindowShown() {
- }
-
- @Override
- public void requestAppKeyboardShortcuts(
- IResultReceiver receiver, int deviceId) throws RemoteException {
- }
-
- @Override
- public void dispatchPointerCaptureChanged(boolean hasCapture) {
- }
-
- @Override
- public IBinder asBinder() {
- // pass for now.
- return null;
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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.content.ClipData;
-import android.graphics.Rect;
-import android.graphics.Region;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.MergedConfiguration;
-import android.view.IWindow;
-import android.view.IWindowId;
-import android.view.IWindowSession;
-import android.view.InputChannel;
-import android.view.Surface;
-import android.view.SurfaceView;
-import android.view.WindowManager.LayoutParams;
-
-/**
- * Implementation of {@link IWindowSession} so that mSession is not null in
- * the {@link SurfaceView}.
- */
-public final class BridgeWindowSession implements IWindowSession {
-
- @Override
- public int add(IWindow arg0, int seq, LayoutParams arg1, int arg2, Rect arg3, Rect arg4,
- InputChannel outInputchannel)
- throws RemoteException {
- // pass for now.
- return 0;
- }
-
- @Override
- public int addToDisplay(IWindow arg0, int seq, LayoutParams arg1, int arg2, int displayId,
- Rect arg3, Rect arg4, Rect arg5, InputChannel outInputchannel)
- throws RemoteException {
- // pass for now.
- return 0;
- }
-
- @Override
- public int addWithoutInputChannel(IWindow arg0, int seq, LayoutParams arg1, int arg2,
- Rect arg3, Rect arg4)
- throws RemoteException {
- // pass for now.
- return 0;
- }
-
- @Override
- public int addToDisplayWithoutInputChannel(IWindow arg0, int seq, LayoutParams arg1, int arg2,
- int displayId, Rect arg3, Rect arg4)
- throws RemoteException {
- // pass for now.
- return 0;
- }
-
- @Override
- public void finishDrawing(IWindow arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public boolean getInTouchMode() throws RemoteException {
- // pass for now.
- return false;
- }
-
- @Override
- public boolean performHapticFeedback(IWindow window, int effectId, boolean always) {
- // pass for now.
- return false;
- }
-
- @Override
- public int relayout(IWindow iWindow, int i, LayoutParams layoutParams, int i2,
- int i3, int i4, int i5, Rect rect, Rect rect2, Rect rect3, Rect rect4, Rect rect5,
- Rect rect6, Rect rect7, MergedConfiguration mergedConfig, Surface surface)
- throws RemoteException {
- // pass for now.
- return 0;
- }
-
- @Override
- public boolean outOfMemory(IWindow window) throws RemoteException {
- return false;
- }
-
- @Override
- public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
- // pass for now.
- }
-
- @Override
- public void remove(IWindow arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void setInTouchMode(boolean arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void setTransparentRegion(IWindow arg0, Region arg1) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void setInsets(IWindow window, int touchable, Rect contentInsets,
- Rect visibleInsets, Region touchableRegion) {
- // pass for now.
- }
-
- @Override
- public IBinder prepareDrag(IWindow window, int flags,
- int thumbnailWidth, int thumbnailHeight, Surface outSurface)
- throws RemoteException {
- // pass for now
- return null;
- }
-
- @Override
- public boolean performDrag(IWindow window, IBinder dragToken,
- int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
- ClipData data)
- throws RemoteException {
- // pass for now
- return false;
- }
-
- @Override
- public boolean startMovingTask(IWindow window, float startX, float startY)
- throws RemoteException {
- // pass for now
- return false;
- }
-
- @Override
- public void reportDropResult(IWindow window, boolean consumed) throws RemoteException {
- // pass for now
- }
-
- @Override
- public void cancelDragAndDrop(IBinder dragToken) throws RemoteException {
- // pass for now
- }
-
- @Override
- public void dragRecipientEntered(IWindow window) throws RemoteException {
- // pass for now
- }
-
- @Override
- public void dragRecipientExited(IWindow window) throws RemoteException {
- // pass for now
- }
-
- @Override
- public void setWallpaperPosition(IBinder window, float x, float y,
- float xStep, float yStep) {
- // pass for now.
- }
-
- @Override
- public void wallpaperOffsetsComplete(IBinder window) {
- // pass for now.
- }
-
- @Override
- public void setWallpaperDisplayOffset(IBinder windowToken, int x, int y) {
- // pass for now.
- }
-
- @Override
- public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
- int z, Bundle extras, boolean sync) {
- // pass for now.
- return null;
- }
-
- @Override
- public void wallpaperCommandComplete(IBinder window, Bundle result) {
- // pass for now.
- }
-
- @Override
- public IBinder asBinder() {
- // pass for now.
- return null;
- }
-
- @Override
- public void onRectangleOnScreenRequested(IBinder window, Rect rectangle) {
- // pass for now.
- }
-
- @Override
- public IWindowId getWindowId(IBinder window) throws RemoteException {
- // pass for now.
- return null;
- }
-
- @Override
- public void pokeDrawLock(IBinder window) {
- // pass for now.
- }
-
- @Override
- public void prepareToReplaceWindows(IBinder appToken, boolean childrenOnly) {
- // pass for now.
- }
-
- @Override
- public void updatePointerIcon(IWindow window) {
- // pass for now.
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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 com.android.ide.common.rendering.api.ILayoutPullParser;
-import com.android.layoutlib.bridge.impl.ParserFactory;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.res.XmlResourceParser;
-import android.util.AttributeSet;
-import android.util.BridgeXmlPullAttributes;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-
-/**
- * {@link BridgeXmlBlockParser} reimplements most of android.xml.XmlBlock.Parser.
- * It delegates to both an instance of {@link XmlPullParser} and an instance of
- * XmlPullAttributes (for the {@link AttributeSet} part).
- */
-public class BridgeXmlBlockParser implements XmlResourceParser {
-
- private final XmlPullParser mParser;
- private final BridgeXmlPullAttributes mAttrib;
- private final BridgeContext mContext;
- private final boolean mPlatformFile;
-
- private boolean mStarted = false;
- private int mEventType = START_DOCUMENT;
-
- private boolean mPopped = true; // default to true in case it's not pushed.
-
- /**
- * Builds a {@link BridgeXmlBlockParser}.
- * @param parser The XmlPullParser to get the content from.
- * @param context the Context.
- * @param platformFile Indicates whether the the file is a platform file or not.
- */
- public BridgeXmlBlockParser(XmlPullParser parser, BridgeContext context, boolean platformFile) {
- if (ParserFactory.LOG_PARSER) {
- System.out.println("CRTE " + parser.toString());
- }
-
- mParser = parser;
- mContext = context;
- mPlatformFile = platformFile;
- mAttrib = new BridgeXmlPullAttributes(parser, context, mPlatformFile);
-
- if (mContext != null) {
- mContext.pushParser(this);
- mPopped = false;
- }
- }
-
- public XmlPullParser getParser() {
- return mParser;
- }
-
- public boolean isPlatformFile() {
- return mPlatformFile;
- }
-
- public Object getViewCookie() {
- if (mParser instanceof ILayoutPullParser) {
- return ((ILayoutPullParser)mParser).getViewCookie();
- }
-
- return null;
- }
-
- public void ensurePopped() {
- if (mContext != null && mPopped == false) {
- mContext.popParser();
- mPopped = true;
- }
- }
-
- // ------- XmlResourceParser implementation
-
- @Override
- public void setFeature(String name, boolean state)
- throws XmlPullParserException {
- if (FEATURE_PROCESS_NAMESPACES.equals(name) && state) {
- return;
- }
- if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name) && state) {
- return;
- }
- throw new XmlPullParserException("Unsupported feature: " + name);
- }
-
- @Override
- public boolean getFeature(String name) {
- if (FEATURE_PROCESS_NAMESPACES.equals(name)) {
- return true;
- }
- if (FEATURE_REPORT_NAMESPACE_ATTRIBUTES.equals(name)) {
- return true;
- }
- return false;
- }
-
- @Override
- public void setProperty(String name, Object value) throws XmlPullParserException {
- throw new XmlPullParserException("setProperty() not supported");
- }
-
- @Override
- public Object getProperty(String name) {
- return null;
- }
-
- @Override
- public void setInput(Reader in) throws XmlPullParserException {
- mParser.setInput(in);
- }
-
- @Override
- public void setInput(InputStream inputStream, String inputEncoding)
- throws XmlPullParserException {
- mParser.setInput(inputStream, inputEncoding);
- }
-
- @Override
- public void defineEntityReplacementText(String entityName,
- String replacementText) throws XmlPullParserException {
- throw new XmlPullParserException(
- "defineEntityReplacementText() not supported");
- }
-
- @Override
- public String getNamespacePrefix(int pos) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespacePrefix() not supported");
- }
-
- @Override
- public String getInputEncoding() {
- return null;
- }
-
- @Override
- public String getNamespace(String prefix) {
- throw new RuntimeException("getNamespace() not supported");
- }
-
- @Override
- public int getNamespaceCount(int depth) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespaceCount() not supported");
- }
-
- @Override
- public String getPositionDescription() {
- return "Binary XML file line #" + getLineNumber();
- }
-
- @Override
- public String getNamespaceUri(int pos) throws XmlPullParserException {
- throw new XmlPullParserException("getNamespaceUri() not supported");
- }
-
- @Override
- public int getColumnNumber() {
- return -1;
- }
-
- @Override
- public int getDepth() {
- return mParser.getDepth();
- }
-
- @Override
- public String getText() {
- return mParser.getText();
- }
-
- @Override
- public int getLineNumber() {
- return mParser.getLineNumber();
- }
-
- @Override
- public int getEventType() {
- return mEventType;
- }
-
- @Override
- public boolean isWhitespace() throws XmlPullParserException {
- // Original comment: whitespace was stripped by aapt.
- return mParser.isWhitespace();
- }
-
- @Override
- public String getPrefix() {
- throw new RuntimeException("getPrefix not supported");
- }
-
- @Override
- public char[] getTextCharacters(int[] holderForStartAndLength) {
- String txt = getText();
- char[] chars = null;
- if (txt != null) {
- holderForStartAndLength[0] = 0;
- holderForStartAndLength[1] = txt.length();
- chars = new char[txt.length()];
- txt.getChars(0, txt.length(), chars, 0);
- }
- return chars;
- }
-
- @Override
- public String getNamespace() {
- return mParser.getNamespace();
- }
-
- @Override
- public String getName() {
- return mParser.getName();
- }
-
- @Override
- public String getAttributeNamespace(int index) {
- return mParser.getAttributeNamespace(index);
- }
-
- @Override
- public String getAttributeName(int index) {
- return mParser.getAttributeName(index);
- }
-
- @Override
- public String getAttributePrefix(int index) {
- throw new RuntimeException("getAttributePrefix not supported");
- }
-
- @Override
- public boolean isEmptyElementTag() {
- // XXX Need to detect this.
- return false;
- }
-
- @Override
- public int getAttributeCount() {
- return mParser.getAttributeCount();
- }
-
- @Override
- public String getAttributeValue(int index) {
- return mParser.getAttributeValue(index);
- }
-
- @Override
- public String getAttributeType(int index) {
- return "CDATA";
- }
-
- @Override
- public boolean isAttributeDefault(int index) {
- return false;
- }
-
- @Override
- public int nextToken() throws XmlPullParserException, IOException {
- return next();
- }
-
- @Override
- public String getAttributeValue(String namespace, String name) {
- return mParser.getAttributeValue(namespace, name);
- }
-
- @Override
- public int next() throws XmlPullParserException, IOException {
- if (!mStarted) {
- mStarted = true;
-
- if (ParserFactory.LOG_PARSER) {
- System.out.println("STRT " + mParser.toString());
- }
-
- return START_DOCUMENT;
- }
-
- int ev = mParser.next();
-
- if (ParserFactory.LOG_PARSER) {
- System.out.println("NEXT " + mParser.toString() + " " +
- eventTypeToString(mEventType) + " -> " + eventTypeToString(ev));
- }
-
- if (ev == END_TAG && mParser.getDepth() == 1) {
- // done with parser remove it from the context stack.
- ensurePopped();
-
- if (ParserFactory.LOG_PARSER) {
- System.out.println("");
- }
- }
-
- mEventType = ev;
- return ev;
- }
-
- public static String eventTypeToString(int eventType) {
- switch (eventType) {
- case START_DOCUMENT:
- return "START_DOC";
- case END_DOCUMENT:
- return "END_DOC";
- case START_TAG:
- return "START_TAG";
- case END_TAG:
- return "END_TAG";
- case TEXT:
- return "TEXT";
- case CDSECT:
- return "CDSECT";
- case ENTITY_REF:
- return "ENTITY_REF";
- case IGNORABLE_WHITESPACE:
- return "IGNORABLE_WHITESPACE";
- case PROCESSING_INSTRUCTION:
- return "PROCESSING_INSTRUCTION";
- case COMMENT:
- return "COMMENT";
- case DOCDECL:
- return "DOCDECL";
- }
-
- return "????";
- }
-
- @Override
- public void require(int type, String namespace, String name)
- throws XmlPullParserException {
- if (type != getEventType()
- || (namespace != null && !namespace.equals(getNamespace()))
- || (name != null && !name.equals(getName())))
- throw new XmlPullParserException("expected " + TYPES[type]
- + getPositionDescription());
- }
-
- @Override
- public String nextText() throws XmlPullParserException, IOException {
- if (getEventType() != START_TAG) {
- throw new XmlPullParserException(getPositionDescription()
- + ": parser must be on START_TAG to read next text", this,
- null);
- }
- int eventType = next();
- if (eventType == TEXT) {
- String result = getText();
- eventType = next();
- if (eventType != END_TAG) {
- throw new XmlPullParserException(
- getPositionDescription()
- + ": event TEXT it must be immediately followed by END_TAG",
- this, null);
- }
- return result;
- } else if (eventType == END_TAG) {
- return "";
- } else {
- throw new XmlPullParserException(getPositionDescription()
- + ": parser must be on START_TAG or TEXT to read text",
- this, null);
- }
- }
-
- @Override
- public int nextTag() throws XmlPullParserException, IOException {
- int eventType = next();
- if (eventType == TEXT && isWhitespace()) { // skip whitespace
- eventType = next();
- }
- if (eventType != START_TAG && eventType != END_TAG) {
- throw new XmlPullParserException(getPositionDescription()
- + ": expected start or end tag", this, null);
- }
- return eventType;
- }
-
- // AttributeSet implementation
-
-
- @Override
- public void close() {
- // pass
- }
-
- @Override
- public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
- return mAttrib.getAttributeBooleanValue(index, defaultValue);
- }
-
- @Override
- public boolean getAttributeBooleanValue(String namespace, String attribute,
- boolean defaultValue) {
- return mAttrib.getAttributeBooleanValue(namespace, attribute, defaultValue);
- }
-
- @Override
- public float getAttributeFloatValue(int index, float defaultValue) {
- return mAttrib.getAttributeFloatValue(index, defaultValue);
- }
-
- @Override
- public float getAttributeFloatValue(String namespace, String attribute, float defaultValue) {
- return mAttrib.getAttributeFloatValue(namespace, attribute, defaultValue);
- }
-
- @Override
- public int getAttributeIntValue(int index, int defaultValue) {
- return mAttrib.getAttributeIntValue(index, defaultValue);
- }
-
- @Override
- public int getAttributeIntValue(String namespace, String attribute, int defaultValue) {
- return mAttrib.getAttributeIntValue(namespace, attribute, defaultValue);
- }
-
- @Override
- public int getAttributeListValue(int index, String[] options, int defaultValue) {
- return mAttrib.getAttributeListValue(index, options, defaultValue);
- }
-
- @Override
- public int getAttributeListValue(String namespace, String attribute,
- String[] options, int defaultValue) {
- return mAttrib.getAttributeListValue(namespace, attribute, options, defaultValue);
- }
-
- @Override
- public int getAttributeNameResource(int index) {
- return mAttrib.getAttributeNameResource(index);
- }
-
- @Override
- public int getAttributeResourceValue(int index, int defaultValue) {
- return mAttrib.getAttributeResourceValue(index, defaultValue);
- }
-
- @Override
- public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
- return mAttrib.getAttributeResourceValue(namespace, attribute, defaultValue);
- }
-
- @Override
- public int getAttributeUnsignedIntValue(int index, int defaultValue) {
- return mAttrib.getAttributeUnsignedIntValue(index, defaultValue);
- }
-
- @Override
- public int getAttributeUnsignedIntValue(String namespace, String attribute, int defaultValue) {
- return mAttrib.getAttributeUnsignedIntValue(namespace, attribute, defaultValue);
- }
-
- @Override
- public String getClassAttribute() {
- return mAttrib.getClassAttribute();
- }
-
- @Override
- public String getIdAttribute() {
- return mAttrib.getIdAttribute();
- }
-
- @Override
- public int getIdAttributeResourceValue(int defaultValue) {
- return mAttrib.getIdAttributeResourceValue(defaultValue);
- }
-
- @Override
- public int getStyleAttribute() {
- return mAttrib.getStyleAttribute();
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.android;
-
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.RenderParams;
-import com.android.ide.common.rendering.api.SessionParams.Key;
-
-/**
- * This contains all known keys for the {@link RenderParams#getFlag(Key)}.
- * <p/>
- * The IDE has its own copy of this class which may be newer or older than this one.
- * <p/>
- * Constants should never be modified or removed from this class.
- */
-public final class RenderParamsFlags {
-
- public static final Key<String> FLAG_KEY_ROOT_TAG =
- new Key<String>("rootTag", String.class);
- public static final Key<Boolean> FLAG_KEY_DISABLE_BITMAP_CACHING =
- new Key<Boolean>("disableBitmapCaching", Boolean.class);
- public static final Key<Boolean> FLAG_KEY_RENDER_ALL_DRAWABLE_STATES =
- new Key<Boolean>("renderAllDrawableStates", Boolean.class);
- /**
- * To tell LayoutLib that the IDE supports RecyclerView.
- * <p/>
- * Default is false.
- */
- public static final Key<Boolean> FLAG_KEY_RECYCLER_VIEW_SUPPORT =
- new Key<Boolean>("recyclerViewSupport", Boolean.class);
- /**
- * The application package name. Used via {@link LayoutlibCallback#getFlag(Key)}
- */
- public static final Key<String> FLAG_KEY_APPLICATION_PACKAGE =
- new Key<String>("applicationPackage", String.class);
- /**
- * To tell LayoutLib that IDE supports providing XML Parser for a file (useful for getting in
- * memory contents of the file). Used via {@link LayoutlibCallback#getFlag(Key)}
- */
- public static final Key<Boolean> FLAG_KEY_XML_FILE_PARSER_SUPPORT =
- new Key<Boolean>("xmlFileParser", Boolean.class);
- /**
- * To tell LayoutLib to not render when creating a new session. This allows controlling when the first
- * layout rendering will happen.
- */
- public static final Key<Boolean> FLAG_DO_NOT_RENDER_ON_CREATE =
- new Key<Boolean>("doNotRenderOnCreate", Boolean.class);
-
- // Disallow instances.
- private RenderParamsFlags() {}
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.android.graphics;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.NinePatch;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Picture;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.Rect;
-import android.graphics.RectF;
-
-/**
- * Canvas implementation that does not do any rendering
- */
-public class NopCanvas extends Canvas {
- private boolean mIsInitialized = false;
-
- public NopCanvas() {
- super();
- mIsInitialized = true;
- }
-
- @Override
- public boolean isHardwareAccelerated() {
- // We return true the first time so there are no allocations for the software renderer in
- // the constructor
- return !mIsInitialized;
- }
-
- @Override
- public int save() {
- return 0;
- }
-
- @Override
- public int save(int saveFlags) {
- return 0;
- }
-
- @Override
- public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
- return 0;
- }
-
- @Override
- public int saveLayer(RectF bounds, Paint paint) {
- return 0;
- }
-
- @Override
- public int saveLayer(float left, float top, float right, float bottom, Paint paint,
- int saveFlags) {
- return 0;
- }
-
- @Override
- public int saveLayer(float left, float top, float right, float bottom, Paint paint) {
- return 0;
- }
-
- @Override
- public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
- return 0;
- }
-
- @Override
- public int saveLayerAlpha(RectF bounds, int alpha) {
- return 0;
- }
-
- @Override
- public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
- int saveFlags) {
- return 0;
- }
-
- @Override
- public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha) {
- return 0;
- }
-
- @Override
- public void restore() {
- }
-
- @Override
- public int getSaveCount() {
- return 0;
- }
-
- @Override
- public void restoreToCount(int saveCount) {
- }
-
- @Override
- public void drawRGB(int r, int g, int b) {
- }
-
- @Override
- public void drawARGB(int a, int r, int g, int b) {
- }
-
- @Override
- public void drawColor(int color) {
- }
-
- @Override
- public void drawColor(int color, Mode mode) {
- }
-
- @Override
- public void drawPaint(Paint paint) {
- }
-
- @Override
- public void drawPoints(float[] pts, int offset, int count, Paint paint) {
- }
-
- @Override
- public void drawPoints(float[] pts, Paint paint) {
- }
-
- @Override
- public void drawPoint(float x, float y, Paint paint) {
- }
-
- @Override
- public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
- }
-
- @Override
- public void drawLines(float[] pts, int offset, int count, Paint paint) {
- }
-
- @Override
- public void drawLines(float[] pts, Paint paint) {
- }
-
- @Override
- public void drawRect(RectF rect, Paint paint) {
- }
-
- @Override
- public void drawRect(Rect r, Paint paint) {
- }
-
- @Override
- public void drawRect(float left, float top, float right, float bottom, Paint paint) {
- }
-
- @Override
- public void drawOval(RectF oval, Paint paint) {
- }
-
- @Override
- public void drawOval(float left, float top, float right, float bottom, Paint paint) {
- }
-
- @Override
- public void drawCircle(float cx, float cy, float radius, Paint paint) {
- }
-
- @Override
- public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
- Paint paint) {
- }
-
- @Override
- public void drawArc(float left, float top, float right, float bottom, float startAngle,
- float sweepAngle, boolean useCenter, Paint paint) {
- }
-
- @Override
- public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
- }
-
- @Override
- public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
- Paint paint) {
- }
-
- @Override
- public void drawPath(Path path, Paint paint) {
- }
-
- @Override
- protected void throwIfCannotDraw(Bitmap bitmap) {
- }
-
- @Override
- public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
- }
-
- @Override
- public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
- }
-
- @Override
- public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
- }
-
- @Override
- public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
- }
-
- @Override
- public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
- }
-
- @Override
- public void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width,
- int height, boolean hasAlpha, Paint paint) {
- }
-
- @Override
- public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width,
- int height, boolean hasAlpha, Paint paint) {
- }
-
- @Override
- public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
- }
-
- @Override
- public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
- int vertOffset, int[] colors, int colorOffset, Paint paint) {
- }
-
- @Override
- public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
- float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
- int indexOffset, int indexCount, Paint paint) {
- }
-
- @Override
- public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
- }
-
- @Override
- public void drawText(String text, float x, float y, Paint paint) {
- }
-
- @Override
- public void drawText(String text, int start, int end, float x, float y, Paint paint) {
- }
-
- @Override
- public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
- }
-
- @Override
- public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
- float x, float y, boolean isRtl, Paint paint) {
- }
-
- @Override
- public void drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd,
- float x, float y, boolean isRtl, Paint paint) {
- }
-
- @Override
- public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
- }
-
- @Override
- public void drawPosText(String text, float[] pos, Paint paint) {
- }
-
- @Override
- public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
- float vOffset, Paint paint) {
- }
-
- @Override
- public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
- }
-
- @Override
- public void drawPicture(Picture picture) {
- }
-
- @Override
- public void drawPicture(Picture picture, RectF dst) {
- }
-
- @Override
- public void drawPicture(Picture picture, Rect dst) {
- }
-}
+++ /dev/null
-/*
- * 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.support;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.view.View;
-
-import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod;
-import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;
-
-/**
- * Utility class for working with the design support lib.
- */
-public class DesignLibUtil {
-
- private static final String PKG_PREFIX = "android.support.design.widget.";
- public static final String CN_COORDINATOR_LAYOUT = PKG_PREFIX + "CoordinatorLayout";
- public static final String CN_APPBAR_LAYOUT = PKG_PREFIX + "AppBarLayout";
- public static final String CN_COLLAPSING_TOOLBAR_LAYOUT =
- PKG_PREFIX + "CollapsingToolbarLayout";
- public static final String CN_TOOLBAR = "android.support.v7.widget.Toolbar";
- public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
-
- /**
- * Tries to set the title of a view. This is used to set the title in a
- * CollapsingToolbarLayout.
- * <p/>
- * Any exceptions thrown during the process are logged in {@link Bridge#getLog()}
- */
- public static void setTitle(@NonNull View view, @Nullable String title) {
- if (title == null) {
- return;
- }
- try {
- invoke(getMethod(view.getClass(), "setTitle", CharSequence.class), view, title);
- } catch (ReflectionException e) {
- Bridge.getLog().warning(LayoutLog.TAG_INFO,
- "Error occurred while trying to set title.", e);
- }
- }
-}
+++ /dev/null
-/*
- * 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.support;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
-
-import android.annotation.Nullable;
-import android.view.View;
-
-import static android.view.Gravity.END;
-import static android.view.Gravity.LEFT;
-import static android.view.Gravity.RIGHT;
-import static android.view.Gravity.START;
-import static com.android.layoutlib.bridge.util.ReflectionUtils.getCause;
-import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod;
-import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;
-
-public class DrawerLayoutUtil {
-
- public static final String CN_DRAWER_LAYOUT = "android.support.v4.widget.DrawerLayout";
-
- public static void openDrawer(View drawerLayout, @Nullable String drawerGravity) {
- int gravity = -1;
- if ("left".equals(drawerGravity)) {
- gravity = LEFT;
- } else if ("right".equals(drawerGravity)) {
- gravity = RIGHT;
- } else if ("start".equals(drawerGravity)) {
- gravity = START;
- } else if ("end".equals(drawerGravity)) {
- gravity = END;
- }
- if (gravity > 0) {
- openDrawer(drawerLayout, gravity);
- }
- }
-
- private static void openDrawer(View drawerLayout, int gravity) {
- try {
- invoke(getMethod(drawerLayout.getClass(), "openDrawer", int.class), drawerLayout,
- gravity);
- } catch (ReflectionException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to open navigation drawer",
- getCause(e), null);
- }
- }
-}
+++ /dev/null
-/*
- * 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.support;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.RenderParamsFlags;
-import com.android.layoutlib.bridge.util.ReflectionUtils;
-import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.view.View;
-
-import static com.android.layoutlib.bridge.util.ReflectionUtils.getCause;
-import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod;
-import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;
-
-/**
- * Utility class for working with android.support.v7.widget.RecyclerView
- */
-public class RecyclerViewUtil {
-
- private static final String RV_PKG_PREFIX = "android.support.v7.widget.";
- public static final String CN_RECYCLER_VIEW = RV_PKG_PREFIX + "RecyclerView";
- private static final String CN_LAYOUT_MANAGER = CN_RECYCLER_VIEW + "$LayoutManager";
- private static final String CN_ADAPTER = CN_RECYCLER_VIEW + "$Adapter";
-
- // LinearLayoutManager related constants.
- private static final String CN_LINEAR_LAYOUT_MANAGER = RV_PKG_PREFIX + "LinearLayoutManager";
- private static final Class<?>[] LLM_CONSTRUCTOR_SIGNATURE = new Class<?>[]{Context.class};
-
- /**
- * Tries to create an Adapter ({@code android.support.v7.widget.RecyclerView.Adapter} and a
- * LayoutManager {@code RecyclerView.LayoutManager} and assign these to the {@code RecyclerView}
- * that is passed.
- * <p/>
- * Any exceptions thrown during the process are logged in {@link Bridge#getLog()}
- */
- public static void setAdapter(@NonNull View recyclerView, @NonNull BridgeContext context,
- @NonNull LayoutlibCallback layoutlibCallback, int adapterLayout) {
- try {
- setLayoutManager(recyclerView, context, layoutlibCallback);
- Object adapter = createAdapter(layoutlibCallback);
- if (adapter != null) {
- setProperty(recyclerView, CN_ADAPTER, adapter, "setAdapter");
- setProperty(adapter, int.class, adapterLayout, "setLayoutId");
- }
- } catch (ReflectionException e) {
- Throwable cause = getCause(e);
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Error occurred while trying to setup RecyclerView.", cause, null);
- }
- }
-
- private static void setLayoutManager(@NonNull View recyclerView, @NonNull BridgeContext context,
- @NonNull LayoutlibCallback callback) throws ReflectionException {
- if (getLayoutManager(recyclerView) == null) {
- // Only set the layout manager if not already set by the recycler view.
- Object layoutManager = createLayoutManager(context, callback);
- if (layoutManager != null) {
- setProperty(recyclerView, CN_LAYOUT_MANAGER, layoutManager, "setLayoutManager");
- }
- }
- }
-
- /** Creates a LinearLayoutManager using the provided context. */
- @Nullable
- private static Object createLayoutManager(@NonNull Context context,
- @NonNull LayoutlibCallback callback)
- throws ReflectionException {
- try {
- return callback.loadView(CN_LINEAR_LAYOUT_MANAGER, LLM_CONSTRUCTOR_SIGNATURE,
- new Object[]{context});
- } catch (Exception e) {
- throw new ReflectionException(e);
- }
- }
-
- @Nullable
- private static Object getLayoutManager(View recyclerView) throws ReflectionException {
- return invoke(getMethod(recyclerView.getClass(), "getLayoutManager"), recyclerView);
- }
-
- @Nullable
- private static Object createAdapter(@NonNull LayoutlibCallback layoutlibCallback)
- throws ReflectionException {
- Boolean ideSupport =
- layoutlibCallback.getFlag(RenderParamsFlags.FLAG_KEY_RECYCLER_VIEW_SUPPORT);
- if (ideSupport != Boolean.TRUE) {
- return null;
- }
- try {
- return layoutlibCallback.loadClass(CN_ADAPTER, new Class[0], new Object[0]);
- } catch (Exception e) {
- throw new ReflectionException(e);
- }
- }
-
- private static void setProperty(@NonNull Object object, @NonNull String propertyClassName,
- @NonNull Object propertyValue, @NonNull String propertySetter)
- throws ReflectionException {
- Class<?> propertyClass = ReflectionUtils.getClassInstance(propertyValue, propertyClassName);
- setProperty(object, propertyClass, propertyValue, propertySetter);
- }
-
- private static void setProperty(@NonNull Object object, @NonNull Class<?> propertyClass,
- @Nullable Object propertyValue, @NonNull String propertySetter)
- throws ReflectionException {
- invoke(getMethod(object.getClass(), propertySetter, propertyClass), object, propertyValue);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.android.support;
-
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.StyleResourceValue;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.view.ContextThemeWrapper;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-import android.widget.LinearLayout.LayoutParams;
-import android.widget.ScrollView;
-
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-
-import static com.android.layoutlib.bridge.util.ReflectionUtils.getAccessibleMethod;
-import static com.android.layoutlib.bridge.util.ReflectionUtils.getClassInstance;
-import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod;
-import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;
-
-/**
- * Class with utility methods to instantiate Preferences provided by the support library.
- * This class uses reflection to access the support preference objects so it heavily depends on
- * the API being stable.
- */
-public class SupportPreferencesUtil {
- private static final String PREFERENCE_PKG = "android.support.v7.preference";
- private static final String PREFERENCE_MANAGER = PREFERENCE_PKG + ".PreferenceManager";
- private static final String PREFERENCE_GROUP = PREFERENCE_PKG + ".PreferenceGroup";
- private static final String PREFERENCE_GROUP_ADAPTER =
- PREFERENCE_PKG + ".PreferenceGroupAdapter";
- private static final String PREFERENCE_INFLATER = PREFERENCE_PKG + ".PreferenceInflater";
-
- private SupportPreferencesUtil() {
- }
-
- @NonNull
- private static Object instantiateClass(@NonNull LayoutlibCallback callback,
- @NonNull String className, @Nullable Class[] constructorSignature,
- @Nullable Object[] constructorArgs) throws ReflectionException {
- try {
- Object instance = callback.loadClass(className, constructorSignature, constructorArgs);
- if (instance == null) {
- throw new ClassNotFoundException(className + " class not found");
- }
- return instance;
- } catch (ClassNotFoundException e) {
- throw new ReflectionException(e);
- }
- }
-
- @NonNull
- private static Object createPreferenceGroupAdapter(@NonNull LayoutlibCallback callback,
- @NonNull Object preferenceScreen) throws ReflectionException {
- Class<?> preferenceGroupClass = getClassInstance(preferenceScreen, PREFERENCE_GROUP);
-
- return instantiateClass(callback, PREFERENCE_GROUP_ADAPTER,
- new Class[]{preferenceGroupClass}, new Object[]{preferenceScreen});
- }
-
- @NonNull
- private static Object createInflatedPreference(@NonNull LayoutlibCallback callback,
- @NonNull Context context, @NonNull XmlPullParser parser, @NonNull Object preferenceScreen,
- @NonNull Object preferenceManager) throws ReflectionException {
- Class<?> preferenceGroupClass = getClassInstance(preferenceScreen, PREFERENCE_GROUP);
- Object preferenceInflater = instantiateClass(callback, PREFERENCE_INFLATER,
- new Class[]{Context.class, preferenceManager.getClass()},
- new Object[]{context, preferenceManager});
- Object inflatedPreference =
- invoke(getAccessibleMethod(preferenceInflater.getClass(), "inflate",
- XmlPullParser.class, preferenceGroupClass), preferenceInflater, parser,
- null);
-
- if (inflatedPreference == null) {
- throw new ReflectionException("inflate method returned null");
- }
-
- return inflatedPreference;
- }
-
- /**
- * Returns a themed wrapper context of {@link BridgeContext} with the theme specified in
- * ?attr/preferenceTheme applied to it.
- */
- @Nullable
- private static Context getThemedContext(@NonNull BridgeContext bridgeContext) {
- RenderResources resources = bridgeContext.getRenderResources();
- ResourceValue preferenceTheme = resources.findItemInTheme("preferenceTheme", false);
-
- if (preferenceTheme != null) {
- // resolve it, if needed.
- preferenceTheme = resources.resolveResValue(preferenceTheme);
- }
- if (preferenceTheme instanceof StyleResourceValue) {
- int styleId = bridgeContext.getDynamicIdByStyle(((StyleResourceValue) preferenceTheme));
- if (styleId != 0) {
- return new ContextThemeWrapper(bridgeContext, styleId);
- }
- }
-
- return null;
- }
-
- /**
- * Returns a {@link LinearLayout} containing all the UI widgets representing the preferences
- * passed in the group adapter.
- */
- @Nullable
- private static LinearLayout setUpPreferencesListView(@NonNull BridgeContext bridgeContext,
- @NonNull Context themedContext, @NonNull ArrayList<Object> viewCookie,
- @NonNull Object preferenceGroupAdapter) throws ReflectionException {
- // Setup the LinearLayout that will contain the preferences
- LinearLayout listView = new LinearLayout(themedContext);
- listView.setOrientation(LinearLayout.VERTICAL);
- listView.setLayoutParams(
- new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
-
- if (!viewCookie.isEmpty()) {
- bridgeContext.addViewKey(listView, viewCookie.get(0));
- }
-
- // Get all the preferences and add them to the LinearLayout
- Integer preferencesCount =
- (Integer) invoke(getMethod(preferenceGroupAdapter.getClass(), "getItemCount"),
- preferenceGroupAdapter);
- if (preferencesCount == null) {
- return listView;
- }
-
- Method getItemId = getMethod(preferenceGroupAdapter.getClass(), "getItemId", int.class);
- Method getItemViewType =
- getMethod(preferenceGroupAdapter.getClass(), "getItemViewType", int.class);
- Method onCreateViewHolder =
- getMethod(preferenceGroupAdapter.getClass(), "onCreateViewHolder", ViewGroup.class,
- int.class);
- for (int i = 0; i < preferencesCount; i++) {
- Long id = (Long) invoke(getItemId, preferenceGroupAdapter, i);
- if (id == null) {
- continue;
- }
-
- // Get the type of the preference layout and bind it to a newly created view holder
- Integer type = (Integer) invoke(getItemViewType, preferenceGroupAdapter, i);
- Object viewHolder =
- invoke(onCreateViewHolder, preferenceGroupAdapter, listView, type);
- if (viewHolder == null) {
- continue;
- }
- invoke(getMethod(preferenceGroupAdapter.getClass(), "onBindViewHolder",
- viewHolder.getClass(), int.class), preferenceGroupAdapter, viewHolder, i);
-
- try {
- // Get the view from the view holder and add it to our layout
- View itemView =
- (View) viewHolder.getClass().getField("itemView").get(viewHolder);
-
- int arrayPosition = id.intValue() - 1; // IDs are 1 based
- if (arrayPosition >= 0 && arrayPosition < viewCookie.size()) {
- bridgeContext.addViewKey(itemView, viewCookie.get(arrayPosition));
- }
- listView.addView(itemView);
- } catch (IllegalAccessException | NoSuchFieldException ignored) {
- }
- }
-
- return listView;
- }
-
- /**
- * Inflates a preferences layout using the support library. If the support library is not
- * available, this method will return null without advancing the parsers.
- */
- @Nullable
- public static View inflatePreference(@NonNull BridgeContext bridgeContext,
- @NonNull XmlPullParser parser, @Nullable ViewGroup root) {
- try {
- LayoutlibCallback callback = bridgeContext.getLayoutlibCallback();
-
- Context context = getThemedContext(bridgeContext);
- if (context == null) {
- // Probably we couldn't find the "preferenceTheme" in the theme
- return null;
- }
-
- // Create PreferenceManager
- Object preferenceManager =
- instantiateClass(callback, PREFERENCE_MANAGER, new Class[]{Context.class},
- new Object[]{context});
-
- // From this moment on, we can assume that we found the support library and that
- // nothing should fail
-
- // Create PreferenceScreen
- Object preferenceScreen =
- invoke(getMethod(preferenceManager.getClass(), "createPreferenceScreen",
- Context.class), preferenceManager, context);
- if (preferenceScreen == null) {
- return null;
- }
-
- // Setup a parser that stores the list of cookies in the same order as the preferences
- // are inflated. That way we can later reconstruct the list using the preference id
- // since they are sequential and start in 1.
- ArrayList<Object> viewCookie = new ArrayList<>();
- if (parser instanceof BridgeXmlBlockParser) {
- // Setup a parser that stores the XmlTag
- parser = new BridgeXmlBlockParser(parser, null, false) {
- @Override
- public Object getViewCookie() {
- return ((BridgeXmlBlockParser) getParser()).getViewCookie();
- }
-
- @Override
- public int next() throws XmlPullParserException, IOException {
- int ev = super.next();
- if (ev == XmlPullParser.START_TAG) {
- viewCookie.add(this.getViewCookie());
- }
-
- return ev;
- }
- };
- }
-
- // Create the PreferenceInflater
- Object inflatedPreference =
- createInflatedPreference(callback, context, parser, preferenceScreen,
- preferenceManager);
-
- // Setup the RecyclerView (set adapter and layout manager)
- Object preferenceGroupAdapter =
- createPreferenceGroupAdapter(callback, inflatedPreference);
-
- // Instead of just setting the group adapter as adapter for a RecyclerView, we manually
- // get all the items and add them to a LinearLayout. This allows us to set the view
- // cookies so the preferences are correctly linked to their XML.
- LinearLayout listView = setUpPreferencesListView(bridgeContext, context, viewCookie,
- preferenceGroupAdapter);
-
- ScrollView scrollView = new ScrollView(context);
- scrollView.setLayoutParams(
- new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- scrollView.addView(listView);
-
- if (root != null) {
- root.addView(scrollView);
- }
-
- return scrollView;
- } catch (ReflectionException e) {
- return null;
- }
- }
-}
+++ /dev/null
-/*
- * 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.layoutlib.bridge.android.view;
-
-import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.Display.Mode;
-import android.view.DisplayAdjustments;
-import android.view.DisplayInfo;
-import android.view.View;
-import android.view.WindowManager;
-
-public class WindowManagerImpl implements WindowManager {
-
- private final DisplayMetrics mMetrics;
- private final Display mDisplay;
-
- public WindowManagerImpl(DisplayMetrics metrics) {
- mMetrics = metrics;
-
- DisplayInfo info = new DisplayInfo();
- info.logicalHeight = mMetrics.heightPixels;
- info.logicalWidth = mMetrics.widthPixels;
- info.supportedModes = new Mode[] {
- new Mode(0, mMetrics.widthPixels, mMetrics.heightPixels, 60f)
- };
- mDisplay = new Display(null, Display.DEFAULT_DISPLAY, info,
- DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
- }
-
- @Override
- public Display getDefaultDisplay() {
- return mDisplay;
- }
-
-
- @Override
- public void addView(View arg0, android.view.ViewGroup.LayoutParams arg1) {
- // pass
- }
-
- @Override
- public void removeView(View arg0) {
- // pass
- }
-
- @Override
- public void updateViewLayout(View arg0, android.view.ViewGroup.LayoutParams arg1) {
- // pass
- }
-
-
- @Override
- public void removeViewImmediate(View arg0) {
- // pass
- }
-
- @Override
- public void requestAppKeyboardShortcuts(
- KeyboardShortcutsReceiver receiver, int deviceId) {
- }
-}
+++ /dev/null
-/*
- * 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.bars;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.SessionParams;
-import com.android.ide.common.rendering.api.StyleResourceValue;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.ResourceHelper;
-import com.android.resources.ResourceType;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.view.ContextThemeWrapper;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-
-/**
- * Assumes that the AppCompat library is present in the project's classpath and creates an
- * actionbar around it.
- */
-public class AppCompatActionBar extends BridgeActionBar {
-
- private Object mWindowDecorActionBar;
- private static final String WINDOW_ACTION_BAR_CLASS = "android.support.v7.internal.app.WindowDecorActionBar";
- // This is used on v23.1.1 and later.
- private static final String WINDOW_ACTION_BAR_CLASS_NEW = "android.support.v7.app.WindowDecorActionBar";
- private Class<?> mWindowActionBarClass;
-
- /**
- * Inflate the action bar and attach it to {@code parentView}
- */
- public AppCompatActionBar(@NonNull BridgeContext context, @NonNull SessionParams params) {
- super(context, params);
- int contentRootId = context.getProjectResourceValue(ResourceType.ID,
- "action_bar_activity_content", 0);
- View contentView = getDecorContent().findViewById(contentRootId);
- if (contentView != null) {
- assert contentView instanceof FrameLayout;
- setContentRoot((FrameLayout) contentView);
- } else {
- // Something went wrong. Create a new FrameLayout in the enclosing layout.
- FrameLayout contentRoot = new FrameLayout(context);
- setMatchParent(contentRoot);
- if (mEnclosingLayout != null) {
- mEnclosingLayout.addView(contentRoot);
- }
- setContentRoot(contentRoot);
- }
- try {
- Class[] constructorParams = {View.class};
- Object[] constructorArgs = {getDecorContent()};
- LayoutlibCallback callback = params.getLayoutlibCallback();
-
- // Check if the old action bar class is present.
- String actionBarClass = WINDOW_ACTION_BAR_CLASS;
- try {
- callback.findClass(actionBarClass);
- } catch (ClassNotFoundException expected) {
- // Failed to find the old class, use the newer one.
- actionBarClass = WINDOW_ACTION_BAR_CLASS_NEW;
- }
-
- mWindowDecorActionBar = callback.loadView(actionBarClass,
- constructorParams, constructorArgs);
- mWindowActionBarClass = mWindowDecorActionBar == null ? null :
- mWindowDecorActionBar.getClass();
- setupActionBar();
- } catch (Exception e) {
- Bridge.getLog().warning(LayoutLog.TAG_BROKEN,
- "Failed to load AppCompat ActionBar with unknown error.", e);
- }
- }
-
- @Override
- protected ResourceValue getLayoutResource(BridgeContext context) {
- // We always assume that the app has requested the action bar.
- return context.getRenderResources().getProjectResource(ResourceType.LAYOUT,
- "abc_screen_toolbar");
- }
-
- @Override
- protected LayoutInflater getInflater(BridgeContext context) {
- // Other than the resource resolution part, the code has been taken from the support
- // library. see code from line 269 onwards in
- // https://android.googlesource.com/platform/frameworks/support/+/android-5.1.0_r1/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java
- Context themedContext = context;
- RenderResources resources = context.getRenderResources();
- ResourceValue actionBarTheme = resources.findItemInTheme("actionBarTheme", false);
- if (actionBarTheme != null) {
- // resolve it, if needed.
- actionBarTheme = resources.resolveResValue(actionBarTheme);
- }
- if (actionBarTheme instanceof StyleResourceValue) {
- int styleId = context.getDynamicIdByStyle(((StyleResourceValue) actionBarTheme));
- if (styleId != 0) {
- themedContext = new ContextThemeWrapper(context, styleId);
- }
- }
- return LayoutInflater.from(themedContext);
- }
-
- @Override
- protected void setTitle(CharSequence title) {
- if (title != null && mWindowDecorActionBar != null) {
- Method setTitle = getMethod(mWindowActionBarClass, "setTitle", CharSequence.class);
- invoke(setTitle, mWindowDecorActionBar, title);
- }
- }
-
- @Override
- protected void setSubtitle(CharSequence subtitle) {
- if (subtitle != null && mWindowDecorActionBar != null) {
- Method setSubtitle = getMethod(mWindowActionBarClass, "setSubtitle", CharSequence.class);
- invoke(setSubtitle, mWindowDecorActionBar, subtitle);
- }
- }
-
- @Override
- protected void setIcon(String icon) {
- // Do this only if the action bar doesn't already have an icon.
- if (icon != null && !icon.isEmpty() && mWindowDecorActionBar != null) {
- if (invoke(getMethod(mWindowActionBarClass, "hasIcon"), mWindowDecorActionBar)
- == Boolean.TRUE) {
- Drawable iconDrawable = getDrawable(icon, false);
- if (iconDrawable != null) {
- Method setIcon = getMethod(mWindowActionBarClass, "setIcon", Drawable.class);
- invoke(setIcon, mWindowDecorActionBar, iconDrawable);
- }
- }
- }
- }
-
- @Override
- protected void setHomeAsUp(boolean homeAsUp) {
- if (mWindowDecorActionBar != null) {
- Method setHomeAsUp = getMethod(mWindowActionBarClass,
- "setDefaultDisplayHomeAsUpEnabled", boolean.class);
- invoke(setHomeAsUp, mWindowDecorActionBar, homeAsUp);
- }
- }
-
- @Override
- public void createMenuPopup() {
- // it's hard to add menus to appcompat's actionbar, since it'll use a lot of reflection.
- // so we skip it for now.
- }
-
- @Nullable
- private static Method getMethod(Class<?> owner, String name, Class<?>... parameterTypes) {
- try {
- return owner == null ? null : owner.getMethod(name, parameterTypes);
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- @Nullable
- private static Object invoke(Method method, Object owner, Object... args) {
- try {
- return method == null ? null : method.invoke(owner, args);
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- // TODO: this is duplicated from FrameworkActionBarWrapper$WindowActionBarWrapper
- @Nullable
- private Drawable getDrawable(@NonNull String name, boolean isFramework) {
- RenderResources res = mBridgeContext.getRenderResources();
- ResourceValue value = res.findResValue(name, isFramework);
- value = res.resolveResValue(value);
- if (value != null) {
- return ResourceHelper.getDrawable(value, mBridgeContext);
- }
- return null;
- }
-}
+++ /dev/null
-/*
- * 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.bars;
-
-import com.android.ide.common.rendering.api.ActionBarCallback;
-import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.SessionParams;
-import com.android.layoutlib.bridge.MockView;
-import com.android.layoutlib.bridge.android.BridgeContext;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.FrameLayout;
-import android.widget.RelativeLayout;
-
-/**
- * An abstraction over two implementations of the ActionBar - framework and appcompat.
- */
-public abstract class BridgeActionBar {
- // Store a reference to the context so that we don't have to cast it repeatedly.
- @NonNull protected final BridgeContext mBridgeContext;
- @NonNull protected final SessionParams mParams;
- // A Layout that contains the inflated action bar. The menu popup is added to this layout.
- @Nullable protected final ViewGroup mEnclosingLayout;
-
- private final View mDecorContent;
- private final ActionBarCallback mCallback;
-
- @SuppressWarnings("NullableProblems") // Should be initialized by subclasses.
- @NonNull private FrameLayout mContentRoot;
-
- public BridgeActionBar(@NonNull BridgeContext context, @NonNull SessionParams params) {
- mBridgeContext = context;
- mParams = params;
- mCallback = params.getLayoutlibCallback().getActionBarCallback();
- ResourceValue layoutName = getLayoutResource(context);
-
- int layoutId = 0;
- if (layoutName == null) {
- assert false : "Unable to find the layout for Action Bar.";
- }
- else {
- if (layoutName.isFramework()) {
- layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(),
- layoutName.getName(), 0);
- } else {
- layoutId = context.getProjectResourceValue(layoutName.getResourceType(),
- layoutName.getName(), 0);
-
- }
- }
- if (layoutId == 0) {
- assert false : String.format("Unable to resolve attribute \"%1$s\" of type \"%2$s\"",
- layoutName.getName(), layoutName.getResourceType());
- mDecorContent = new MockView(context);
- mEnclosingLayout = null;
- }
- else {
- if (mCallback.isOverflowPopupNeeded()) {
- // Create a RelativeLayout around the action bar, to which the overflow popup may be
- // added.
- mEnclosingLayout = new RelativeLayout(mBridgeContext);
- setMatchParent(mEnclosingLayout);
- } else {
- mEnclosingLayout = null;
- }
-
- // Inflate action bar layout.
- mDecorContent = getInflater(context).inflate(layoutId, mEnclosingLayout,
- mEnclosingLayout != null);
- }
- }
-
- /**
- * Returns the Layout Resource that should be used to inflate the action bar. This layout
- * should cover the complete screen, and have a FrameLayout included, where the content will
- * be inflated.
- */
- protected abstract ResourceValue getLayoutResource(BridgeContext context);
-
- protected LayoutInflater getInflater(BridgeContext context) {
- return LayoutInflater.from(context);
- }
-
- protected void setContentRoot(@NonNull FrameLayout contentRoot) {
- mContentRoot = contentRoot;
- }
-
- @NonNull
- public FrameLayout getContentRoot() {
- return mContentRoot;
- }
-
- /**
- * Returns the view inflated. This should contain both the ActionBar and the app content in it.
- */
- protected View getDecorContent() {
- return mDecorContent;
- }
-
- /** Setup things like the title, subtitle, icon etc. */
- protected void setupActionBar() {
- setTitle();
- setSutTitle();
- setIcon();
- setHomeAsUp(mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP);
- }
-
- protected abstract void setTitle(CharSequence title);
- protected abstract void setSubtitle(CharSequence subtitle);
- protected abstract void setIcon(String icon);
- protected abstract void setHomeAsUp(boolean homeAsUp);
-
- private void setTitle() {
- RenderResources res = mBridgeContext.getRenderResources();
-
- String title = mParams.getAppLabel();
- ResourceValue titleValue = res.findResValue(title, false);
- if (titleValue != null && titleValue.getValue() != null) {
- setTitle(titleValue.getValue());
- } else {
- setTitle(title);
- }
- }
-
- private void setSutTitle() {
- String subTitle = mCallback.getSubTitle();
- if (subTitle != null) {
- setSubtitle(subTitle);
- }
- }
-
- private void setIcon() {
- String appIcon = mParams.getAppIcon();
- if (appIcon != null) {
- setIcon(appIcon);
- }
- }
-
- public abstract void createMenuPopup();
-
- /**
- * The root view that represents the action bar and possibly the content included in it.
- */
- public View getRootView() {
- return mEnclosingLayout == null ? mDecorContent : mEnclosingLayout;
- }
-
- public ActionBarCallback getCallBack() {
- return mCallback;
- }
-
- protected static void setMatchParent(View view) {
- view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
- LayoutParams.MATCH_PARENT));
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.bars;
-
-import android.os._Original_Build.VERSION_CODES;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import static android.os._Original_Build.VERSION_CODES.*;
-
-/**
- * Various helper methods to simulate older versions of platform.
- */
-public class Config {
-
- // each of these resource dirs must end in '/'
- private static final String GINGERBREAD_DIR = "/bars/v9/";
- private static final String JELLYBEAN_DIR = "/bars/v18/";
- private static final String KITKAT_DIR = "/bars/v19/";
- private static final String DEFAULT_RESOURCE_DIR = "/bars/v21/";
-
- private static final List<String> sDefaultResourceDir =
- Collections.singletonList(DEFAULT_RESOURCE_DIR);
-
- private static final int WHITE = 0xFFFFFFFF;
- private static final int BLACK = 0xFF000000;
-
- public static boolean showOnScreenNavBar(int platformVersion) {
- return isGreaterOrEqual(platformVersion, ICE_CREAM_SANDWICH);
- }
-
- public static int getStatusBarColor(int platformVersion) {
- // return white for froyo and earlier; black otherwise.
- return isGreaterOrEqual(platformVersion, GINGERBREAD) ? BLACK : WHITE;
- }
-
- public static List<String> getResourceDirs(int platformVersion) {
- // Special case the most used scenario.
- if (platformVersion == 0) {
- return sDefaultResourceDir;
- }
- List<String> list = new ArrayList<String>(4);
- // Gingerbread - uses custom battery and wifi icons.
- if (platformVersion <= GINGERBREAD) {
- list.add(GINGERBREAD_DIR);
- }
- // ICS - JellyBean uses custom battery, wifi.
- if (platformVersion <= JELLY_BEAN_MR2) {
- list.add(JELLYBEAN_DIR);
- }
- // KitKat - uses custom wifi and nav icons.
- if (platformVersion <= KITKAT) {
- list.add(KITKAT_DIR);
- }
- list.add(DEFAULT_RESOURCE_DIR);
-
- return Collections.unmodifiableList(list);
- }
-
- public static String getTime(int platformVersion) {
- if (isGreaterOrEqual(platformVersion, N)) {
- return "7:00";
- }
- if (platformVersion < GINGERBREAD) {
- return "2:20";
- }
- if (platformVersion < ICE_CREAM_SANDWICH) {
- return "2:30";
- }
- if (platformVersion < JELLY_BEAN) {
- return "4:00";
- }
- if (platformVersion < KITKAT) {
- return "4:30";
- }
- if (platformVersion < LOLLIPOP) {
- return "4:40";
- }
- if (platformVersion < LOLLIPOP_MR1) {
- return "5:00";
- }
- if (platformVersion < M) {
- return "5:10";
- }
- if (platformVersion < N) {
- return "6:00";
- }
- // Should never happen.
- return "4:04";
- }
-
- public static int getTimeColor(int platformVersion) {
- if (isGreaterOrEqual(platformVersion, KITKAT) ||
- platformVersion > FROYO && platformVersion < HONEYCOMB) {
- // Gingerbread and KitKat onwards.
- return WHITE;
- }
- // Black for froyo.
- if (platformVersion < GINGERBREAD) {
- return BLACK;
- } else if (platformVersion < KITKAT) {
- // Honeycomb to JB-mr2: Holo blue light.
- return 0xff33b5e5;
- }
- // Should never happen.
- return WHITE;
- }
-
- public static String getWifiIconType(int platformVersion) {
- return isGreaterOrEqual(platformVersion, LOLLIPOP) ? "xml" : "png";
- }
-
- /**
- * Compare simulated platform version and code from {@link VERSION_CODES} to check if
- * the simulated platform is greater than or equal to the version code.
- */
- public static boolean isGreaterOrEqual(int platformVersion, int code) {
- // simulated platform version = 0 means that we use the latest.
- return platformVersion == 0 || platformVersion >= code;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.bars;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.StyleResourceValue;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.impl.ParserFactory;
-import com.android.layoutlib.bridge.impl.ResourceHelper;
-import com.android.resources.Density;
-import com.android.resources.LayoutDirection;
-import com.android.resources.ResourceType;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.NonNull;
-import android.content.res.ColorStateList;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap_Delegate;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import static android.os._Original_Build.VERSION_CODES.LOLLIPOP;
-
-/**
- * Base "bar" class for the window decor around the the edited layout.
- * This is basically an horizontal layout that loads a given layout on creation (it is read
- * through {@link Class#getResourceAsStream(String)}).
- *
- * The given layout should be a merge layout so that all the children belong to this class directly.
- *
- * It also provides a few utility methods to configure the content of the layout.
- */
-abstract class CustomBar extends LinearLayout {
-
-
- private final int mSimulatedPlatformVersion;
-
- protected abstract TextView getStyleableTextView();
-
- protected CustomBar(BridgeContext context, int orientation, String layoutPath,
- String name, int simulatedPlatformVersion) {
- super(context);
- mSimulatedPlatformVersion = simulatedPlatformVersion;
- setOrientation(orientation);
- if (orientation == LinearLayout.HORIZONTAL) {
- setGravity(Gravity.CENTER_VERTICAL);
- } else {
- setGravity(Gravity.CENTER_HORIZONTAL);
- }
-
- LayoutInflater inflater = LayoutInflater.from(mContext);
-
- XmlPullParser parser;
- try {
- parser = ParserFactory.create(getClass().getResourceAsStream(layoutPath), name);
-
- BridgeXmlBlockParser bridgeParser = new BridgeXmlBlockParser(parser, context, false);
-
- try {
- inflater.inflate(bridgeParser, this, true);
- } finally {
- bridgeParser.ensurePopped();
- }
- } catch (XmlPullParserException e) {
- // Should not happen as the resource is bundled with the jar, and ParserFactory should
- // have been initialized.
- assert false;
- }
- }
-
- protected void loadIcon(int index, String iconName, Density density) {
- loadIcon(index, iconName, density, false);
- }
-
- protected void loadIcon(int index, String iconName, Density density, boolean isRtl) {
- View child = getChildAt(index);
- if (child instanceof ImageView) {
- ImageView imageView = (ImageView) child;
-
- LayoutDirection dir = isRtl ? LayoutDirection.RTL : null;
- IconLoader iconLoader = new IconLoader(iconName, density, mSimulatedPlatformVersion,
- dir);
- InputStream stream = iconLoader.getIcon();
-
- if (stream != null) {
- density = iconLoader.getDensity();
- String path = iconLoader.getPath();
- // look for a cached bitmap
- Bitmap bitmap = Bridge.getCachedBitmap(path, Boolean.TRUE /*isFramework*/);
- if (bitmap == null) {
- try {
- bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density);
- Bridge.setCachedBitmap(path, bitmap, Boolean.TRUE /*isFramework*/);
- } catch (IOException e) {
- return;
- }
- }
-
- if (bitmap != null) {
- BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(),
- bitmap);
- imageView.setImageDrawable(drawable);
- }
- }
- }
- }
-
- protected TextView setText(int index, String string, boolean reference) {
- View child = getChildAt(index);
- if (child instanceof TextView) {
- TextView textView = (TextView) child;
- setText(textView, string, reference);
- return textView;
- }
-
- return null;
- }
-
- private void setText(TextView textView, String string, boolean reference) {
- if (reference) {
- ResourceValue value = getResourceValue(string);
- if (value != null) {
- string = value.getValue();
- }
- }
- textView.setText(string);
- }
-
- protected void setStyle(String themeEntryName) {
-
- BridgeContext bridgeContext = getContext();
- RenderResources res = bridgeContext.getRenderResources();
-
- ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/);
- value = res.resolveResValue(value);
-
- if (!(value instanceof StyleResourceValue)) {
- return;
- }
-
- StyleResourceValue style = (StyleResourceValue) value;
-
- // get the background
- ResourceValue backgroundValue = res.findItemInStyle(style, "background",
- true /*isFrameworkAttr*/);
- backgroundValue = res.resolveResValue(backgroundValue);
- if (backgroundValue != null) {
- Drawable d = ResourceHelper.getDrawable(backgroundValue, bridgeContext);
- if (d != null) {
- setBackground(d);
- }
- }
-
- TextView textView = getStyleableTextView();
- if (textView != null) {
- // get the text style
- ResourceValue textStyleValue = res.findItemInStyle(style, "titleTextStyle",
- true /*isFrameworkAttr*/);
- textStyleValue = res.resolveResValue(textStyleValue);
- if (textStyleValue instanceof StyleResourceValue) {
- StyleResourceValue textStyle = (StyleResourceValue) textStyleValue;
-
- ResourceValue textSize = res.findItemInStyle(textStyle, "textSize",
- true /*isFrameworkAttr*/);
- textSize = res.resolveResValue(textSize);
-
- if (textSize != null) {
- TypedValue out = new TypedValue();
- if (ResourceHelper.parseFloatAttribute("textSize", textSize.getValue(), out,
- true /*requireUnit*/)) {
- textView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- out.getDimension(bridgeContext.getResources().getDisplayMetrics()));
- }
- }
-
-
- ResourceValue textColor = res.findItemInStyle(textStyle, "textColor",
- true);
- textColor = res.resolveResValue(textColor);
- if (textColor != null) {
- ColorStateList stateList = ResourceHelper.getColorStateList(
- textColor, bridgeContext);
- if (stateList != null) {
- textView.setTextColor(stateList);
- }
- }
- }
- }
- }
-
- @Override
- public BridgeContext getContext() {
- return (BridgeContext) mContext;
- }
-
- /**
- * Find the background color for this bar from the theme attributes. Only relevant to StatusBar
- * and NavigationBar.
- * <p/>
- * 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.
- */
- protected int getBarColor(@NonNull String colorAttrName, @NonNull String translucentAttrName) {
- if (!Config.isGreaterOrEqual(mSimulatedPlatformVersion, LOLLIPOP)) {
- return 0;
- }
- RenderResources renderResources = getContext().getRenderResources();
- // First check if the bar is translucent.
- boolean translucent = ResourceHelper.getBooleanThemeValue(renderResources,
- translucentAttrName, true, false);
- if (translucent) {
- // Keep in sync with R.color.system_bar_background_semi_transparent from system ui.
- return 0x66000000; // 40% black.
- }
- boolean transparent = ResourceHelper.getBooleanThemeValue(renderResources,
- "windowDrawsSystemBarBackgrounds", true, false);
- if (transparent) {
- return getColor(renderResources, colorAttrName);
- }
- return 0;
- }
-
- 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
- resource = renderResources.resolveResValue(resource);
- if (resource != null) {
- ResourceType type = resource.getResourceType();
- if (type == null || type == ResourceType.COLOR) {
- // if no type is specified, the value may have been specified directly in the style
- // file, rather than referencing a color resource value.
- try {
- return ResourceHelper.getColor(resource.getValue());
- } catch (NumberFormatException e) {
- // Conversion failed.
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
- "Theme attribute @android:" + attr +
- " does not reference a color, instead is '" +
- resource.getValue() + "'.", resource);
- }
- }
- }
- return 0;
- }
-
- private ResourceValue getResourceValue(String reference) {
- RenderResources res = getContext().getRenderResources();
-
- // find the resource
- ResourceValue value = res.findResValue(reference, false);
-
- // resolve it if needed
- return res.resolveResValue(value);
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.bars;
-
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.SessionParams;
-import com.android.internal.R;
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuItemImpl;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.ResourceHelper;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.InflateException;
-import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.ActionMenuPresenter;
-import android.widget.FrameLayout;
-import android.widget.ListAdapter;
-import android.widget.ListView;
-import android.widget.RelativeLayout;
-
-import java.util.ArrayList;
-
-/**
- * Creates the ActionBar as done by the framework.
- */
-public class FrameworkActionBar extends BridgeActionBar {
-
- private static final String LAYOUT_ATTR_NAME = "windowActionBarFullscreenDecorLayout";
-
- // The Action Bar
- @NonNull private FrameworkActionBarWrapper mActionBar;
-
- // A fake parent for measuring views.
- @Nullable private ViewGroup mMeasureParent;
-
- /**
- * Inflate the action bar and attach it to {@code parentView}
- */
- public FrameworkActionBar(@NonNull BridgeContext context, @NonNull SessionParams params) {
- super(context, params);
-
- View decorContent = getDecorContent();
-
- mActionBar = FrameworkActionBarWrapper.getActionBarWrapper(context, getCallBack(),
- decorContent);
-
- FrameLayout contentRoot = (FrameLayout) decorContent.findViewById(android.R.id.content);
-
- // If something went wrong and we were not able to initialize the content root,
- // just add a frame layout inside this and return.
- if (contentRoot == null) {
- contentRoot = new FrameLayout(context);
- setMatchParent(contentRoot);
- if (mEnclosingLayout != null) {
- mEnclosingLayout.addView(contentRoot);
- }
- setContentRoot(contentRoot);
- } else {
- setContentRoot(contentRoot);
- setupActionBar();
- mActionBar.inflateMenus();
- }
- }
-
- @Override
- protected ResourceValue getLayoutResource(BridgeContext context) {
- ResourceValue layoutName =
- context.getRenderResources().findItemInTheme(LAYOUT_ATTR_NAME, true);
- if (layoutName != null) {
- // We may need to resolve the reference obtained.
- layoutName = context.getRenderResources().findResValue(layoutName.getValue(),
- layoutName.isFramework());
- }
- if (layoutName == null) {
- throw new InflateException("Unable to find action bar layout (" + LAYOUT_ATTR_NAME
- + ") in the current theme.");
- }
- return layoutName;
- }
-
- @Override
- protected void setupActionBar() {
- super.setupActionBar();
- mActionBar.setupActionBar();
- }
-
- @Override
- protected void setHomeAsUp(boolean homeAsUp) {
- mActionBar.setHomeAsUp(homeAsUp);
- }
-
- @Override
- protected void setTitle(CharSequence title) {
- mActionBar.setTitle(title);
- }
-
- @Override
- protected void setSubtitle(CharSequence subtitle) {
- mActionBar.setSubTitle(subtitle);
- }
-
- @Override
- protected void setIcon(String icon) {
- mActionBar.setIcon(icon);
- }
-
- /**
- * Creates a Popup and adds it to the content frame. It also adds another {@link FrameLayout} to
- * the content frame which shall serve as the new content root.
- */
- @Override
- public void createMenuPopup() {
- if (!isOverflowPopupNeeded()) {
- return;
- }
-
- DisplayMetrics metrics = mBridgeContext.getMetrics();
- MenuBuilder menu = mActionBar.getMenuBuilder();
- OverflowMenuAdapter adapter = new OverflowMenuAdapter(menu, mActionBar.getPopupContext());
-
- ListView listView = new ListView(mActionBar.getPopupContext(), null,
- R.attr.dropDownListViewStyle);
- RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
- measureContentWidth(adapter), LayoutParams.WRAP_CONTENT);
- layoutParams.addRule(RelativeLayout.ALIGN_PARENT_END);
- if (mActionBar.isSplit()) {
- layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
- layoutParams.bottomMargin = getActionBarHeight() + mActionBar.getMenuPopupMargin();
- } else {
- layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
- layoutParams.topMargin = getActionBarHeight() + mActionBar.getMenuPopupMargin();
- }
- layoutParams.setMarginEnd(getPixelValue("5dp", metrics));
- listView.setLayoutParams(layoutParams);
- listView.setAdapter(adapter);
- final TypedArray a = mActionBar.getPopupContext().obtainStyledAttributes(null,
- R.styleable.PopupWindow, R.attr.popupMenuStyle, 0);
- listView.setBackground(a.getDrawable(R.styleable.PopupWindow_popupBackground));
- listView.setDivider(a.getDrawable(R.attr.actionBarDivider));
- a.recycle();
- listView.setElevation(mActionBar.getMenuPopupElevation());
- assert mEnclosingLayout != null : "Unable to find view to attach ActionMenuPopup.";
- mEnclosingLayout.addView(listView);
- }
-
- private boolean isOverflowPopupNeeded() {
- boolean needed = mActionBar.isOverflowPopupNeeded();
- if (!needed) {
- return false;
- }
- // Copied from android.widget.ActionMenuPresenter.updateMenuView()
- ArrayList<MenuItemImpl> menus = mActionBar.getMenuBuilder().getNonActionItems();
- ActionMenuPresenter presenter = mActionBar.getActionMenuPresenter();
- if (presenter == null) {
- assert false : "Failed to create a Presenter for Action Bar Menus.";
- return false;
- }
- if (presenter.isOverflowReserved() &&
- menus != null) {
- final int count = menus.size();
- if (count == 1) {
- needed = !menus.get(0).isActionViewExpanded();
- } else {
- needed = count > 0;
- }
- }
- return needed;
- }
-
- // Copied from com.android.internal.view.menu.MenuPopHelper.measureContentWidth()
- private int measureContentWidth(@NonNull ListAdapter adapter) {
- // Menus don't tend to be long, so this is more sane than it looks.
- int maxWidth = 0;
- View itemView = null;
- int itemType = 0;
-
- Context context = mActionBar.getPopupContext();
- final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- final int count = adapter.getCount();
- for (int i = 0; i < count; i++) {
- final int positionType = adapter.getItemViewType(i);
- if (positionType != itemType) {
- itemType = positionType;
- itemView = null;
- }
-
- if (mMeasureParent == null) {
- mMeasureParent = new FrameLayout(context);
- }
-
- itemView = adapter.getView(i, itemView, mMeasureParent);
- itemView.measure(widthMeasureSpec, heightMeasureSpec);
-
- final int itemWidth = itemView.getMeasuredWidth();
- int popupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
- context.getResources().getDimensionPixelSize(R.dimen.config_prefDialogWidth));
- if (itemWidth >= popupMaxWidth) {
- return popupMaxWidth;
- } else if (itemWidth > maxWidth) {
- maxWidth = itemWidth;
- }
- }
-
- return maxWidth;
- }
-
- static int getPixelValue(@NonNull String value, @NonNull DisplayMetrics metrics) {
- TypedValue typedValue = ResourceHelper.getValue(null, value, false /*requireUnit*/);
- return (int) typedValue.getDimension(metrics);
- }
-
- // TODO: This is duplicated from RenderSessionImpl.
- private int getActionBarHeight() {
- RenderResources resources = mBridgeContext.getRenderResources();
- DisplayMetrics metrics = mBridgeContext.getMetrics();
- ResourceValue value = resources.findItemInTheme("actionBarSize", true);
-
- // resolve it
- value = resources.resolveResValue(value);
-
- if (value != null) {
- // get the numerical value, if available
- TypedValue typedValue = ResourceHelper.getValue("actionBarSize", value.getValue(),
- true);
- if (typedValue != null) {
- // compute the pixel value based on the display metrics
- return (int) typedValue.getDimension(metrics);
-
- }
- }
- return 0;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.bars;
-
-import com.android.ide.common.rendering.api.ActionBarCallback;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.internal.R;
-import com.android.internal.app.ToolbarActionBar;
-import com.android.internal.app.WindowDecorActionBar;
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.widget.ActionBarAccessor;
-import com.android.internal.widget.ActionBarView;
-import com.android.internal.widget.DecorToolbar;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.ResourceHelper;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActionBar;
-import android.app.ActionBar.Tab;
-import android.app.ActionBar.TabListener;
-import android.app.FragmentTransaction;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-import android.view.MenuInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowCallback;
-import android.widget.ActionMenuPresenter;
-import android.widget.ActionMenuView;
-import android.widget.Toolbar;
-import android.widget.Toolbar_Accessor;
-
-import static com.android.SdkConstants.ANDROID_NS_NAME_PREFIX;
-import static com.android.resources.ResourceType.MENU;
-
-/**
- * A common API to access {@link ToolbarActionBar} and {@link WindowDecorActionBar}.
- */
-public abstract class FrameworkActionBarWrapper {
-
- @NonNull protected ActionBar mActionBar;
- @NonNull protected ActionBarCallback mCallback;
- @NonNull protected BridgeContext mContext;
-
- /**
- * Returns a wrapper around different implementations of the Action Bar to provide a common API.
- *
- * @param decorContent the top level view returned by inflating
- * ?attr/windowActionBarFullscreenDecorLayout
- */
- @NonNull
- public static FrameworkActionBarWrapper getActionBarWrapper(@NonNull BridgeContext context,
- @NonNull ActionBarCallback callback, @NonNull View decorContent) {
- View view = decorContent.findViewById(R.id.action_bar);
- if (view instanceof Toolbar) {
- return new ToolbarWrapper(context, callback, (Toolbar) view);
- } else if (view instanceof ActionBarView) {
- return new WindowActionBarWrapper(context, callback, decorContent,
- (ActionBarView) view);
- } else {
- throw new IllegalStateException("Can't make an action bar out of " +
- view.getClass().getSimpleName());
- }
- }
-
- FrameworkActionBarWrapper(@NonNull BridgeContext context, @NonNull ActionBarCallback callback,
- @NonNull ActionBar actionBar) {
- mActionBar = actionBar;
- mCallback = callback;
- mContext = context;
- }
-
- /** A call to setup any custom properties. */
- protected void setupActionBar() {
- // Nothing to do here.
- }
-
- public void setTitle(CharSequence title) {
- mActionBar.setTitle(title);
- }
-
- public void setSubTitle(CharSequence subTitle) {
- if (subTitle != null) {
- mActionBar.setSubtitle(subTitle);
- }
- }
-
- public void setHomeAsUp(boolean homeAsUp) {
- mActionBar.setDisplayHomeAsUpEnabled(homeAsUp);
- }
-
- public void setIcon(String icon) {
- // Nothing to do.
- }
-
- protected boolean isSplit() {
- return getDecorToolbar().isSplit();
- }
-
- protected boolean isOverflowPopupNeeded() {
- return mCallback.isOverflowPopupNeeded();
- }
-
- /**
- * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
- * adds them to the action bar.
- */
- protected void inflateMenus() {
- MenuInflater inflater = new MenuInflater(getActionMenuContext());
- MenuBuilder menuBuilder = getMenuBuilder();
- for (String name : mCallback.getMenuIdNames()) {
- int id;
- if (name.startsWith(ANDROID_NS_NAME_PREFIX)) {
- // Framework menu.
- name = name.substring(ANDROID_NS_NAME_PREFIX.length());
- id = mContext.getFrameworkResourceValue(MENU, name, -1);
- } else {
- // Project menu.
- id = mContext.getProjectResourceValue(MENU, name, -1);
- }
- if (id > -1) {
- inflater.inflate(id, menuBuilder);
- }
- }
- }
-
- /**
- * The context used for the ActionBar and the menus in the ActionBarView.
- */
- @NonNull
- protected Context getActionMenuContext() {
- return mActionBar.getThemedContext();
- }
-
- /**
- * The context used to inflate the popup menu.
- */
- @NonNull
- abstract Context getPopupContext();
-
- /**
- * The Menu in which to inflate the user's menus.
- */
- @NonNull
- abstract MenuBuilder getMenuBuilder();
-
- @Nullable
- abstract ActionMenuPresenter getActionMenuPresenter();
-
- /**
- * Framework's wrapper over two ActionBar implementations.
- */
- @NonNull
- abstract DecorToolbar getDecorToolbar();
-
- abstract int getMenuPopupElevation();
-
- /**
- * Margin between the menu popup and the action bar.
- */
- abstract int getMenuPopupMargin();
-
- // ---- The implementations ----
-
- /**
- * Material theme uses {@link Toolbar} as the action bar. This wrapper provides access to
- * Toolbar using a common API.
- */
- private static class ToolbarWrapper extends FrameworkActionBarWrapper {
-
- @NonNull
- private final Toolbar mToolbar; // This is the view.
-
- ToolbarWrapper(@NonNull BridgeContext context, @NonNull ActionBarCallback callback,
- @NonNull Toolbar toolbar) {
- super(context, callback, new ToolbarActionBar(toolbar, "", new WindowCallback()));
- mToolbar = toolbar;
- }
-
- @Override
- protected void inflateMenus() {
- super.inflateMenus();
- // Inflating the menus isn't enough. ActionMenuPresenter needs to be initialized too.
- MenuBuilder menu = getMenuBuilder();
- DecorToolbar decorToolbar = getDecorToolbar();
- // Setting a menu different from the above initializes the presenter.
- decorToolbar.setMenu(new MenuBuilder(getActionMenuContext()), null);
- // ActionMenuView needs to be recreated to be able to set the menu back.
- ActionMenuPresenter presenter = getActionMenuPresenter();
- if (presenter != null) {
- presenter.setMenuView(new ActionMenuView(getPopupContext()));
- }
- decorToolbar.setMenu(menu, null);
- }
-
- @NonNull
- @Override
- Context getPopupContext() {
- return Toolbar_Accessor.getPopupContext(mToolbar);
- }
-
- @NonNull
- @Override
- MenuBuilder getMenuBuilder() {
- return (MenuBuilder) mToolbar.getMenu();
- }
-
- @Nullable
- @Override
- ActionMenuPresenter getActionMenuPresenter() {
- return Toolbar_Accessor.getActionMenuPresenter(mToolbar);
- }
-
- @NonNull
- @Override
- DecorToolbar getDecorToolbar() {
- return mToolbar.getWrapper();
- }
-
- @Override
- int getMenuPopupElevation() {
- return 10;
- }
-
- @Override
- int getMenuPopupMargin() {
- return 0;
- }
- }
-
- /**
- * Holo theme uses {@link WindowDecorActionBar} as the action bar. This wrapper provides
- * access to it using a common API.
- */
- private static class WindowActionBarWrapper extends FrameworkActionBarWrapper {
-
- @NonNull private final WindowDecorActionBar mActionBar;
- @NonNull private final ActionBarView mActionBarView;
- @NonNull private final View mDecorContentRoot;
- private MenuBuilder mMenuBuilder;
-
- public WindowActionBarWrapper(@NonNull BridgeContext context,
- @NonNull ActionBarCallback callback, @NonNull View decorContentRoot,
- @NonNull ActionBarView actionBarView) {
- super(context, callback, new WindowDecorActionBar(decorContentRoot));
- mActionBarView = actionBarView;
- mActionBar = (WindowDecorActionBar) super.mActionBar;
- mDecorContentRoot = decorContentRoot;
- }
-
- @Override
- protected void setupActionBar() {
-
- // Set the navigation mode.
- int navMode = mCallback.getNavigationMode();
- mActionBar.setNavigationMode(navMode);
- //noinspection deprecation
- if (navMode == ActionBar.NAVIGATION_MODE_TABS) {
- setupTabs(3);
- }
-
- // Set action bar to be split, if needed.
- ViewGroup splitView = (ViewGroup) mDecorContentRoot.findViewById(R.id.split_action_bar);
- if (splitView != null) {
- mActionBarView.setSplitView(splitView);
- Resources res = mContext.getResources();
- boolean split = res.getBoolean(R.bool.split_action_bar_is_narrow)
- && mCallback.getSplitActionBarWhenNarrow();
- mActionBarView.setSplitToolbar(split);
- }
- }
-
- @Override
- public void setIcon(String icon) {
- // Set the icon only if the action bar doesn't specify an icon.
- if (!mActionBar.hasIcon() && icon != null) {
- Drawable iconDrawable = getDrawable(icon, false);
- if (iconDrawable != null) {
- mActionBar.setIcon(iconDrawable);
- }
- }
- }
-
- @Override
- protected void inflateMenus() {
- super.inflateMenus();
- // The super implementation doesn't set the menu on the view. Set it here.
- mActionBarView.setMenu(getMenuBuilder(), null);
- }
-
- @NonNull
- @Override
- Context getPopupContext() {
- return getActionMenuContext();
- }
-
- @NonNull
- @Override
- MenuBuilder getMenuBuilder() {
- if (mMenuBuilder == null) {
- mMenuBuilder = new MenuBuilder(getActionMenuContext());
- }
- return mMenuBuilder;
- }
-
- @Nullable
- @Override
- ActionMenuPresenter getActionMenuPresenter() {
- return ActionBarAccessor.getActionMenuPresenter(mActionBarView);
- }
-
- @NonNull
- @Override
- ActionBarView getDecorToolbar() {
- return mActionBarView;
- }
-
- @Override
- int getMenuPopupElevation() {
- return 0;
- }
-
- @Override
- int getMenuPopupMargin() {
- return -FrameworkActionBar.getPixelValue("10dp", mContext.getMetrics());
- }
-
- // TODO: Use an adapter, like List View to set up tabs.
- @SuppressWarnings("deprecation") // For Tab
- private void setupTabs(int num) {
- for (int i = 1; i <= num; i++) {
- Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
- @Override
- public void onTabUnselected(Tab t, FragmentTransaction ft) {
- // pass
- }
- @Override
- public void onTabSelected(Tab t, FragmentTransaction ft) {
- // pass
- }
- @Override
- public void onTabReselected(Tab t, FragmentTransaction ft) {
- // pass
- }
- });
- mActionBar.addTab(tab);
- }
- }
-
- @Nullable
- private Drawable getDrawable(@NonNull String name, boolean isFramework) {
- RenderResources res = mContext.getRenderResources();
- ResourceValue value = res.findResValue(name, isFramework);
- value = res.resolveResValue(value);
- if (value != null) {
- return ResourceHelper.getDrawable(value, mContext);
- }
- return null;
- }
-
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.bars;
-
-import com.android.resources.Density;
-import com.android.resources.LayoutDirection;
-
-import java.io.InputStream;
-
-public class IconLoader {
-
- private final String mIconName;
- private final Density mDesiredDensity;
- private final int mPlatformVersion;
- private final LayoutDirection mDirection;
-
- private Density mCurrentDensity;
- private StringBuilder mCurrentPath;
-
- IconLoader(String iconName, Density density, int platformVersion, LayoutDirection direction) {
- mIconName = iconName;
- mDesiredDensity = density;
- mPlatformVersion = platformVersion;
- mDirection = direction;
- // An upper bound on the length of the path for the icon: /bars/v21/ldrtl-xxxhdpi/
- final int iconPathLength = 24;
- mCurrentPath = new StringBuilder(iconPathLength + iconName.length());
- }
-
- public InputStream getIcon() {
- for (String resourceDir : Config.getResourceDirs(mPlatformVersion)) {
- mCurrentDensity = null;
- InputStream stream = getIcon(resourceDir);
- if (stream != null) {
- return stream;
- }
- }
- return null;
- }
-
- /**
- * Should only be called after {@link #getIcon()}. Returns the density of the icon, if found by
- * {@code getIcon()}. If no icon was found, then the return value has no meaning.
- */
- public Density getDensity() {
- return mCurrentDensity;
- }
-
- /**
- * Should only be called after {@link #getIcon()}. Returns the path to the icon, if found by
- * {@code getIcon()}. If no icon was found, then the return value has no meaning.
- */
- public String getPath() {
- return mCurrentPath.toString();
- }
-
- /**
- * Search for icon in the resource directory. This iterates over all densities.
- * If a match is found, mCurrentDensity will be set to the icon's density.
- */
- private InputStream getIcon(String resourceDir) {
- // First check for the desired density.
- InputStream stream = getIcon(resourceDir, mDesiredDensity);
- if (stream != null) {
- mCurrentDensity = mDesiredDensity;
- return stream;
- }
- // Didn't find in the desired density. Search in all.
- for (Density density : Density.values()) {
- if (density == mDesiredDensity) {
- // Skip the desired density since it's already been checked.
- continue;
- }
- stream = getIcon(resourceDir, density);
- if (stream != null) {
- mCurrentDensity = density;
- return stream;
- }
- }
- return null;
- }
-
- /**
- * Returns the icon for given density present in the given resource directory, taking layout
- * direction into consideration.
- */
- private InputStream getIcon(String resourceDir, Density density) {
- mCurrentPath.setLength(0);
- // Currently we don't have any LTR only resources and hence the check is skipped. If they
- // are ever added, change to:
- // if (mDirection == LayoutDirection.RTL || mDirection == LayoutDirection.LTR) {
- if (mDirection == LayoutDirection.RTL) {
- mCurrentPath.append(resourceDir)
- .append(mDirection.getResourceValue())
- .append('-')
- .append(density.getResourceValue())
- .append('/')
- .append(mIconName);
- InputStream stream = getClass().getResourceAsStream(mCurrentPath.toString());
- if (stream != null) {
- return stream;
- }
- mCurrentPath.setLength(0);
- }
- mCurrentPath.append(resourceDir)
- .append(density.getResourceValue())
- .append('/')
- .append(mIconName);
- return getClass().getResourceAsStream(mCurrentPath.toString());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.bars;
-
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.resources.Density;
-
-import android.util.DisplayMetrics;
-import android.view.View;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class NavigationBar extends CustomBar {
-
- /** Navigation bar background color attribute name. */
- private static final String ATTR_COLOR = "navigationBarColor";
- /** Attribute for translucency property. */
- public static final String ATTR_TRANSLUCENT = "windowTranslucentNavigation";
- // These correspond to @dimen/navigation_side_padding in the system ui code.
- private static final int PADDING_WIDTH_DEFAULT = 36;
- private static final int PADDING_WIDTH_SW360 = 40;
- private static final int PADDING_WIDTH_SW400 = 50;
- // These corresponds to @dimen/navigation_key_width in the system ui code.
- private static final int WIDTH_DEFAULT = 36;
- private static final int WIDTH_SW360 = 40;
- private static final int WIDTH_SW600 = 48;
- protected static final String LAYOUT_XML = "/bars/navigation_bar.xml";
- private static final String LAYOUT_600DP_XML = "/bars/navigation_bar600dp.xml";
-
- public NavigationBar(BridgeContext context, Density density, int orientation, boolean isRtl,
- boolean rtlEnabled, int simulatedPlatformVersion) {
- this(context, density, orientation, isRtl, rtlEnabled, simulatedPlatformVersion,
- getShortestWidth(context)>= 600 ? LAYOUT_600DP_XML : LAYOUT_XML);
- }
-
- protected NavigationBar(BridgeContext context, Density density, int orientation, boolean isRtl,
- boolean rtlEnabled, int simulatedPlatformVersion, String layoutPath) {
- super(context, orientation, layoutPath, "navigation_bar.xml", simulatedPlatformVersion);
-
- 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.
- // We do know the order though.
- // 0 is a spacer.
- int back = 1;
- int recent = 5;
- if (orientation == LinearLayout.VERTICAL || (isRtl && !rtlEnabled)) {
- // If RTL is enabled, then layoutlib mirrors the layout for us.
- back = 5;
- recent = 1;
- }
-
- //noinspection SpellCheckingInspection
- loadIcon(back, "ic_sysbar_back.png", density, isRtl);
- //noinspection SpellCheckingInspection
- loadIcon(3, "ic_sysbar_home.png", density, isRtl);
- //noinspection SpellCheckingInspection
- loadIcon(recent, "ic_sysbar_recent.png", density, isRtl);
- setupNavBar(context, orientation);
- }
-
- private void setupNavBar(BridgeContext context, int orientation) {
- float sw = getShortestWidth(context);
- View leftPadding = getChildAt(0);
- View rightPadding = getChildAt(6);
- 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, navButtonWidth);
- }
- if (sw >= 600) {
- setSize(context, getChildAt(2), orientation, 128);
- setSize(context, getChildAt(4), orientation, 128);
- }
- }
-
- private static void setSize(BridgeContext context, View view, int orientation, int size) {
- size *= context.getMetrics().density;
- LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
- if (orientation == HORIZONTAL) {
- layoutParams.width = size;
- } else {
- layoutParams.height = size;
- }
- view.setLayoutParams(layoutParams);
- }
-
- protected int getSidePadding(float sw) {
- if (sw >= 400) {
- return PADDING_WIDTH_SW400;
- }
- if (sw >= 360) {
- return PADDING_WIDTH_SW360;
- }
- return PADDING_WIDTH_DEFAULT;
- }
-
- private static int getWidth(float sw) {
- if (sw >= 600) {
- return WIDTH_SW600;
- }
- if (sw >= 360) {
- return WIDTH_SW360;
- }
- 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;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.bars;
-
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuItemImpl;
-import com.android.internal.view.menu.MenuView;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-
-import java.util.ArrayList;
-
-/**
- * Provides an adapter for Overflow menu popup. This is very similar to
- * {@code MenuPopupHelper.MenuAdapter}
- */
-public class OverflowMenuAdapter extends BaseAdapter {
-
- private final MenuBuilder mMenu;
- private int mExpandedIndex = -1;
- private final Context context;
-
- public OverflowMenuAdapter(MenuBuilder menu, Context context) {
- mMenu = menu;
- findExpandedIndex();
- this.context = context;
- }
-
- @Override
- public int getCount() {
- ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
- if (mExpandedIndex < 0) {
- return items.size();
- }
- return items.size() - 1;
- }
-
- @Override
- public MenuItemImpl getItem(int position) {
- ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
- if (mExpandedIndex >= 0 && position >= mExpandedIndex) {
- position++;
- }
- return items.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- // Since a menu item's ID is optional, we'll use the position as an
- // ID for the item in the AdapterView
- return position;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- LayoutInflater mInflater = LayoutInflater.from(context);
- convertView = mInflater.inflate(com.android.internal.R.layout.popup_menu_item_layout,
- parent, false);
- }
-
- MenuView.ItemView itemView = (MenuView.ItemView) convertView;
- itemView.initialize(getItem(position), 0);
- return convertView;
- }
-
- private void findExpandedIndex() {
- final MenuItemImpl expandedItem = mMenu.getExpandedItem();
- if (expandedItem != null) {
- final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
- final int count = items.size();
- for (int i = 0; i < count; i++) {
- final MenuItemImpl item = items.get(i);
- if (item == expandedItem) {
- mExpandedIndex = i;
- return;
- }
- }
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.bars;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.impl.ParserFactory;
-import com.android.resources.Density;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.view.Gravity;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public class StatusBar extends CustomBar {
-
- private final int mSimulatedPlatformVersion;
- /** Status bar background color attribute name. */
- private static final String ATTR_COLOR = "statusBarColor";
- /** Attribute for translucency property. */
- public static final String ATTR_TRANSLUCENT = "windowTranslucentStatus";
-
- /**
- * Constructor to be used when creating the {@link StatusBar} as a regular control. This
- * is currently used by the theme editor.
- */
- @SuppressWarnings("UnusedParameters")
- public StatusBar(Context context, AttributeSet attrs) {
- this((BridgeContext) context,
- Density.getEnum(((BridgeContext) context).getMetrics().densityDpi),
- ((BridgeContext) context).getConfiguration().getLayoutDirection() ==
- View.LAYOUT_DIRECTION_RTL,
- (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0,
- context.getApplicationInfo().targetSdkVersion);
- }
-
- @SuppressWarnings("UnusedParameters")
- public StatusBar(BridgeContext context, Density density, boolean isRtl, boolean rtlEnabled,
- int simulatedPlatformVersion) {
- // FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar.
- super(context, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml",
- simulatedPlatformVersion);
- mSimulatedPlatformVersion = simulatedPlatformVersion;
-
- // FIXME: use FILL_H?
- setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
-
- 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.
- // We do know the order though.
- // 0 is the spacer
- loadIcon(1, "stat_sys_wifi_signal_4_fully."
- + Config.getWifiIconType(simulatedPlatformVersion), density);
- loadIcon(2, "stat_sys_battery_100.png", density);
- setText(3, Config.getTime(simulatedPlatformVersion), false)
- .setTextColor(Config.getTimeColor(simulatedPlatformVersion));
- }
-
- @Override
- protected void loadIcon(int index, String iconName, Density density) {
- if (!iconName.endsWith(".xml")) {
- super.loadIcon(index, iconName, density);
- return;
- }
- View child = getChildAt(index);
- if (child instanceof ImageView) {
- ImageView imageView = (ImageView) child;
- // The xml is stored only in xhdpi.
- IconLoader iconLoader = new IconLoader(iconName, Density.XHIGH,
- mSimulatedPlatformVersion, null);
- InputStream stream = iconLoader.getIcon();
-
- if (stream != null) {
- try {
- BridgeXmlBlockParser parser = new BridgeXmlBlockParser(
- ParserFactory.create(stream, null), (BridgeContext) mContext, true);
- imageView.setImageDrawable(
- Drawable.createFromXml(mContext.getResources(), parser));
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to draw wifi icon", e,
- null);
- } catch (IOException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, "Unable to draw wifi icon", e,
- null);
- }
- }
- }
- }
-
- @Override
- protected TextView getStyleableTextView() {
- return null;
- }
-}
+++ /dev/null
-/*
- * 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.bars;
-
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.resources.Density;
-
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.LinearLayout;
-
-/**
- * Navigation Bar for the Theme Editor preview.
- *
- * For small bars, it is identical to {@link NavigationBar}.
- * But wide bars from {@link NavigationBar} are too wide for the Theme Editor preview.
- * To solve that problem, {@link ThemePreviewNavigationBar} use the layout for small bars,
- * and have no padding on the sides. That way, they have a similar look as the true ones,
- * and they fit in the Theme Editor preview.
- */
-public class ThemePreviewNavigationBar extends NavigationBar {
- private static final int PADDING_WIDTH_SW600 = 0;
-
- @SuppressWarnings("unused")
- public ThemePreviewNavigationBar(Context context, AttributeSet attrs) {
- super((BridgeContext) context,
- Density.getEnum(((BridgeContext) context).getMetrics().densityDpi),
- LinearLayout.HORIZONTAL, // In this mode, it doesn't need to be render vertically
- ((BridgeContext) context).getConfiguration().getLayoutDirection() ==
- View.LAYOUT_DIRECTION_RTL,
- (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SUPPORTS_RTL) != 0,
- 0, LAYOUT_XML);
- }
-
- @Override
- protected int getSidePadding(float sw) {
- if (sw >= 600) {
- return PADDING_WIDTH_SW600;
- }
- return super.getSidePadding(sw);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.bars;
-
-import com.android.layoutlib.bridge.android.BridgeContext;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class TitleBar extends CustomBar {
-
- private TextView mTextView;
-
- public TitleBar(BridgeContext context, String label, int simulatedPlatformVersion) {
- super(context, LinearLayout.HORIZONTAL, "/bars/title_bar.xml", "title_bar.xml",
- simulatedPlatformVersion);
-
- // Cannot access the inside items through id because no R.id values have been
- // created for them.
- // We do know the order though.
- mTextView = setText(0, label, true);
-
- setStyle("windowTitleBackgroundStyle");
- }
-
- @Override
- protected TextView getStyleableTextView() {
- return mTextView;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl;
-
-import com.android.layoutlib.bridge.util.Debug;
-import com.android.layoutlib.bridge.util.SparseWeakArray;
-
-import android.annotation.Nullable;
-import android.util.SparseArray;
-
-import java.io.PrintStream;
-import java.lang.ref.WeakReference;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Manages native delegates.
- *
- * This is used in conjunction with layoublib_create: certain Android java classes are mere
- * wrappers around a heavily native based implementation, and we need a way to run these classes
- * in our Android Studio rendering framework without bringing all the native code from the Android
- * platform.
- *
- * Thus we instruct layoutlib_create to modify the bytecode of these classes to replace their
- * native methods by "delegate calls".
- *
- * For example, a native method android.graphics.Matrix.init(...) will actually become
- * a call to android.graphics.Matrix_Delegate.init(...).
- *
- * The Android java classes that use native code uses an int (Java side) to reference native
- * objects. This int is generally directly the pointer to the C structure counterpart.
- * Typically a creation method will return such an int, and then this int will be passed later
- * to a Java method to identify the C object to manipulate.
- *
- * Since we cannot use the Java object reference as the int directly, DelegateManager manages the
- * 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(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.
- *
- * The JNI references are counted, so we do the same through a {@link WeakReference}. Because
- * 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(long)} adds and removes
- * the delegate to/from a set. This set holds the reference and prevents the GC from reclaiming
- * the delegate.
- *
- * - {@link #addNewDelegate(Object)} also adds the delegate to a {@link SparseArray} that holds a
- * {@link WeakReference} to the delegate. This allows the delegate to be deleted automatically
- * when nothing references it. This means that any class that holds a delegate (except for the
- * Java main class) must not use the int but the Delegate class instead. The integers must
- * only be used in the API between the main Java class and the Delegate.
- *
- * @param <T> the delegate class to manage
- */
-public final class DelegateManager<T> {
- @SuppressWarnings("FieldCanBeLocal")
- private final Class<T> mClass;
- private static final SparseWeakArray<Object> sDelegates = new SparseWeakArray<>();
- /** Set 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(long)
- */
- private static final Set<Object> sJavaReferences = new HashSet<>();
- private static final AtomicLong sDelegateCounter = new AtomicLong(1);
-
- public DelegateManager(Class<T> theClass) {
- mClass = theClass;
- }
-
- /**
- * Returns the delegate from the given native int.
- * <p>
- * If the int is zero, then this will always return null.
- * <p>
- * If the int is non zero and the delegate is not found, this will throw an assert.
- *
- * @param native_object the native int.
- * @return the delegate or null if not found.
- */
- @Nullable
- public T getDelegate(long native_object) {
- if (native_object > 0) {
- Object delegate;
- synchronized (DelegateManager.class) {
- delegate = sDelegates.get(native_object);
- }
-
- if (Debug.DEBUG) {
- if (delegate == null) {
- System.err.println("Unknown " + mClass.getSimpleName() + " with int " +
- native_object);
- }
- }
-
- assert delegate != null;
- //noinspection unchecked
- return (T)delegate;
- }
- return null;
- }
-
- /**
- * Adds a delegate to the manager and returns the native int used to identify it.
- * @param newDelegate the delegate to add
- * @return a unique native int to identify the delegate
- */
- public long addNewDelegate(T newDelegate) {
- long native_object = sDelegateCounter.getAndIncrement();
- synchronized (DelegateManager.class) {
- sDelegates.put(native_object, newDelegate);
- // Only for development: assert !sJavaReferences.contains(newDelegate);
- sJavaReferences.add(newDelegate);
- }
-
- if (Debug.DEBUG) {
- System.out.println(
- "New " + mClass.getSimpleName() + " " +
- "with int " +
- native_object);
- }
-
- return native_object;
- }
-
- /**
- * Removes the main reference on the given delegate.
- * @param native_object the native integer representing the delegate.
- */
- public void removeJavaReferenceFor(long native_object) {
- synchronized (DelegateManager.class) {
- T delegate = getDelegate(native_object);
-
- if (Debug.DEBUG) {
- System.out.println("Removing main Java ref on " + mClass.getSimpleName() +
- " with int " + native_object);
- }
-
- sJavaReferences.remove(delegate);
- }
- }
-
- public synchronized static void dump(PrintStream out) {
- for (Object reference : sJavaReferences) {
- int idx = sDelegates.indexOfValue(reference);
- out.printf("[%d] %s\n", sDelegates.keyAt(idx), reference.getClass().getSimpleName());
- }
- out.printf("\nTotal number of objects: %d\n", sJavaReferences.size());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-
-import android.graphics.Bitmap_Delegate;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter_Delegate;
-import android.graphics.Paint;
-import android.graphics.Paint_Delegate;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Region;
-import android.graphics.Region_Delegate;
-import android.graphics.Shader_Delegate;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Composite;
-import java.awt.Graphics2D;
-import java.awt.Rectangle;
-import java.awt.RenderingHints;
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Area;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.util.ArrayList;
-
-/**
- * Class representing a graphics context snapshot, as well as a context stack as a linked list.
- * <p>
- * This is based on top of {@link Graphics2D} but can operate independently if none are available
- * yet when setting transforms and clip information.
- * <p>
- * This allows for drawing through {@link #draw(Drawable, Paint_Delegate, boolean, boolean)} and
- * {@link #draw(Drawable)}
- *
- * Handling of layers (created with {@link Canvas#saveLayer(RectF, Paint, int)}) is handled through
- * a list of Graphics2D for each layers. The class actually maintains a list of {@link Layer}
- * for each layer. Doing a save() will duplicate this list so that each graphics2D object
- * ({@link Layer#getGraphics()}) is configured only for the new snapshot.
- */
-public class GcSnapshot {
-
- private final GcSnapshot mPrevious;
- private final int mFlags;
-
- /** list of layers. The first item in the list is always the */
- private final ArrayList<Layer> mLayers = new ArrayList<Layer>();
-
- /** temp transform in case transformation are set before a Graphics2D exists */
- private AffineTransform mTransform = null;
- /** temp clip in case clipping is set before a Graphics2D exists */
- private Area mClip = null;
-
- // local layer data
- /** a local layer created with {@link Canvas#saveLayer(RectF, Paint, int)}.
- * If this is null, this does not mean there's no layer, just that the snapshot is not the
- * one that created the layer.
- * @see #getLayerSnapshot()
- */
- private final Layer mLocalLayer;
- private final Paint_Delegate mLocalLayerPaint;
- private final Rect mLayerBounds;
-
- public interface Drawable {
- void draw(Graphics2D graphics, Paint_Delegate paint);
- }
-
- /**
- * Class containing information about a layer.
- *
- * This contains graphics, bitmap and layer information.
- */
- private static class Layer {
- private final Graphics2D mGraphics;
- private final Bitmap_Delegate mBitmap;
- private final BufferedImage mImage;
- /** the flags that were used to configure the layer. This is never changed, and passed
- * as is when {@link #makeCopy()} is called */
- private final int mFlags;
- /** the original content of the layer when the next object was created. This is not
- * passed in {@link #makeCopy()} and instead is recreated when a new layer is added
- * (depending on its flags) */
- private BufferedImage mOriginalCopy;
-
- /**
- * Creates a layer with a graphics and a bitmap. This is only used to create
- * the base layer.
- *
- * @param graphics the graphics
- * @param bitmap the bitmap
- */
- Layer(Graphics2D graphics, Bitmap_Delegate bitmap) {
- mGraphics = graphics;
- mBitmap = bitmap;
- mImage = mBitmap.getImage();
- mFlags = 0;
- }
-
- /**
- * Creates a layer with a graphics and an image. If the image belongs to a
- * {@link Bitmap_Delegate} (case of the base layer), then
- * {@link Layer#Layer(Graphics2D, Bitmap_Delegate)} should be used.
- *
- * @param graphics the graphics the new graphics for this layer
- * @param image the image the image from which the graphics came
- * @param flags the flags that were used to save this layer
- */
- Layer(Graphics2D graphics, BufferedImage image, int flags) {
- mGraphics = graphics;
- mBitmap = null;
- mImage = image;
- mFlags = flags;
- }
-
- /** The Graphics2D, guaranteed to be non null */
- Graphics2D getGraphics() {
- return mGraphics;
- }
-
- /** The BufferedImage, guaranteed to be non null */
- BufferedImage getImage() {
- return mImage;
- }
-
- /** Returns the layer save flags. This is only valid for additional layers.
- * For the base layer this will always return 0;
- * For a given layer, all further copies of this {@link Layer} object in new snapshots
- * will always return the same value.
- */
- int getFlags() {
- return mFlags;
- }
-
- Layer makeCopy() {
- if (mBitmap != null) {
- return new Layer((Graphics2D) mGraphics.create(), mBitmap);
- }
-
- return new Layer((Graphics2D) mGraphics.create(), mImage, mFlags);
- }
-
- /** sets an optional copy of the original content to be used during restore */
- void setOriginalCopy(BufferedImage image) {
- mOriginalCopy = image;
- }
-
- BufferedImage getOriginalCopy() {
- return mOriginalCopy;
- }
-
- void change() {
- if (mBitmap != null) {
- mBitmap.change();
- }
- }
-
- /**
- * Sets the clip for the graphics2D object associated with the layer.
- * This should be used over the normal Graphics2D setClip method.
- *
- * @param clipShape the shape to use a the clip shape.
- */
- void setClip(Shape clipShape) {
- // because setClip is only guaranteed to work with rectangle shape,
- // first reset the clip to max and then intersect the current (empty)
- // clip with the shap.
- mGraphics.setClip(null);
- mGraphics.clip(clipShape);
- }
-
- /**
- * Clips the layer with the given shape. This performs an intersect between the current
- * clip shape and the given shape.
- * @param shape the new clip shape.
- */
- public void clip(Shape shape) {
- mGraphics.clip(shape);
- }
- }
-
- /**
- * Creates the root snapshot associating it with a given bitmap.
- * <p>
- * If <var>bitmap</var> is null, then {@link GcSnapshot#setBitmap(Bitmap_Delegate)} must be
- * called before the snapshot can be used to draw. Transform and clip operations are permitted
- * before.
- *
- * @param bitmap the image to associate to the snapshot or null.
- * @return the root snapshot
- */
- public static GcSnapshot createDefaultSnapshot(Bitmap_Delegate bitmap) {
- GcSnapshot snapshot = new GcSnapshot();
- if (bitmap != null) {
- snapshot.setBitmap(bitmap);
- }
-
- return snapshot;
- }
-
- /**
- * Saves the current state according to the given flags and returns the new current snapshot.
- * <p/>
- * This is the equivalent of {@link Canvas#save(int)}
- *
- * @param flags the save flags.
- * @return the new snapshot
- *
- * @see Canvas#save(int)
- */
- public GcSnapshot save(int flags) {
- return new GcSnapshot(this, null /*layerbounds*/, null /*paint*/, flags);
- }
-
- /**
- * Saves the current state and creates a new layer, and returns the new current snapshot.
- * <p/>
- * This is the equivalent of {@link Canvas#saveLayer(RectF, Paint, int)}
- *
- * @param layerBounds the layer bounds
- * @param paint the Paint information used to blit the layer back into the layers underneath
- * upon restore
- * @param flags the save flags.
- * @return the new snapshot
- *
- * @see Canvas#saveLayer(RectF, Paint, int)
- */
- public GcSnapshot saveLayer(RectF layerBounds, Paint_Delegate paint, int flags) {
- return new GcSnapshot(this, layerBounds, paint, flags);
- }
-
- /**
- * Creates the root snapshot.
- * {@link #setGraphics2D(Graphics2D)} will have to be called on it when possible.
- */
- private GcSnapshot() {
- mPrevious = null;
- mFlags = 0;
- mLocalLayer = null;
- mLocalLayerPaint = null;
- mLayerBounds = null;
- }
-
- /**
- * Creates a new {@link GcSnapshot} on top of another one, with a layer data to be restored
- * into the main graphics when {@link #restore()} is called.
- *
- * @param previous the previous snapshot head.
- * @param layerBounds the region of the layer. Optional, if null, this is a normal save()
- * @param paint the Paint information used to blit the layer back into the layers underneath
- * upon restore
- * @param flags the flags regarding what should be saved.
- */
- private GcSnapshot(GcSnapshot previous, RectF layerBounds, Paint_Delegate paint, int flags) {
- assert previous != null;
- mPrevious = previous;
- mFlags = flags;
-
- // make a copy of the current layers before adding the new one.
- // This keeps the same BufferedImage reference but creates new Graphics2D for this
- // snapshot.
- // It does not copy whatever original copy the layers have, as they will be done
- // only if the new layer doesn't clip drawing to itself.
- for (Layer layer : mPrevious.mLayers) {
- mLayers.add(layer.makeCopy());
- }
-
- if (layerBounds != null) {
- // get the current transform
- AffineTransform matrix = mLayers.get(0).getGraphics().getTransform();
-
- // transform the layerBounds with the current transform and stores it into a int rect
- RectF rect2 = new RectF();
- mapRect(matrix, rect2, layerBounds);
- mLayerBounds = new Rect();
- rect2.round(mLayerBounds);
-
- // get the base layer (always at index 0)
- Layer baseLayer = mLayers.get(0);
-
- // create the image for the layer
- BufferedImage layerImage = new BufferedImage(
- baseLayer.getImage().getWidth(),
- baseLayer.getImage().getHeight(),
- (mFlags & Canvas.HAS_ALPHA_LAYER_SAVE_FLAG) != 0 ?
- BufferedImage.TYPE_INT_ARGB :
- BufferedImage.TYPE_INT_RGB);
-
- // create a graphics for it so that drawing can be done.
- Graphics2D layerGraphics = layerImage.createGraphics();
-
- // because this layer inherits the current context for transform and clip,
- // set them to one from the base layer.
- AffineTransform currentMtx = baseLayer.getGraphics().getTransform();
- layerGraphics.setTransform(currentMtx);
-
- // create a new layer for this new layer and add it to the list at the end.
- mLayers.add(mLocalLayer = new Layer(layerGraphics, layerImage, flags));
-
- // set the clip on it.
- Shape currentClip = baseLayer.getGraphics().getClip();
- mLocalLayer.setClip(currentClip);
-
- // if the drawing is not clipped to the local layer only, we save the current content
- // of all other layers. We are only interested in the part that will actually
- // be drawn, so we create as small bitmaps as we can.
- // This is so that we can erase the drawing that goes in the layers below that will
- // be coming from the layer itself.
- if ((mFlags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0) {
- int w = mLayerBounds.width();
- int h = mLayerBounds.height();
- for (int i = 0 ; i < mLayers.size() - 1 ; i++) {
- Layer layer = mLayers.get(i);
- BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
- Graphics2D graphics = image.createGraphics();
- graphics.drawImage(layer.getImage(),
- 0, 0, w, h,
- mLayerBounds.left, mLayerBounds.top,
- mLayerBounds.right, mLayerBounds.bottom,
- null);
- graphics.dispose();
- layer.setOriginalCopy(image);
- }
- }
- } else {
- mLocalLayer = null;
- mLayerBounds = null;
- }
-
- mLocalLayerPaint = paint;
- }
-
- public void dispose() {
- for (Layer layer : mLayers) {
- layer.getGraphics().dispose();
- }
-
- if (mPrevious != null) {
- mPrevious.dispose();
- }
- }
-
- /**
- * Restores the top {@link GcSnapshot}, and returns the next one.
- */
- public GcSnapshot restore() {
- return doRestore();
- }
-
- /**
- * Restores the {@link GcSnapshot} to <var>saveCount</var>.
- * @param saveCount the saveCount or -1 to only restore 1.
- *
- * @return the new head of the Gc snapshot stack.
- */
- public GcSnapshot restoreTo(int saveCount) {
- return doRestoreTo(size(), saveCount);
- }
-
- public int size() {
- if (mPrevious != null) {
- return mPrevious.size() + 1;
- }
-
- return 1;
- }
-
- /**
- * Link the snapshot to a Bitmap_Delegate.
- * <p/>
- * This is only for the case where the snapshot was created with a null image when calling
- * {@link #createDefaultSnapshot(Bitmap_Delegate)}, and is therefore not yet linked to
- * a previous snapshot.
- * <p/>
- * If any transform or clip information was set before, they are put into the Graphics object.
- * @param bitmap the bitmap to link to.
- */
- public void setBitmap(Bitmap_Delegate bitmap) {
- // create a new Layer for the bitmap. This will be the base layer.
- Graphics2D graphics2D = bitmap.getImage().createGraphics();
- Layer baseLayer = new Layer(graphics2D, bitmap);
-
- // Set the current transform and clip which can either come from mTransform/mClip if they
- // were set when there was no bitmap/layers or from the current base layers if there is
- // one already.
-
- graphics2D.setTransform(getTransform());
- // reset mTransform in case there was one.
- mTransform = null;
-
- baseLayer.setClip(getClip());
- // reset mClip in case there was one.
- mClip = null;
-
- // replace whatever current layers we have with this.
- mLayers.clear();
- mLayers.add(baseLayer);
-
- }
-
- public void translate(float dx, float dy) {
- if (mLayers.size() > 0) {
- for (Layer layer : mLayers) {
- layer.getGraphics().translate(dx, dy);
- }
- } else {
- if (mTransform == null) {
- mTransform = new AffineTransform();
- }
- mTransform.translate(dx, dy);
- }
- }
-
- public void rotate(double radians) {
- if (mLayers.size() > 0) {
- for (Layer layer : mLayers) {
- layer.getGraphics().rotate(radians);
- }
- } else {
- if (mTransform == null) {
- mTransform = new AffineTransform();
- }
- mTransform.rotate(radians);
- }
- }
-
- public void scale(float sx, float sy) {
- if (mLayers.size() > 0) {
- for (Layer layer : mLayers) {
- layer.getGraphics().scale(sx, sy);
- }
- } else {
- if (mTransform == null) {
- mTransform = new AffineTransform();
- }
- mTransform.scale(sx, sy);
- }
- }
-
- public AffineTransform getTransform() {
- if (mLayers.size() > 0) {
- // all graphics2D in the list have the same transform
- return mLayers.get(0).getGraphics().getTransform();
- } else {
- if (mTransform == null) {
- mTransform = new AffineTransform();
- }
- return mTransform;
- }
- }
-
- public void setTransform(AffineTransform transform) {
- if (mLayers.size() > 0) {
- for (Layer layer : mLayers) {
- layer.getGraphics().setTransform(transform);
- }
- } else {
- if (mTransform == null) {
- mTransform = new AffineTransform();
- }
- mTransform.setTransform(transform);
- }
- }
-
- public boolean clip(Shape shape, int regionOp) {
- // Simple case of intersect with existing layers.
- // Because Graphics2D#setClip works a bit peculiarly, we optimize
- // the case of clipping by intersection, as it's supported natively.
- if (regionOp == Region.Op.INTERSECT.nativeInt && mLayers.size() > 0) {
- for (Layer layer : mLayers) {
- layer.clip(shape);
- }
-
- Shape currentClip = getClip();
- return currentClip != null && currentClip.getBounds().isEmpty() == false;
- }
-
- Area area = null;
-
- if (regionOp == Region.Op.REPLACE.nativeInt) {
- area = new Area(shape);
- } else {
- area = Region_Delegate.combineShapes(getClip(), shape, regionOp);
- }
-
- assert area != null;
-
- if (mLayers.size() > 0) {
- if (area != null) {
- for (Layer layer : mLayers) {
- layer.setClip(area);
- }
- }
-
- Shape currentClip = getClip();
- return currentClip != null && currentClip.getBounds().isEmpty() == false;
- } else {
- if (area != null) {
- mClip = area;
- } else {
- mClip = new Area();
- }
-
- return mClip.getBounds().isEmpty() == false;
- }
- }
-
- public boolean clipRect(float left, float top, float right, float bottom, int regionOp) {
- return clip(new Rectangle2D.Float(left, top, right - left, bottom - top), regionOp);
- }
-
- /**
- * Returns the current clip, or null if none have been setup.
- */
- public Shape getClip() {
- if (mLayers.size() > 0) {
- // they all have the same clip
- return mLayers.get(0).getGraphics().getClip();
- } else {
- return mClip;
- }
- }
-
- private GcSnapshot doRestoreTo(int size, int saveCount) {
- if (size <= saveCount) {
- return this;
- }
-
- // restore the current one first.
- GcSnapshot previous = doRestore();
-
- if (size == saveCount + 1) { // this was the only one that needed restore.
- return previous;
- } else {
- return previous.doRestoreTo(size - 1, saveCount);
- }
- }
-
- /**
- * Executes the Drawable's draw method, with a null paint delegate.
- * <p/>
- * Note that the method can be called several times if there are more than one active layer.
- */
- public void draw(Drawable drawable) {
- draw(drawable, null, false /*compositeOnly*/, false /*forceSrcMode*/);
- }
-
- /**
- * Executes the Drawable's draw method.
- * <p/>
- * Note that the method can be called several times if there are more than one active layer.
- * @param compositeOnly whether the paint is used for composite only. This is typically
- * the case for bitmaps.
- * @param forceSrcMode if true, this overrides the composite to be SRC
- */
- public void draw(Drawable drawable, Paint_Delegate paint, boolean compositeOnly,
- boolean forceSrcMode) {
- int forceMode = forceSrcMode ? AlphaComposite.SRC : 0;
- // the current snapshot may not have a mLocalLayer (ie it was created on save() instead
- // of saveLayer(), but that doesn't mean there's no layer.
- // mLayers however saves all the information we need (flags).
- if (mLayers.size() == 1) {
- // no layer, only base layer. easy case.
- drawInLayer(mLayers.get(0), drawable, paint, compositeOnly, forceMode);
- } else {
- // draw in all the layers until the layer save flags tells us to stop (ie drawing
- // in that layer is limited to the layer itself.
- int flags;
- int i = mLayers.size() - 1;
-
- do {
- Layer layer = mLayers.get(i);
-
- drawInLayer(layer, drawable, paint, compositeOnly, forceMode);
-
- // then go to previous layer, only if there are any left, and its flags
- // doesn't restrict drawing to the layer itself.
- i--;
- flags = layer.getFlags();
- } while (i >= 0 && (flags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0);
- }
- }
-
- private void drawInLayer(Layer layer, Drawable drawable, Paint_Delegate paint,
- boolean compositeOnly, int forceMode) {
- Graphics2D originalGraphics = layer.getGraphics();
- if (paint == null) {
- drawOnGraphics((Graphics2D) originalGraphics.create(), drawable,
- null /*paint*/, layer);
- } else {
- ColorFilter_Delegate filter = paint.getColorFilter();
- if (filter == null || !filter.isSupported()) {
- // get a Graphics2D object configured with the drawing parameters.
- Graphics2D configuredGraphics = createCustomGraphics(originalGraphics, paint,
- compositeOnly, forceMode);
- drawOnGraphics(configuredGraphics, drawable, paint, layer);
- return;
- }
-
- int x = 0;
- int y = 0;
- int width;
- int height;
- Rectangle clipBounds = originalGraphics.getClip() != null ? originalGraphics
- .getClipBounds() : null;
- if (clipBounds != null) {
- if (clipBounds.width == 0 || clipBounds.height == 0) {
- // Clip is 0 so no need to paint anything.
- return;
- }
- // If we have clipBounds available, use them as they will always be
- // smaller than the full layer size.
- x = clipBounds.x;
- y = clipBounds.y;
- width = clipBounds.width;
- height = clipBounds.height;
- } else {
- width = layer.getImage().getWidth();
- height = layer.getImage().getHeight();
- }
-
- // Create a temporary image to which the color filter will be applied.
- BufferedImage image = new BufferedImage(width, height,
- BufferedImage.TYPE_INT_ARGB);
- Graphics2D imageBaseGraphics = (Graphics2D) image.getGraphics();
- // Configure the Graphics2D object with drawing parameters and shader.
- Graphics2D imageGraphics = createCustomGraphics(
- imageBaseGraphics, paint, compositeOnly,
- AlphaComposite.SRC_OVER);
- // get a Graphics2D object configured with the drawing parameters, but no shader.
- Graphics2D configuredGraphics = createCustomGraphics(originalGraphics, paint,
- true /*compositeOnly*/, forceMode);
- try {
- // The main draw operation.
- // We translate the operation to take into account that the rendering does not
- // know about the clipping area.
- imageGraphics.translate(-x, -y);
- drawable.draw(imageGraphics, paint);
-
- // Apply the color filter.
- // Restore the original coordinates system and apply the filter only to the
- // clipped area.
- imageGraphics.translate(x, y);
- filter.applyFilter(imageGraphics, width, height);
-
- // Draw the tinted image on the main layer using as start point the clipping
- // upper left coordinates.
- configuredGraphics.drawImage(image, x, y, null);
- layer.change();
- } finally {
- // dispose Graphics2D objects
- imageGraphics.dispose();
- imageBaseGraphics.dispose();
- configuredGraphics.dispose();
- }
- }
- }
-
- private void drawOnGraphics(Graphics2D g, Drawable drawable, Paint_Delegate paint,
- Layer layer) {
- try {
- drawable.draw(g, paint);
- layer.change();
- } finally {
- g.dispose();
- }
- }
-
- private GcSnapshot doRestore() {
- if (mPrevious != null) {
- if (mLocalLayer != null) {
- // prepare to blit the layers in which we have draw, in the layer beneath
- // them, starting with the top one (which is the current local layer).
- int i = mLayers.size() - 1;
- int flags;
- do {
- Layer dstLayer = mLayers.get(i - 1);
-
- restoreLayer(dstLayer);
-
- flags = dstLayer.getFlags();
- i--;
- } while (i > 0 && (flags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) == 0);
- }
-
- // if this snapshot does not save everything, then set the previous snapshot
- // to this snapshot content
-
- // didn't save the matrix? set the current matrix on the previous snapshot
- if ((mFlags & Canvas.MATRIX_SAVE_FLAG) == 0) {
- AffineTransform mtx = getTransform();
- for (Layer layer : mPrevious.mLayers) {
- layer.getGraphics().setTransform(mtx);
- }
- }
-
- // didn't save the clip? set the current clip on the previous snapshot
- if ((mFlags & Canvas.CLIP_SAVE_FLAG) == 0) {
- Shape clip = getClip();
- for (Layer layer : mPrevious.mLayers) {
- layer.setClip(clip);
- }
- }
- }
-
- for (Layer layer : mLayers) {
- layer.getGraphics().dispose();
- }
-
- return mPrevious;
- }
-
- private void restoreLayer(Layer dstLayer) {
-
- Graphics2D baseGfx = dstLayer.getImage().createGraphics();
-
- // if the layer contains an original copy this means the flags
- // didn't restrict drawing to the local layer and we need to make sure the
- // layer bounds in the layer beneath didn't receive any drawing.
- // so we use the originalCopy to erase the new drawings in there.
- BufferedImage originalCopy = dstLayer.getOriginalCopy();
- if (originalCopy != null) {
- Graphics2D g = (Graphics2D) baseGfx.create();
- g.setComposite(AlphaComposite.Src);
-
- g.drawImage(originalCopy,
- mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom,
- 0, 0, mLayerBounds.width(), mLayerBounds.height(),
- null);
- g.dispose();
- }
-
- // now draw put the content of the local layer onto the layer,
- // using the paint information
- Graphics2D g = createCustomGraphics(baseGfx, mLocalLayerPaint,
- true /*alphaOnly*/, 0 /*forceMode*/);
-
- g.drawImage(mLocalLayer.getImage(),
- mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom,
- mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom,
- null);
- g.dispose();
-
- baseGfx.dispose();
- }
-
- /**
- * Creates a new {@link Graphics2D} based on the {@link Paint} parameters.
- * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used.
- */
- private Graphics2D createCustomGraphics(Graphics2D original, Paint_Delegate paint,
- boolean compositeOnly, int forceMode) {
- // make new one graphics
- Graphics2D g = (Graphics2D) original.create();
-
- // configure it
-
- if (paint.isAntiAliased()) {
- g.setRenderingHint(
- RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- g.setRenderingHint(
- RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
- }
-
- // set the shader first, as it'll replace the color if it can be used it.
- boolean customShader = false;
- if (!compositeOnly) {
- customShader = setShader(g, paint);
- // set the stroke
- g.setStroke(paint.getJavaStroke());
- }
- // set the composite.
- setComposite(g, paint, compositeOnly || customShader, forceMode);
-
- return g;
- }
-
- private boolean setShader(Graphics2D g, Paint_Delegate paint) {
- Shader_Delegate shaderDelegate = paint.getShader();
- if (shaderDelegate != null) {
- if (shaderDelegate.isSupported()) {
- java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint();
- assert shaderPaint != null;
- if (shaderPaint != null) {
- g.setPaint(shaderPaint);
- return true;
- }
- } else {
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_SHADER,
- shaderDelegate.getSupportMessage(),
- null /*throwable*/, null /*data*/);
- }
- }
-
- // if no shader, use the paint color
- g.setColor(new Color(paint.getColor(), true /*hasAlpha*/));
-
- return false;
- }
-
- private void setComposite(Graphics2D g, Paint_Delegate paint, boolean usePaintAlpha,
- int forceMode) {
- // the alpha for the composite. Always opaque if the normal paint color is used since
- // it contains the alpha
- int alpha = usePaintAlpha ? paint.getAlpha() : 0xFF;
- if (forceMode != 0) {
- g.setComposite(AlphaComposite.getInstance(forceMode, (float) alpha / 255.f));
- return;
- }
- Mode mode = PorterDuff.intToMode(paint.getPorterDuffMode());
- Composite composite = PorterDuffUtility.getComposite(mode, alpha);
- g.setComposite(composite);
- }
-
- private void mapRect(AffineTransform matrix, RectF dst, RectF src) {
- // array with 4 corners
- float[] corners = new float[] {
- src.left, src.top,
- src.right, src.top,
- src.right, src.bottom,
- src.left, src.bottom,
- };
-
- // apply the transform to them.
- matrix.transform(corners, 0, corners, 0, 4);
-
- // now put the result in the rect. We take the min/max of Xs and min/max of Ys
- dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
- dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
-
- dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
- dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
- }
-
- /**
- * Returns the clip of the oldest snapshot of the stack, appropriately translated to be
- * expressed in the coordinate system of the latest snapshot.
- */
- public Rectangle getOriginalClip() {
- GcSnapshot originalSnapshot = this;
- while (originalSnapshot.mPrevious != null) {
- originalSnapshot = originalSnapshot.mPrevious;
- }
- if (originalSnapshot.mLayers.isEmpty()) {
- return null;
- }
- Graphics2D graphics2D = originalSnapshot.mLayers.get(0).getGraphics();
- Rectangle bounds = graphics2D.getClipBounds();
- if (bounds == null) {
- return null;
- }
- try {
- AffineTransform originalTransform =
- ((Graphics2D) graphics2D.create()).getTransform().createInverse();
- AffineTransform latestTransform = getTransform().createInverse();
- bounds.x += latestTransform.getTranslateX() - originalTransform.getTranslateX();
- bounds.y += latestTransform.getTranslateY() - originalTransform.getTranslateY();
- } catch (NoninvertibleTransformException e) {
- Bridge.getLog().warning(null, "Non invertible transformation", null);
- }
- return bounds;
- }
-
-}
+++ /dev/null
-/*
- * 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.impl;
-
-import com.android.ide.common.rendering.api.HardwareConfig;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.SessionParams;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.RenderParamsFlags;
-import com.android.layoutlib.bridge.bars.AppCompatActionBar;
-import com.android.layoutlib.bridge.bars.BridgeActionBar;
-import com.android.layoutlib.bridge.bars.Config;
-import com.android.layoutlib.bridge.bars.FrameworkActionBar;
-import com.android.layoutlib.bridge.bars.NavigationBar;
-import com.android.layoutlib.bridge.bars.StatusBar;
-import com.android.layoutlib.bridge.bars.TitleBar;
-import com.android.resources.Density;
-import com.android.resources.ResourceType;
-import com.android.resources.ScreenOrientation;
-
-import android.annotation.NonNull;
-import android.graphics.drawable.Drawable;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.AttachInfo_Accessor;
-import android.view.View;
-import android.view.ViewRootImpl;
-import android.view.ViewRootImpl_Accessor;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.RelativeLayout;
-
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.widget.LinearLayout.VERTICAL;
-import static com.android.layoutlib.bridge.impl.ResourceHelper.getBooleanThemeValue;
-
-/**
- * The Layout used to create the system decor.
- *
- * The layout inflated will contain a content frame where the user's layout can be inflated.
- * <pre>
- * +-------------------------------------------------+---+
- * | Status bar | N |
- * +-------------------------------------------------+ a |
- * | Title/Action bar (optional) | v |
- * +-------------------------------------------------+ |
- * | Content, vertical extending | b |
- * | | a |
- * | | r |
- * +-------------------------------------------------+---+
- * </pre>
- * or
- * <pre>
- * +-------------------------------------+
- * | Status bar |
- * +-------------------------------------+
- * | Title/Action bar (optional) |
- * +-------------------------------------+
- * | Content, vertical extending |
- * | |
- * | |
- * +-------------------------------------+
- * | Nav bar |
- * +-------------------------------------+
- * </pre>
- *
- */
-class Layout extends RelativeLayout {
-
- // Theme attributes used for configuring appearance of the system decor.
- private static final String ATTR_WINDOW_FLOATING = "windowIsFloating";
- private static final String ATTR_WINDOW_BACKGROUND = "windowBackground";
- private static final String ATTR_WINDOW_FULL_SCREEN = "windowFullscreen";
- private static final String ATTR_NAV_BAR_HEIGHT = "navigation_bar_height";
- private static final String ATTR_NAV_BAR_WIDTH = "navigation_bar_width";
- private static final String ATTR_STATUS_BAR_HEIGHT = "status_bar_height";
- private static final String ATTR_WINDOW_ACTION_BAR = "windowActionBar";
- private static final String ATTR_ACTION_BAR_SIZE = "actionBarSize";
- private static final String ATTR_WINDOW_NO_TITLE = "windowNoTitle";
- private static final String ATTR_WINDOW_TITLE_SIZE = "windowTitleSize";
- private static final String ATTR_WINDOW_TRANSLUCENT_STATUS = StatusBar.ATTR_TRANSLUCENT;
- private static final String ATTR_WINDOW_TRANSLUCENT_NAV = NavigationBar.ATTR_TRANSLUCENT;
-
- // Default sizes
- private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
- private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
- private static final int DEFAULT_NAV_BAR_SIZE = 48;
-
- // Ids assigned to components created. This is so that we can refer to other components in
- // layout params.
- private static final String ID_NAV_BAR = "navBar";
- private static final String ID_STATUS_BAR = "statusBar";
- private static final String ID_TITLE_BAR = "titleBar";
- // Prefix used with the above ids in order to make them unique in framework namespace.
- private static final String ID_PREFIX = "android_layoutlib_";
-
- /**
- * Temporarily store the builder so that it doesn't have to be passed to all methods used
- * during inflation.
- */
- private Builder mBuilder;
-
- /**
- * This holds user's layout.
- */
- private FrameLayout mContentRoot;
-
- public Layout(@NonNull Builder builder) {
- super(builder.mContext);
- mBuilder = builder;
- if (builder.mWindowBackground != null) {
- Drawable d = ResourceHelper.getDrawable(builder.mWindowBackground, builder.mContext);
- setBackground(d);
- }
-
- int simulatedPlatformVersion = getParams().getSimulatedPlatformVersion();
- HardwareConfig hwConfig = getParams().getHardwareConfig();
- Density density = hwConfig.getDensity();
- boolean isRtl = Bridge.isLocaleRtl(getParams().getLocale());
- setLayoutDirection(isRtl? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR);
-
- NavigationBar navBar = null;
- if (mBuilder.hasNavBar()) {
- navBar = createNavBar(getContext(), density, isRtl, getParams().isRtlSupported(),
- simulatedPlatformVersion);
- }
-
- StatusBar statusBar = null;
- if (builder.mStatusBarSize > 0) {
- statusBar = createStatusBar(getContext(), density, isRtl, getParams().isRtlSupported(),
- simulatedPlatformVersion);
- }
-
- View actionBar = null;
- TitleBar titleBar = null;
- if (builder.mActionBarSize > 0) {
- BridgeActionBar bar = createActionBar(getContext(), getParams());
- mContentRoot = bar.getContentRoot();
- actionBar = bar.getRootView();
- } else if (mBuilder.mTitleBarSize > 0) {
- titleBar = createTitleBar(getContext(), getParams().getAppLabel(),
- simulatedPlatformVersion);
- }
-
- addViews(titleBar, mContentRoot == null ? (mContentRoot = createContentFrame()) : actionBar,
- statusBar, navBar);
- // Done with the builder. Don't hold a reference to it.
- mBuilder = null;
- }
-
- @NonNull
- private FrameLayout createContentFrame() {
- FrameLayout contentRoot = new FrameLayout(getContext());
- LayoutParams params = createLayoutParams(MATCH_PARENT, MATCH_PARENT);
- int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE;
- if (mBuilder.hasSolidNavBar()) {
- params.addRule(rule, getId(ID_NAV_BAR));
- }
- int below = -1;
- if (mBuilder.mActionBarSize <= 0 && mBuilder.mTitleBarSize > 0) {
- below = getId(ID_TITLE_BAR);
- } else if (mBuilder.hasSolidStatusBar()) {
- below = getId(ID_STATUS_BAR);
- }
- if (below != -1) {
- params.addRule(BELOW, below);
- }
- contentRoot.setLayoutParams(params);
- return contentRoot;
- }
-
- @NonNull
- private LayoutParams createLayoutParams(int width, int height) {
- DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
- if (width > 0) {
- width = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, metrics);
- }
- if (height > 0) {
- height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, height, metrics);
- }
- return new LayoutParams(width, height);
- }
-
- @NonNull
- public FrameLayout getContentRoot() {
- return mContentRoot;
- }
-
- @NonNull
- private SessionParams getParams() {
- return mBuilder.mParams;
- }
-
- @NonNull
- @Override
- public BridgeContext getContext(){
- return (BridgeContext) super.getContext();
- }
-
- /**
- * @param isRtl whether the current locale is an RTL locale.
- * @param isRtlSupported whether the applications supports RTL (i.e. has supportsRtl=true
- * in the manifest and targetSdkVersion >= 17.
- */
- @NonNull
- private StatusBar createStatusBar(BridgeContext context, Density density, boolean isRtl,
- boolean isRtlSupported, int simulatedPlatformVersion) {
- StatusBar statusBar =
- new StatusBar(context, density, isRtl, isRtlSupported, simulatedPlatformVersion);
- LayoutParams params = createLayoutParams(MATCH_PARENT, mBuilder.mStatusBarSize);
- if (mBuilder.isNavBarVertical()) {
- params.addRule(START_OF, getId(ID_NAV_BAR));
- }
- statusBar.setLayoutParams(params);
- statusBar.setId(getId(ID_STATUS_BAR));
- return statusBar;
- }
-
- private BridgeActionBar createActionBar(@NonNull BridgeContext context,
- @NonNull SessionParams params) {
- boolean isMenu = "menu".equals(params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG));
-
- BridgeActionBar actionBar;
- if (context.isAppCompatTheme() && !isMenu) {
- actionBar = new AppCompatActionBar(context, params);
- } else {
- actionBar = new FrameworkActionBar(context, params);
- }
- LayoutParams layoutParams = createLayoutParams(MATCH_PARENT, MATCH_PARENT);
- int rule = mBuilder.isNavBarVertical() ? START_OF : ABOVE;
- if (mBuilder.hasSolidNavBar()) {
- layoutParams.addRule(rule, getId(ID_NAV_BAR));
- }
- if (mBuilder.hasSolidStatusBar()) {
- layoutParams.addRule(BELOW, getId(ID_STATUS_BAR));
- }
- actionBar.getRootView().setLayoutParams(layoutParams);
- actionBar.createMenuPopup();
- return actionBar;
- }
-
- @NonNull
- private TitleBar createTitleBar(BridgeContext context, String title,
- int simulatedPlatformVersion) {
- TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion);
- LayoutParams params = createLayoutParams(MATCH_PARENT, mBuilder.mTitleBarSize);
- if (mBuilder.hasSolidStatusBar()) {
- params.addRule(BELOW, getId(ID_STATUS_BAR));
- }
- if (mBuilder.isNavBarVertical() && mBuilder.hasSolidNavBar()) {
- params.addRule(START_OF, getId(ID_NAV_BAR));
- }
- titleBar.setLayoutParams(params);
- titleBar.setId(getId(ID_TITLE_BAR));
- return titleBar;
- }
-
- /**
- * @param isRtl whether the current locale is an RTL locale.
- * @param isRtlSupported whether the applications supports RTL (i.e. has supportsRtl=true
- * in the manifest and targetSdkVersion >= 17.
- */
- @NonNull
- private NavigationBar createNavBar(BridgeContext context, Density density, boolean isRtl,
- boolean isRtlSupported, int simulatedPlatformVersion) {
- int orientation = mBuilder.mNavBarOrientation;
- int size = mBuilder.mNavBarSize;
- NavigationBar navBar = new NavigationBar(context, density, orientation, isRtl,
- isRtlSupported, simulatedPlatformVersion);
- boolean isVertical = mBuilder.isNavBarVertical();
- int w = isVertical ? size : MATCH_PARENT;
- int h = isVertical ? MATCH_PARENT : size;
- LayoutParams params = createLayoutParams(w, h);
- params.addRule(isVertical ? ALIGN_PARENT_END : ALIGN_PARENT_BOTTOM);
- navBar.setLayoutParams(params);
- navBar.setId(getId(ID_NAV_BAR));
- return navBar;
- }
-
- private void addViews(@NonNull View... views) {
- for (View view : views) {
- if (view != null) {
- addView(view);
- }
- }
- }
-
- private int getId(String name) {
- return Bridge.getResourceId(ResourceType.ID, ID_PREFIX + name);
- }
-
- @SuppressWarnings("deprecation")
- @Override
- public void requestFitSystemWindows() {
- // The framework call would usually bubble up to ViewRootImpl but, in layoutlib, Layout will
- // act as view root for most purposes. That way, we can also save going through the Handler
- // to dispatch the new applied insets.
- ViewRootImpl root = AttachInfo_Accessor.getRootView(this);
- if (root != null) {
- ViewRootImpl_Accessor.dispatchApplyInsets(root, this);
- }
- }
-
- /**
- * A helper class to help initialize the Layout.
- */
- static class Builder {
- @NonNull
- private final SessionParams mParams;
- @NonNull
- private final BridgeContext mContext;
- private final RenderResources mResources;
-
- private final boolean mWindowIsFloating;
- private ResourceValue mWindowBackground;
- private int mStatusBarSize;
- private int mNavBarSize;
- private int mNavBarOrientation;
- private int mActionBarSize;
- private int mTitleBarSize;
- private boolean mTranslucentStatus;
- private boolean mTranslucentNav;
-
- public Builder(@NonNull SessionParams params, @NonNull BridgeContext context) {
- mParams = params;
- mContext = context;
- mResources = mParams.getResources();
- mWindowIsFloating = getBooleanThemeValue(mResources, ATTR_WINDOW_FLOATING, true, true);
-
- findBackground();
-
- if (!mParams.isForceNoDecor()) {
- findStatusBar();
- findActionBar();
- findNavBar();
- }
- }
-
- private void findBackground() {
- if (!mParams.isBgColorOverridden()) {
- mWindowBackground = mResources.findItemInTheme(ATTR_WINDOW_BACKGROUND, true);
- mWindowBackground = mResources.resolveResValue(mWindowBackground);
- }
- }
-
- private void findStatusBar() {
- boolean windowFullScreen =
- getBooleanThemeValue(mResources, ATTR_WINDOW_FULL_SCREEN, true, false);
- if (!windowFullScreen && !mWindowIsFloating) {
- mStatusBarSize =
- getDimension(ATTR_STATUS_BAR_HEIGHT, true, DEFAULT_STATUS_BAR_HEIGHT);
- mTranslucentStatus = getBooleanThemeValue(mResources,
- ATTR_WINDOW_TRANSLUCENT_STATUS, true, false);
- }
- }
-
- private void findActionBar() {
- if (mWindowIsFloating) {
- return;
- }
- // Check if an actionbar is needed
- boolean isMenu = "menu".equals(mParams.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG));
- boolean windowActionBar = isMenu ||
- getBooleanThemeValue(mResources, ATTR_WINDOW_ACTION_BAR,
- !mContext.isAppCompatTheme(), true);
- if (windowActionBar) {
- mActionBarSize = getDimension(ATTR_ACTION_BAR_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT);
- } else {
- // Maybe the gingerbread era title bar is needed
- boolean windowNoTitle =
- getBooleanThemeValue(mResources, ATTR_WINDOW_NO_TITLE, true, false);
- if (!windowNoTitle) {
- mTitleBarSize =
- getDimension(ATTR_WINDOW_TITLE_SIZE, true, DEFAULT_TITLE_BAR_HEIGHT);
- }
- }
- }
-
- private void findNavBar() {
- if (hasSoftwareButtons() && !mWindowIsFloating) {
-
- // get orientation
- HardwareConfig hwConfig = mParams.getHardwareConfig();
- boolean barOnBottom = true;
-
- if (hwConfig.getOrientation() == ScreenOrientation.LANDSCAPE) {
- int shortSize = hwConfig.getScreenHeight();
- int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT /
- hwConfig.getDensity().getDpiValue();
-
- // 0-599dp: "phone" UI with bar on the side
- // 600+dp: "tablet" UI with bar on the bottom
- barOnBottom = shortSizeDp >= 600;
- }
-
- mNavBarOrientation = barOnBottom ? LinearLayout.HORIZONTAL : VERTICAL;
- mNavBarSize = getDimension(barOnBottom ? ATTR_NAV_BAR_HEIGHT : ATTR_NAV_BAR_WIDTH,
- true, DEFAULT_NAV_BAR_SIZE);
- mTranslucentNav = getBooleanThemeValue(mResources,
- ATTR_WINDOW_TRANSLUCENT_NAV, true, false);
- }
- }
-
- @SuppressWarnings("SameParameterValue")
- private int getDimension(String attr, boolean isFramework, int defaultValue) {
- ResourceValue value = mResources.findItemInTheme(attr, isFramework);
- value = mResources.resolveResValue(value);
- if (value != null) {
- TypedValue typedValue = ResourceHelper.getValue(attr, value.getValue(), true);
- if (typedValue != null) {
- return (int) typedValue.getDimension(mContext.getMetrics());
- }
- }
- return defaultValue;
- }
-
- private boolean hasSoftwareButtons() {
- return mParams.getHardwareConfig().hasSoftwareButtons();
- }
-
- /**
- * Return true if the nav bar is present and not translucent
- */
- private boolean hasSolidNavBar() {
- return hasNavBar() && !mTranslucentNav;
- }
-
- /**
- * Return true if the status bar is present and not translucent
- */
- private boolean hasSolidStatusBar() {
- return hasStatusBar() && !mTranslucentStatus;
- }
-
- private boolean hasNavBar() {
- return Config.showOnScreenNavBar(mParams.getSimulatedPlatformVersion()) &&
- hasSoftwareButtons() && mNavBarSize > 0;
- }
-
- private boolean hasStatusBar() {
- return mStatusBarSize > 0;
- }
-
- /**
- * Return true if the nav bar is present and is vertical.
- */
- private boolean isNavBarVertical() {
- return hasNavBar() && mNavBarOrientation == VERTICAL;
- }
- }
-}
+++ /dev/null
-/*
- * 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.impl;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.Nullable;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A wrapper around XmlPullParser that can peek forward to inspect if the file is a data-binding
- * layout and some parts need to be stripped.
- */
-public class LayoutParserWrapper implements XmlPullParser {
-
- // Data binding constants.
- private static final String TAG_LAYOUT = "layout";
- private static final String TAG_DATA = "data";
- private static final String DEFAULT = "default=";
-
- private final XmlPullParser mDelegate;
-
- // Storage for peeked values.
- private boolean mPeeked;
- private int mEventType;
- private int mDepth;
- private int mNext;
- private List<Attribute> mAttributes;
- private String mText;
- private String mName;
-
- // Used to end the document before the actual parser ends.
- private int mFinalDepth = -1;
- private boolean mEndNow;
-
- public LayoutParserWrapper(XmlPullParser delegate) {
- mDelegate = delegate;
- }
-
- public LayoutParserWrapper peekTillLayoutStart() throws IOException, XmlPullParserException {
- final int STATE_LAYOUT_NOT_STARTED = 0; // <layout> tag not encountered yet.
- final int STATE_ROOT_NOT_STARTED = 1; // the main view root not found yet.
- final int STATE_INSIDE_DATA = 2; // START_TAG for <data> found, but not END_TAG.
-
- int state = STATE_LAYOUT_NOT_STARTED;
- int dataDepth = -1; // depth of the <data> tag. Should be two.
- while (true) {
- int peekNext = peekNext();
- switch (peekNext) {
- case START_TAG:
- if (state == STATE_LAYOUT_NOT_STARTED) {
- if (mName.equals(TAG_LAYOUT)) {
- state = STATE_ROOT_NOT_STARTED;
- } else {
- return this; // no layout tag in the file.
- }
- } else if (state == STATE_ROOT_NOT_STARTED) {
- if (mName.equals(TAG_DATA)) {
- state = STATE_INSIDE_DATA;
- dataDepth = mDepth;
- } else {
- mFinalDepth = mDepth;
- return this;
- }
- }
- break;
- case END_TAG:
- if (state == STATE_INSIDE_DATA) {
- if (mDepth <= dataDepth) {
- state = STATE_ROOT_NOT_STARTED;
- }
- }
- break;
- case END_DOCUMENT:
- // No layout start found.
- return this;
- }
- // consume the peeked tag.
- next();
- }
- }
-
- private int peekNext() throws IOException, XmlPullParserException {
- if (mPeeked) {
- return mNext;
- }
- mEventType = mDelegate.getEventType();
- mNext = mDelegate.next();
- if (mEventType == START_TAG) {
- int count = mDelegate.getAttributeCount();
- mAttributes = count > 0 ? new ArrayList<Attribute>(count) :
- Collections.<Attribute>emptyList();
- for (int i = 0; i < count; i++) {
- mAttributes.add(new Attribute(mDelegate.getAttributeNamespace(i),
- mDelegate.getAttributeName(i), mDelegate.getAttributeValue(i)));
- }
- }
- mDepth = mDelegate.getDepth();
- mText = mDelegate.getText();
- mName = mDelegate.getName();
- mPeeked = true;
- return mNext;
- }
-
- private void reset() {
- mAttributes = null;
- mText = null;
- mName = null;
- mPeeked = false;
- }
-
- @Override
- public int next() throws XmlPullParserException, IOException {
- int returnValue;
- int depth;
- if (mPeeked) {
- returnValue = mNext;
- depth = mDepth;
- reset();
- } else if (mEndNow) {
- return END_DOCUMENT;
- } else {
- returnValue = mDelegate.next();
- depth = getDepth();
- }
- if (returnValue == END_TAG && depth <= mFinalDepth) {
- mEndNow = true;
- }
- return returnValue;
- }
-
- @Override
- public int getEventType() throws XmlPullParserException {
- return mPeeked ? mEventType : mDelegate.getEventType();
- }
-
- @Override
- public int getDepth() {
- return mPeeked ? mDepth : mDelegate.getDepth();
- }
-
- @Override
- public String getName() {
- return mPeeked ? mName : mDelegate.getName();
- }
-
- @Override
- public String getText() {
- return mPeeked ? mText : mDelegate.getText();
- }
-
- @Override
- public String getAttributeValue(@Nullable String namespace, String name) {
- String returnValue = null;
- if (mPeeked) {
- if (mAttributes == null) {
- if (mEventType != START_TAG) {
- throw new IndexOutOfBoundsException("getAttributeValue() called when not at START_TAG.");
- } else {
- return null;
- }
- } else {
- for (Attribute attribute : mAttributes) {
- //noinspection StringEquality for nullness check.
- if (attribute.name.equals(name) && (attribute.namespace == namespace ||
- attribute.namespace != null && attribute.namespace.equals(namespace))) {
- returnValue = attribute.value;
- break;
- }
- }
- }
- } else {
- returnValue = mDelegate.getAttributeValue(namespace, name);
- }
- // Check if the value is bound via data-binding, if yes get the default value.
- if (returnValue != null && mFinalDepth >= 0 && returnValue.startsWith("@{")) {
- // TODO: Improve the detection of default keyword.
- int i = returnValue.lastIndexOf(DEFAULT);
- return i > 0 ? returnValue.substring(i + DEFAULT.length(), returnValue.length() - 1)
- : null;
- }
- return returnValue;
- }
-
- private static class Attribute {
- @Nullable
- public final String namespace;
- public final String name;
- public final String value;
-
- public Attribute(@Nullable String namespace, String name, String value) {
- this.namespace = namespace;
- this.name = name;
- this.value = value;
- }
- }
-
- // Not affected by peeking.
-
- @Override
- public void setFeature(String s, boolean b) throws XmlPullParserException {
- mDelegate.setFeature(s, b);
- }
-
- @Override
- public void setProperty(String s, Object o) throws XmlPullParserException {
- mDelegate.setProperty(s, o);
- }
-
- @Override
- public void setInput(InputStream inputStream, String s) throws XmlPullParserException {
- mDelegate.setInput(inputStream, s);
- }
-
- @Override
- public void setInput(Reader reader) throws XmlPullParserException {
- mDelegate.setInput(reader);
- }
-
- @Override
- public String getInputEncoding() {
- return mDelegate.getInputEncoding();
- }
-
- @Override
- public String getNamespace(String s) {
- return mDelegate.getNamespace(s);
- }
-
- @Override
- public String getPositionDescription() {
- return mDelegate.getPositionDescription();
- }
-
- @Override
- public int getLineNumber() {
- return mDelegate.getLineNumber();
- }
-
- @Override
- public String getNamespace() {
- return mDelegate.getNamespace();
- }
-
- @Override
- public int getColumnNumber() {
- return mDelegate.getColumnNumber();
- }
-
- // -- We don't care much about the methods that follow.
-
- @Override
- public void require(int i, String s, String s1) throws XmlPullParserException, IOException {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public boolean getFeature(String s) {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public void defineEntityReplacementText(String s, String s1) throws XmlPullParserException {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public Object getProperty(String s) {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public int nextToken() throws XmlPullParserException, IOException {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public int getNamespaceCount(int i) throws XmlPullParserException {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public String getNamespacePrefix(int i) throws XmlPullParserException {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public String getNamespaceUri(int i) throws XmlPullParserException {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public boolean isWhitespace() throws XmlPullParserException {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public char[] getTextCharacters(int[] ints) {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public String getPrefix() {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public boolean isEmptyElementTag() throws XmlPullParserException {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public int getAttributeCount() {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public String getAttributeNamespace(int i) {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public String getAttributeName(int i) {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public String getAttributePrefix(int i) {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public String getAttributeType(int i) {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public boolean isAttributeDefault(int i) {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public String getAttributeValue(int i) {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public String nextText() throws XmlPullParserException, IOException {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-
- @Override
- public int nextTag() throws XmlPullParserException, IOException {
- throw new UnsupportedOperationException("Only few parser methods are supported.");
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl;
-
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * A factory for {@link XmlPullParser}.
- *
- */
-public class ParserFactory {
-
- public final static boolean LOG_PARSER = false;
-
- // Used to get a new XmlPullParser from the client.
- @Nullable
- private static com.android.ide.common.rendering.api.ParserFactory sParserFactory;
-
- public static void setParserFactory(
- @Nullable com.android.ide.common.rendering.api.ParserFactory parserFactory) {
- sParserFactory = parserFactory;
- }
-
- @NonNull
- public static XmlPullParser create(@NonNull File f)
- throws XmlPullParserException, FileNotFoundException {
- return create(f, false);
- }
-
- public static XmlPullParser create(@NonNull File f, boolean isLayout)
- throws XmlPullParserException, FileNotFoundException {
- InputStream stream = new FileInputStream(f);
- return create(stream, f.getName(), f.length(), isLayout);
- }
- @NonNull
- public static XmlPullParser create(@NonNull InputStream stream, @Nullable String name)
- throws XmlPullParserException {
- return create(stream, name, -1, false);
- }
-
- @NonNull
- private static XmlPullParser create(@NonNull InputStream stream, @Nullable String name,
- long size, boolean isLayout) throws XmlPullParserException {
- XmlPullParser parser = instantiateParser(name);
-
- stream = readAndClose(stream, name, size);
-
- parser.setInput(stream, null);
- if (isLayout) {
- try {
- return new LayoutParserWrapper(parser).peekTillLayoutStart();
- } catch (IOException e) {
- throw new XmlPullParserException(null, parser, e);
- }
- }
- return parser;
- }
-
- @NonNull
- public static XmlPullParser instantiateParser(@Nullable String name)
- throws XmlPullParserException {
- if (sParserFactory == null) {
- throw new XmlPullParserException("ParserFactory not initialized.");
- }
- XmlPullParser parser = sParserFactory.createParser(name);
- parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
- return parser;
- }
-
- @NonNull
- private static InputStream readAndClose(@NonNull InputStream stream, @Nullable String name,
- long size) throws XmlPullParserException {
- // just a sanity check. It's doubtful we'll have such big files!
- if (size > Integer.MAX_VALUE) {
- throw new XmlPullParserException("File " + name + " is too big to be parsed");
- }
- int intSize = (int) size;
-
- // create a buffered reader to facilitate reading.
- BufferedInputStream bufferedStream = new BufferedInputStream(stream);
- try {
- int avail;
- if (intSize != -1) {
- avail = intSize;
- } else {
- // get the size to read.
- avail = bufferedStream.available();
- }
-
- // create the initial buffer and read it.
- byte[] buffer = new byte[avail];
- int read = stream.read(buffer);
-
- // this is the easy case.
- if (read == intSize) {
- return new ByteArrayInputStream(buffer);
- }
-
- // check if there is more to read (read() does not necessarily read all that
- // available() returned!)
- while ((avail = bufferedStream.available()) > 0) {
- if (read + avail > buffer.length) {
- // just allocate what is needed. We're mostly reading small files
- // so it shouldn't be too problematic.
- byte[] moreBuffer = new byte[read + avail];
- System.arraycopy(buffer, 0, moreBuffer, 0, read);
- buffer = moreBuffer;
- }
-
- read += stream.read(buffer, read, avail);
- }
-
- // return a new stream encapsulating this buffer.
- return new ByteArrayInputStream(buffer);
-
- } catch (IOException e) {
- throw new XmlPullParserException("Failed to read " + name, null, e);
- } finally {
- try {
- bufferedStream.close();
- } catch (IOException ignored) {
- }
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl;
-
-import com.android.ide.common.rendering.api.IAnimationListener;
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.Result.Status;
-
-import android.animation.AnimationThread;
-import android.animation.Animator;
-
-public class PlayAnimationThread extends AnimationThread {
-
- private final Animator mAnimator;
-
- public PlayAnimationThread(Animator animator, RenderSessionImpl scene, String animName,
- IAnimationListener listener) {
- super(scene, animName, listener);
- mAnimator = animator;
- }
-
- @Override
- public Result preAnimation() {
- // start the animation. This will send a message to the handler right away, so
- // the queue is filled when this method returns.
- mAnimator.start();
-
- return Status.SUCCESS.createResult();
- }
-
- @Override
- public void postAnimation() {
- // nothing to be done.
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.impl;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-
-import android.graphics.BlendComposite;
-import android.graphics.BlendComposite.BlendingMode;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuff.Mode;
-import android.graphics.PorterDuffColorFilter_Delegate;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-
-/**
- * Provides various utility methods for {@link PorterDuffColorFilter_Delegate}.
- */
-public final class PorterDuffUtility {
-
- private static final int MODES_COUNT = Mode.values().length;
-
- // Make the class non-instantiable.
- private PorterDuffUtility() {
- }
-
- /**
- * Convert the porterDuffMode from the framework to its corresponding enum. This defaults to
- * {@link Mode#SRC_OVER} for invalid modes.
- */
- public static Mode getPorterDuffMode(int porterDuffMode) {
- if (porterDuffMode >= 0 && porterDuffMode < MODES_COUNT) {
- return PorterDuff.intToMode(porterDuffMode);
- }
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- String.format("Unknown PorterDuff.Mode: %1$d", porterDuffMode), null);
- assert false;
- return Mode.SRC_OVER;
- }
-
- /**
- * A utility method to get the {@link Composite} that represents the filter for the given
- * PorterDuff mode and the alpha. Defaults to {@link Mode#SRC_OVER} for invalid modes.
- */
- public static Composite getComposite(Mode mode, int alpha255) {
- float alpha1 = alpha255 != 0xFF ? alpha255 / 255.f : 1.f;
- switch (mode) {
- case CLEAR:
- return AlphaComposite.getInstance(AlphaComposite.CLEAR, alpha1);
- case SRC:
- return AlphaComposite.getInstance(AlphaComposite.SRC, alpha1);
- case DST:
- return AlphaComposite.getInstance(AlphaComposite.DST, alpha1);
- case SRC_OVER:
- return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1);
- case DST_OVER:
- return AlphaComposite.getInstance(AlphaComposite.DST_OVER, alpha1);
- case SRC_IN:
- return AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha1);
- case DST_IN:
- return AlphaComposite.getInstance(AlphaComposite.DST_IN, alpha1);
- case SRC_OUT:
- return AlphaComposite.getInstance(AlphaComposite.SRC_OUT, alpha1);
- case DST_OUT:
- return AlphaComposite.getInstance(AlphaComposite.DST_OUT, alpha1);
- case SRC_ATOP:
- return AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha1);
- case DST_ATOP:
- return AlphaComposite.getInstance(AlphaComposite.DST_ATOP, alpha1);
- case XOR:
- return AlphaComposite.getInstance(AlphaComposite.XOR, alpha1);
- case DARKEN:
- return BlendComposite.getInstance(BlendingMode.DARKEN, alpha1);
- case LIGHTEN:
- return BlendComposite.getInstance(BlendingMode.LIGHTEN, alpha1);
- case MULTIPLY:
- return BlendComposite.getInstance(BlendingMode.MULTIPLY, alpha1);
- case SCREEN:
- return BlendComposite.getInstance(BlendingMode.SCREEN, alpha1);
- case ADD:
- return BlendComposite.getInstance(BlendingMode.ADD, alpha1);
- case OVERLAY:
- return BlendComposite.getInstance(BlendingMode.OVERLAY, alpha1);
- default:
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
- String.format("Unsupported PorterDuff Mode: %1$s", mode.name()),
- null, null /*data*/);
-
- return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl;
-
-import com.android.ide.common.rendering.api.HardwareConfig;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.RenderParams;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.RenderResources.FrameworkResourceIdProvider;
-import com.android.ide.common.rendering.api.Result;
-import com.android.layoutlib.bridge.Bridge;
-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;
-import android.os.HandlerThread_Delegate;
-import android.util.DisplayMetrics;
-import android.view.ViewConfiguration_Accessor;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodManager_Accessor;
-
-import java.util.Locale;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.ReentrantLock;
-
-import static com.android.ide.common.rendering.api.Result.Status.ERROR_LOCK_INTERRUPTED;
-import static com.android.ide.common.rendering.api.Result.Status.ERROR_TIMEOUT;
-import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
-
-/**
- * Base class for rendering action.
- *
- * It provides life-cycle methods to init and stop the rendering.
- * The most important methods are:
- * {@link #init(long)} and {@link #acquire(long)} to start a rendering and {@link #release()}
- * after the rendering.
- *
- *
- * @param <T> the {@link RenderParams} implementation
- *
- */
-public abstract class RenderAction<T extends RenderParams> extends FrameworkResourceIdProvider {
-
- /**
- * The current context being rendered. This is set through {@link #acquire(long)} and
- * {@link #init(long)}, and unset in {@link #release()}.
- */
- private static BridgeContext sCurrentContext = null;
-
- private final T mParams;
-
- private BridgeContext mContext;
-
- /**
- * Creates a renderAction.
- * <p>
- * This <b>must</b> be followed by a call to {@link RenderAction#init(long)}, which act as a
- * call to {@link RenderAction#acquire(long)}
- *
- * @param params the RenderParams. This must be a copy that the action can keep
- *
- */
- protected RenderAction(T params) {
- mParams = params;
- }
-
- /**
- * Initializes and acquires the scene, creating various Android objects such as context,
- * inflater, and parser.
- *
- * @param timeout the time to wait if another rendering is happening.
- *
- * @return whether the scene was prepared
- *
- * @see #acquire(long)
- * @see #release()
- */
- public Result init(long timeout) {
- // acquire the lock. if the result is null, lock was just acquired, otherwise, return
- // the result.
- Result result = acquireLock(timeout);
- if (result != null) {
- return result;
- }
-
- HardwareConfig hardwareConfig = mParams.getHardwareConfig();
-
- // setup the display Metrics.
- DisplayMetrics metrics = new DisplayMetrics();
- metrics.densityDpi = metrics.noncompatDensityDpi =
- hardwareConfig.getDensity().getDpiValue();
-
- metrics.density = metrics.noncompatDensity =
- metrics.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
-
- metrics.scaledDensity = metrics.noncompatScaledDensity = metrics.density;
-
- metrics.widthPixels = metrics.noncompatWidthPixels = hardwareConfig.getScreenWidth();
- metrics.heightPixels = metrics.noncompatHeightPixels = hardwareConfig.getScreenHeight();
- metrics.xdpi = metrics.noncompatXdpi = hardwareConfig.getXdpi();
- metrics.ydpi = metrics.noncompatYdpi = hardwareConfig.getYdpi();
-
- RenderResources resources = mParams.getResources();
-
- // build the context
- mContext = new BridgeContext(mParams.getProjectKey(), metrics, resources,
- mParams.getAssets(), mParams.getLayoutlibCallback(), getConfiguration(mParams),
- mParams.getTargetSdkVersion(), mParams.isRtlSupported());
-
- setUp();
-
- return SUCCESS.createResult();
- }
-
- /**
- * Prepares the scene for action.
- * <p>
- * This call is blocking if another rendering/inflating is currently happening, and will return
- * whether the preparation worked.
- *
- * The preparation can fail if another rendering took too long and the timeout was elapsed.
- *
- * More than one call to this from the same thread will have no effect and will return
- * {@link Result.Status#SUCCESS}.
- *
- * After scene actions have taken place, only one call to {@link #release()} must be
- * done.
- *
- * @param timeout the time to wait if another rendering is happening.
- *
- * @return whether the scene was prepared
- *
- * @see #release()
- *
- * @throws IllegalStateException if {@link #init(long)} was never called.
- */
- public Result acquire(long timeout) {
- if (mContext == null) {
- throw new IllegalStateException("After scene creation, #init() must be called");
- }
-
- // acquire the lock. if the result is null, lock was just acquired, otherwise, return
- // the result.
- Result result = acquireLock(timeout);
- if (result != null) {
- return result;
- }
-
- setUp();
-
- return SUCCESS.createResult();
- }
-
- /**
- * Acquire the lock so that the scene can be acted upon.
- * <p>
- * This returns null if the lock was just acquired, otherwise it returns
- * {@link Result.Status#SUCCESS} if the lock already belonged to that thread, or another
- * instance (see {@link Result#getStatus()}) if an error occurred.
- *
- * @param timeout the time to wait if another rendering is happening.
- * @return null if the lock was just acquire or another result depending on the state.
- *
- * @throws IllegalStateException if the current context is different than the one owned by
- * the scene.
- */
- private Result acquireLock(long timeout) {
- ReentrantLock lock = Bridge.getLock();
- if (!lock.isHeldByCurrentThread()) {
- try {
- boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);
-
- if (!acquired) {
- return ERROR_TIMEOUT.createResult();
- }
- } catch (InterruptedException e) {
- return ERROR_LOCK_INTERRUPTED.createResult();
- }
- } else {
- // This thread holds the lock already. Checks that this wasn't for a different context.
- // If this is called by init, mContext will be null and so should sCurrentContext
- // anyway
- if (mContext != sCurrentContext) {
- throw new IllegalStateException("Acquiring different scenes from same thread without releases");
- }
- return SUCCESS.createResult();
- }
-
- return null;
- }
-
- /**
- * Cleans up the scene after an action.
- */
- public void release() {
- ReentrantLock lock = Bridge.getLock();
-
- // with the use of finally blocks, it is possible to find ourself calling this
- // without a successful call to prepareScene. This test makes sure that unlock() will
- // not throw IllegalMonitorStateException.
- if (lock.isHeldByCurrentThread()) {
- tearDown();
- lock.unlock();
- }
- }
-
- /**
- * Sets up the session for rendering.
- * <p/>
- * The counterpart is {@link #tearDown()}.
- */
- private void setUp() {
- // setup the ParserFactory
- ParserFactory.setParserFactory(mParams.getLayoutlibCallback().getParserFactory());
-
- // make sure the Resources object references the context (and other objects) for this
- // scene
- mContext.initResources();
- sCurrentContext = mContext;
-
- // create an InputMethodManager
- InputMethodManager.getInstance();
-
- LayoutLog currentLog = mParams.getLog();
- Bridge.setLog(currentLog);
- mContext.getRenderResources().setFrameworkResourceIdProvider(this);
- mContext.getRenderResources().setLogger(currentLog);
- }
-
- /**
- * Tear down the session after rendering.
- * <p/>
- * The counterpart is {@link #setUp()}.
- */
- private void tearDown() {
- // The context may be null, if there was an error during init().
- if (mContext != null) {
- // Make sure to remove static references, otherwise we could not unload the lib
- mContext.disposeResources();
- }
-
- if (sCurrentContext != null) {
- // quit HandlerThread created during this session.
- HandlerThread_Delegate.cleanUp(sCurrentContext);
- }
-
- // clear the stored ViewConfiguration since the map is per density and not per context.
- ViewConfiguration_Accessor.clearConfigurations();
-
- // remove the InputMethodManager
- InputMethodManager_Accessor.resetInstance();
-
- sCurrentContext = null;
-
- Bridge.setLog(null);
- if (mContext != null) {
- mContext.getRenderResources().setFrameworkResourceIdProvider(null);
- mContext.getRenderResources().setLogger(null);
- }
- ParserFactory.setParserFactory(null);
- }
-
- public static BridgeContext getCurrentContext() {
- return sCurrentContext;
- }
-
- protected T getParams() {
- return mParams;
- }
-
- protected BridgeContext getContext() {
- return mContext;
- }
-
- /**
- * Returns the log associated with the session.
- * @return the log or null if there are none.
- */
- public LayoutLog getLog() {
- if (mParams != null) {
- return mParams.getLog();
- }
-
- return null;
- }
-
- /**
- * Checks that the lock is owned by the current thread and that the current context is the one
- * from this scene.
- *
- * @throws IllegalStateException if the current context is different than the one owned by
- * the scene, or if {@link #acquire(long)} was not called.
- */
- protected void checkLock() {
- ReentrantLock lock = Bridge.getLock();
- if (!lock.isHeldByCurrentThread()) {
- throw new IllegalStateException("scene must be acquired first. see #acquire(long)");
- }
- if (sCurrentContext != mContext) {
- throw new IllegalStateException("Thread acquired a scene but is rendering a different one");
- }
- }
-
- // VisibleForTesting
- public static Configuration getConfiguration(RenderParams params) {
- Configuration config = new Configuration();
-
- HardwareConfig hardwareConfig = params.getHardwareConfig();
-
- ScreenSize screenSize = hardwareConfig.getScreenSize();
- if (screenSize != null) {
- switch (screenSize) {
- case SMALL:
- config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_SMALL;
- break;
- case NORMAL:
- config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_NORMAL;
- break;
- case LARGE:
- config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_LARGE;
- break;
- case XLARGE:
- config.screenLayout |= Configuration.SCREENLAYOUT_SIZE_XLARGE;
- break;
- }
- }
-
- Density density = hardwareConfig.getDensity();
- if (density == null) {
- density = Density.MEDIUM;
- }
-
- config.screenWidthDp = hardwareConfig.getScreenWidth() / density.getDpiValue();
- config.screenHeightDp = hardwareConfig.getScreenHeight() / density.getDpiValue();
- if (config.screenHeightDp < config.screenWidthDp) {
- //noinspection SuspiciousNameCombination
- config.smallestScreenWidthDp = config.screenHeightDp;
- } else {
- config.smallestScreenWidthDp = config.screenWidthDp;
- }
- config.densityDpi = density.getDpiValue();
-
- // never run in compat mode:
- config.compatScreenWidthDp = config.screenWidthDp;
- config.compatScreenHeightDp = config.screenHeightDp;
-
- ScreenOrientation orientation = hardwareConfig.getOrientation();
- if (orientation != null) {
- switch (orientation) {
- case PORTRAIT:
- config.orientation = Configuration.ORIENTATION_PORTRAIT;
- break;
- case LANDSCAPE:
- config.orientation = Configuration.ORIENTATION_LANDSCAPE;
- break;
- case SQUARE:
- //noinspection deprecation
- config.orientation = Configuration.ORIENTATION_SQUARE;
- break;
- }
- } else {
- config.orientation = Configuration.ORIENTATION_UNDEFINED;
- }
-
- 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;
- }
- String locale = params.getLocale();
- if (locale != null && !locale.isEmpty()) config.locale = new Locale(locale);
-
- // TODO: fill in more config info.
-
- return config;
- }
-
-
- // --- FrameworkResourceIdProvider methods
-
- @Override
- public Integer getId(ResourceType resType, String resName) {
- return Bridge.getResourceId(resType, resName);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl;
-
-import com.android.ide.common.rendering.api.DrawableParams;
-import com.android.ide.common.rendering.api.HardwareConfig;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.Result.Status;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.RenderParamsFlags;
-import com.android.resources.ResourceType;
-
-import android.graphics.Bitmap;
-import android.graphics.Bitmap_Delegate;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.StateListDrawable;
-import android.view.AttachInfo_Accessor;
-import android.view.View.MeasureSpec;
-import android.widget.FrameLayout;
-
-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;
-
-/**
- * Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}.
- *
- * The class only provides a simple {@link #render()} method, but the full life-cycle of the
- * action must be respected.
- *
- * @see RenderAction
- *
- */
-public class RenderDrawable extends RenderAction<DrawableParams> {
-
- public RenderDrawable(DrawableParams params) {
- super(new DrawableParams(params));
- }
-
- public Result render() {
- checkLock();
- // get the drawable resource value
- DrawableParams params = getParams();
- HardwareConfig hardwareConfig = params.getHardwareConfig();
- ResourceValue drawableResource = params.getDrawable();
-
- // resolve it
- BridgeContext context = getContext();
- drawableResource = context.getRenderResources().resolveResValue(drawableResource);
-
- if (drawableResource == null) {
- return Status.ERROR_NOT_A_DRAWABLE.createResult();
- }
-
- ResourceType resourceType = drawableResource.getResourceType();
- if (resourceType != ResourceType.DRAWABLE && resourceType != ResourceType.MIPMAP) {
- return Status.ERROR_NOT_A_DRAWABLE.createResult();
- }
-
- Drawable d = ResourceHelper.getDrawable(drawableResource, context);
-
- final Boolean allStates =
- params.getFlag(RenderParamsFlags.FLAG_KEY_RENDER_ALL_DRAWABLE_STATES);
- if (allStates == Boolean.TRUE) {
- final List<BufferedImage> result;
-
- if (d instanceof StateListDrawable) {
- result = new ArrayList<BufferedImage>();
- final StateListDrawable stateList = (StateListDrawable) d;
- for (int i = 0; i < stateList.getStateCount(); i++) {
- final Drawable stateDrawable = stateList.getStateDrawable(i);
- result.add(renderImage(hardwareConfig, stateDrawable, context));
- }
- } else {
- result = Collections.singletonList(renderImage(hardwareConfig, d, context));
- }
-
- return Status.SUCCESS.createResult(result);
- } else {
- BufferedImage image = renderImage(hardwareConfig, d, context);
- return Status.SUCCESS.createResult(image);
- }
- }
-
- private BufferedImage renderImage(HardwareConfig hardwareConfig, Drawable d,
- BridgeContext context) {
- // create a simple FrameLayout
- FrameLayout content = new FrameLayout(context);
-
- // get the actual Drawable object to draw
- content.setBackground(d);
-
- // set the AttachInfo on the root view.
- AttachInfo_Accessor.setAttachInfo(content);
-
-
- // measure
- int w = d.getIntrinsicWidth();
- int h = d.getIntrinsicHeight();
-
- final int screenWidth = hardwareConfig.getScreenWidth();
- final int screenHeight = hardwareConfig.getScreenHeight();
-
- if (w == -1 || h == -1) {
- // Use screen size when either intrinsic width or height isn't available
- w = screenWidth;
- h = screenHeight;
- } else if (w > screenWidth || h > screenHeight) {
- // If image wouldn't fit to the screen, resize it to avoid cropping.
-
- // We need to find scale such that scale * w <= screenWidth, scale * h <= screenHeight
- double scale = Math.min((double) screenWidth / w, (double) screenHeight / h);
-
- // scale * w / scale * h = w / h, so, proportions are preserved.
- w = (int) Math.floor(scale * w);
- h = (int) Math.floor(scale * h);
- }
-
- int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY);
- int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
- content.measure(w_spec, h_spec);
-
- // now do the layout.
- content.layout(0, 0, w, h);
-
- // preDraw setup
- AttachInfo_Accessor.dispatchOnPreDraw(content);
-
- // draw into a new image
- BufferedImage image = getImage(w, h);
-
- // create an Android bitmap around the BufferedImage
- Bitmap bitmap = Bitmap_Delegate.createBitmap(image,
- true /*isMutable*/, hardwareConfig.getDensity());
-
- // create a Canvas around the Android bitmap
- Canvas canvas = new Canvas(bitmap);
- canvas.setDensity(hardwareConfig.getDensity().getDpiValue());
-
- // and draw
- content.draw(canvas);
- return image;
- }
-
- protected BufferedImage getImage(int w, int h) {
- BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
- Graphics2D gc = image.createGraphics();
- gc.setComposite(AlphaComposite.Src);
-
- gc.setColor(new Color(0x00000000, true));
- gc.fillRect(0, 0, w, h);
-
- // done
- gc.dispose();
-
- return image;
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl;
-
-import com.android.ide.common.rendering.api.AdapterBinding;
-import com.android.ide.common.rendering.api.HardwareConfig;
-import com.android.ide.common.rendering.api.IAnimationListener;
-import com.android.ide.common.rendering.api.ILayoutPullParser;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.RenderSession;
-import com.android.ide.common.rendering.api.ResourceReference;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.Result.Status;
-import com.android.ide.common.rendering.api.SessionParams;
-import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
-import com.android.ide.common.rendering.api.ViewInfo;
-import com.android.ide.common.rendering.api.ViewType;
-import com.android.internal.view.menu.ActionMenuItemView;
-import com.android.internal.view.menu.BridgeMenuItemImpl;
-import com.android.internal.view.menu.IconMenuItemView;
-import com.android.internal.view.menu.ListMenuItemView;
-import com.android.internal.view.menu.MenuItemImpl;
-import com.android.internal.view.menu.MenuView;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.android.RenderParamsFlags;
-import com.android.layoutlib.bridge.android.graphics.NopCanvas;
-import com.android.layoutlib.bridge.android.support.DesignLibUtil;
-import com.android.layoutlib.bridge.android.support.SupportPreferencesUtil;
-import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
-import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
-import com.android.resources.ResourceType;
-import com.android.tools.layoutlib.java.System_Delegate;
-import com.android.util.Pair;
-import com.android.util.PropertiesMap;
-
-import android.animation.AnimationThread;
-import android.animation.Animator;
-import android.animation.AnimatorInflater;
-import android.animation.LayoutTransition;
-import android.animation.LayoutTransition.TransitionListener;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.Fragment_Delegate;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap_Delegate;
-import android.graphics.Canvas;
-import android.os.Looper;
-import android.preference.Preference_Delegate;
-import android.view.AttachInfo_Accessor;
-import android.view.BridgeInflater;
-import android.view.Choreographer_Delegate;
-import android.view.IWindowManager;
-import android.view.IWindowManagerImpl;
-import android.view.Surface;
-import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.ViewGroup.MarginLayoutParams;
-import android.view.ViewParent;
-import android.view.WindowManagerGlobal_Delegate;
-import android.widget.AbsListView;
-import android.widget.AbsSpinner;
-import android.widget.ActionMenuView;
-import android.widget.AdapterView;
-import android.widget.ExpandableListView;
-import android.widget.FrameLayout;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.QuickContactBadge;
-import android.widget.TabHost;
-import android.widget.TabHost.TabSpec;
-import android.widget.TabWidget;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import static com.android.ide.common.rendering.api.Result.Status.ERROR_ANIM_NOT_FOUND;
-import static com.android.ide.common.rendering.api.Result.Status.ERROR_INFLATION;
-import static com.android.ide.common.rendering.api.Result.Status.ERROR_NOT_INFLATED;
-import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN;
-import static com.android.ide.common.rendering.api.Result.Status.ERROR_VIEWGROUP_NO_CHILDREN;
-import static com.android.ide.common.rendering.api.Result.Status.SUCCESS;
-import static com.android.layoutlib.bridge.util.ReflectionUtils.isInstanceOf;
-
-/**
- * Class implementing the render session.
- * <p/>
- * A session is a stateful representation of a layout file. It is initialized with data coming
- * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
- * be done on the layout.
- */
-public class RenderSessionImpl extends RenderAction<SessionParams> {
-
- private static final Canvas NOP_CANVAS = new NopCanvas();
-
- // scene state
- private RenderSession mScene;
- private BridgeXmlBlockParser mBlockParser;
- private BridgeInflater mInflater;
- private ViewGroup mViewRoot;
- private FrameLayout mContentRoot;
- private Canvas mCanvas;
- private int mMeasuredScreenWidth = -1;
- private int mMeasuredScreenHeight = -1;
- private boolean mIsAlphaChannelImage;
- /** If >= 0, a frame will be executed */
- private long mElapsedFrameTimeNanos = -1;
- /** True if one frame has been already executed to start the animations */
- private boolean mFirstFrameExecuted = false;
-
- // information being returned through the API
- private BufferedImage mImage;
- private List<ViewInfo> mViewInfoList;
- private List<ViewInfo> mSystemViewInfoList;
- private Layout.Builder mLayoutBuilder;
- private boolean mNewRenderSize;
-
- private static final class PostInflateException extends Exception {
- private static final long serialVersionUID = 1L;
-
- private PostInflateException(String message) {
- super(message);
- }
- }
-
- /**
- * Creates a layout scene with all the information coming from the layout bridge API.
- * <p>
- * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)},
- * which act as a
- * call to {@link RenderSessionImpl#acquire(long)}
- *
- * @see Bridge#createSession(SessionParams)
- */
- public RenderSessionImpl(SessionParams params) {
- super(new SessionParams(params));
- }
-
- /**
- * Initializes and acquires the scene, creating various Android objects such as context,
- * inflater, and parser.
- *
- * @param timeout the time to wait if another rendering is happening.
- *
- * @return whether the scene was prepared
- *
- * @see #acquire(long)
- * @see #release()
- */
- @Override
- public Result init(long timeout) {
- Result result = super.init(timeout);
- if (!result.isSuccess()) {
- return result;
- }
-
- SessionParams params = getParams();
- BridgeContext context = getContext();
-
- // use default of true in case it's not found to use alpha by default
- mIsAlphaChannelImage = ResourceHelper.getBooleanThemeValue(params.getResources(),
- "windowIsFloating", true, true);
-
- mLayoutBuilder = new Layout.Builder(params, context);
-
- // FIXME: find those out, and possibly add them to the render params
- boolean hasNavigationBar = true;
- //noinspection ConstantConditions
- IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
- context.getMetrics(), Surface.ROTATION_0, hasNavigationBar);
- WindowManagerGlobal_Delegate.setWindowManagerService(iwm);
-
- // build the inflater and parser.
- mInflater = new BridgeInflater(context, params.getLayoutlibCallback());
- context.setBridgeInflater(mInflater);
-
- mBlockParser = new BridgeXmlBlockParser(params.getLayoutDescription(), context, false);
-
- return SUCCESS.createResult();
- }
-
- /**
- * Measures the the current layout if needed (see {@link #invalidateRenderingSize}).
- */
- private void measureLayout(@NonNull SessionParams params) {
- // only do the screen measure when needed.
- if (mMeasuredScreenWidth != -1) {
- return;
- }
-
- RenderingMode renderingMode = params.getRenderingMode();
- HardwareConfig hardwareConfig = params.getHardwareConfig();
-
- mNewRenderSize = true;
- mMeasuredScreenWidth = hardwareConfig.getScreenWidth();
- mMeasuredScreenHeight = hardwareConfig.getScreenHeight();
-
- if (renderingMode != RenderingMode.NORMAL) {
- int widthMeasureSpecMode = renderingMode.isHorizExpand() ?
- MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
- : MeasureSpec.EXACTLY;
- int heightMeasureSpecMode = renderingMode.isVertExpand() ?
- MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
- : MeasureSpec.EXACTLY;
-
- // We used to compare the measured size of the content to the screen size but
- // this does not work anymore due to the 2 following issues:
- // - If the content is in a decor (system bar, title/action bar), the root view
- // will not resize even with the UNSPECIFIED because of the embedded layout.
- // - If there is no decor, but a dialog frame, then the dialog padding prevents
- // comparing the size of the content to the screen frame (as it would not
- // take into account the dialog padding).
-
- // The solution is to first get the content size in a normal rendering, inside
- // the decor or the dialog padding.
- // Then measure only the content with UNSPECIFIED to see the size difference
- // and apply this to the screen size.
-
- View measuredView = mContentRoot.getChildAt(0);
-
- // first measure the full layout, with EXACTLY to get the size of the
- // content as it is inside the decor/dialog
- @SuppressWarnings("deprecation")
- Pair<Integer, Integer> exactMeasure = measureView(
- mViewRoot, measuredView,
- mMeasuredScreenWidth, MeasureSpec.EXACTLY,
- mMeasuredScreenHeight, MeasureSpec.EXACTLY);
-
- // now measure the content only using UNSPECIFIED (where applicable, based on
- // the rendering mode). This will give us the size the content needs.
- @SuppressWarnings("deprecation")
- Pair<Integer, Integer> result = measureView(
- mContentRoot, mContentRoot.getChildAt(0),
- mMeasuredScreenWidth, widthMeasureSpecMode,
- mMeasuredScreenHeight, heightMeasureSpecMode);
-
- // If measuredView is not null, exactMeasure nor result will be null.
- assert exactMeasure != null;
- assert result != null;
-
- // now look at the difference and add what is needed.
- if (renderingMode.isHorizExpand()) {
- int measuredWidth = exactMeasure.getFirst();
- int neededWidth = result.getFirst();
- if (neededWidth > measuredWidth) {
- mMeasuredScreenWidth += neededWidth - measuredWidth;
- }
- if (mMeasuredScreenWidth < measuredWidth) {
- // If the screen width is less than the exact measured width,
- // expand to match.
- mMeasuredScreenWidth = measuredWidth;
- }
- }
-
- if (renderingMode.isVertExpand()) {
- int measuredHeight = exactMeasure.getSecond();
- int neededHeight = result.getSecond();
- if (neededHeight > measuredHeight) {
- mMeasuredScreenHeight += neededHeight - measuredHeight;
- }
- if (mMeasuredScreenHeight < measuredHeight) {
- // If the screen height is less than the exact measured height,
- // expand to match.
- mMeasuredScreenHeight = measuredHeight;
- }
- }
- }
- }
-
- /**
- * Inflates the layout.
- * <p>
- * {@link #acquire(long)} must have been called before this.
- *
- * @throws IllegalStateException if the current context is different than the one owned by
- * the scene, or if {@link #init(long)} was not called.
- */
- public Result inflate() {
- checkLock();
-
- try {
- mViewRoot = new Layout(mLayoutBuilder);
- mLayoutBuilder = null; // Done with the builder.
- mContentRoot = ((Layout) mViewRoot).getContentRoot();
- SessionParams params = getParams();
- BridgeContext context = getContext();
-
- if (Bridge.isLocaleRtl(params.getLocale())) {
- if (!params.isRtlSupported()) {
- Bridge.getLog().warning(LayoutLog.TAG_RTL_NOT_ENABLED,
- "You are using a right-to-left " +
- "(RTL) locale but RTL is not enabled", null);
- } else if (params.getSimulatedPlatformVersion() < 17) {
- // This will render ok because we are using the latest layoutlib but at least
- // warn the user that this might fail in a real device.
- Bridge.getLog().warning(LayoutLog.TAG_RTL_NOT_SUPPORTED, "You are using a " +
- "right-to-left " +
- "(RTL) locale but RTL is not supported for API level < 17", null);
- }
- }
-
- // Sets the project callback (custom view loader) to the fragment delegate so that
- // it can instantiate the custom Fragment.
- Fragment_Delegate.setLayoutlibCallback(params.getLayoutlibCallback());
-
- String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG);
- boolean isPreference = "PreferenceScreen".equals(rootTag);
- View view;
- if (isPreference) {
- // First try to use the support library inflater. If something fails, fallback
- // to the system preference inflater.
- view = SupportPreferencesUtil.inflatePreference(getContext(), mBlockParser,
- mContentRoot);
- if (view == null) {
- view = Preference_Delegate.inflatePreference(getContext(), mBlockParser,
- mContentRoot);
- }
- } else {
- view = mInflater.inflate(mBlockParser, mContentRoot);
- }
-
- // done with the parser, pop it.
- context.popParser();
-
- Fragment_Delegate.setLayoutlibCallback(null);
-
- // set the AttachInfo on the root view.
- AttachInfo_Accessor.setAttachInfo(mViewRoot);
-
- // post-inflate process. For now this supports TabHost/TabWidget
- postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null);
- mInflater.onDoneInflation();
-
- setActiveToolbar(view, context, params);
-
- measureLayout(params);
- measureView(mViewRoot, null /*measuredView*/,
- mMeasuredScreenWidth, MeasureSpec.EXACTLY,
- mMeasuredScreenHeight, MeasureSpec.EXACTLY);
- mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
- mSystemViewInfoList =
- visitAllChildren(mViewRoot, 0, 0, params.getExtendedViewInfoMode(),
- false);
-
- return SUCCESS.createResult();
- } catch (PostInflateException e) {
- return ERROR_INFLATION.createResult(e.getMessage(), e);
- } catch (Throwable e) {
- // get the real cause of the exception.
- Throwable t = e;
- while (t.getCause() != null) {
- t = t.getCause();
- }
-
- return ERROR_INFLATION.createResult(t.getMessage(), t);
- }
- }
-
- /**
- * Sets the time for which the next frame will be selected. The time is the elapsed time from
- * the current system nanos time. You
- */
- public void setElapsedFrameTimeNanos(long nanos) {
- mElapsedFrameTimeNanos = nanos;
- }
-
- /**
- * Runs a layout pass for the given view root
- */
- private static void doLayout(@NonNull BridgeContext context, @NonNull ViewGroup viewRoot,
- int width, int height) {
- // measure again with the size we need
- // This must always be done before the call to layout
- measureView(viewRoot, null /*measuredView*/,
- width, MeasureSpec.EXACTLY,
- height, MeasureSpec.EXACTLY);
-
- // now do the layout.
- viewRoot.layout(0, 0, width, height);
- handleScrolling(context, viewRoot);
- }
-
- /**
- * Renders the given view hierarchy to the passed canvas and returns the result of the render
- * operation.
- * @param canvas an optional canvas to render the views to. If null, only the measure and
- * layout steps will be executed.
- */
- private static Result renderAndBuildResult(@NonNull ViewGroup viewRoot, @Nullable Canvas canvas) {
- if (canvas == null) {
- return SUCCESS.createResult();
- }
-
- AttachInfo_Accessor.dispatchOnPreDraw(viewRoot);
- viewRoot.draw(canvas);
-
- return SUCCESS.createResult();
- }
-
- /**
- * Renders the scene.
- * <p>
- * {@link #acquire(long)} must have been called before this.
- *
- * @param freshRender whether the render is a new one and should erase the existing bitmap (in
- * the case where bitmaps are reused). This is typically needed when not playing
- * animations.)
- *
- * @throws IllegalStateException if the current context is different than the one owned by
- * the scene, or if {@link #acquire(long)} was not called.
- *
- * @see SessionParams#getRenderingMode()
- * @see RenderSession#render(long)
- */
- public Result render(boolean freshRender) {
- return renderAndBuildResult(freshRender, false);
- }
-
- /**
- * Measures the layout
- * <p>
- * {@link #acquire(long)} must have been called before this.
- *
- * @throws IllegalStateException if the current context is different than the one owned by
- * the scene, or if {@link #acquire(long)} was not called.
- *
- * @see SessionParams#getRenderingMode()
- * @see RenderSession#render(long)
- */
- public Result measure() {
- return renderAndBuildResult(false, true);
- }
-
- /**
- * Renders the scene.
- * <p>
- * {@link #acquire(long)} must have been called before this.
- *
- * @param freshRender whether the render is a new one and should erase the existing bitmap (in
- * the case where bitmaps are reused). This is typically needed when not playing
- * animations.)
- *
- * @throws IllegalStateException if the current context is different than the one owned by
- * the scene, or if {@link #acquire(long)} was not called.
- *
- * @see SessionParams#getRenderingMode()
- * @see RenderSession#render(long)
- */
- private Result renderAndBuildResult(boolean freshRender, boolean onlyMeasure) {
- checkLock();
-
- SessionParams params = getParams();
-
- try {
- if (mViewRoot == null) {
- return ERROR_NOT_INFLATED.createResult();
- }
-
- measureLayout(params);
-
- HardwareConfig hardwareConfig = params.getHardwareConfig();
- Result renderResult = SUCCESS.createResult();
- if (onlyMeasure) {
- // delete the canvas and image to reset them on the next full rendering
- mImage = null;
- mCanvas = null;
- doLayout(getContext(), mViewRoot, mMeasuredScreenWidth, mMeasuredScreenHeight);
- } else {
- // draw the views
- // create the BufferedImage into which the layout will be rendered.
- boolean newImage = false;
-
- // When disableBitmapCaching is true, we do not reuse mImage and
- // we create a new one in every render.
- // This is useful when mImage is just a wrapper of Graphics2D so
- // it doesn't get cached.
- boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag(
- RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING));
- if (mNewRenderSize || mCanvas == null || disableBitmapCaching) {
- mNewRenderSize = false;
- if (params.getImageFactory() != null) {
- mImage = params.getImageFactory().getImage(
- mMeasuredScreenWidth,
- mMeasuredScreenHeight);
- } else {
- mImage = new BufferedImage(
- mMeasuredScreenWidth,
- mMeasuredScreenHeight,
- BufferedImage.TYPE_INT_ARGB);
- newImage = true;
- }
-
- if (params.isBgColorOverridden()) {
- // since we override the content, it's the same as if it was a new image.
- newImage = true;
- Graphics2D gc = mImage.createGraphics();
- gc.setColor(new Color(params.getOverrideBgColor(), true));
- gc.setComposite(AlphaComposite.Src);
- gc.fillRect(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
- gc.dispose();
- }
-
- // create an Android bitmap around the BufferedImage
- Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
- true /*isMutable*/, hardwareConfig.getDensity());
-
- if (mCanvas == null) {
- // create a Canvas around the Android bitmap
- mCanvas = new Canvas(bitmap);
- } else {
- mCanvas.setBitmap(bitmap);
- }
- mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
- }
-
- if (freshRender && !newImage) {
- Graphics2D gc = mImage.createGraphics();
- gc.setComposite(AlphaComposite.Src);
-
- gc.setColor(new Color(0x00000000, true));
- gc.fillRect(0, 0,
- mMeasuredScreenWidth, mMeasuredScreenHeight);
-
- // done
- gc.dispose();
- }
-
- doLayout(getContext(), mViewRoot, mMeasuredScreenWidth, mMeasuredScreenHeight);
- if (mElapsedFrameTimeNanos >= 0) {
- long initialTime = System_Delegate.nanoTime();
- if (!mFirstFrameExecuted) {
- // We need to run an initial draw call to initialize the animations
- renderAndBuildResult(mViewRoot, NOP_CANVAS);
-
- // The first frame will initialize the animations
- Choreographer_Delegate.doFrame(initialTime);
- mFirstFrameExecuted = true;
- }
- // Second frame will move the animations
- Choreographer_Delegate.doFrame(initialTime + mElapsedFrameTimeNanos);
- }
- renderResult = renderAndBuildResult(mViewRoot, mCanvas);
- }
-
- mSystemViewInfoList =
- visitAllChildren(mViewRoot, 0, 0, params.getExtendedViewInfoMode(),
- false);
-
- // success!
- return renderResult;
- } catch (Throwable e) {
- // get the real cause of the exception.
- Throwable t = e;
- while (t.getCause() != null) {
- t = t.getCause();
- }
-
- return ERROR_UNKNOWN.createResult(t.getMessage(), t);
- }
- }
-
- /**
- * Executes {@link View#measure(int, int)} on a given view with the given parameters (used
- * to create measure specs with {@link MeasureSpec#makeMeasureSpec(int, int)}.
- *
- * if <var>measuredView</var> is non null, the method returns a {@link Pair} of (width, height)
- * for the view (using {@link View#getMeasuredWidth()} and {@link View#getMeasuredHeight()}).
- *
- * @param viewToMeasure the view on which to execute measure().
- * @param measuredView if non null, the view to query for its measured width/height.
- * @param width the width to use in the MeasureSpec.
- * @param widthMode the MeasureSpec mode to use for the width.
- * @param height the height to use in the MeasureSpec.
- * @param heightMode the MeasureSpec mode to use for the height.
- * @return the measured width/height if measuredView is non-null, null otherwise.
- */
- @SuppressWarnings("deprecation") // For the use of Pair
- private static Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
- int width, int widthMode, int height, int heightMode) {
- int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
- int h_spec = MeasureSpec.makeMeasureSpec(height, heightMode);
- viewToMeasure.measure(w_spec, h_spec);
-
- if (measuredView != null) {
- return Pair.of(measuredView.getMeasuredWidth(), measuredView.getMeasuredHeight());
- }
-
- return null;
- }
-
- /**
- * Animate an object
- * <p>
- * {@link #acquire(long)} must have been called before this.
- *
- * @throws IllegalStateException if the current context is different than the one owned by
- * the scene, or if {@link #acquire(long)} was not called.
- *
- * @see RenderSession#animate(Object, String, boolean, IAnimationListener)
- */
- public Result animate(Object targetObject, String animationName,
- boolean isFrameworkAnimation, IAnimationListener listener) {
- checkLock();
-
- BridgeContext context = getContext();
-
- // find the animation file.
- ResourceValue animationResource;
- int animationId = 0;
- if (isFrameworkAnimation) {
- animationResource = context.getRenderResources().getFrameworkResource(
- ResourceType.ANIMATOR, animationName);
- if (animationResource != null) {
- animationId = Bridge.getResourceId(ResourceType.ANIMATOR, animationName);
- }
- } else {
- animationResource = context.getRenderResources().getProjectResource(
- ResourceType.ANIMATOR, animationName);
- if (animationResource != null) {
- animationId = context.getLayoutlibCallback().getResourceId(
- ResourceType.ANIMATOR, animationName);
- }
- }
-
- if (animationResource != null) {
- try {
- Animator anim = AnimatorInflater.loadAnimator(context, animationId);
- if (anim != null) {
- anim.setTarget(targetObject);
-
- new PlayAnimationThread(anim, this, animationName, listener).start();
-
- return SUCCESS.createResult();
- }
- } catch (Exception e) {
- // get the real cause of the exception.
- Throwable t = e;
- while (t.getCause() != null) {
- t = t.getCause();
- }
-
- return ERROR_UNKNOWN.createResult(t.getMessage(), t);
- }
- }
-
- return ERROR_ANIM_NOT_FOUND.createResult();
- }
-
- /**
- * Insert a new child into an existing parent.
- * <p>
- * {@link #acquire(long)} must have been called before this.
- *
- * @throws IllegalStateException if the current context is different than the one owned by
- * the scene, or if {@link #acquire(long)} was not called.
- *
- * @see RenderSession#insertChild(Object, ILayoutPullParser, int, IAnimationListener)
- */
- public Result insertChild(final ViewGroup parentView, ILayoutPullParser childXml,
- final int index, IAnimationListener listener) {
- checkLock();
-
- BridgeContext context = getContext();
-
- // create a block parser for the XML
- BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
- childXml, context, false /* platformResourceFlag */);
-
- // inflate the child without adding it to the root since we want to control where it'll
- // get added. We do pass the parentView however to ensure that the layoutParams will
- // be created correctly.
- final View child = mInflater.inflate(blockParser, parentView, false /*attachToRoot*/);
- blockParser.ensurePopped();
-
- invalidateRenderingSize();
-
- if (listener != null) {
- new AnimationThread(this, "insertChild", listener) {
-
- @Override
- public Result preAnimation() {
- parentView.setLayoutTransition(new LayoutTransition());
- return addView(parentView, child, index);
- }
-
- @Override
- public void postAnimation() {
- parentView.setLayoutTransition(null);
- }
- }.start();
-
- // always return success since the real status will come through the listener.
- return SUCCESS.createResult(child);
- }
-
- // add it to the parentView in the correct location
- Result result = addView(parentView, child, index);
- if (!result.isSuccess()) {
- return result;
- }
-
- result = render(false /*freshRender*/);
- if (result.isSuccess()) {
- result = result.getCopyWithData(child);
- }
-
- return result;
- }
-
- /**
- * Adds a given view to a given parent at a given index.
- *
- * @param parent the parent to receive the view
- * @param view the view to add to the parent
- * @param index the index where to do the add.
- *
- * @return a Result with {@link Status#SUCCESS} or
- * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
- * adding views.
- */
- private Result addView(ViewGroup parent, View view, int index) {
- try {
- parent.addView(view, index);
- return SUCCESS.createResult();
- } catch (UnsupportedOperationException e) {
- // looks like this is a view class that doesn't support children manipulation!
- return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
- }
- }
-
- /**
- * Moves a view to a new parent at a given location
- * <p>
- * {@link #acquire(long)} must have been called before this.
- *
- * @throws IllegalStateException if the current context is different than the one owned by
- * the scene, or if {@link #acquire(long)} was not called.
- *
- * @see RenderSession#moveChild(Object, Object, int, Map, IAnimationListener)
- */
- public Result moveChild(final ViewGroup newParentView, final View childView, final int index,
- Map<String, String> layoutParamsMap, final IAnimationListener listener) {
- checkLock();
-
- invalidateRenderingSize();
-
- LayoutParams layoutParams = null;
- if (layoutParamsMap != null) {
- // need to create a new LayoutParams object for the new parent.
- layoutParams = newParentView.generateLayoutParams(
- new BridgeLayoutParamsMapAttributes(layoutParamsMap));
- }
-
- // get the current parent of the view that needs to be moved.
- final ViewGroup previousParent = (ViewGroup) childView.getParent();
-
- if (listener != null) {
- final LayoutParams params = layoutParams;
-
- // there is no support for animating views across layouts, so in case the new and old
- // parent views are different we fake the animation through a no animation thread.
- if (previousParent != newParentView) {
- new Thread("not animated moveChild") {
- @Override
- public void run() {
- Result result = moveView(previousParent, newParentView, childView, index,
- params);
- if (!result.isSuccess()) {
- listener.done(result);
- }
-
- // ready to do the work, acquire the scene.
- result = acquire(250);
- if (!result.isSuccess()) {
- listener.done(result);
- return;
- }
-
- try {
- result = render(false /*freshRender*/);
- if (result.isSuccess()) {
- listener.onNewFrame(RenderSessionImpl.this.getSession());
- }
- } finally {
- release();
- }
-
- listener.done(result);
- }
- }.start();
- } else {
- new AnimationThread(this, "moveChild", listener) {
-
- @Override
- public Result preAnimation() {
- // set up the transition for the parent.
- LayoutTransition transition = new LayoutTransition();
- previousParent.setLayoutTransition(transition);
-
- // tweak the animation durations and start delays (to match the duration of
- // animation playing just before).
- // Note: Cannot user Animation.setDuration() directly. Have to set it
- // on the LayoutTransition.
- transition.setDuration(LayoutTransition.DISAPPEARING, 100);
- // CHANGE_DISAPPEARING plays after DISAPPEARING
- transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 100);
-
- transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, 100);
-
- transition.setDuration(LayoutTransition.CHANGE_APPEARING, 100);
- // CHANGE_APPEARING plays after CHANGE_APPEARING
- transition.setStartDelay(LayoutTransition.APPEARING, 100);
-
- transition.setDuration(LayoutTransition.APPEARING, 100);
-
- return moveView(previousParent, newParentView, childView, index, params);
- }
-
- @Override
- public void postAnimation() {
- previousParent.setLayoutTransition(null);
- newParentView.setLayoutTransition(null);
- }
- }.start();
- }
-
- // always return success since the real status will come through the listener.
- return SUCCESS.createResult(layoutParams);
- }
-
- Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
- if (!result.isSuccess()) {
- return result;
- }
-
- result = render(false /*freshRender*/);
- if (layoutParams != null && result.isSuccess()) {
- result = result.getCopyWithData(layoutParams);
- }
-
- return result;
- }
-
- /**
- * Moves a View from its current parent to a new given parent at a new given location, with
- * an optional new {@link LayoutParams} instance
- *
- * @param previousParent the previous parent, still owning the child at the time of the call.
- * @param newParent the new parent
- * @param movedView the view to move
- * @param index the new location in the new parent
- * @param params an option (can be null) {@link LayoutParams} instance.
- *
- * @return a Result with {@link Status#SUCCESS} or
- * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
- * adding views.
- */
- private Result moveView(ViewGroup previousParent, final ViewGroup newParent,
- final View movedView, final int index, final LayoutParams params) {
- try {
- // check if there is a transition on the previousParent.
- LayoutTransition previousTransition = previousParent.getLayoutTransition();
- if (previousTransition != null) {
- // in this case there is an animation. This means we have to wait for the child's
- // parent reference to be null'ed out so that we can add it to the new parent.
- // It is technically removed right before the DISAPPEARING animation is done (if
- // the animation of this type is not null, otherwise it's after which is impossible
- // to handle).
- // Because there is no move animation, if the new parent is the same as the old
- // parent, we need to wait until the CHANGE_DISAPPEARING animation is done before
- // adding the child or the child will appear in its new location before the
- // other children have made room for it.
-
- // add a listener to the transition to be notified of the actual removal.
- previousTransition.addTransitionListener(new TransitionListener() {
- private int mChangeDisappearingCount = 0;
-
- @Override
- public void startTransition(LayoutTransition transition, ViewGroup container,
- View view, int transitionType) {
- if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
- mChangeDisappearingCount++;
- }
- }
-
- @Override
- public void endTransition(LayoutTransition transition, ViewGroup container,
- View view, int transitionType) {
- if (transitionType == LayoutTransition.CHANGE_DISAPPEARING) {
- mChangeDisappearingCount--;
- }
-
- if (transitionType == LayoutTransition.CHANGE_DISAPPEARING &&
- mChangeDisappearingCount == 0) {
- // add it to the parentView in the correct location
- if (params != null) {
- newParent.addView(movedView, index, params);
- } else {
- newParent.addView(movedView, index);
- }
- }
- }
- });
-
- // remove the view from the current parent.
- previousParent.removeView(movedView);
-
- // and return since adding the view to the new parent is done in the listener.
- return SUCCESS.createResult();
- } else {
- // standard code with no animation. pretty simple.
- previousParent.removeView(movedView);
-
- // add it to the parentView in the correct location
- if (params != null) {
- newParent.addView(movedView, index, params);
- } else {
- newParent.addView(movedView, index);
- }
-
- return SUCCESS.createResult();
- }
- } catch (UnsupportedOperationException e) {
- // looks like this is a view class that doesn't support children manipulation!
- return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
- }
- }
-
- /**
- * Removes a child from its current parent.
- * <p>
- * {@link #acquire(long)} must have been called before this.
- *
- * @throws IllegalStateException if the current context is different than the one owned by
- * the scene, or if {@link #acquire(long)} was not called.
- *
- * @see RenderSession#removeChild(Object, IAnimationListener)
- */
- public Result removeChild(final View childView, IAnimationListener listener) {
- checkLock();
-
- invalidateRenderingSize();
-
- final ViewGroup parent = (ViewGroup) childView.getParent();
-
- if (listener != null) {
- new AnimationThread(this, "moveChild", listener) {
-
- @Override
- public Result preAnimation() {
- parent.setLayoutTransition(new LayoutTransition());
- return removeView(parent, childView);
- }
-
- @Override
- public void postAnimation() {
- parent.setLayoutTransition(null);
- }
- }.start();
-
- // always return success since the real status will come through the listener.
- return SUCCESS.createResult();
- }
-
- Result result = removeView(parent, childView);
- if (!result.isSuccess()) {
- return result;
- }
-
- return render(false /*freshRender*/);
- }
-
- /**
- * Removes a given view from its current parent.
- *
- * @param view the view to remove from its parent
- *
- * @return a Result with {@link Status#SUCCESS} or
- * {@link Status#ERROR_VIEWGROUP_NO_CHILDREN} if the given parent doesn't support
- * adding views.
- */
- private Result removeView(ViewGroup parent, View view) {
- try {
- parent.removeView(view);
- return SUCCESS.createResult();
- } catch (UnsupportedOperationException e) {
- // looks like this is a view class that doesn't support children manipulation!
- return ERROR_VIEWGROUP_NO_CHILDREN.createResult();
- }
- }
-
- /**
- * Post process on a view hierarchy that was just inflated.
- * <p/>
- * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the
- * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
- * based on the content of the {@link FrameLayout}.
- * @param view the root view to process.
- * @param layoutlibCallback callback to the project.
- * @param skip the view and it's children are not processed.
- */
- @SuppressWarnings("deprecation") // For the use of Pair
- private void postInflateProcess(View view, LayoutlibCallback layoutlibCallback, View skip)
- throws PostInflateException {
- if (view == skip) {
- return;
- }
- if (view instanceof TabHost) {
- setupTabHost((TabHost) view, layoutlibCallback);
- } else if (view instanceof QuickContactBadge) {
- QuickContactBadge badge = (QuickContactBadge) view;
- badge.setImageToDefault();
- } else if (view instanceof AdapterView<?>) {
- // get the view ID.
- int id = view.getId();
-
- BridgeContext context = getContext();
-
- // get a ResourceReference from the integer ID.
- ResourceReference listRef = context.resolveId(id);
-
- if (listRef != null) {
- SessionParams params = getParams();
- AdapterBinding binding = params.getAdapterBindings().get(listRef);
-
- // if there was no adapter binding, trying to get it from the call back.
- if (binding == null) {
- binding = layoutlibCallback.getAdapterBinding(
- listRef, context.getViewKey(view), view);
- }
-
- if (binding != null) {
-
- if (view instanceof AbsListView) {
- if ((binding.getFooterCount() > 0 || binding.getHeaderCount() > 0) &&
- view instanceof ListView) {
- ListView list = (ListView) view;
-
- boolean skipCallbackParser = false;
-
- int count = binding.getHeaderCount();
- for (int i = 0; i < count; i++) {
- Pair<View, Boolean> pair = context.inflateView(
- binding.getHeaderAt(i),
- list, false, skipCallbackParser);
- if (pair.getFirst() != null) {
- list.addHeaderView(pair.getFirst());
- }
-
- skipCallbackParser |= pair.getSecond();
- }
-
- count = binding.getFooterCount();
- for (int i = 0; i < count; i++) {
- Pair<View, Boolean> pair = context.inflateView(
- binding.getFooterAt(i),
- list, false, skipCallbackParser);
- if (pair.getFirst() != null) {
- list.addFooterView(pair.getFirst());
- }
-
- skipCallbackParser |= pair.getSecond();
- }
- }
-
- if (view instanceof ExpandableListView) {
- ((ExpandableListView) view).setAdapter(
- new FakeExpandableAdapter(listRef, binding, layoutlibCallback));
- } else {
- ((AbsListView) view).setAdapter(
- new FakeAdapter(listRef, binding, layoutlibCallback));
- }
- } else if (view instanceof AbsSpinner) {
- ((AbsSpinner) view).setAdapter(
- new FakeAdapter(listRef, binding, layoutlibCallback));
- }
- }
- }
- } else if (view instanceof ViewGroup) {
- mInflater.postInflateProcess(view);
- ViewGroup group = (ViewGroup) view;
- final int count = group.getChildCount();
- for (int c = 0; c < count; c++) {
- View child = group.getChildAt(c);
- postInflateProcess(child, layoutlibCallback, skip);
- }
- }
- }
-
- /**
- * If the root layout is a CoordinatorLayout with an AppBar:
- * Set the title of the AppBar to the title of the activity context.
- */
- private void setActiveToolbar(View view, BridgeContext context, SessionParams params) {
- View coordinatorLayout = findChildView(view, DesignLibUtil.CN_COORDINATOR_LAYOUT);
- if (coordinatorLayout == null) {
- return;
- }
- View appBar = findChildView(coordinatorLayout, DesignLibUtil.CN_APPBAR_LAYOUT);
- if (appBar == null) {
- return;
- }
- ViewGroup collapsingToolbar =
- (ViewGroup) findChildView(appBar, DesignLibUtil.CN_COLLAPSING_TOOLBAR_LAYOUT);
- if (collapsingToolbar == null) {
- return;
- }
- if (!hasToolbar(collapsingToolbar)) {
- return;
- }
- RenderResources res = context.getRenderResources();
- String title = params.getAppLabel();
- ResourceValue titleValue = res.findResValue(title, false);
- if (titleValue != null && titleValue.getValue() != null) {
- title = titleValue.getValue();
- }
- DesignLibUtil.setTitle(collapsingToolbar, title);
- }
-
- private View findChildView(View view, String className) {
- if (!(view instanceof ViewGroup)) {
- return null;
- }
- ViewGroup group = (ViewGroup) view;
- for (int i = 0; i < group.getChildCount(); i++) {
- if (isInstanceOf(group.getChildAt(i), className)) {
- return group.getChildAt(i);
- }
- }
- return null;
- }
-
- private boolean hasToolbar(View collapsingToolbar) {
- if (!(collapsingToolbar instanceof ViewGroup)) {
- return false;
- }
- ViewGroup group = (ViewGroup) collapsingToolbar;
- for (int i = 0; i < group.getChildCount(); i++) {
- if (isInstanceOf(group.getChildAt(i), DesignLibUtil.CN_TOOLBAR)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Set the scroll position on all the components with the "scrollX" and "scrollY" attribute. If
- * the component supports nested scrolling attempt that first, then use the unconsumed scroll
- * part to scroll the content in the component.
- */
- private static void handleScrolling(BridgeContext context, View view) {
- int scrollPosX = context.getScrollXPos(view);
- int scrollPosY = context.getScrollYPos(view);
- if (scrollPosX != 0 || scrollPosY != 0) {
- if (view.isNestedScrollingEnabled()) {
- int[] consumed = new int[2];
- int axis = scrollPosX != 0 ? View.SCROLL_AXIS_HORIZONTAL : 0;
- axis |= scrollPosY != 0 ? View.SCROLL_AXIS_VERTICAL : 0;
- if (view.startNestedScroll(axis)) {
- view.dispatchNestedPreScroll(scrollPosX, scrollPosY, consumed, null);
- view.dispatchNestedScroll(consumed[0], consumed[1], scrollPosX, scrollPosY,
- null);
- view.stopNestedScroll();
- scrollPosX -= consumed[0];
- scrollPosY -= consumed[1];
- }
- }
- if (scrollPosX != 0 || scrollPosY != 0) {
- view.scrollTo(scrollPosX, scrollPosY);
- }
- }
-
- if (!(view instanceof ViewGroup)) {
- return;
- }
- ViewGroup group = (ViewGroup) view;
- for (int i = 0; i < group.getChildCount(); i++) {
- View child = group.getChildAt(i);
- handleScrolling(context, child);
- }
- }
-
- /**
- * Sets up a {@link TabHost} object.
- * @param tabHost the TabHost to setup.
- * @param layoutlibCallback The project callback object to access the project R class.
- * @throws PostInflateException if TabHost is missing the required ids for TabHost
- */
- private void setupTabHost(TabHost tabHost, LayoutlibCallback layoutlibCallback)
- throws PostInflateException {
- // look for the TabWidget, and the FrameLayout. They have their own specific names
- View v = tabHost.findViewById(android.R.id.tabs);
-
- if (v == null) {
- throw new PostInflateException(
- "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
- }
-
- if (!(v instanceof TabWidget)) {
- throw new PostInflateException(String.format(
- "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
- "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
- }
-
- v = tabHost.findViewById(android.R.id.tabcontent);
-
- if (v == null) {
- // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty)
- //noinspection SpellCheckingInspection
- throw new PostInflateException(
- "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
- }
-
- if (!(v instanceof FrameLayout)) {
- //noinspection SpellCheckingInspection
- throw new PostInflateException(String.format(
- "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
- "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
- }
-
- FrameLayout content = (FrameLayout)v;
-
- // now process the content of the frameLayout and dynamically create tabs for it.
- final int count = content.getChildCount();
-
- // this must be called before addTab() so that the TabHost searches its TabWidget
- // and FrameLayout.
- tabHost.setup();
-
- if (count == 0) {
- // Create a dummy child to get a single tab
- TabSpec spec = tabHost.newTabSpec("tag")
- .setIndicator("Tab Label", tabHost.getResources()
- .getDrawable(android.R.drawable.ic_menu_info_details, null))
- .setContent(tag -> new LinearLayout(getContext()));
- tabHost.addTab(spec);
- } else {
- // for each child of the frameLayout, add a new TabSpec
- for (int i = 0 ; i < count ; i++) {
- View child = content.getChildAt(i);
- String tabSpec = String.format("tab_spec%d", i+1);
- @SuppressWarnings("ConstantConditions") // child cannot be null.
- int id = child.getId();
- @SuppressWarnings("deprecation")
- Pair<ResourceType, String> resource = layoutlibCallback.resolveResourceId(id);
- String name;
- if (resource != null) {
- name = resource.getSecond();
- } else {
- name = String.format("Tab %d", i+1); // default name if id is unresolved.
- }
- tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
- }
- }
- }
-
- /**
- * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the
- * bounds of all the views.
- *
- * @param view the root View
- * @param hOffset horizontal offset for the view bounds.
- * @param vOffset vertical offset for the view bounds.
- * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
- * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
- * content frame.
- *
- * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
- */
- private ViewInfo visit(View view, int hOffset, int vOffset, boolean setExtendedInfo,
- boolean isContentFrame) {
- ViewInfo result = createViewInfo(view, hOffset, vOffset, setExtendedInfo, isContentFrame);
-
- if (view instanceof ViewGroup) {
- ViewGroup group = ((ViewGroup) view);
- result.setChildren(visitAllChildren(group, isContentFrame ? 0 : hOffset,
- isContentFrame ? 0 : vOffset,
- setExtendedInfo, isContentFrame));
- }
- return result;
- }
-
- /**
- * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo}
- * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with
- * the children of the {@code mContentRoot}.
- *
- * @param viewGroup the root View
- * @param hOffset horizontal offset from the top for the content view frame.
- * @param vOffset vertical offset from the top for the content view frame.
- * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
- * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
- * content frame. {@code false} if the {@code ViewInfo} to be created is
- * part of the system decor.
- */
- private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int hOffset, int vOffset,
- boolean setExtendedInfo, boolean isContentFrame) {
- if (viewGroup == null) {
- return null;
- }
-
- if (!isContentFrame) {
- vOffset += viewGroup.getTop();
- hOffset += viewGroup.getLeft();
- }
-
- int childCount = viewGroup.getChildCount();
- if (viewGroup == mContentRoot) {
- List<ViewInfo> childrenWithoutOffset = new ArrayList<>(childCount);
- List<ViewInfo> childrenWithOffset = new ArrayList<>(childCount);
- for (int i = 0; i < childCount; i++) {
- ViewInfo[] childViewInfo =
- visitContentRoot(viewGroup.getChildAt(i), hOffset, vOffset,
- setExtendedInfo);
- childrenWithoutOffset.add(childViewInfo[0]);
- childrenWithOffset.add(childViewInfo[1]);
- }
- mViewInfoList = childrenWithOffset;
- return childrenWithoutOffset;
- } else {
- List<ViewInfo> children = new ArrayList<>(childCount);
- for (int i = 0; i < childCount; i++) {
- children.add(visit(viewGroup.getChildAt(i), hOffset, vOffset, setExtendedInfo,
- isContentFrame));
- }
- return children;
- }
- }
-
- /**
- * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the
- * bounds of all the views. It returns two {@code ViewInfo} objects with the same children,
- * one with the {@code offset} and other without the {@code offset}. The offset is needed to
- * get the right bounds if the {@code ViewInfo} hierarchy is accessed from
- * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
- * offset is not needed.
- *
- * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
- * index 1 is with the offset.
- */
- @NonNull
- private ViewInfo[] visitContentRoot(View view, int hOffset, int vOffset,
- boolean setExtendedInfo) {
- ViewInfo[] result = new ViewInfo[2];
- if (view == null) {
- return result;
- }
-
- result[0] = createViewInfo(view, 0, 0, setExtendedInfo, true);
- result[1] = createViewInfo(view, hOffset, vOffset, setExtendedInfo, true);
- if (view instanceof ViewGroup) {
- List<ViewInfo> children =
- visitAllChildren((ViewGroup) view, 0, 0, setExtendedInfo, true);
- result[0].setChildren(children);
- result[1].setChildren(children);
- }
- return result;
- }
-
- /**
- * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
- * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
- * set.
- * @param hOffset horizontal offset for the view bounds. Used only if view is part of the
- * content frame.
- * @param vOffset vertial an offset for the view bounds. Used only if view is part of the
- * content frame.
- */
- private ViewInfo createViewInfo(View view, int hOffset, int vOffset, boolean setExtendedInfo,
- boolean isContentFrame) {
- if (view == null) {
- return null;
- }
-
- ViewParent parent = view.getParent();
- ViewInfo result;
- if (isContentFrame) {
- // Account for parent scroll values when calculating the bounding box
- int scrollX = parent != null ? ((View)parent).getScrollX() : 0;
- int scrollY = parent != null ? ((View)parent).getScrollY() : 0;
-
- // The view is part of the layout added by the user. Hence,
- // the ViewCookie may be obtained only through the Context.
- result = new ViewInfo(view.getClass().getName(),
- getContext().getViewKey(view), -scrollX + view.getLeft() + hOffset,
- -scrollY + view.getTop() + vOffset, -scrollX + view.getRight() + hOffset,
- -scrollY + view.getBottom() + vOffset,
- view, view.getLayoutParams());
- } else {
- // We are part of the system decor.
- SystemViewInfo r = new SystemViewInfo(view.getClass().getName(),
- getViewKey(view),
- view.getLeft(), view.getTop(), view.getRight(),
- view.getBottom(), view, view.getLayoutParams());
- result = r;
- // We currently mark three kinds of views:
- // 1. Menus in the Action Bar
- // 2. Menus in the Overflow popup.
- // 3. The overflow popup button.
- if (view instanceof ListMenuItemView) {
- // Mark 2.
- // All menus in the popup are of type ListMenuItemView.
- r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU);
- } else {
- // Mark 3.
- ViewGroup.LayoutParams lp = view.getLayoutParams();
- if (lp instanceof ActionMenuView.LayoutParams &&
- ((ActionMenuView.LayoutParams) lp).isOverflowButton) {
- r.setViewType(ViewType.ACTION_BAR_OVERFLOW);
- } else {
- // Mark 1.
- // A view is a menu in the Action Bar is it is not the overflow button and of
- // its parent is of type ActionMenuView. We can also check if the view is
- // instanceof ActionMenuItemView but that will fail for menus using
- // actionProviderClass.
- while (parent != mViewRoot && parent instanceof ViewGroup) {
- if (parent instanceof ActionMenuView) {
- r.setViewType(ViewType.ACTION_BAR_MENU);
- break;
- }
- parent = parent.getParent();
- }
- }
- }
- }
-
- if (setExtendedInfo) {
- MarginLayoutParams marginParams = null;
- LayoutParams params = view.getLayoutParams();
- if (params instanceof MarginLayoutParams) {
- marginParams = (MarginLayoutParams) params;
- }
- result.setExtendedInfo(view.getBaseline(),
- marginParams != null ? marginParams.leftMargin : 0,
- marginParams != null ? marginParams.topMargin : 0,
- marginParams != null ? marginParams.rightMargin : 0,
- marginParams != null ? marginParams.bottomMargin : 0);
- }
-
- return result;
- }
-
- /* (non-Javadoc)
- * The cookie for menu items are stored in menu item and not in the map from View stored in
- * BridgeContext.
- */
- @Nullable
- private Object getViewKey(View view) {
- BridgeContext context = getContext();
- if (!(view instanceof MenuView.ItemView)) {
- return context.getViewKey(view);
- }
- MenuItemImpl menuItem;
- if (view instanceof ActionMenuItemView) {
- menuItem = ((ActionMenuItemView) view).getItemData();
- } else if (view instanceof ListMenuItemView) {
- menuItem = ((ListMenuItemView) view).getItemData();
- } else if (view instanceof IconMenuItemView) {
- menuItem = ((IconMenuItemView) view).getItemData();
- } else {
- menuItem = null;
- }
- if (menuItem instanceof BridgeMenuItemImpl) {
- return ((BridgeMenuItemImpl) menuItem).getViewCookie();
- }
-
- return null;
- }
-
- public void invalidateRenderingSize() {
- mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
- }
-
- public BufferedImage getImage() {
- return mImage;
- }
-
- public boolean isAlphaChannelImage() {
- return mIsAlphaChannelImage;
- }
-
- public List<ViewInfo> getViewInfos() {
- return mViewInfoList;
- }
-
- public List<ViewInfo> getSystemViewInfos() {
- return mSystemViewInfoList;
- }
-
- public Map<Object, PropertiesMap> getDefaultProperties() {
- return getContext().getDefaultProperties();
- }
-
- public void setScene(RenderSession session) {
- mScene = session;
- }
-
- public RenderSession getSession() {
- return mScene;
- }
-
- public void dispose() {
- boolean createdLooper = false;
- if (Looper.myLooper() == null) {
- // Detaching the root view from the window will try to stop any running animations.
- // The stop method checks that it can run in the looper so, if there is no current
- // looper, we create a temporary one to complete the shutdown.
- Bridge.prepareThread();
- createdLooper = true;
- }
- AttachInfo_Accessor.detachFromWindow(mViewRoot);
- if (mCanvas != null) {
- mCanvas.release();
- mCanvas = null;
- }
- if (mViewInfoList != null) {
- mViewInfoList.clear();
- }
- if (mSystemViewInfoList != null) {
- mSystemViewInfoList.clear();
- }
- mImage = null;
- mViewRoot = null;
- mContentRoot = null;
-
- if (createdLooper) {
- Bridge.cleanupThread();
- Choreographer_Delegate.dispose();
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl;
-
-import com.android.SdkConstants;
-import com.android.ide.common.rendering.api.DensityBasedResourceValue;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.internal.util.XmlUtils;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.android.RenderParamsFlags;
-import com.android.ninepatch.NinePatch;
-import com.android.ninepatch.NinePatchChunk;
-import com.android.resources.Density;
-
-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.content.res.ComplexColor;
-import android.content.res.ComplexColor_Accessor;
-import android.content.res.FontResourcesParser;
-import android.content.res.GradientColor;
-import android.content.res.Resources.Theme;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap_Delegate;
-import android.graphics.Color;
-import android.graphics.NinePatch_Delegate;
-import android.graphics.Rect;
-import android.graphics.Typeface;
-import android.graphics.Typeface_Accessor;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.NinePatchDrawable;
-import android.text.FontConfig;
-import android.util.TypedValue;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Helper class to provide various conversion method used in handling android resources.
- */
-public final class ResourceHelper {
-
- private final static Pattern sFloatPattern = Pattern.compile("(-?[0-9]+(?:\\.[0-9]+)?)(.*)");
- private final static float[] sFloatOut = new float[1];
-
- private final static TypedValue mValue = new TypedValue();
-
- /**
- * Returns the color value represented by the given string value
- * @param value the color value
- * @return the color as an int
- * @throws NumberFormatException if the conversion failed.
- */
- public static int getColor(String value) {
- if (value != null) {
- value = value.trim();
- if (!value.startsWith("#")) {
- if (value.startsWith(SdkConstants.PREFIX_THEME_REF)) {
- throw new NumberFormatException(String.format(
- "Attribute '%s' not found. Are you using the right theme?", value));
- }
- throw new NumberFormatException(
- String.format("Color value '%s' must start with #", value));
- }
-
- value = value.substring(1);
-
- // make sure it's not longer than 32bit
- if (value.length() > 8) {
- throw new NumberFormatException(String.format(
- "Color value '%s' is too long. Format is either" +
- "#AARRGGBB, #RRGGBB, #RGB, or #ARGB",
- value));
- }
-
- if (value.length() == 3) { // RGB format
- char[] color = new char[8];
- color[0] = color[1] = 'F';
- color[2] = color[3] = value.charAt(0);
- color[4] = color[5] = value.charAt(1);
- color[6] = color[7] = value.charAt(2);
- value = new String(color);
- } else if (value.length() == 4) { // ARGB format
- char[] color = new char[8];
- color[0] = color[1] = value.charAt(0);
- color[2] = color[3] = value.charAt(1);
- color[4] = color[5] = value.charAt(2);
- color[6] = color[7] = value.charAt(3);
- value = new String(color);
- } else if (value.length() == 6) {
- value = "FF" + value;
- }
-
- // this is a RRGGBB or AARRGGBB value
-
- // Integer.parseInt will fail to parse strings like "ff191919", so we use
- // a Long, but cast the result back into an int, since we know that we're only
- // dealing with 32 bit values.
- return (int)Long.parseLong(value, 16);
- }
-
- throw new NumberFormatException();
- }
-
- /**
- * Returns a {@link ComplexColor} from the given {@link ResourceValue}
- *
- * @param resValue the value containing a color value or a file path to a complex color
- * definition
- * @param context the current context
- * @param theme the theme to use when resolving the complex color
- * @param allowGradients when false, only {@link ColorStateList} will be returned. If a {@link
- * GradientColor} is found, null will be returned.
- */
- @Nullable
- private static ComplexColor getInternalComplexColor(@NonNull ResourceValue resValue,
- @NonNull BridgeContext context, @Nullable Theme theme, boolean allowGradients) {
- String value = resValue.getValue();
- if (value == null || RenderResources.REFERENCE_NULL.equals(value)) {
- return null;
- }
-
- XmlPullParser parser = null;
- // first check if the value is a file (xml most likely)
- Boolean psiParserSupport = context.getLayoutlibCallback().getFlag(
- RenderParamsFlags.FLAG_KEY_XML_FILE_PARSER_SUPPORT);
- if (psiParserSupport != null && psiParserSupport) {
- parser = context.getLayoutlibCallback().getXmlFileParser(value);
- }
- if (parser == null) {
- File f = new File(value);
- if (f.isFile()) {
- // let the framework inflate the color from the XML file, by
- // providing an XmlPullParser
- try {
- parser = ParserFactory.create(f);
- } catch (XmlPullParserException | FileNotFoundException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + value, e, null /*data*/);
- }
- }
- }
-
- if (parser != null) {
- try {
- BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
- parser, context, resValue.isFramework());
- try {
- // Advance the parser to the first element so we can detect if it's a
- // color list or a gradient color
- int type;
- //noinspection StatementWithEmptyBody
- while ((type = blockParser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- // Seek parser to start tag.
- }
-
- if (type != XmlPullParser.START_TAG) {
- assert false : "No start tag found";
- return null;
- }
-
- final String name = blockParser.getName();
- if (allowGradients && "gradient".equals(name)) {
- return ComplexColor_Accessor.createGradientColorFromXmlInner(
- context.getResources(),
- blockParser, blockParser,
- theme);
- } else if ("selector".equals(name)) {
- return ComplexColor_Accessor.createColorStateListFromXmlInner(
- context.getResources(),
- blockParser, blockParser,
- theme);
- }
- } finally {
- blockParser.ensurePopped();
- }
- } catch (XmlPullParserException e) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- "Failed to configure parser for " + value, e, null /*data*/);
- // we'll return null below.
- } catch (Exception e) {
- // this is an error and not warning since the file existence is
- // checked before attempting to parse it.
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed to parse file " + value, e, null /*data*/);
-
- return null;
- }
- } else {
- // try to load the color state list from an int
- try {
- int color = getColor(value);
- return ColorStateList.valueOf(color);
- } catch (NumberFormatException e) {
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Failed to convert " + value + " into a ColorStateList", e,
- null /*data*/);
- }
- }
-
- return null;
- }
-
- /**
- * Returns a {@link ColorStateList} from the given {@link ResourceValue}
- *
- * @param resValue the value containing a color value or a file path to a complex color
- * definition
- * @param context the current context
- */
- @Nullable
- public static ColorStateList getColorStateList(@NonNull ResourceValue resValue,
- @NonNull BridgeContext context) {
- return (ColorStateList) getInternalComplexColor(resValue, context, context.getTheme(),
- false);
- }
-
- /**
- * Returns a {@link ComplexColor} from the given {@link ResourceValue}
- *
- * @param resValue the value containing a color value or a file path to a complex color
- * definition
- * @param context the current context
- */
- @Nullable
- public static ComplexColor getComplexColor(@NonNull ResourceValue resValue,
- @NonNull BridgeContext context) {
- return getInternalComplexColor(resValue, context, context.getTheme(), true);
- }
-
- /**
- * Returns a drawable from the given value.
- * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable,
- * or an hexadecimal color
- * @param context the current context
- */
- public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
- return getDrawable(value, context, null);
- }
-
- /**
- * Returns a drawable from the given value.
- * @param value The value that contains a path to a 9 patch, a bitmap or a xml based drawable,
- * or an hexadecimal color
- * @param context the current context
- * @param theme the theme to be used to inflate the drawable.
- */
- public static Drawable getDrawable(ResourceValue value, BridgeContext context, Theme theme) {
- if (value == null) {
- return null;
- }
- String stringValue = value.getValue();
- if (RenderResources.REFERENCE_NULL.equals(stringValue)) {
- return null;
- }
-
- String lowerCaseValue = stringValue.toLowerCase();
-
- Density density = Density.MEDIUM;
- if (value instanceof DensityBasedResourceValue) {
- density = ((DensityBasedResourceValue) value).getResourceDensity();
- }
-
- if (lowerCaseValue.endsWith(NinePatch.EXTENSION_9PATCH)) {
- File file = new File(stringValue);
- if (file.isFile()) {
- try {
- return getNinePatchDrawable(new FileInputStream(file), density,
- value.isFramework(), stringValue, context);
- } catch (IOException e) {
- // failed to read the file, we'll return null below.
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed lot load " + file.getAbsolutePath(), e, null /*data*/);
- }
- }
-
- return null;
- } else if (lowerCaseValue.endsWith(".xml") || stringValue.startsWith("@aapt:_aapt/")) {
- // create a block parser for the file
- try {
- XmlPullParser parser = context.getLayoutlibCallback().getParser(value);
- if (parser == null) {
- File drawableFile = new File(stringValue);
- if (drawableFile.isFile()) {
- parser = ParserFactory.create(drawableFile);
- }
- }
-
- BridgeXmlBlockParser blockParser =
- new BridgeXmlBlockParser(parser, context, value.isFramework());
- try {
- return Drawable.createFromXml(context.getResources(), blockParser, theme);
- } finally {
- blockParser.ensurePopped();
- }
- } catch (Exception e) {
- // this is an error and not warning since the file existence is checked before
- // attempting to parse it.
- Bridge.getLog().error(null, "Failed to parse file " + stringValue, e,
- null /*data*/);
- }
-
- return null;
- } else {
- File bmpFile = new File(stringValue);
- if (bmpFile.isFile()) {
- try {
- Bitmap bitmap = Bridge.getCachedBitmap(stringValue,
- value.isFramework() ? null : context.getProjectKey());
-
- if (bitmap == null) {
- bitmap =
- Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/, density);
- Bridge.setCachedBitmap(stringValue, bitmap,
- value.isFramework() ? null : context.getProjectKey());
- }
-
- return new BitmapDrawable(context.getResources(), bitmap);
- } catch (IOException e) {
- // we'll return null below
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
- "Failed lot load " + bmpFile.getAbsolutePath(), e, null /*data*/);
- }
- } else {
- // attempt to get a color from the value
- try {
- int color = getColor(stringValue);
- return new ColorDrawable(color);
- } catch (NumberFormatException e) {
- // we'll return null below.
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT,
- "Failed to convert " + stringValue + " into a drawable", e,
- null /*data*/);
- }
- }
- }
-
- return null;
- }
-
- /**
- * Returns a {@link Typeface} given a font name. The font name, can be a system font family
- * (like sans-serif) or a full path if the font is to be loaded from resources.
- */
- public static Typeface getFont(String fontName, BridgeContext context, Theme theme, boolean
- isFramework) {
- if (fontName == null) {
- return null;
- }
-
- if (Typeface_Accessor.isSystemFont(fontName)) {
- // Shortcut for the case where we are asking for a system font name. Those are not
- // loaded using external resources.
- return null;
- }
-
- // Check if this is an asset that we've already loaded dynamically
- Typeface typeface = Typeface.findFromCache(context.getAssets(), fontName);
- if (typeface != null) {
- return typeface;
- }
-
- String lowerCaseValue = fontName.toLowerCase();
- if (lowerCaseValue.endsWith(".xml")) {
- // create a block parser for the file
- Boolean psiParserSupport = context.getLayoutlibCallback().getFlag(
- RenderParamsFlags.FLAG_KEY_XML_FILE_PARSER_SUPPORT);
- XmlPullParser parser = null;
- if (psiParserSupport != null && psiParserSupport) {
- parser = context.getLayoutlibCallback().getXmlFileParser(fontName);
- }
- else {
- File f = new File(fontName);
- if (f.isFile()) {
- try {
- parser = ParserFactory.create(f);
- } catch (XmlPullParserException | FileNotFoundException e) {
- // this is an error and not warning since the file existence is checked before
- // attempting to parse it.
- Bridge.getLog().error(null, "Failed to parse file " + fontName,
- e, null /*data*/);
- }
- }
- }
-
- if (parser != null) {
- BridgeXmlBlockParser blockParser = new BridgeXmlBlockParser(
- parser, context, isFramework);
- try {
- FontResourcesParser.FamilyResourceEntry entry =
- FontResourcesParser.parse(blockParser, context.getResources());
- typeface = Typeface.createFromResources(entry, context.getAssets(),
- fontName);
- } catch (XmlPullParserException | IOException e) {
- Bridge.getLog().error(null, "Failed to parse file " + fontName,
- e, null /*data*/);
- } finally {
- blockParser.ensurePopped();
- }
- } else {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN,
- String.format("File %s does not exist (or is not a file)", fontName),
- null /*data*/);
- }
- } else {
- typeface = Typeface.createFromResources(context.getAssets(), fontName, 0);
- }
-
- return typeface;
- }
-
- /**
- * Returns a {@link Typeface} given a font name. The font name, can be a system font family
- * (like sans-serif) or a full path if the font is to be loaded from resources.
- */
- public static Typeface getFont(ResourceValue value, BridgeContext context, Theme theme) {
- if (value == null) {
- return null;
- }
-
- return getFont(value.getValue(), context, theme, value.isFramework());
- }
-
- private static Drawable getNinePatchDrawable(InputStream inputStream, Density density,
- boolean isFramework, String cacheKey, BridgeContext context) throws IOException {
- // see if we still have both the chunk and the bitmap in the caches
- NinePatchChunk chunk = Bridge.getCached9Patch(cacheKey,
- isFramework ? null : context.getProjectKey());
- Bitmap bitmap = Bridge.getCachedBitmap(cacheKey,
- isFramework ? null : context.getProjectKey());
-
- // if either chunk or bitmap is null, then we reload the 9-patch file.
- if (chunk == null || bitmap == null) {
- try {
- NinePatch ninePatch = NinePatch.load(inputStream, true /*is9Patch*/,
- false /* convert */);
- if (ninePatch != null) {
- if (chunk == null) {
- chunk = ninePatch.getChunk();
-
- Bridge.setCached9Patch(cacheKey, chunk,
- isFramework ? null : context.getProjectKey());
- }
-
- if (bitmap == null) {
- bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(),
- false /*isMutable*/,
- density);
-
- Bridge.setCachedBitmap(cacheKey, bitmap,
- isFramework ? null : context.getProjectKey());
- }
- }
- } catch (MalformedURLException e) {
- // URL is wrong, we'll return null below
- }
- }
-
- if (chunk != null && bitmap != null) {
- int[] padding = chunk.getPadding();
- Rect paddingRect = new Rect(padding[0], padding[1], padding[2], padding[3]);
-
- return new NinePatchDrawable(context.getResources(), bitmap,
- NinePatch_Delegate.serialize(chunk),
- paddingRect, null);
- }
-
- return null;
- }
-
- /**
- * Looks for an attribute in the current theme.
- *
- * @param resources the render resources
- * @param name the name of the attribute
- * @param defaultValue the default value.
- * @param isFrameworkAttr if the attribute is in android namespace
- * @return the value of the attribute or the default one if not found.
- */
- public static boolean getBooleanThemeValue(@NonNull RenderResources resources, String name,
- boolean isFrameworkAttr, boolean defaultValue) {
- ResourceValue value = resources.findItemInTheme(name, isFrameworkAttr);
- value = resources.resolveResValue(value);
- if (value == null) {
- return defaultValue;
- }
- return XmlUtils.convertValueToBoolean(value.getValue(), defaultValue);
- }
-
- // ------- TypedValue stuff
- // This is taken from //device/libs/utils/ResourceTypes.cpp
-
- private static final class UnitEntry {
- String name;
- int type;
- int unit;
- float scale;
-
- UnitEntry(String name, int type, int unit, float scale) {
- this.name = name;
- this.type = type;
- this.unit = unit;
- this.scale = scale;
- }
- }
-
- private final static UnitEntry[] sUnitNames = new UnitEntry[] {
- new UnitEntry("px", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_PX, 1.0f),
- new UnitEntry("dip", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_DIP, 1.0f),
- new UnitEntry("dp", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_DIP, 1.0f),
- new UnitEntry("sp", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_SP, 1.0f),
- new UnitEntry("pt", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_PT, 1.0f),
- new UnitEntry("in", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_IN, 1.0f),
- new UnitEntry("mm", TypedValue.TYPE_DIMENSION, TypedValue.COMPLEX_UNIT_MM, 1.0f),
- new UnitEntry("%", TypedValue.TYPE_FRACTION, TypedValue.COMPLEX_UNIT_FRACTION, 1.0f/100),
- new UnitEntry("%p", TypedValue.TYPE_FRACTION, TypedValue.COMPLEX_UNIT_FRACTION_PARENT, 1.0f/100),
- };
-
- /**
- * Returns the raw value from the given attribute float-type value string.
- * This object is only valid until the next call on to {@link ResourceHelper}.
- */
- public static TypedValue getValue(String attribute, String value, boolean requireUnit) {
- if (parseFloatAttribute(attribute, value, mValue, requireUnit)) {
- return mValue;
- }
-
- return null;
- }
-
- /**
- * Parse a float attribute and return the parsed value into a given TypedValue.
- * @param attribute the name of the attribute. Can be null if <var>requireUnit</var> is false.
- * @param value the string value of the attribute
- * @param outValue the TypedValue to receive the parsed value
- * @param requireUnit whether the value is expected to contain a unit.
- * @return true if success.
- */
- public static boolean parseFloatAttribute(String attribute, @NonNull String value,
- TypedValue outValue, boolean requireUnit) {
- assert !requireUnit || attribute != null;
-
- // remove the space before and after
- value = value.trim();
- int len = value.length();
-
- if (len <= 0) {
- return false;
- }
-
- // check that there's no non ascii characters.
- char[] buf = value.toCharArray();
- for (int i = 0 ; i < len ; i++) {
- if (buf[i] > 255) {
- return false;
- }
- }
-
- // check the first character
- if ((buf[0] < '0' || buf[0] > '9') && buf[0] != '.' && buf[0] != '-' && buf[0] != '+') {
- return false;
- }
-
- // now look for the string that is after the float...
- Matcher m = sFloatPattern.matcher(value);
- if (m.matches()) {
- String f_str = m.group(1);
- String end = m.group(2);
-
- float f;
- try {
- f = Float.parseFloat(f_str);
- } catch (NumberFormatException e) {
- // this shouldn't happen with the regexp above.
- return false;
- }
-
- if (end.length() > 0 && end.charAt(0) != ' ') {
- // Might be a unit...
- if (parseUnit(end, outValue, sFloatOut)) {
- computeTypedValue(outValue, f, sFloatOut[0]);
- return true;
- }
- return false;
- }
-
- // make sure it's only spaces at the end.
- end = end.trim();
-
- if (end.length() == 0) {
- if (outValue != null) {
- if (!requireUnit) {
- outValue.type = TypedValue.TYPE_FLOAT;
- outValue.data = Float.floatToIntBits(f);
- } else {
- // no unit when required? Use dp and out an error.
- applyUnit(sUnitNames[1], outValue, sFloatOut);
- computeTypedValue(outValue, f, sFloatOut[0]);
-
- Bridge.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
- String.format(
- "Dimension \"%1$s\" in attribute \"%2$s\" is missing unit!",
- value, attribute),
- null);
- }
- return true;
- }
- }
- }
-
- return false;
- }
-
- private static void computeTypedValue(TypedValue outValue, float value, float scale) {
- value *= scale;
- boolean neg = value < 0;
- if (neg) {
- value = -value;
- }
- long bits = (long)(value*(1<<23)+.5f);
- int radix;
- int shift;
- if ((bits&0x7fffff) == 0) {
- // Always use 23p0 if there is no fraction, just to make
- // things easier to read.
- radix = TypedValue.COMPLEX_RADIX_23p0;
- shift = 23;
- } else if ((bits&0xffffffffff800000L) == 0) {
- // Magnitude is zero -- can fit in 0 bits of precision.
- radix = TypedValue.COMPLEX_RADIX_0p23;
- shift = 0;
- } else if ((bits&0xffffffff80000000L) == 0) {
- // Magnitude can fit in 8 bits of precision.
- radix = TypedValue.COMPLEX_RADIX_8p15;
- shift = 8;
- } else if ((bits&0xffffff8000000000L) == 0) {
- // Magnitude can fit in 16 bits of precision.
- radix = TypedValue.COMPLEX_RADIX_16p7;
- shift = 16;
- } else {
- // Magnitude needs entire range, so no fractional part.
- radix = TypedValue.COMPLEX_RADIX_23p0;
- shift = 23;
- }
- int mantissa = (int)(
- (bits>>shift) & TypedValue.COMPLEX_MANTISSA_MASK);
- if (neg) {
- mantissa = (-mantissa) & TypedValue.COMPLEX_MANTISSA_MASK;
- }
- outValue.data |=
- (radix<<TypedValue.COMPLEX_RADIX_SHIFT)
- | (mantissa<<TypedValue.COMPLEX_MANTISSA_SHIFT);
- }
-
- private static boolean parseUnit(String str, TypedValue outValue, float[] outScale) {
- str = str.trim();
-
- for (UnitEntry unit : sUnitNames) {
- if (unit.name.equals(str)) {
- applyUnit(unit, outValue, outScale);
- return true;
- }
- }
-
- return false;
- }
-
- private static void applyUnit(UnitEntry unit, TypedValue outValue, float[] outScale) {
- outValue.type = unit.type;
- // COMPLEX_UNIT_SHIFT is 0 and hence intelliJ complains about it. Suppress the warning.
- //noinspection PointlessBitwiseExpression
- outValue.data = unit.unit << TypedValue.COMPLEX_UNIT_SHIFT;
- outScale[0] = unit.scale;
- }
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl;
-
-import java.util.ArrayList;
-
-/**
- * Custom Stack implementation on top of an {@link ArrayList} instead of
- * using {@link java.util.Stack} which is on top of a vector.
- *
- * @param <T>
- */
-public class Stack<T> extends ArrayList<T> {
-
- private static final long serialVersionUID = 1L;
-
- public Stack() {
- super();
- }
-
- public Stack(int size) {
- super(size);
- }
-
- /**
- * Pushes the given object to the stack
- * @param object the object to push
- */
- public void push(T object) {
- add(object);
- }
-
- /**
- * Remove the object at the top of the stack and returns it.
- * @return the removed object or null if the stack was empty.
- */
- public T pop() {
- if (size() > 0) {
- return remove(size() - 1);
- }
-
- return null;
- }
-
- /**
- * Returns the object at the top of the stack.
- * @return the object at the top or null if the stack is empty.
- */
- public T peek() {
- if (size() > 0) {
- return get(size() - 1);
- }
-
- return null;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.impl;
-
-import com.android.ide.common.rendering.api.ViewInfo;
-import com.android.ide.common.rendering.api.ViewType;
-
-/**
- * ViewInfo for views added by the platform.
- */
-public class SystemViewInfo extends ViewInfo {
-
- private ViewType mViewType;
-
- public SystemViewInfo(String name, Object cookie, int left, int top,
- int right, int bottom) {
- super(name, cookie, left, top, right, bottom);
- }
-
- public SystemViewInfo(String name, Object cookie, int left, int top,
- int right, int bottom, Object viewObject, Object layoutParamsObject) {
- super(name, cookie, left, top, right, bottom, viewObject,
- layoutParamsObject);
- }
-
- @Override
- public ViewType getViewType() {
- if (mViewType != null) {
- return mViewType;
- }
- return ViewType.SYSTEM_UNKNOWN;
- }
-
- public void setViewType(ViewType type) {
- mViewType = type;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.impl.binding;
-
-import com.android.ide.common.rendering.api.DataBindingItem;
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.ResourceReference;
-import com.android.ide.common.rendering.api.IProjectCallback.ViewAttribute;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.impl.RenderAction;
-import com.android.util.Pair;
-
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.Checkable;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-/**
- * A Helper class to do fake data binding in {@link AdapterView} objects.
- */
-public class AdapterHelper {
-
- @SuppressWarnings("deprecation")
- static Pair<View, Boolean> getView(AdapterItem item, AdapterItem parentItem, ViewGroup parent,
- LayoutlibCallback callback, ResourceReference adapterRef, boolean skipCallbackParser) {
- // we don't care about recycling here because we never scroll.
- DataBindingItem dataBindingItem = item.getDataBindingItem();
-
- BridgeContext context = RenderAction.getCurrentContext();
-
- Pair<View, Boolean> pair = context.inflateView(dataBindingItem.getViewReference(),
- parent, false /*attachToRoot*/, skipCallbackParser);
-
- View view = pair.getFirst();
- skipCallbackParser |= pair.getSecond();
-
- if (view != null) {
- fillView(context, view, item, parentItem, callback, adapterRef);
- } else {
- // create a text view to display an error.
- TextView tv = new TextView(context);
- tv.setText("Unable to find layout: " + dataBindingItem.getViewReference().getName());
- view = tv;
- }
-
- return Pair.of(view, skipCallbackParser);
- }
-
- private static void fillView(BridgeContext context, View view, AdapterItem item,
- AdapterItem parentItem, LayoutlibCallback callback, ResourceReference adapterRef) {
- if (view instanceof ViewGroup) {
- ViewGroup group = (ViewGroup) view;
- final int count = group.getChildCount();
- for (int i = 0 ; i < count ; i++) {
- fillView(context, group.getChildAt(i), item, parentItem, callback, adapterRef);
- }
- } else {
- int id = view.getId();
- if (id != 0) {
- ResourceReference resolvedRef = context.resolveId(id);
- if (resolvedRef != null) {
- int fullPosition = item.getFullPosition();
- int positionPerType = item.getPositionPerType();
- int fullParentPosition = parentItem != null ? parentItem.getFullPosition() : 0;
- int parentPositionPerType = parentItem != null ?
- parentItem.getPositionPerType() : 0;
-
- if (view instanceof TextView) {
- TextView tv = (TextView) view;
- Object value = callback.getAdapterItemValue(
- adapterRef, context.getViewKey(view),
- item.getDataBindingItem().getViewReference(),
- fullPosition, positionPerType,
- fullParentPosition, parentPositionPerType,
- resolvedRef, ViewAttribute.TEXT, tv.getText().toString());
- if (value != null) {
- if (value.getClass() != ViewAttribute.TEXT.getAttributeClass()) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
- "Wrong Adapter Item value class for TEXT. Expected String, got %s",
- value.getClass().getName()), null);
- } else {
- tv.setText((String) value);
- }
- }
- }
-
- if (view instanceof Checkable) {
- Checkable cb = (Checkable) view;
-
- Object value = callback.getAdapterItemValue(
- adapterRef, context.getViewKey(view),
- item.getDataBindingItem().getViewReference(),
- fullPosition, positionPerType,
- fullParentPosition, parentPositionPerType,
- resolvedRef, ViewAttribute.IS_CHECKED, cb.isChecked());
- if (value != null) {
- if (value.getClass() != ViewAttribute.IS_CHECKED.getAttributeClass()) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
- "Wrong Adapter Item value class for IS_CHECKED. Expected Boolean, got %s",
- value.getClass().getName()), null);
- } else {
- cb.setChecked((Boolean) value);
- }
- }
- }
-
- if (view instanceof ImageView) {
- ImageView iv = (ImageView) view;
-
- Object value = callback.getAdapterItemValue(
- adapterRef, context.getViewKey(view),
- item.getDataBindingItem().getViewReference(),
- fullPosition, positionPerType,
- fullParentPosition, parentPositionPerType,
- resolvedRef, ViewAttribute.SRC, iv.getDrawable());
- if (value != null) {
- if (value.getClass() != ViewAttribute.SRC.getAttributeClass()) {
- Bridge.getLog().error(LayoutLog.TAG_BROKEN, String.format(
- "Wrong Adapter Item value class for SRC. Expected Boolean, got %s",
- value.getClass().getName()), null);
- } else {
- // FIXME
- }
- }
- }
- }
- }
- }
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.impl.binding;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import com.android.ide.common.rendering.api.DataBindingItem;
-
-/**
- * This is the items provided by the adapter. They are dynamically generated.
- */
-final class AdapterItem {
- private final DataBindingItem mItem;
- private final int mType;
- private final int mFullPosition;
- private final int mPositionPerType;
- private List<AdapterItem> mChildren;
-
- protected AdapterItem(DataBindingItem item, int type, int fullPosition,
- int positionPerType) {
- mItem = item;
- mType = type;
- mFullPosition = fullPosition;
- mPositionPerType = positionPerType;
- }
-
- void addChild(AdapterItem child) {
- if (mChildren == null) {
- mChildren = new ArrayList<AdapterItem>();
- }
-
- mChildren.add(child);
- }
-
- List<AdapterItem> getChildren() {
- if (mChildren != null) {
- return mChildren;
- }
-
- return Collections.emptyList();
- }
-
- int getType() {
- return mType;
- }
-
- int getFullPosition() {
- return mFullPosition;
- }
-
- int getPositionPerType() {
- return mPositionPerType;
- }
-
- DataBindingItem getDataBindingItem() {
- return mItem;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl.binding;
-
-import com.android.ide.common.rendering.api.AdapterBinding;
-import com.android.ide.common.rendering.api.DataBindingItem;
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.ResourceReference;
-import com.android.util.Pair;
-
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.ListAdapter;
-import android.widget.SpinnerAdapter;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Fake adapter to do fake data binding in {@link AdapterView} objects for {@link ListAdapter}
- * and {@link SpinnerAdapter}.
- *
- */
-public class FakeAdapter extends BaseAdapter {
-
- // don't use a set because the order is important.
- private final List<ResourceReference> mTypes = new ArrayList<ResourceReference>();
- private final LayoutlibCallback mCallback;
- private final ResourceReference mAdapterRef;
- private final List<AdapterItem> mItems = new ArrayList<AdapterItem>();
- private boolean mSkipCallbackParser = false;
-
- public FakeAdapter(ResourceReference adapterRef, AdapterBinding binding,
- LayoutlibCallback callback) {
- mAdapterRef = adapterRef;
- mCallback = callback;
-
- final int repeatCount = binding.getRepeatCount();
- final int itemCount = binding.getItemCount();
-
- // Need an array to count for each type.
- // This is likely too big, but is the max it can be.
- int[] typeCount = new int[itemCount];
-
- // We put several repeating sets.
- for (int r = 0 ; r < repeatCount ; r++) {
- // loop on the type of list items, and add however many for each type.
- for (DataBindingItem dataBindingItem : binding) {
- ResourceReference viewRef = dataBindingItem.getViewReference();
- int typeIndex = mTypes.indexOf(viewRef);
- if (typeIndex == -1) {
- typeIndex = mTypes.size();
- mTypes.add(viewRef);
- }
-
- int count = dataBindingItem.getCount();
-
- int index = typeCount[typeIndex];
- typeCount[typeIndex] += count;
-
- for (int k = 0 ; k < count ; k++) {
- mItems.add(new AdapterItem(dataBindingItem, typeIndex, mItems.size(), index++));
- }
- }
- }
- }
-
- @Override
- public boolean isEnabled(int position) {
- return true;
- }
-
- @Override
- public int getCount() {
- return mItems.size();
- }
-
- @Override
- public Object getItem(int position) {
- return mItems.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public int getItemViewType(int position) {
- return mItems.get(position).getType();
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- // we don't care about recycling here because we never scroll.
- AdapterItem item = mItems.get(position);
- @SuppressWarnings("deprecation")
- Pair<View, Boolean> pair = AdapterHelper.getView(item, null, parent, mCallback,
- mAdapterRef, mSkipCallbackParser);
- mSkipCallbackParser = pair.getSecond();
- return pair.getFirst();
- }
-
- @Override
- public int getViewTypeCount() {
- return mTypes.size();
- }
-
- // ---- SpinnerAdapter
-
- @Override
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- // pass
- return null;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.impl.binding;
-
-import com.android.ide.common.rendering.api.AdapterBinding;
-import com.android.ide.common.rendering.api.DataBindingItem;
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.ResourceReference;
-import com.android.util.Pair;
-
-import android.database.DataSetObserver;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ExpandableListAdapter;
-import android.widget.HeterogeneousExpandableList;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@SuppressWarnings("deprecation")
-public class FakeExpandableAdapter implements ExpandableListAdapter, HeterogeneousExpandableList {
-
- private final LayoutlibCallback mCallback;
- private final ResourceReference mAdapterRef;
- private boolean mSkipCallbackParser = false;
-
- protected final List<AdapterItem> mItems = new ArrayList<AdapterItem>();
-
- // don't use a set because the order is important.
- private final List<ResourceReference> mGroupTypes = new ArrayList<ResourceReference>();
- private final List<ResourceReference> mChildrenTypes = new ArrayList<ResourceReference>();
-
- public FakeExpandableAdapter(ResourceReference adapterRef, AdapterBinding binding,
- LayoutlibCallback callback) {
- mAdapterRef = adapterRef;
- mCallback = callback;
-
- createItems(binding, binding.getItemCount(), binding.getRepeatCount(), mGroupTypes, 1);
- }
-
- private void createItems(Iterable<DataBindingItem> iterable, final int itemCount,
- final int repeatCount, List<ResourceReference> types, int depth) {
- // Need an array to count for each type.
- // This is likely too big, but is the max it can be.
- int[] typeCount = new int[itemCount];
-
- // we put several repeating sets.
- for (int r = 0 ; r < repeatCount ; r++) {
- // loop on the type of list items, and add however many for each type.
- for (DataBindingItem dataBindingItem : iterable) {
- ResourceReference viewRef = dataBindingItem.getViewReference();
- int typeIndex = types.indexOf(viewRef);
- if (typeIndex == -1) {
- typeIndex = types.size();
- types.add(viewRef);
- }
-
- List<DataBindingItem> children = dataBindingItem.getChildren();
- int count = dataBindingItem.getCount();
-
- // if there are children, we use the count as a repeat count for the children.
- if (children.size() > 0) {
- count = 1;
- }
-
- int index = typeCount[typeIndex];
- typeCount[typeIndex] += count;
-
- for (int k = 0 ; k < count ; k++) {
- AdapterItem item = new AdapterItem(dataBindingItem, typeIndex, mItems.size(),
- index++);
- mItems.add(item);
-
- if (children.size() > 0) {
- createItems(dataBindingItem, depth + 1);
- }
- }
- }
- }
- }
-
- private void createItems(DataBindingItem item, int depth) {
- if (depth == 2) {
- createItems(item, item.getChildren().size(), item.getCount(), mChildrenTypes, depth);
- }
- }
-
- private AdapterItem getChildItem(int groupPosition, int childPosition) {
- AdapterItem item = mItems.get(groupPosition);
-
- List<AdapterItem> children = item.getChildren();
- return children.get(childPosition);
- }
-
- // ---- ExpandableListAdapter
-
- @Override
- public int getGroupCount() {
- return mItems.size();
- }
-
- @Override
- public int getChildrenCount(int groupPosition) {
- AdapterItem item = mItems.get(groupPosition);
- return item.getChildren().size();
- }
-
- @Override
- public Object getGroup(int groupPosition) {
- return mItems.get(groupPosition);
- }
-
- @Override
- public Object getChild(int groupPosition, int childPosition) {
- return getChildItem(groupPosition, childPosition);
- }
-
- @Override
- public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
- ViewGroup parent) {
- // we don't care about recycling here because we never scroll.
- AdapterItem item = mItems.get(groupPosition);
- Pair<View, Boolean> pair = AdapterHelper.getView(item, null /*parentItem*/, parent,
- mCallback, mAdapterRef, mSkipCallbackParser);
- mSkipCallbackParser = pair.getSecond();
- return pair.getFirst();
- }
-
- @Override
- public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
- View convertView, ViewGroup parent) {
- // we don't care about recycling here because we never scroll.
- AdapterItem parentItem = mItems.get(groupPosition);
- AdapterItem item = getChildItem(groupPosition, childPosition);
- Pair<View, Boolean> pair = AdapterHelper.getView(item, parentItem, parent, mCallback,
- mAdapterRef, mSkipCallbackParser);
- mSkipCallbackParser = pair.getSecond();
- return pair.getFirst();
- }
-
- @Override
- public long getGroupId(int groupPosition) {
- return groupPosition;
- }
-
- @Override
- public long getChildId(int groupPosition, int childPosition) {
- return childPosition;
- }
-
- @Override
- public long getCombinedGroupId(long groupId) {
- return groupId << 16 | 0x0000FFFF;
- }
-
- @Override
- public long getCombinedChildId(long groupId, long childId) {
- return groupId << 16 | childId;
- }
-
- @Override
- public boolean isChildSelectable(int groupPosition, int childPosition) {
- return true;
- }
-
- @Override
- public void onGroupCollapsed(int groupPosition) {
- // pass
- }
-
- @Override
- public void onGroupExpanded(int groupPosition) {
- // pass
- }
-
- @Override
- public void registerDataSetObserver(DataSetObserver observer) {
- // pass
- }
-
- @Override
- public void unregisterDataSetObserver(DataSetObserver observer) {
- // pass
- }
-
- @Override
- public boolean hasStableIds() {
- return true;
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return true;
- }
-
- @Override
- public boolean isEmpty() {
- return mItems.isEmpty();
- }
-
- // ---- HeterogeneousExpandableList
-
- @Override
- public int getChildType(int groupPosition, int childPosition) {
- return getChildItem(groupPosition, childPosition).getType();
- }
-
- @Override
- public int getChildTypeCount() {
- return mChildrenTypes.size();
- }
-
- @Override
- public int getGroupType(int groupPosition) {
- return mItems.get(groupPosition).getType();
- }
-
- @Override
- public int getGroupTypeCount() {
- return mGroupTypes.size();
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.libcore.io;
-
-import java.nio.ByteBuffer;
-
-import libcore.io.BufferIterator;
-
-/**
- * Provides an implementation of {@link BufferIterator} over a {@link ByteBuffer}.
- */
-public class BridgeBufferIterator extends BufferIterator {
-
- private final long mSize;
- private final ByteBuffer mByteBuffer;
-
- public BridgeBufferIterator(long size, ByteBuffer buffer) {
- mSize = size;
- mByteBuffer = buffer;
- }
-
- @Override
- public void seek(int offset) {
- assert offset <= mSize;
- mByteBuffer.position(offset);
- }
-
- @Override
- public int pos() {
- return mByteBuffer.position();
- }
-
- @Override
- public void skip(int byteCount) {
- int newPosition = mByteBuffer.position() + byteCount;
- assert newPosition <= mSize;
- mByteBuffer.position(newPosition);
- }
-
- @Override
- public void readByteArray(byte[] dst, int dstOffset, int byteCount) {
- assert dst.length >= dstOffset + byteCount;
- mByteBuffer.get(dst, dstOffset, byteCount);
- }
-
- @Override
- public byte readByte() {
- return mByteBuffer.get();
- }
-
- @Override
- public int readInt() {
- return mByteBuffer.getInt();
- }
-
- @Override
- public void readIntArray(int[] dst, int dstOffset, int intCount) {
- while (--intCount >= 0) {
- dst[dstOffset++] = mByteBuffer.getInt();
- }
- }
-
- @Override
- public short readShort() {
- return mByteBuffer.getShort();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.shadowutil;
-
-import android.annotation.NonNull;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-
-public class ShadowBuffer {
-
- private int mWidth;
- private int mHeight;
- private Bitmap mBitmap;
- private int[] mData;
-
- public ShadowBuffer(int width, int height) {
- mWidth = width;
- mHeight = height;
- mBitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
- mData = new int[mBitmap.getWidth() * mBitmap.getHeight()];
- mBitmap.getPixels(mData, 0, mBitmap.getWidth(), 0, 0, mBitmap.getWidth(),
- mBitmap.getHeight());
- }
-
- public void generateTriangles(@NonNull float[] strip, float scale) {
- for (int i = 0; i < strip.length - 8; i += 3) {
- float fx3 = strip[i];
- float fy3 = strip[i + 1];
- float fz3 = scale * strip[i + 2];
-
- float fx2 = strip[i + 3];
- float fy2 = strip[i + 4];
- float fz2 = scale * strip[i + 5];
-
- float fx1 = strip[i + 6];
- float fy1 = strip[i + 7];
- float fz1 = scale * strip[i + 8];
-
- if (fx1 * (fy2 - fy3) + fx2 * (fy3 - fy1) + fx3 * (fy1 - fy2) == 0) {
- continue;
- }
-
- triangleZBuffMin(mData, mWidth, mHeight, fx3, fy3, fz3, fx2, fy2, fz2, fx1, fy1, fz1);
- triangleZBuffMin(mData, mWidth, mHeight, fx1, fy1, fz1, fx2, fy2, fz2, fx3, fy3, fz3);
- }
- mBitmap.setPixels(mData, 0, mBitmap.getWidth(), 0, 0, mBitmap.getWidth(),
- mBitmap.getHeight());
- }
-
- private void triangleZBuffMin(@NonNull int[] buff, int w, int h, float fx3, float fy3,
- float fz3, float fx2, float fy2, float fz2, float fx1, float fy1, float fz1) {
- if (((fx1 - fx2) * (fy3 - fy2) - (fy1 - fy2) * (fx3 - fx2)) < 0) {
- float tmpX = fx1;
- float tmpY = fy1;
- float tmpZ = fz1;
- fx1 = fx2;
- fy1 = fy2;
- fz1 = fz2;
- fx2 = tmpX;
- fy2 = tmpY;
- fz2 = tmpZ;
- }
- double d = (fx1 * (fy3 - fy2) - fx2 * fy3 + fx3 * fy2 + (fx2 - fx3) * fy1);
-
- if (d == 0) {
- return;
- }
- float dx = (float) (-(fy1 * (fz3 - fz2) - fy2 * fz3 + fy3 * fz2 + (fy2 - fy3) * fz1) / d);
- float dy = (float) ((fx1 * (fz3 - fz2) - fx2 * fz3 + fx3 * fz2 + (fx2 - fx3) * fz1) / d);
- float zOff = (float) ((fx1 * (fy3 * fz2 - fy2 * fz3) + fy1 * (fx2 * fz3 - fx3 * fz2) +
- (fx3 * fy2 - fx2 * fy3) * fz1) / d);
-
- int Y1 = (int) (16.0f * fy1 + .5f);
- int Y2 = (int) (16.0f * fy2 + .5f);
- int Y3 = (int) (16.0f * fy3 + .5f);
-
- int X1 = (int) (16.0f * fx1 + .5f);
- int X2 = (int) (16.0f * fx2 + .5f);
- int X3 = (int) (16.0f * fx3 + .5f);
-
- int DX12 = X1 - X2;
- int DX23 = X2 - X3;
- int DX31 = X3 - X1;
-
- int DY12 = Y1 - Y2;
- int DY23 = Y2 - Y3;
- int DY31 = Y3 - Y1;
-
- int FDX12 = DX12 << 4;
- int FDX23 = DX23 << 4;
- int FDX31 = DX31 << 4;
-
- int FDY12 = DY12 << 4;
- int FDY23 = DY23 << 4;
- int FDY31 = DY31 << 4;
-
- int minX = (min(X1, X2, X3) + 0xF) >> 4;
- int maxX = (max(X1, X2, X3) + 0xF) >> 4;
- int minY = (min(Y1, Y2, Y3) + 0xF) >> 4;
- int maxY = (max(Y1, Y2, Y3) + 0xF) >> 4;
-
- if (minY < 0) {
- minY = 0;
- }
- if (minX < 0) {
- minX = 0;
- }
- if (maxX > w) {
- maxX = w;
- }
- if (maxY > h) {
- maxY = h;
- }
- int off = minY * w;
-
- int C1 = DY12 * X1 - DX12 * Y1;
- int C2 = DY23 * X2 - DX23 * Y2;
- int C3 = DY31 * X3 - DX31 * Y3;
-
- if (DY12 < 0 || (DY12 == 0 && DX12 > 0)) {
- C1++;
- }
- if (DY23 < 0 || (DY23 == 0 && DX23 > 0)) {
- C2++;
- }
- if (DY31 < 0 || (DY31 == 0 && DX31 > 0)) {
- C3++;
- }
- int CY1 = C1 + DX12 * (minY << 4) - DY12 * (minX << 4);
- int CY2 = C2 + DX23 * (minY << 4) - DY23 * (minX << 4);
- int CY3 = C3 + DX31 * (minY << 4) - DY31 * (minX << 4);
-
- for (int y = minY; y < maxY; y++) {
- int CX1 = CY1;
- int CX2 = CY2;
- int CX3 = CY3;
- float p = zOff + dy * y;
- for (int x = minX; x < maxX; x++) {
- if (CX1 > 0 && CX2 > 0 && CX3 > 0) {
- int point = x + off;
- float zVal = p + dx * x;
- buff[point] |= ((int) (zVal * 255)) << 24;
- }
- CX1 -= FDY12;
- CX2 -= FDY23;
- CX3 -= FDY31;
- }
- CY1 += FDX12;
- CY2 += FDX23;
- CY3 += FDX31;
- off += w;
- }
- }
-
- private int min(int x1, int x2, int x3) {
- return (x1 > x2) ? ((x2 > x3) ? x3 : x2) : ((x1 > x3) ? x3 : x1);
- }
-
- private int max(int x1, int x2, int x3) {
- return (x1 < x2) ? ((x2 < x3) ? x3 : x2) : ((x1 < x3) ? x3 : x1);
- }
-
- public void draw(@NonNull Canvas c) {
- c.drawBitmap(mBitmap, 0, 0, null);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.shadowutil;
-
-import android.annotation.NonNull;
-
-public class SpotShadow {
-
- private static float rayIntersectPoly(@NonNull float[] poly, int polyLength, float px, float py,
- float dx, float dy) {
- int p1 = polyLength - 1;
- for (int p2 = 0; p2 < polyLength; p2++) {
- float p1x = poly[p1 * 2 + 0];
- float p1y = poly[p1 * 2 + 1];
- float p2x = poly[p2 * 2 + 0];
- float p2y = poly[p2 * 2 + 1];
- float div = (dx * (p1y - p2y) + dy * p2x - dy * p1x);
- if (div != 0) {
- float t = (dx * (p1y - py) + dy * px - dy * p1x) / (div);
- if (t >= 0 && t <= 1) {
- float t2 = (p1x * (py - p2y) + p2x * (p1y - py) + px * (p2y - p1y)) / div;
- if (t2 > 0) {
- return t2;
- }
- }
- }
- p1 = p2;
- }
- return Float.NaN;
- }
-
- private static void centroid2d(@NonNull float[] poly, int len, @NonNull float[] ret) {
- float sumX = 0;
- float sumY = 0;
- int p1 = len - 1;
- float area = 0;
- for (int p2 = 0; p2 < len; p2++) {
- float x1 = poly[p1 * 2 + 0];
- float y1 = poly[p1 * 2 + 1];
- float x2 = poly[p2 * 2 + 0];
- float y2 = poly[p2 * 2 + 1];
- float a = (x1 * y2 - x2 * y1);
- sumX += (x1 + x2) * a;
- sumY += (y1 + y2) * a;
- area += a;
- p1 = p2;
- }
-
- float centroidX = sumX / (3 * area);
- float centroidY = sumY / (3 * area);
- ret[0] = centroidX;
- ret[1] = centroidY;
- }
-
- /**
- * calculates the Centroid of a 3d polygon
- * @param poly The flatten 3d vertices coordinates of polygon, the format is like
- * [x0, y0, z0, x1, y1, z1, x2, ...]
- * @param len The number of polygon vertices. So the length of poly should be len * 3.
- * @param ret The array used to sotre the result. The length should be 3.
- */
- private static void centroid3d(@NonNull float[] poly, int len, @NonNull float[] ret) {
- int n = len - 1;
- double area = 0;
- double cx = 0, cy = 0, cz = 0;
- for (int i = 1; i < n; i++) {
- int k = i + 1;
- float a0 = poly[i * 3 + 0] - poly[0 * 3 + 0];
- float a1 = poly[i * 3 + 1] - poly[0 * 3 + 1];
- float a2 = poly[i * 3 + 2] - poly[0 * 3 + 2];
- float b0 = poly[k * 3 + 0] - poly[0 * 3 + 0];
- float b1 = poly[k * 3 + 1] - poly[0 * 3 + 1];
- float b2 = poly[k * 3 + 2] - poly[0 * 3 + 2];
- float c0 = a1 * b2 - b1 * a2;
- float c1 = a2 * b0 - b2 * a0;
- float c2 = a0 * b1 - b0 * a1;
- double areaOfTriangle = Math.sqrt(c0 * c0 + c1 * c1 + c2 * c2);
- area += areaOfTriangle;
- cx += areaOfTriangle * (poly[i * 3 + 0] + poly[k * 3 + 0] + poly[0 * 3 + 0]);
- cy += areaOfTriangle * (poly[i * 3 + 1] + poly[k * 3 + 1] + poly[0 * 3 + 1]);
- cz += areaOfTriangle * (poly[i * 3 + 2] + poly[k * 3 + 2] + poly[0 * 3 + 2]);
- }
- ret[0] = (float) (cx / (3 * area));
- ret[1] = (float) (cy / (3 * area));
- ret[2] = (float) (cz / (3 * area));
- }
-
- /**
- * Extracts the convex hull of a polygon.
- * @param points The vertices coordinates of polygon
- * @param pointsLength The number of polygon vertices. So the length of poly should be len * 3.
- * @param retPoly retPoly is at most the size of the input polygon
- * @return The number of points in the retPolygon
- */
- private static int hull(@NonNull float[] points, int pointsLength, @NonNull float[] retPoly) {
- quicksortX(points, 0, pointsLength - 1);
- int n = pointsLength;
- float[] lUpper = new float[n * 2];
- lUpper[0] = points[0];
- lUpper[1] = points[1];
- lUpper[2] = points[2];
- lUpper[3] = points[3];
-
- int lUpperSize = 2;
-
- for (int i = 2; i < n; i++) {
- lUpper[lUpperSize * 2 + 0] = points[i * 2 + 0];
- lUpper[lUpperSize * 2 + 1] = points[i * 2 + 1];
- lUpperSize++;
-
- while (lUpperSize > 2 &&
- !rightTurn(lUpper[(lUpperSize - 3) * 2], lUpper[(lUpperSize - 3) * 2 + 1],
- lUpper[(lUpperSize - 2) * 2], lUpper[(lUpperSize - 2) * 2 + 1],
- lUpper[(lUpperSize - 1) * 2], lUpper[(lUpperSize - 1) * 2 + 1])) {
- // Remove the middle point of the three last
- lUpper[(lUpperSize - 2) * 2 + 0] = lUpper[(lUpperSize - 1) * 2 + 0];
- lUpper[(lUpperSize - 2) * 2 + 1] = lUpper[(lUpperSize - 1) * 2 + 1];
- lUpperSize--;
- }
- }
-
- float[] lLower = new float[n * 2];
- lLower[0] = points[(n - 1) * 2 + 0];
- lLower[1] = points[(n - 1) * 2 + 1];
- lLower[2] = points[(n - 2) * 2 + 0];
- lLower[3] = points[(n - 2) * 2 + 1];
-
- int lLowerSize = 2;
-
- for (int i = n - 3; i >= 0; i--) {
- lLower[lLowerSize * 2 + 0] = points[i * 2 + 0];
- lLower[lLowerSize * 2 + 1] = points[i * 2 + 1];
- lLowerSize++;
-
- while (lLowerSize > 2 &&
- !rightTurn(lLower[(lLowerSize - 3) * 2], lLower[(lLowerSize - 3) * 2 + 1],
- lLower[(lLowerSize - 2) * 2], lLower[(lLowerSize - 2) * 2 + 1],
- lLower[(lLowerSize - 1) * 2], lLower[(lLowerSize - 1) * 2 + 1])) {
- // Remove the middle point of the three last
- lLower[(lLowerSize - 2) * 2 + 0] = lLower[(lLowerSize - 1) * 2 + 0];
- lLower[(lLowerSize - 2) * 2 + 1] = lLower[(lLowerSize - 1) * 2 + 1];
- lLowerSize--;
- }
- }
-
- int count = 0;
- for (int i = 0; i < lUpperSize; i++) {
- retPoly[count * 2 + 0] = lUpper[i * 2 + 0];
- retPoly[count * 2 + 1] = lUpper[i * 2 + 1];
- count++;
- }
- for (int i = 1; i < lLowerSize - 1; i++) {
- retPoly[count * 2 + 0] = lLower[i * 2 + 0];
- retPoly[count * 2 + 1] = lLower[i * 2 + 1];
- count++;
- }
- return count;
- }
-
- private static boolean rightTurn(float ax, float ay, float bx, float by, float cx, float cy) {
- return (bx - ax) * (cy - ay) - (by - ay) * (cx - ax) > 0.00001;
- }
-
- /**
- * calculates the intersection of poly1 with poly2 and put in poly2
- * @param poly1 The flatten 2d coordinates of polygon
- * @param poly1length The vertices number of poly1
- * @param poly2 The flatten 2d coordinates of polygon
- * @param poly2length The vertices number of poly2
- * @return number of vertices in poly2
- */
- private static int intersection(@NonNull float[] poly1, int poly1length, @NonNull float[] poly2,
- int poly2length) {
- makeClockwise(poly1, poly1length);
- makeClockwise(poly2, poly2length);
- float[] poly = new float[(poly1length * poly2length + 2) * 2];
- int count = 0;
- int pCount = 0;
- for (int i = 0; i < poly1length; i++) {
- if (pointInsidePolygon(poly1[i * 2 + 0], poly1[i * 2 + 1], poly2, poly2length)) {
- poly[count * 2 + 0] = poly1[i * 2 + 0];
- poly[count * 2 + 1] = poly1[i * 2 + 1];
- count++;
- pCount++;
- }
- }
- int fromP1 = pCount;
- for (int i = 0; i < poly2length; i++) {
- if (pointInsidePolygon(poly2[i * 2 + 0], poly2[i * 2 + 1], poly1, poly1length)) {
- poly[count * 2 + 0] = poly2[i * 2 + 0];
- poly[count * 2 + 1] = poly2[i * 2 + 1];
- count++;
- }
- }
- int fromP2 = count - fromP1;
- if (fromP1 == poly1length) { // use p1
- for (int i = 0; i < poly1length; i++) {
- poly2[i * 2 + 0] = poly1[i * 2 + 0];
- poly2[i * 2 + 1] = poly1[i * 2 + 1];
- }
- return poly1length;
- }
- if (fromP2 == poly2length) { // use p2
- return poly2length;
- }
- float[] intersection = new float[2];
- for (int i = 0; i < poly2length; i++) {
- for (int j = 0; j < poly1length; j++) {
- int i1_by_2 = i * 2;
- int i2_by_2 = ((i + 1) % poly2length) * 2;
- int j1_by_2 = j * 2;
- int j2_by_2 = ((j + 1) % poly1length) * 2;
- boolean found =
- lineIntersection(poly2[i1_by_2 + 0], poly2[i1_by_2 + 1], poly2[i2_by_2 + 0],
- poly2[i2_by_2 + 1], poly1[j1_by_2 + 0], poly1[j1_by_2 + 1],
- poly1[j2_by_2 + 0], poly1[j2_by_2 + 1], intersection);
- if (found) {
- poly[count * 2 + 0] = intersection[0];
- poly[count * 2 + 1] = intersection[1];
- count++;
- } else {
- float dx = poly2[i * 2 + 0] - poly1[j * 2 + 0];
- float dy = poly2[i * 2 + 1] - poly1[j * 2 + 1];
-
- if (dx * dx + dy * dy < 0.01) {
- poly[count * 2 + 0] = poly2[i * 2 + 0];
- poly[count * 2 + 1] = poly2[i * 2 + 1];
- count++;
- }
- }
- }
- }
- if (count == 0) {
- return 0;
- }
- float avgX = 0;
- float avgY = 0;
- for (int i = 0; i < count; i++) {
- avgX += poly[i * 2 + 0];
- avgY += poly[i * 2 + 1];
- }
- avgX /= count;
- avgY /= count;
-
- float[] ctr = new float[]{avgX, avgY};
- sort(poly, count, ctr);
- int size = count;
-
- poly2[0] = poly[0];
- poly2[1] = poly[1];
-
- count = 1;
- for (int i = 1; i < size; i++) {
- float dx = poly[i * 2 + 0] - poly[(i - 1) * 2 + 0];
- float dy = poly[i * 2 + 1] - poly[(i - 1) * 2 + 1];
- if (dx * dx + dy * dy >= 0.01) {
- poly2[count * 2 + 0] = poly[i * 2 + 0];
- poly2[count * 2 + 1] = poly[i * 2 + 1];
- count++;
- }
- }
- return count;
- }
-
- public static void sort(@NonNull float[] poly, int polyLength, @NonNull float[] ctr) {
- quicksortCircle(poly, 0, polyLength - 1, ctr);
- }
-
- public static float angle(float x1, float y1, @NonNull float[] ctr) {
- return -(float) Math.atan2(x1 - ctr[0], y1 - ctr[1]);
- }
-
- private static void swapPair(@NonNull float[] points, int i, int j) {
- float x = points[i * 2 + 0];
- float y = points[i * 2 + 1];
- points[i * 2 + 0] = points[j * 2 + 0];
- points[i * 2 + 1] = points[j * 2 + 1];
- points[j * 2 + 0] = x;
- points[j * 2 + 1] = y;
- }
-
- private static void quicksortCircle(@NonNull float[] points, int low, int high,
- @NonNull float[] ctr) {
- int i = low, j = high;
- int p = low + (high - low) / 2;
- float pivot = angle(points[p * 2], points[p * 2 + 1], ctr);
- while (i <= j) {
- while (angle(points[i * 2 + 0], points[i * 2 + 1], ctr) < pivot) {
- i++;
- }
- while (angle(points[j * 2 + 0], points[j * 2 + 1], ctr) > pivot) {
- j--;
- }
- if (i <= j) {
- swapPair(points, i, j);
- i++;
- j--;
- }
- }
- if (low < j) {
- quicksortCircle(points, low, j, ctr);
- }
- if (i < high) {
- quicksortCircle(points, i, high, ctr);
- }
- }
-
- /**
- * This function do Quick Sort by comparing X axis only.<br>
- * Note that the input values of points are paired coordinates, e.g. {@code [x0, y0, x1, y1, x2,
- * y2, ...]).}
- * @param points The input point pairs. Every {@code (2 * i, 2 * i + 1)} points are pairs.
- * @param low lowest index used to do quick sort sort
- * @param high highest index used to do quick sort
- */
- private static void quicksortX(@NonNull float[] points, int low, int high) {
- int i = low, j = high;
- int p = low + (high - low) / 2;
- float pivot = points[p * 2];
- while (i <= j) {
- while (points[i * 2 + 0] < pivot) {
- i++;
- }
- while (points[j * 2 + 0] > pivot) {
- j--;
- }
-
- if (i <= j) {
- swapPair(points, i, j);
- i++;
- j--;
- }
- }
- if (low < j) {
- quicksortX(points, low, j);
- }
- if (i < high) {
- quicksortX(points, i, high);
- }
- }
-
- private static boolean pointInsidePolygon(float x, float y, @NonNull float[] poly, int len) {
- boolean c = false;
- float testX = x;
- float testY = y;
- for (int i = 0, j = len - 1; i < len; j = i++) {
- if (((poly[i * 2 + 1] > testY) != (poly[j * 2 + 1] > testY)) && (testX <
- (poly[j * 2 + 0] - poly[i * 2 + 0]) * (testY - poly[i * 2 + 1]) /
- (poly[j * 2 + 1] - poly[i * 2 + 1]) + poly[i * 2 + 0])) {
- c = !c;
- }
- }
- return c;
- }
-
- private static void makeClockwise(@NonNull float[] polygon, int len) {
- if (polygon == null || len == 0) {
- return;
- }
- if (!isClockwise(polygon, len)) {
- reverse(polygon, len);
- }
- }
-
- private static boolean isClockwise(@NonNull float[] polygon, int len) {
- float sum = 0;
- float p1x = polygon[(len - 1) * 2 + 0];
- float p1y = polygon[(len - 1) * 2 + 1];
- for (int i = 0; i < len; i++) {
- float p2x = polygon[i * 2 + 0];
- float p2y = polygon[i * 2 + 1];
- sum += p1x * p2y - p2x * p1y;
- p1x = p2x;
- p1y = p2y;
- }
- return sum < 0;
- }
-
- private static void reverse(@NonNull float[] polygon, int len) {
- int n = len / 2;
- for (int i = 0; i < n; i++) {
- float tmp0 = polygon[i * 2 + 0];
- float tmp1 = polygon[i * 2 + 1];
- int k = len - 1 - i;
- polygon[i * 2 + 0] = polygon[k * 2 + 0];
- polygon[i * 2 + 1] = polygon[k * 2 + 1];
- polygon[k * 2 + 0] = tmp0;
- polygon[k * 2 + 1] = tmp1;
- }
- }
-
- /**
- * Intersects two lines in parametric form.
- */
- private static final boolean lineIntersection(float x1, float y1, float x2, float y2, float x3,
- float y3, float x4, float y4, @NonNull float[] ret) {
- float d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
- if (d == 0.000f) {
- return false;
- }
-
- float dx = (x1 * y2 - y1 * x2);
- float dy = (x3 * y4 - y3 * x4);
- float x = (dx * (x3 - x4) - (x1 - x2) * dy) / d;
- float y = (dx * (y3 - y4) - (y1 - y2) * dy) / d;
-
- if (((x - x1) * (x - x2) > 0.0000001) || ((x - x3) * (x - x4) > 0.0000001) ||
- ((y - y1) * (y - y2) > 0.0000001) || ((y - y3) * (y - y4) > 0.0000001)) {
- return false;
- }
- ret[0] = x;
- ret[1] = y;
- return true;
- }
-
- @NonNull
- public static float[] calculateLight(float size, int points, float x, float y, float height) {
- float[] ret = new float[points * 3];
- for (int i = 0; i < points; i++) {
- double angle = 2 * i * Math.PI / points;
- ret[i * 3 + 0] = (float) Math.cos(angle) * size + x;
- ret[i * 3 + 1] = (float) Math.sin(angle) * size + y;
- ret[i * 3 + 2] = (height);
- }
- return ret;
- }
-
- /**
- layers indicates the number of circular strips to generate.
- Strength is how dark a shadow to generate.
-
- /**
- * This calculates a collection of triangles that represent the shadow cast by a polygonal
- * light source (lightPoly) hitting a convex polygon (poly).
- * @param lightPoly The flatten 3d coordinates of light
- * @param lightPolyLength The vertices number of light polygon.
- * @param poly The flatten 3d coordinates of item
- * @param polyLength The vertices number of light polygon.
- * @param rays defines the number of points around the perimeter of the shadow to generate
- * @param layers The number of shadow's fading.
- * @param strength The factor of the black color of shadow.
- * @param retStrips Used to store the calculated shadow strength
- * @return true if the params is able to calculate a shadow, else false.
- */
- public static boolean calcShadow(@NonNull float[] lightPoly, int lightPolyLength,
- @NonNull float[] poly, int polyLength, int rays, int layers, float strength,
- @NonNull float[] retStrips) {
- float[] shadowRegion = new float[lightPolyLength * polyLength * 2];
- float[] outline = new float[polyLength * 2];
- float[] umbra = new float[polyLength * lightPolyLength * 2];
- int umbraLength = 0;
-
- int k = 0;
- for (int j = 0; j < lightPolyLength; j++) {
- int m = 0;
- for (int i = 0; i < polyLength; i++) {
- float t = lightPoly[j * 3 + 2] - poly[i * 3 + 2];
- if (t == 0) {
- return false;
- }
- t = lightPoly[j * 3 + 2] / t;
- float x = lightPoly[j * 3 + 0] - t * (lightPoly[j * 3 + 0] - poly[i * 3 + 0]);
- float y = lightPoly[j * 3 + 1] - t * (lightPoly[j * 3 + 1] - poly[i * 3 + 1]);
-
- shadowRegion[k * 2 + 0] = x;
- shadowRegion[k * 2 + 1] = y;
- outline[m * 2 + 0] = x;
- outline[m * 2 + 1] = y;
-
- k++;
- m++;
- }
- if (umbraLength == 0) {
- System.arraycopy(outline, 0, umbra, 0, polyLength);
- umbraLength = polyLength;
- } else {
- umbraLength = intersection(outline, polyLength, umbra, umbraLength);
- if (umbraLength == 0) {
- break;
- }
- }
- }
- int shadowRegionLength = k;
-
- float[] penumbra = new float[k * 2];
- int penumbraLength = hull(shadowRegion, shadowRegionLength, penumbra);
- if (umbraLength < 3) {// no real umbra make a fake one
- float[] p = new float[3];
- centroid3d(lightPoly, lightPolyLength, p);
- float[] centShadow = new float[polyLength * 2];
- for (int i = 0; i < polyLength; i++) {
- float t = p[2] - poly[i * 3 + 2];
- if (t == 0) {
- return false;
- }
- t = p[2] / t;
- float x = p[0] - t * (p[0] - poly[i * 3 + 0]);
- float y = p[1] - t * (p[1] - poly[i * 3 + 1]);
-
- centShadow[i * 2 + 0] = x;
- centShadow[i * 2 + 1] = y;
- }
- float[] c = new float[2];
- centroid2d(centShadow, polyLength, c);
- for (int i = 0; i < polyLength; i++) {
- centShadow[i * 2 + 0] = (c[0] * 9 + centShadow[i * 2 + 0]) / 10;
- centShadow[i * 2 + 1] = (c[1] * 9 + centShadow[i * 2 + 1]) / 10;
- }
- umbra = centShadow; // fake umbra
- umbraLength = polyLength; // same size as the original polygon
- }
-
- triangulateConcentricPolygon(penumbra, penumbraLength, umbra, umbraLength, rays, layers,
- strength, retStrips);
- return true;
- }
-
- /**
- * triangulate concentric circles.
- * This takes the inner and outer polygons of the umbra and penumbra and triangulates it.
- * @param penumbra The 2d flatten vertices of penumbra polygons.
- * @param penumbraLength The number of vertices in penumbra.
- * @param umbra The 2d flatten vertices of umbra polygons.
- * @param umbraLength The number of vertices in umbra.
- * @param rays defines the number of points around the perimeter of the shadow to generate
- * @param layers The number of shadow's fading.
- * @param strength The factor of the black color of shadow.
- * @param retStrips Used to store the calculated shadow strength.
- */
- private static void triangulateConcentricPolygon(@NonNull float[] penumbra, int penumbraLength,
- @NonNull float[] umbra, int umbraLength, int rays, int layers, float strength,
- @NonNull float[] retStrips) {
- int rings = layers + 1;
- double step = Math.PI * 2 / rays;
- float[] retXY = new float[2];
- centroid2d(umbra, umbraLength, retXY);
- float cx = retXY[0];
- float cy = retXY[1];
-
- float[] t1 = new float[rays];
- float[] t2 = new float[rays];
-
- for (int i = 0; i < rays; i++) {
- float dx = (float) Math.cos(Math.PI / 4 + step * i);
- float dy = (float) Math.sin(Math.PI / 4 + step * i);
- t2[i] = rayIntersectPoly(umbra, umbraLength, cx, cy, dx, dy);
- t1[i] = rayIntersectPoly(penumbra, penumbraLength, cx, cy, dx, dy);
- }
-
- int p = 0;
- // Calculate the vertex
- for (int r = 0; r < layers; r++) {
- int startP = p;
- for (int i = 0; i < rays; i++) {
- float dx = (float) Math.cos(Math.PI / 4 + step * i);
- float dy = (float) Math.sin(Math.PI / 4 + step * i);
-
- for (int j = r; j < (r + 2); j++) {
- float jf = j / (float) (rings - 1);
- float t = t1[i] + jf * (t2[i] - t1[i]);
- float op = (jf + 1 - 1 / (1 + (t - t1[i]) * (t - t1[i]))) / 2;
- retStrips[p * 3 + 0] = dx * t + cx;
- retStrips[p * 3 + 1] = dy * t + cy;
- retStrips[p * 3 + 2] = jf * op * strength;
- p++;
-
- }
- }
- retStrips[p * 3 + 0] = retStrips[startP * 3 + 0];
- retStrips[p * 3 + 1] = retStrips[startP * 3 + 1];
- retStrips[p * 3 + 2] = retStrips[startP * 3 + 2];
- p++;
- startP++;
- retStrips[p * 3 + 0] = retStrips[startP * 3 + 0];
- retStrips[p * 3 + 1] = retStrips[startP * 3 + 1];
- retStrips[p * 3 + 2] = retStrips[startP * 3 + 2];
- p++;
- }
- int oldP = p - 1;
- retStrips[p * 3 + 0] = retStrips[oldP * 3 + 0];
- retStrips[p * 3 + 1] = retStrips[oldP * 3 + 1];
- retStrips[p * 3 + 2] = retStrips[oldP * 3 + 2];
- p++;
-
- // Skip the first point here, then make it same as last point later.
- oldP = p;
- p++;
- for (int k = 0; k < rays; k++) {
- int i = k / 2;
- if ((k & 1) == 1) { // traverse the inside in a zig zag pattern
- // for strips
- i = rays - i - 1;
- }
- float dx = (float) Math.cos(Math.PI / 4 + step * i);
- float dy = (float) Math.sin(Math.PI / 4 + step * i);
-
- float jf = 1;
-
- float t = t1[i] + jf * (t2[i] - t1[i]);
- float op = (jf + 1 - 1 / (1 + (t - t1[i]) * (t - t1[i]))) / 2;
-
- retStrips[p * 3 + 0] = dx * t + cx;
- retStrips[p * 3 + 1] = dy * t + cy;
- retStrips[p * 3 + 2] = jf * op * strength;
- p++;
- }
- p = oldP;
- retStrips[p * 3 + 0] = retStrips[oldP * 3 + 0];
- retStrips[p * 3 + 1] = retStrips[oldP * 3 + 1];
- retStrips[p * 3 + 2] = retStrips[oldP * 3 + 2];
- }
-
- public static int getStripSize(int rays, int layers) {
- return (2 + rays + ((layers) * 2 * (rays + 1)));
- }
-}
+++ /dev/null
-/*
- * 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.util;
-
-import android.annotation.NonNull;
-
-import java.awt.geom.CubicCurve2D;
-import java.awt.geom.PathIterator;
-import java.awt.geom.Point2D;
-import java.awt.geom.QuadCurve2D;
-import java.util.ArrayList;
-
-import com.google.android.collect.Lists;
-
-/**
- * Class that returns iterators for a given path. These iterators are lightweight and can be reused
- * multiple times to iterate over the path.
- */
-public class CachedPathIteratorFactory {
- /*
- * A few conventions used in the code:
- * Coordinates or coords arrays store segment coordinates. They use the same format as
- * PathIterator#currentSegment coordinates array.
- * float arrays store always points where the first element is X and the second is Y.
- */
-
- // This governs how accurate the approximation of the Path is.
- private static final float PRECISION = 0.002f;
-
- private final int mWindingRule;
- private final int[] mTypes;
- private final float[][] mCoordinates;
- private final float[] mSegmentsLength;
- private final float mTotalLength;
-
- public CachedPathIteratorFactory(@NonNull PathIterator iterator) {
- mWindingRule = iterator.getWindingRule();
-
- ArrayList<Integer> typesArray = Lists.newArrayList();
- ArrayList<float[]> pointsArray = Lists.newArrayList();
- float[] points = new float[6];
- while (!iterator.isDone()) {
- int type = iterator.currentSegment(points);
- int nPoints = getNumberOfPoints(type) * 2; // 2 coordinates per point
-
- typesArray.add(type);
- float[] itemPoints = new float[nPoints];
- System.arraycopy(points, 0, itemPoints, 0, nPoints);
- pointsArray.add(itemPoints);
- iterator.next();
- }
-
- mTypes = new int[typesArray.size()];
- mCoordinates = new float[mTypes.length][];
- for (int i = 0; i < typesArray.size(); i++) {
- mTypes[i] = typesArray.get(i);
- mCoordinates[i] = pointsArray.get(i);
- }
-
- // Do measurement
- mSegmentsLength = new float[mTypes.length];
-
- // Curves that we can reuse to estimate segments length
- CubicCurve2D.Float cubicCurve = new CubicCurve2D.Float();
- QuadCurve2D.Float quadCurve = new QuadCurve2D.Float();
- float lastX = 0;
- float lastY = 0;
- float totalLength = 0;
- for (int i = 0; i < mTypes.length; i++) {
- switch (mTypes[i]) {
- case PathIterator.SEG_CUBICTO:
- cubicCurve.setCurve(lastX, lastY,
- mCoordinates[i][0], mCoordinates[i][1], mCoordinates[i][2],
- mCoordinates[i][3], lastX = mCoordinates[i][4],
- lastY = mCoordinates[i][5]);
- mSegmentsLength[i] =
- getFlatPathLength(cubicCurve.getPathIterator(null, PRECISION));
- break;
- case PathIterator.SEG_QUADTO:
- quadCurve.setCurve(lastX, lastY, mCoordinates[i][0], mCoordinates[i][1],
- lastX = mCoordinates[i][2], lastY = mCoordinates[i][3]);
- mSegmentsLength[i] =
- getFlatPathLength(quadCurve.getPathIterator(null, PRECISION));
- break;
- case PathIterator.SEG_CLOSE:
- mSegmentsLength[i] = (float) Point2D.distance(lastX, lastY,
- lastX = mCoordinates[0][0],
- lastY = mCoordinates[0][1]);
- mCoordinates[i] = new float[2];
- // We convert a SEG_CLOSE segment to a SEG_LINETO so we do not have to worry
- // about this special case in the rest of the code.
- mTypes[i] = PathIterator.SEG_LINETO;
- mCoordinates[i][0] = mCoordinates[0][0];
- mCoordinates[i][1] = mCoordinates[0][1];
- break;
- case PathIterator.SEG_MOVETO:
- mSegmentsLength[i] = 0;
- lastX = mCoordinates[i][0];
- lastY = mCoordinates[i][1];
- break;
- case PathIterator.SEG_LINETO:
- mSegmentsLength[i] = (float) Point2D.distance(lastX, lastY, mCoordinates[i][0],
- mCoordinates[i][1]);
- lastX = mCoordinates[i][0];
- lastY = mCoordinates[i][1];
- default:
- }
- totalLength += mSegmentsLength[i];
- }
-
- mTotalLength = totalLength;
- }
-
- private static void quadCurveSegment(float[] coords, float t0, float t1) {
- // Calculate X and Y at 0.5 (We'll use this to reconstruct the control point later)
- float mt = t0 + (t1 - t0) / 2;
- float mu = 1 - mt;
- float mx = mu * mu * coords[0] + 2 * mu * mt * coords[2] + mt * mt * coords[4];
- float my = mu * mu * coords[1] + 2 * mu * mt * coords[3] + mt * mt * coords[5];
-
- float u0 = 1 - t0;
- float u1 = 1 - t1;
-
- // coords at t0
- coords[0] = coords[0] * u0 * u0 + coords[2] * 2 * t0 * u0 + coords[4] * t0 * t0;
- coords[1] = coords[1] * u0 * u0 + coords[3] * 2 * t0 * u0 + coords[5] * t0 * t0;
-
- // coords at t1
- coords[4] = coords[0] * u1 * u1 + coords[2] * 2 * t1 * u1 + coords[4] * t1 * t1;
- coords[5] = coords[1] * u1 * u1 + coords[3] * 2 * t1 * u1 + coords[5] * t1 * t1;
-
- // estimated control point at t'=0.5
- coords[2] = 2 * mx - coords[0] / 2 - coords[4] / 2;
- coords[3] = 2 * my - coords[1] / 2 - coords[5] / 2;
- }
-
- private static void cubicCurveSegment(float[] coords, float t0, float t1) {
- // http://stackoverflow.com/questions/11703283/cubic-bezier-curve-segment
- float u0 = 1 - t0;
- float u1 = 1 - t1;
-
- // Calculate the points at t0 and t1 for the quadratic curves formed by (P0, P1, P2) and
- // (P1, P2, P3)
- float qxa = coords[0] * u0 * u0 + coords[2] * 2 * t0 * u0 + coords[4] * t0 * t0;
- float qxb = coords[0] * u1 * u1 + coords[2] * 2 * t1 * u1 + coords[4] * t1 * t1;
- float qxc = coords[2] * u0 * u0 + coords[4] * 2 * t0 * u0 + coords[6] * t0 * t0;
- float qxd = coords[2] * u1 * u1 + coords[4] * 2 * t1 * u1 + coords[6] * t1 * t1;
-
- float qya = coords[1] * u0 * u0 + coords[3] * 2 * t0 * u0 + coords[5] * t0 * t0;
- float qyb = coords[1] * u1 * u1 + coords[3] * 2 * t1 * u1 + coords[5] * t1 * t1;
- float qyc = coords[3] * u0 * u0 + coords[5] * 2 * t0 * u0 + coords[7] * t0 * t0;
- float qyd = coords[3] * u1 * u1 + coords[5] * 2 * t1 * u1 + coords[7] * t1 * t1;
-
- // Linear interpolation
- coords[0] = qxa * u0 + qxc * t0;
- coords[1] = qya * u0 + qyc * t0;
-
- coords[2] = qxa * u1 + qxc * t1;
- coords[3] = qya * u1 + qyc * t1;
-
- coords[4] = qxb * u0 + qxd * t0;
- coords[5] = qyb * u0 + qyd * t0;
-
- coords[6] = qxb * u1 + qxd * t1;
- coords[7] = qyb * u1 + qyd * t1;
- }
-
- /**
- * Returns the end point of a given segment
- *
- * @param type the segment type
- * @param coords the segment coordinates array
- * @param point the return array where the point will be stored
- */
- private static void getShapeEndPoint(int type, @NonNull float[] coords, @NonNull float[]
- point) {
- // start index of the end point for the segment type
- int pointIndex = (getNumberOfPoints(type) - 1) * 2;
- point[0] = coords[pointIndex];
- point[1] = coords[pointIndex + 1];
- }
-
- /**
- * Returns the number of points stored in a coordinates array for the given segment type.
- */
- private static int getNumberOfPoints(int segmentType) {
- switch (segmentType) {
- case PathIterator.SEG_QUADTO:
- return 2;
- case PathIterator.SEG_CUBICTO:
- return 3;
- case PathIterator.SEG_CLOSE:
- return 0;
- default:
- return 1;
- }
- }
-
- /**
- * Returns the estimated length of a flat path. If the passed path is not flat (i.e. contains a
- * segment that is not {@link PathIterator#SEG_CLOSE}, {@link PathIterator#SEG_MOVETO} or {@link
- * PathIterator#SEG_LINETO} this method will fail.
- */
- private static float getFlatPathLength(@NonNull PathIterator iterator) {
- float segment[] = new float[6];
- float totalLength = 0;
- float[] previousPoint = new float[2];
- boolean isFirstPoint = true;
-
- while (!iterator.isDone()) {
- int type = iterator.currentSegment(segment);
- assert type == PathIterator.SEG_LINETO || type == PathIterator.SEG_CLOSE || type ==
- PathIterator.SEG_MOVETO;
-
- // MoveTo shouldn't affect the length
- if (!isFirstPoint && type != PathIterator.SEG_MOVETO) {
- totalLength += Point2D.distance(previousPoint[0], previousPoint[1], segment[0],
- segment[1]);
- } else {
- isFirstPoint = false;
- }
- previousPoint[0] = segment[0];
- previousPoint[1] = segment[1];
- iterator.next();
- }
-
- return totalLength;
- }
-
- /**
- * Returns the estimated position along a path of the given length.
- */
- private void getPointAtLength(int type, @NonNull float[] coords, float lastX, float
- lastY, float t, @NonNull float[] point) {
- if (type == PathIterator.SEG_LINETO) {
- point[0] = lastX + (coords[0] - lastX) * t;
- point[1] = lastY + (coords[1] - lastY) * t;
- // Return here, since we do not need a shape to estimate
- return;
- }
-
- float[] curve = new float[8];
- int lastPointIndex = (getNumberOfPoints(type) - 1) * 2;
-
- System.arraycopy(coords, 0, curve, 2, coords.length);
- curve[0] = lastX;
- curve[1] = lastY;
- if (type == PathIterator.SEG_CUBICTO) {
- cubicCurveSegment(curve, 0f, t);
- } else {
- quadCurveSegment(curve, 0f, t);
- }
-
- point[0] = curve[2 + lastPointIndex];
- point[1] = curve[2 + lastPointIndex + 1];
- }
-
- public CachedPathIterator iterator() {
- return new CachedPathIterator();
- }
-
- /**
- * Class that allows us to iterate over a path multiple times
- */
- public class CachedPathIterator implements PathIterator {
- private int mNextIndex;
-
- /**
- * Current segment type.
- *
- * @see PathIterator
- */
- private int mCurrentType;
-
- /**
- * Stores the coordinates array of the current segment. The number of points stored depends
- * on the segment type.
- *
- * @see PathIterator
- */
- private float[] mCurrentCoords = new float[6];
- private float mCurrentSegmentLength;
-
- /**
- * Current segment length offset. When asking for the length of the current segment, the
- * length will be reduced by this amount. This is useful when we are only using portions of
- * the segment.
- *
- * @see #jumpToSegment(float)
- */
- private float mOffsetLength;
-
- /** Point where the current segment started */
- private float[] mLastPoint = new float[2];
- private boolean isIteratorDone;
-
- private CachedPathIterator() {
- next();
- }
-
- public float getCurrentSegmentLength() {
- return mCurrentSegmentLength;
- }
-
- @Override
- public int getWindingRule() {
- return mWindingRule;
- }
-
- @Override
- public boolean isDone() {
- return isIteratorDone;
- }
-
- @Override
- public void next() {
- if (mNextIndex >= mTypes.length) {
- isIteratorDone = true;
- return;
- }
-
- if (mNextIndex >= 1) {
- // We've already called next() once so there is a previous segment in this path.
- // We want to get the coordinates where the path ends.
- getShapeEndPoint(mCurrentType, mCurrentCoords, mLastPoint);
- } else {
- // This is the first segment, no previous point so initialize to 0, 0
- mLastPoint[0] = mLastPoint[1] = 0f;
- }
- mCurrentType = mTypes[mNextIndex];
- mCurrentSegmentLength = mSegmentsLength[mNextIndex] - mOffsetLength;
-
- if (mOffsetLength > 0f && (mCurrentType == SEG_CUBICTO || mCurrentType == SEG_QUADTO)) {
- // We need to skip part of the start of the current segment (because
- // mOffsetLength > 0)
- float[] points = new float[8];
-
- if (mNextIndex < 1) {
- points[0] = points[1] = 0f;
- } else {
- getShapeEndPoint(mTypes[mNextIndex - 1], mCoordinates[mNextIndex - 1], points);
- }
-
- System.arraycopy(mCoordinates[mNextIndex], 0, points, 2,
- mCoordinates[mNextIndex].length);
- float t0 = (mSegmentsLength[mNextIndex] - mCurrentSegmentLength) /
- mSegmentsLength[mNextIndex];
- if (mCurrentType == SEG_CUBICTO) {
- cubicCurveSegment(points, t0, 1f);
- } else {
- quadCurveSegment(points, t0, 1f);
- }
- System.arraycopy(points, 2, mCurrentCoords, 0, mCoordinates[mNextIndex].length);
- } else {
- System.arraycopy(mCoordinates[mNextIndex], 0, mCurrentCoords, 0,
- mCoordinates[mNextIndex].length);
- }
-
- mOffsetLength = 0f;
- mNextIndex++;
- }
-
- @Override
- public int currentSegment(float[] coords) {
- System.arraycopy(mCurrentCoords, 0, coords, 0, getNumberOfPoints(mCurrentType) * 2);
- return mCurrentType;
- }
-
- @Override
- public int currentSegment(double[] coords) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the point where the current segment ends
- */
- public void getCurrentSegmentEnd(float[] point) {
- point[0] = mLastPoint[0];
- point[1] = mLastPoint[1];
- }
-
- /**
- * Restarts the iterator and jumps all the segments of this path up to the length value.
- */
- public void jumpToSegment(float length) {
- isIteratorDone = false;
- if (length <= 0f) {
- mNextIndex = 0;
- return;
- }
-
- float accLength = 0;
- float lastPoint[] = new float[2];
- for (mNextIndex = 0; mNextIndex < mTypes.length; mNextIndex++) {
- float segmentLength = mSegmentsLength[mNextIndex];
- if (accLength + segmentLength >= length && mTypes[mNextIndex] != SEG_MOVETO) {
- float[] estimatedPoint = new float[2];
- getPointAtLength(mTypes[mNextIndex],
- mCoordinates[mNextIndex], lastPoint[0], lastPoint[1],
- (length - accLength) / segmentLength,
- estimatedPoint);
-
- // This segment makes us go further than length so we go back one step,
- // set a moveto and offset the length of the next segment by the length
- // of this segment that we've already used.
- mCurrentType = PathIterator.SEG_MOVETO;
- mCurrentCoords[0] = estimatedPoint[0];
- mCurrentCoords[1] = estimatedPoint[1];
- mCurrentSegmentLength = 0;
-
- // We need to offset next path length to account for the segment we've just
- // skipped.
- mOffsetLength = length - accLength;
- return;
- }
- accLength += segmentLength;
- getShapeEndPoint(mTypes[mNextIndex], mCoordinates[mNextIndex], lastPoint);
- }
- }
-
- /**
- * Returns the current segment up to certain length. If the current segment is shorter than
- * length, then the whole segment is returned. The segment coordinates are copied into the
- * coords array.
- *
- * @return the segment type
- */
- public int currentSegment(@NonNull float[] coords, float length) {
- int type = currentSegment(coords);
- // If the length is greater than the current segment length, no need to find
- // the cut point. Same if this is a SEG_MOVETO.
- if (mCurrentSegmentLength <= length || type == SEG_MOVETO) {
- return type;
- }
-
- float t = length / getCurrentSegmentLength();
-
- // We find at which offset the end point is located within the coords array and set
- // a new end point to cut the segment short
- switch (type) {
- case SEG_CUBICTO:
- case SEG_QUADTO:
- float[] curve = new float[8];
- curve[0] = mLastPoint[0];
- curve[1] = mLastPoint[1];
- System.arraycopy(coords, 0, curve, 2, coords.length);
- if (type == SEG_CUBICTO) {
- cubicCurveSegment(curve, 0f, t);
- } else {
- quadCurveSegment(curve, 0f, t);
- }
- System.arraycopy(curve, 2, coords, 0, coords.length);
- break;
- default:
- float[] point = new float[2];
- getPointAtLength(type, coords, mLastPoint[0], mLastPoint[1], t, point);
- coords[0] = point[0];
- coords[1] = point[1];
- }
-
- return type;
- }
-
- /**
- * Returns the total length of the path
- */
- public float getTotalLength() {
- return mTotalLength;
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.util;
-
-public class Debug {
-
- public final static boolean DEBUG = false;
-
-}
+++ /dev/null
-/*
- * 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.layoutlib.bridge.util;
-
-import com.android.resources.ResourceType;
-import com.android.util.Pair;
-
-import android.annotation.NonNull;
-import android.util.SparseArray;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class DynamicIdMap {
-
- private final Map<Pair<ResourceType, String>, Integer> mDynamicIds = new HashMap<>();
- private final SparseArray<Pair<ResourceType, String>> mRevDynamicIds = new SparseArray<>();
- private int mDynamicSeed;
-
- public DynamicIdMap(int seed) {
- mDynamicSeed = seed;
- }
-
- public void reset(int seed) {
- mDynamicIds.clear();
- mRevDynamicIds.clear();
- mDynamicSeed = seed;
- }
-
- /**
- * Returns a dynamic integer for the given resource type/name, creating it if it doesn't
- * already exist.
- *
- * @param type the type of the resource
- * @param name the name of the resource
- * @return an integer.
- */
- @NonNull
- public Integer getId(ResourceType type, String name) {
- return getId(Pair.of(type, name));
- }
-
- /**
- * Returns a dynamic integer for the given resource type/name, creating it if it doesn't
- * already exist.
- *
- * @param resource the type/name of the resource
- * @return an integer.
- */
- @NonNull
- public Integer getId(Pair<ResourceType, String> resource) {
- Integer value = mDynamicIds.get(resource);
- if (value == null) {
- value = ++mDynamicSeed;
- mDynamicIds.put(resource, value);
- mRevDynamicIds.put(value, resource);
- }
-
- return value;
- }
-
- public Pair<ResourceType, String> resolveId(int id) {
- return mRevDynamicIds.get(id);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.util;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-
-/**
- * Simpler wrapper around FileInputStream. This is used when the input stream represent
- * not a normal bitmap but a nine patch.
- * This is useful when the InputStream is created in a method but used in another that needs
- * to know whether this is 9-patch or not, such as BitmapFactory.
- */
-public class NinePatchInputStream extends FileInputStream {
- private boolean mFakeMarkSupport = true;
- public NinePatchInputStream(File file) throws FileNotFoundException {
- super(file);
- }
-
- @Override
- public boolean markSupported() {
- // this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream.
- return mFakeMarkSupport || super.markSupported();
-
- }
-
- public void disableFakeMarkSupport() {
- // disable fake mark support so that in case codec actually try to use them
- // we don't lie to them.
- mFakeMarkSupport = false;
- }
-}
+++ /dev/null
-/*
- * 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.util;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-/**
- * Utility to convert checked Reflection exceptions to unchecked exceptions.
- */
-public class ReflectionUtils {
-
- @NonNull
- public static Method getMethod(@NonNull Class<?> clazz, @NonNull String name,
- @Nullable Class<?>... params) throws ReflectionException {
- try {
- return clazz.getMethod(name, params);
- } catch (NoSuchMethodException e) {
- throw new ReflectionException(e);
- }
- }
-
- @NonNull
- public static Method getAccessibleMethod(@NonNull Class<?> clazz, @NonNull String name,
- @Nullable Class<?>... params) throws ReflectionException {
- Method method = getMethod(clazz, name, params);
- method.setAccessible(true);
-
- return method;
- }
-
- @Nullable
- public static Object invoke(@NonNull Method method, @Nullable Object object,
- @Nullable Object... args) throws ReflectionException {
- Exception ex;
- try {
- return method.invoke(object, args);
- } catch (IllegalAccessException | InvocationTargetException e) {
- ex = e;
- }
- throw new ReflectionException(ex);
- }
-
- /**
- * Check if the object is an instance of a class named {@code className}. This doesn't work
- * for interfaces.
- */
- public static boolean isInstanceOf(Object object, String className) {
- Class superClass = object.getClass();
- while (superClass != null) {
- String name = superClass.getName();
- if (name.equals(className)) {
- return true;
- }
- superClass = superClass.getSuperclass();
- }
- return false;
- }
-
- @NonNull
- public static Throwable getCause(@NonNull Throwable throwable) {
- Throwable cause = throwable.getCause();
- return cause == null ? throwable : cause;
- }
-
- /**
- * Looks through the class hierarchy of {@code object} at runtime and returns the class matching
- * the name {@code className}.
- * <p>
- * This is used when we cannot use Class.forName() since the class we want was loaded from a
- * different ClassLoader.
- */
- @NonNull
- public static Class<?> getClassInstance(@NonNull Object object, @NonNull String className) {
- Class<?> superClass = object.getClass();
- while (superClass != null) {
- if (className.equals(superClass.getName())) {
- return superClass;
- }
- superClass = superClass.getSuperclass();
- }
- throw new RuntimeException("invalid object/classname combination.");
- }
-
- /**
- * Wraps all reflection related exceptions. Created since ReflectiveOperationException was
- * introduced in 1.7 and we are still on 1.6
- */
- public static class ReflectionException extends Exception {
- public ReflectionException() {
- super();
- }
-
- public ReflectionException(String message) {
- super(message);
- }
-
- public ReflectionException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public ReflectionException(Throwable cause) {
- super(cause);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.util;
-
-
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.GrowingArrayUtils;
-
-import android.util.SparseArray;
-
-import java.lang.ref.WeakReference;
-
-/**
- * This is a custom {@link SparseArray} that uses {@link WeakReference} around the objects added
- * to it. When the array is compacted, not only deleted indices but also empty references
- * are removed, making the array efficient at removing references that were reclaimed.
- *
- * The code is taken from {@link SparseArray} directly and adapted to use weak references.
- *
- * Because our usage means that we never actually call {@link #remove(long)} or
- * {@link #delete(long)}, we must manually check if there are reclaimed references to
- * trigger an internal compact step (which is normally only triggered when an item is manually
- * removed).
- *
- * SparseArrays map integral values to Objects. Unlike a normal array of Objects,
- * there can be gaps in the indices. It is intended to be more efficient
- * than using a HashMap to map Integers (or Longs) to Objects.
- */
-@SuppressWarnings("unchecked")
-public class SparseWeakArray<E> {
-
- private static final Object DELETED_REF = new Object();
- private static final WeakReference<?> DELETED = new WeakReference(DELETED_REF);
- private boolean mGarbage = false;
-
- /**
- * Creates a new SparseArray containing no mappings.
- */
- public SparseWeakArray() {
- this(10);
- }
-
- /**
- * Creates a new SparseArray containing no mappings that will not
- * require any additional memory allocation to store the specified
- * number of mappings.
- */
- public SparseWeakArray(int initialCapacity) {
- mKeys = ArrayUtils.newUnpaddedLongArray(initialCapacity);
- mValues = new WeakReference[mKeys.length];
- mSize = 0;
- }
-
- /**
- * Gets the Object mapped from the specified key, or <code>null</code>
- * if no such mapping has been made.
- */
- public E get(long key) {
- return get(key, null);
- }
-
- /**
- * Gets the Object mapped from the specified key, or the specified Object
- * if no such mapping has been made.
- */
- public E get(long key, E valueIfKeyNotFound) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i < 0 || mValues[i] == DELETED || mValues[i].get() == null) {
- return valueIfKeyNotFound;
- } else {
- return (E) mValues[i].get();
- }
- }
-
- /**
- * Removes the mapping from the specified key, if there was any.
- */
- public void delete(long key) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i >= 0) {
- if (mValues[i] != DELETED) {
- mValues[i] = DELETED;
- mGarbage = true;
- }
- }
- }
-
- /**
- * Alias for {@link #delete(long)}.
- */
- public void remove(long key) {
- delete(key);
- }
-
- /**
- * Removes the mapping at the specified index.
- */
- public void removeAt(int index) {
- if (mValues[index] != DELETED) {
- mValues[index] = DELETED;
- mGarbage = true;
- }
- }
-
- private void gc() {
- int n = mSize;
- int o = 0;
- long[] keys = mKeys;
- WeakReference<?>[] values = mValues;
-
- for (int i = 0; i < n; i++) {
- WeakReference<?> val = values[i];
-
- // Don't keep any non DELETED values, but only the one that still have a valid
- // reference.
- if (val != DELETED && val.get() != null) {
- if (i != o) {
- keys[o] = keys[i];
- values[o] = val;
- }
-
- o++;
- }
- }
-
- mGarbage = false;
- mSize = o;
- }
-
- /**
- * Adds a mapping from the specified key to the specified value,
- * replacing the previous mapping from the specified key if there
- * was one.
- */
- public void put(long key, E value) {
- int i = binarySearch(mKeys, 0, mSize, key);
-
- if (i >= 0) {
- mValues[i] = new WeakReference(value);
- } else {
- i = ~i;
-
- if (i < mSize && (mValues[i] == DELETED || mValues[i].get() == null)) {
- mKeys[i] = key;
- mValues[i] = new WeakReference(value);
- return;
- }
-
- if (mSize >= mKeys.length && (mGarbage || hasReclaimedRefs())) {
- gc();
-
- // Search again because indices may have changed.
- i = ~binarySearch(mKeys, 0, mSize, key);
- }
-
- mKeys = GrowingArrayUtils.insert(mKeys, mSize, i, key);
- mValues = GrowingArrayUtils.insert(mValues, mSize, i, new WeakReference(value));
- mSize++;
- }
- }
-
- /**
- * Returns the number of key-value mappings that this SparseArray
- * currently stores.
- */
- public int size() {
- if (mGarbage) {
- gc();
- }
-
- return mSize;
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the key from the <code>index</code>th key-value mapping that this
- * SparseArray stores.
- */
- public long keyAt(int index) {
- if (mGarbage) {
- gc();
- }
-
- return mKeys[index];
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, returns
- * the value from the <code>index</code>th key-value mapping that this
- * SparseArray stores.
- */
- public E valueAt(int index) {
- if (mGarbage) {
- gc();
- }
-
- return (E) mValues[index].get();
- }
-
- /**
- * Given an index in the range <code>0...size()-1</code>, sets a new
- * value for the <code>index</code>th key-value mapping that this
- * SparseArray stores.
- */
- public void setValueAt(int index, E value) {
- if (mGarbage) {
- gc();
- }
-
- mValues[index] = new WeakReference(value);
- }
-
- /**
- * Returns the index for which {@link #keyAt} would return the
- * specified key, or a negative number if the specified
- * key is not mapped.
- */
- public int indexOfKey(long key) {
- if (mGarbage) {
- gc();
- }
-
- return binarySearch(mKeys, 0, mSize, key);
- }
-
- /**
- * Returns an index for which {@link #valueAt} would return the
- * specified key, or a negative number if no keys map to the
- * specified value.
- * Beware that this is a linear search, unlike lookups by key,
- * and that multiple keys can map to the same value and this will
- * find only one of them.
- */
- public int indexOfValue(E value) {
- if (mGarbage) {
- gc();
- }
-
- for (int i = 0; i < mSize; i++)
- if (mValues[i].get() == value)
- return i;
-
- return -1;
- }
-
- /**
- * Removes all key-value mappings from this SparseArray.
- */
- public void clear() {
- int n = mSize;
- WeakReference<?>[] values = mValues;
-
- for (int i = 0; i < n; i++) {
- values[i] = null;
- }
-
- mSize = 0;
- mGarbage = false;
- }
-
- /**
- * Puts a key/value pair into the array, optimizing for the case where
- * the key is greater than all existing keys in the array.
- */
- public void append(long key, E value) {
- if (mSize != 0 && key <= mKeys[mSize - 1]) {
- put(key, value);
- return;
- }
-
- if (mSize >= mKeys.length && (mGarbage || hasReclaimedRefs())) {
- gc();
- }
-
- mKeys = GrowingArrayUtils.append(mKeys, mSize, key);
- mValues = GrowingArrayUtils.append(mValues, mSize, new WeakReference(value));
- mSize++;
- }
-
- private boolean hasReclaimedRefs() {
- for (int i = 0 ; i < mSize ; i++) {
- if (mValues[i].get() == null) { // DELETED.get() never returns null.
- return true;
- }
- }
-
- return false;
- }
-
- private static int binarySearch(long[] a, int start, int len, long key) {
- int high = start + len, low = start - 1, guess;
-
- while (high - low > 1) {
- guess = (high + low) / 2;
-
- if (a[guess] < key)
- low = guess;
- else
- high = guess;
- }
-
- if (high == start + len)
- return ~(start + len);
- else if (a[high] == key)
- return high;
- else
- return ~high;
- }
-
- private long[] mKeys;
- private WeakReference<?>[] mValues;
- private int mSize;
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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.google.android.maps;
-
-import com.android.layoutlib.bridge.MockView;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.util.AttributeSet;
-import android.view.View;
-
-/**
- * Mock version of the MapView.
- * Only non override public methods from the real MapView have been added in there.
- * Methods that take an unknown class as parameter or as return object, have been removed for now.
- *
- * TODO: generate automatically.
- *
- */
-public class MapView extends MockView {
-
- /**
- * Construct a new WebView with a Context object.
- * @param context A Context object used to access application assets.
- */
- public MapView(Context context) {
- this(context, null);
- }
-
- /**
- * Construct a new WebView with layout parameters.
- * @param context A Context object used to access application assets.
- * @param attrs An AttributeSet passed to our parent.
- */
- public MapView(Context context, AttributeSet attrs) {
- this(context, attrs, com.android.internal.R.attr.mapViewStyle);
- }
-
- /**
- * Construct a new WebView with layout parameters and a default style.
- * @param context A Context object used to access application assets.
- * @param attrs An AttributeSet passed to our parent.
- * @param defStyle The default style resource ID.
- */
- public MapView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- // START FAKE PUBLIC METHODS
-
- public void displayZoomControls(boolean takeFocus) {
- }
-
- public boolean canCoverCenter() {
- return false;
- }
-
- public void preLoad() {
- }
-
- public int getZoomLevel() {
- return 0;
- }
-
- public void setSatellite(boolean on) {
- }
-
- public boolean isSatellite() {
- return false;
- }
-
- public void setTraffic(boolean on) {
- }
-
- public boolean isTraffic() {
- return false;
- }
-
- public void setStreetView(boolean on) {
- }
-
- public boolean isStreetView() {
- return false;
- }
-
- public int getLatitudeSpan() {
- return 0;
- }
-
- public int getLongitudeSpan() {
- return 0;
- }
-
- public int getMaxZoomLevel() {
- return 0;
- }
-
- public void onSaveInstanceState(Bundle state) {
- }
-
- public void onRestoreInstanceState(Bundle state) {
- }
-
- public View getZoomControls() {
- return null;
- }
-}
+++ /dev/null
-/*
- * 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 dalvik.system;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate used to provide implementation of a select few native methods of {@link VMRuntime}
- * <p/>
- * Through the layoutlib_create tool, the original native methods of VMRuntime have been replaced
- * by calls to methods of the same name in this delegate class.
- */
-public class VMRuntime_Delegate {
-
- // Copied from libcore/libdvm/src/main/java/dalvik/system/VMRuntime
- @LayoutlibDelegate
- /*package*/ static Object newUnpaddedArray(VMRuntime runtime, Class<?> componentType,
- int minLength) {
- // Dalvik has 32bit pointers, the array header is 16bytes plus 4bytes for dlmalloc,
- // allocations are 8byte aligned so having 4bytes of array data avoids padding.
- if (!componentType.isPrimitive()) {
- int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
- return java.lang.reflect.Array.newInstance(componentType, size);
- } else if (componentType == char.class) {
- int bytes = 20 + (2 * minLength);
- int alignedUpBytes = (bytes + 7) & -8;
- int dataBytes = alignedUpBytes - 20;
- int size = dataBytes / 2;
- return new char[size];
- } else if (componentType == int.class) {
- int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
- return new int[size];
- } else if (componentType == byte.class) {
- int bytes = 20 + minLength;
- int alignedUpBytes = (bytes + 7) & -8;
- int dataBytes = alignedUpBytes - 20;
- int size = dataBytes;
- return new byte[size];
- } else if (componentType == boolean.class) {
- int bytes = 20 + minLength;
- int alignedUpBytes = (bytes + 7) & -8;
- int dataBytes = alignedUpBytes - 20;
- int size = dataBytes;
- return new boolean[size];
- } else if (componentType == short.class) {
- int bytes = 20 + (2 * minLength);
- int alignedUpBytes = (bytes + 7) & -8;
- int dataBytes = alignedUpBytes - 20;
- int size = dataBytes / 2;
- return new short[size];
- } else if (componentType == float.class) {
- int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
- return new float[size];
- } else if (componentType == long.class) {
- return new long[minLength];
- } else if (componentType == double.class) {
- return new double[minLength];
- } else {
- assert componentType == void.class;
- throw new IllegalArgumentException("Can't allocate an array of void");
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.icu;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.icu.text.DateTimePatternGenerator;
-import android.icu.util.Currency;
-import android.icu.util.ULocale;
-import android.icu.util.VersionInfo;
-
-import java.util.Locale;
-
-/**
- * Delegate implementing the native methods of libcore.icu.ICU
- *
- * Through the layoutlib_create tool, the original native methods of ICU have been replaced
- * by calls to methods of the same name in this delegate class.
- *
- */
-public class ICU_Delegate {
-
- // --- Java delegates
-
- @LayoutlibDelegate
- /*package*/ static String toLowerCase(String s, String localeName) {
- return s.toLowerCase();
- }
-
- @LayoutlibDelegate
- /*package*/ static String toUpperCase(String s, String localeName) {
- return s.toUpperCase();
- }
-
- // --- Native methods accessing ICU's database.
-
- @LayoutlibDelegate
- /*package*/ static String getBestDateTimePatternNative(String skeleton, String localeName) {
- return DateTimePatternGenerator.getInstance(new ULocale(localeName))
- .getBestPattern(skeleton);
- }
-
- @LayoutlibDelegate
- @SuppressWarnings("deprecation")
- /*package*/ static String getCldrVersion() {
- return VersionInfo.ICU_DATA_VERSION.toString();
- }
-
- @LayoutlibDelegate
- /*package*/ static String getIcuVersion() {
- return VersionInfo.ICU_VERSION.toString();
- }
-
- @LayoutlibDelegate
- /*package*/ static String getUnicodeVersion() {
- return VersionInfo.UNICODE_7_0.toString();
- }
-
- @LayoutlibDelegate
- /*package*/ static String[] getAvailableBreakIteratorLocalesNative() {
- return new String[0];
- }
-
- @LayoutlibDelegate
- /*package*/ static String[] getAvailableCalendarLocalesNative() {
- return new String[0];
- }
-
- @LayoutlibDelegate
- /*package*/ static String[] getAvailableCollatorLocalesNative() {
- return new String[0];
- }
-
- @LayoutlibDelegate
- /*package*/ static String[] getAvailableDateFormatLocalesNative() {
- return new String[0];
- }
-
- @LayoutlibDelegate
- /*package*/ static String[] getAvailableLocalesNative() {
- return new String[0];
- }
-
- @LayoutlibDelegate
- /*package*/ static String[] getAvailableNumberFormatLocalesNative() {
- return new String[0];
- }
-
- @LayoutlibDelegate
- /*package*/ static String[] getAvailableCurrencyCodes() {
- return new String[0];
- }
-
- @LayoutlibDelegate
- /*package*/ static String getCurrencyCode(String locale) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static String getCurrencyDisplayName(String locale, String currencyCode) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static int getCurrencyFractionDigits(String currencyCode) {
- return 0;
- }
-
- @LayoutlibDelegate
- /*package*/ static int getCurrencyNumericCode(String currencyCode) {
- return Currency.getInstance(currencyCode).getNumericCode();
- }
-
- @LayoutlibDelegate
- /*package*/ static String getCurrencySymbol(String locale, String currencyCode) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static String getDisplayCountryNative(String countryCode, String locale) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static String getDisplayLanguageNative(String languageCode, String locale) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static String getDisplayVariantNative(String variantCode, String locale) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static String getDisplayScriptNative(String variantCode, String locale) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static String getISO3Country(String locale) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static String getISO3Language(String locale) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static String addLikelySubtags(String locale) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static String getScript(String locale) {
- return "";
- }
-
- @LayoutlibDelegate
- /*package*/ static String[] getISOLanguagesNative() {
- return Locale.getISOLanguages();
- }
-
- @LayoutlibDelegate
- /*package*/ static String[] getISOCountriesNative() {
- return Locale.getISOCountries();
- }
-
- @LayoutlibDelegate
- /*package*/ static boolean initLocaleDataNative(String locale, LocaleData result) {
-
- // Used by Calendar.
- result.firstDayOfWeek = 1;
- result.minimalDaysInFirstWeek = 1;
-
- // Used by DateFormatSymbols.
- result.amPm = new String[] { "AM", "PM" };
- result.eras = new String[] { "BC", "AD" };
-
- result.longMonthNames = new String[] { "January", "February", "March", "April", "May",
- "June", "July", "August", "September", "October", "November", "December" };
- result.shortMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May",
- "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
- result.longStandAloneMonthNames = result.longMonthNames;
- result.shortStandAloneMonthNames = result.shortMonthNames;
-
- // The platform code expects this to begin at index 1, rather than 0. It maps it directly to
- // the constants from java.util.Calendar.<weekday>
- result.longWeekdayNames = new String[] {
- "", "Sunday", "Monday" ,"Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };
- result.shortWeekdayNames = new String[] {
- "", "Sun", "Mon" ,"Tue", "Wed", "Thu", "Fri", "Sat" };
- result.tinyWeekdayNames = new String[] {
- "", "S", "M", "T", "W", "T", "F", "S" };
-
- result.longStandAloneWeekdayNames = result.longWeekdayNames;
- result.shortStandAloneWeekdayNames = result.shortWeekdayNames;
- result.tinyStandAloneWeekdayNames = result.tinyWeekdayNames;
-
- result.fullTimeFormat = "";
- result.longTimeFormat = "";
- result.mediumTimeFormat = "";
- result.shortTimeFormat = "";
-
- result.fullDateFormat = "";
- result.longDateFormat = "";
- result.mediumDateFormat = "";
- result.shortDateFormat = "";
-
- // Used by DecimalFormatSymbols.
- result.zeroDigit = '0';
- result.decimalSeparator = '.';
- result.groupingSeparator = ',';
- result.patternSeparator = ' ';
- result.percent = "%";
- result.perMill = '\u2030';
- result.monetarySeparator = ' ';
- result.minusSign = "-";
- result.exponentSeparator = "e";
- result.infinity = "\u221E";
- result.NaN = "NaN";
- // Also used by Currency.
- result.currencySymbol = "$";
- result.internationalCurrencySymbol = "USD";
-
- // Used by DecimalFormat and NumberFormat.
- result.numberPattern = "%f";
- result.integerPattern = "%d";
- result.currencyPattern = "%s";
- result.percentPattern = "%f";
-
- return true;
- }
-
- @LayoutlibDelegate
- /*package*/ static void setDefaultLocale(String locale) {
- ICU.setDefaultLocale(locale);
- }
-
- @LayoutlibDelegate
- /*package*/ static String getDefaultLocale() {
- return ICU.getDefaultLocale();
- }
-
- @LayoutlibDelegate
- /*package*/ static String getTZDataVersion() {
- return ICU.getTZDataVersion();
- }
-}
+++ /dev/null
-/*
- * 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 libcore.io;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.libcore.io.BridgeBufferIterator;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import android.system.ErrnoException;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.ByteOrder;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel.MapMode;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Delegate used to provide alternate implementation of select methods of {@link MemoryMappedFile}.
- */
-public class MemoryMappedFile_Delegate {
-
- private static final DelegateManager<MemoryMappedFile_Delegate> sManager = new
- DelegateManager<MemoryMappedFile_Delegate>(MemoryMappedFile_Delegate.class);
-
- private static final Map<MemoryMappedFile, Long> sMemoryMappedFileMap =
- new HashMap<MemoryMappedFile, Long>();
-
- private final MappedByteBuffer mMappedByteBuffer;
- private final long mSize;
-
- /** Path on the target device where the data file is available. */
- private static final String TARGET_PATH = System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo";
- /** Path on the host (inside the SDK) where the data files are available. */
- private static File sRootPath;
-
- @LayoutlibDelegate
- static MemoryMappedFile mmapRO(String path) throws ErrnoException {
- if (!path.startsWith(TARGET_PATH)) {
- throw new ErrnoException("Custom timezone data files are not supported.", 1);
- }
- if (sRootPath == null) {
- throw new ErrnoException("Bridge has not been initialized properly.", 1);
- }
- path = path.substring(TARGET_PATH.length());
- try {
- File f = new File(sRootPath, path);
- if (!f.exists()) {
- throw new ErrnoException("File not found: " + f.getPath(), 1);
- }
- RandomAccessFile file = new RandomAccessFile(f, "r");
- try {
- long size = file.length();
- MemoryMappedFile_Delegate newDelegate = new MemoryMappedFile_Delegate(file);
- long filePointer = file.getFilePointer();
- MemoryMappedFile mmFile = new MemoryMappedFile(filePointer, size);
- long delegateIndex = sManager.addNewDelegate(newDelegate);
- sMemoryMappedFileMap.put(mmFile, delegateIndex);
- return mmFile;
- } finally {
- file.close();
- }
- } catch (IOException e) {
- throw new ErrnoException("mmapRO", 1, e);
- }
- }
-
- @LayoutlibDelegate
- static void close(MemoryMappedFile thisFile) throws ErrnoException {
- Long index = sMemoryMappedFileMap.get(thisFile);
- if (index != null) {
- sMemoryMappedFileMap.remove(thisFile);
- sManager.removeJavaReferenceFor(index);
- }
- }
-
- @LayoutlibDelegate
- static BufferIterator bigEndianIterator(MemoryMappedFile file) {
- MemoryMappedFile_Delegate delegate = getDelegate(file);
- return new BridgeBufferIterator(delegate.mSize, delegate.mMappedByteBuffer.duplicate());
- }
-
- // TODO: implement littleEndianIterator()
-
- public MemoryMappedFile_Delegate(RandomAccessFile file) throws IOException {
- mSize = file.length();
- // It's weird that map() takes size as long, but returns MappedByteBuffer which uses an int
- // to store the marker to the position.
- mMappedByteBuffer = file.getChannel().map(MapMode.READ_ONLY, 0, mSize);
- assert mMappedByteBuffer.order() == ByteOrder.BIG_ENDIAN;
- }
-
- public static void setDataDir(File path) {
- sRootPath = path;
- }
-
- private static MemoryMappedFile_Delegate getDelegate(MemoryMappedFile file) {
- Long index = sMemoryMappedFileMap.get(file);
- return index == null ? null : sManager.getDelegate(index);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package libcore.util;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-/**
- * Delegate implementing the native methods of {@link NativeAllocationRegistry}
- *
- * Through the layoutlib_create tool, the original native methods of NativeAllocationRegistry have
- * been replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original NativeAllocationRegistry class.
- *
- * @see DelegateManager
- */
-public class NativeAllocationRegistry_Delegate {
-
- // ---- delegate manager ----
- private static final DelegateManager<NativeAllocationRegistry_Delegate> sManager =
- new DelegateManager<>(NativeAllocationRegistry_Delegate.class);
-
- private final FreeFunction mFinalizer;
-
- private NativeAllocationRegistry_Delegate(FreeFunction finalizer) {
- mFinalizer = finalizer;
- }
-
- /**
- * The result of this method should be cached by the class and reused.
- */
- public static long createFinalizer(FreeFunction finalizer) {
- return sManager.addNewDelegate(new NativeAllocationRegistry_Delegate(finalizer));
- }
-
- @LayoutlibDelegate
- /*package*/ static void applyFreeFunction(long freeFunction, long nativePtr) {
- // This method MIGHT run in the context of the finalizer thread. If the delegate method
- // crashes, it could bring down the VM. That's why we catch all the exceptions and ignore
- // them.
- try {
- NativeAllocationRegistry_Delegate delegate = sManager.getDelegate(freeFunction);
- if (delegate != null) {
- delegate.mFinalizer.free(nativePtr);
- }
- } catch (Throwable ignore) {
- }
- }
-
- public interface FreeFunction {
- void free(long nativePtr);
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="res"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry combineaccessrules="false" kind="src" path="/layoutlib_bridge"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
- <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>layoutlib_bridge-tests</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Only compile source java files in this lib.
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src) \
- $(call all-java-files-under, res/testApp/MyApplication/src/main/myapplication.widgets)
-LOCAL_JAVA_RESOURCE_DIRS := res
-
-LOCAL_MODULE := layoutlib-tests
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_JAVA_LIBRARIES := layoutlib \
- kxml2-2.3.0 \
- layoutlib_api-prebuilt \
- tools-common-prebuilt \
- sdk-common \
- junit-host \
- guavalib \
- mockito-host
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-# Copy the jar to DIST_DIR for sdk builds
-$(call dist-for-goals, sdk win_sdk, $(LOCAL_INSTALLED_MODULE))
-
-# Build all sub-directories
-include $(call all-makefiles-under,$(LOCAL_PATH))
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- Copyright (C) 2008 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
->
- <Button
- android:id="@+id/bouton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="My Button Text"
- >
- </Button>
- <View
- android:id="@+id/surface"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="2"
- />
- <TextView
- android:id="@+id/status"
- android:paddingLeft="2dip"
- android:layout_weight="0"
- android:background="@drawable/black"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:lines="1"
- android:gravity="center_vertical|center_horizontal"
- android:text="My TextView Text"
- />
-</LinearLayout>
+++ /dev/null
-.gradle
-local.properties
-.idea
-.DS_Store
-*.iml
-# We need the built .class files to load custom views and R class.
-# The only way to negate an exclusion is by including every single parent
-# and excluding all children of those parents.
-
-/build/*
-!/build/intermediates/
-
-/build/intermediates/*
-!/build/intermediates/classes/
+++ /dev/null
-buildscript {
- repositories {
- jcenter()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:1.2.3'
-
- // NOTE: Do not place your application dependencies here; they belong
- // in the individual module build.gradle files
- }
-}
-
-allprojects {
- repositories {
- jcenter()
- }
-}
-
-apply plugin: 'com.android.application'
-
-android {
- compileSdkVersion 25
- buildToolsVersion '25.0.0'
- defaultConfig {
- applicationId 'com.android.layoutlib.test.myapplication'
- minSdkVersion 21
- targetSdkVersion 25
- versionCode 1
- versionName '1.0'
- }
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- }
- }
- lintOptions {
- abortOnError false
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_6
- targetCompatibility JavaVersion.VERSION_1_6
- }
-}
-
-dependencies {
- compile fileTree(dir: 'libs', include: ['*.jar'])
-}
+++ /dev/null
-# Project-wide Gradle settings.
-
-# IDE (e.g. Android Studio) users:
-# Settings specified in this file will override any Gradle settings
-# configured through the IDE.
-
-# For more details on how to configure your build environment visit
-# http://www.gradle.org/docs/current/userguide/build_environment.html
-
-# Specifies the JVM arguments used for the daemon process.
-# The setting is particularly useful for tweaking memory settings.
-# Default value: -Xmx10248m -XX:MaxPermSize=256m
-# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
-
-# When configured, Gradle will run in incubating parallel mode.
-# This option should only be used with decoupled projects. More details, visit
-# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
-# org.gradle.parallel=true
\ No newline at end of file
+++ /dev/null
-#Tue Mar 17 15:13:06 PDT 2015
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
+++ /dev/null
-#!/usr/bin/env bash
-
-##############################################################################
-##
-## Gradle start up script for UN*X
-##
-##############################################################################
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
-
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
-
-# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
-
-warn ( ) {
- echo "$*"
-}
-
-die ( ) {
- echo
- echo "$*"
- echo
- exit 1
-}
-
-# OS specific support (must be 'true' or 'false').
-cygwin=false
-msys=false
-darwin=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
-esac
-
-# For Cygwin, ensure paths are in UNIX format before anything is touched.
-if $cygwin ; then
- [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
-fi
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >&-
-APP_HOME="`pwd -P`"
-cd "$SAVED" >&-
-
-CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
-
-# Determine the Java command to use to start the JVM.
-if [ -n "$JAVA_HOME" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- fi
- if [ ! -x "$JAVACMD" ] ; then
- die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
- fi
-else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-
-Please set the JAVA_HOME variable in your environment to match the
-location of your Java installation."
-fi
-
-# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
-fi
-
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
-
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
- # Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
- fi
- i=$((i+1))
- done
- case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
-fi
-
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
- JVM_OPTS=("$@")
-}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
-
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+++ /dev/null
-@if "%DEBUG%" == "" @echo off\r
-@rem ##########################################################################\r
-@rem\r
-@rem Gradle startup script for Windows\r
-@rem\r
-@rem ##########################################################################\r
-\r
-@rem Set local scope for the variables with windows NT shell\r
-if "%OS%"=="Windows_NT" setlocal\r
-\r
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r
-set DEFAULT_JVM_OPTS=\r
-\r
-set DIRNAME=%~dp0\r
-if "%DIRNAME%" == "" set DIRNAME=.\r
-set APP_BASE_NAME=%~n0\r
-set APP_HOME=%DIRNAME%\r
-\r
-@rem Find java.exe\r
-if defined JAVA_HOME goto findJavaFromJavaHome\r
-\r
-set JAVA_EXE=java.exe\r
-%JAVA_EXE% -version >NUL 2>&1\r
-if "%ERRORLEVEL%" == "0" goto init\r
-\r
-echo.\r
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r
-echo.\r
-echo Please set the JAVA_HOME variable in your environment to match the\r
-echo location of your Java installation.\r
-\r
-goto fail\r
-\r
-:findJavaFromJavaHome\r
-set JAVA_HOME=%JAVA_HOME:"=%\r
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe\r
-\r
-if exist "%JAVA_EXE%" goto init\r
-\r
-echo.\r
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r
-echo.\r
-echo Please set the JAVA_HOME variable in your environment to match the\r
-echo location of your Java installation.\r
-\r
-goto fail\r
-\r
-:init\r
-@rem Get command-line arguments, handling Windowz variants\r
-\r
-if not "%OS%" == "Windows_NT" goto win9xME_args\r
-if "%@eval[2+2]" == "4" goto 4NT_args\r
-\r
-:win9xME_args\r
-@rem Slurp the command line arguments.\r
-set CMD_LINE_ARGS=\r
-set _SKIP=2\r
-\r
-:win9xME_args_slurp\r
-if "x%~1" == "x" goto execute\r
-\r
-set CMD_LINE_ARGS=%*\r
-goto execute\r
-\r
-:4NT_args\r
-@rem Get arguments from the 4NT Shell from JP Software\r
-set CMD_LINE_ARGS=%$\r
-\r
-:execute\r
-@rem Setup the command line\r
-\r
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar\r
-\r
-@rem Execute Gradle\r
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r
-\r
-:end\r
-@rem End local scope for the variables with windows NT shell\r
-if "%ERRORLEVEL%"=="0" goto mainEnd\r
-\r
-:fail\r
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r
-rem the _cmd.exe /c_ return code!\r
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1\r
-exit /b 1\r
-\r
-:mainEnd\r
-if "%OS%"=="Windows_NT" endlocal\r
-\r
-:omega\r
+++ /dev/null
-# Add project specific ProGuard rules here.
-# By default, the flags in this file are appended to flags specified
-# in /usr/local/google/home/deepanshu/ssd/sdk_out/tools/proguard/proguard-android.txt
-# You can edit the include path and order by changing the proguardFiles
-# directive in build.gradle.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# Add any project specific keep options here:
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.layoutlib.test.myapplication" >
-<!-- If changing package here, update LayoutLibCallBack in tests. -->
- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@style/AppTheme" >
- <activity
- android:name="com.android.layoutlib.test.myapplication.MyActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- </application>
-
-</manifest>
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.test.myapplication;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.AttributeSet;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-/**
- * A widget to test obtaining arrays from resources.
- */
-public class ArraysCheckWidget extends LinearLayout {
- public ArraysCheckWidget(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ArraysCheckWidget(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public ArraysCheckWidget(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- Resources resources = context.getResources();
- for (CharSequence chars : resources.getTextArray(R.array.array)) {
- addTextView(context, chars);
- }
- for (int i : resources.getIntArray(R.array.int_array)) {
- addTextView(context, String.valueOf(i));
- }
- for (String string : resources.getStringArray(R.array.string_array)) {
- addTextView(context, string);
- }
- }
-
- private void addTextView(Context context, CharSequence string) {
- TextView textView = new TextView(context);
- textView.setText(string);
- textView.setTextSize(30);
- addView(textView);
- }
-}
+++ /dev/null
-package com.android.layoutlib.test.myapplication;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
-
-public class MyActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity);
- }
-
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- // Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.my, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- int id = item.getItemId();
- if (id == R.id.action_settings) {
- return true;
- }
- return super.onOptionsItemSelected(item);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.test.myapplication.widgets;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.CalendarView;
-
-public class CustomCalendar extends CalendarView {
- public CustomCalendar(Context context) {
- super(context);
- init();
- }
-
- public CustomCalendar(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public CustomCalendar(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init();
- }
-
- public CustomCalendar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- init();
- }
-
- private void init() {
- setDate(871732800000L, false, true);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.test.myapplication.widgets;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.DatePicker;
-
-public class CustomDate extends DatePicker {
- public CustomDate(Context context) {
- super(context);
- init();
- }
-
- public CustomDate(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public CustomDate(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init();
- }
-
- public CustomDate(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- init();
- }
-
- private void init() {
- init(2015, 0, 20, null);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.test.myapplication.widgets;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.WindowInsets;
-import android.widget.TextView;
-
-public class InsetsWidget extends TextView {
- public static boolean sApplyInsetsCalled = false;
-
- public InsetsWidget(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
-
- requestApplyInsets();
- }
-
- @Override
- public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- sApplyInsetsCalled = true;
- return super.onApplyWindowInsets(insets);
- }
-}
+++ /dev/null
-/**
- * This package contains custom widgets used to set a specific time for the DayTimePicker during
- * testing.
- * The classes here are both used from the Android project and from the Bridge test project.
- */
-package com.android.layoutlib.test.myapplication.widgets;
\ No newline at end of file
+++ /dev/null
-<!--
- ~ Copyright (C) 2016 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-
-<gradient xmlns:android="http://schemas.android.com/apk/res/android"
- android:startX="10"
- android:startY="10"
- android:endX="50"
- android:endY="50"
- android:startColor="#ffff0000"
- android:endColor="#ff00ff00" />
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
- <background android:drawable="@android:color/red" />
- <foreground android:drawable="@drawable/headset" />
-</adaptive-icon>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2016 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:viewportWidth="1102"
- android:viewportHeight="642"
- android:width="1102px"
- android:height="642px">
-
- <group
- android:translateX="-126.347"
- android:translateY="6.7928655e-4">
-
-
- <path
- android:fillColor="#94c147"
- android:pathData="
- m 552.777,147.57
- c -14.147,0 -25.622,11.652 -25.622,26.02
- v 101.68
- c 0,14.372 11.475,26.019 25.622,26.019 14.147,0 25.61,-11.646 25.61,-26.019
- V 173.59
- c 0.001,-14.368 -11.462,-26.02 -25.61,-26.02
- z
-
- m -309.011,0
- c -14.155,0 -25.618,11.652 -25.618,26.02
- v 101.68
- c 0,14.372 11.462,26.019 25.618,26.019 14.153,0 25.623,-11.646 25.623,-26.019
- V 173.59
- c -0.008,-14.368 -11.475,-26.02 -25.623,-26.02
- z" />
-
-
- <path
- android:fillColor="#94c147"
- android:pathData="m 284.799,148.364 v 185.768 c 0,11.035 8.948,19.98 19.983,19.98 h 22.815 v 56.567 c 0,14.37 11.47,26.016 25.623,26.016 14.148,0 25.623,-11.646 25.623,-26.016 v -56.567 h 39.878 v 56.567 c 0,14.37 11.463,26.016 25.61,26.016 14.147,0 25.622,-11.646 25.622,-26.016 v -56.567 h 22.828 c 11.022,0 19.971,-8.953 19.971,-19.98 V 148.364 H 284.799 l 0,0 z" />
-
- <group
- android:name="head"
- android:pivotX="400"
- android:pivotY="131.105">
-
- <path
- android:fillColor="#94c147"
- android:pathData="m 452.302,52.105 21.057,-30.572 c 1.245,-1.819 0.939,-4.199 -0.695,-5.329 -1.637,-1.123 -3.968,-0.568 -5.225,1.251 l -21.875,31.75 c -14.404,-5.682 -30.418,-8.844 -47.293,-8.844 -16.87,0 -32.893,3.162 -47.297,8.844 l -21.875,-31.75 c -1.257,-1.819 -3.589,-2.375 -5.225,-1.251 -1.636,1.124 -1.946,3.509 -0.696,5.329 l 21.057,30.572 c -33.464,15.57 -56.951,45.166 -59.941,79.706 H 512.25 C 509.259,97.271 485.772,67.676 452.302,52.105 z M 350.187,100.28 c -6.965,0 -12.617,-5.646 -12.617,-12.616 0,-6.958 5.647,-12.61 12.617,-12.61 6.97,0 12.603,5.652 12.603,12.61 0,6.965 -5.64,12.616 -12.603,12.616 z m 97.744,0 c -6.97,0 -12.609,-5.646 -12.609,-12.616 0,-6.958 5.64,-12.61 12.609,-12.61 6.971,0 12.61,5.652 12.61,12.61 0,6.965 -5.64,12.616 -12.61,12.616 z" />
- </group>
-
- </group>
-
-</vector>
\ No newline at end of file
+++ /dev/null
-<!--
- ~ Copyright (C) 2016 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="150dp"
- android:height="150dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="m12,1c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,-3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h4v1h-7v2h6c1.66,0 3,-1.34 3,-3V10c0,-4.97 -4.03,-9 -9,-9z"/>
-</vector>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="#ff0000" />
- <size
- android:width="20dp"
- android:height="20dp" />
-</shape>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="76dp"
- android:width="76dp"
- android:viewportHeight="48"
- android:viewportWidth="48"
- android:alpha="0.6">
-
- <group
- android:name="root"
- android:translateX="24.0"
- android:translateY="24.0">
- <!--
- This is the same as the material indeterminate progressbar which involves drawing
- several cubic segments
- -->
- <path
- android:pathData="M0, 0 m 0, -19 a 19,19 0 1,1 0,38 a 19,19 0 1,1 0,-38"
- android:strokeColor="#00FF00"
- android:strokeLineCap="square"
- android:strokeLineJoin="miter"
- android:strokeWidth="1"
- android:trimPathEnd="0.8"
- android:trimPathStart="0.3" />
- <!-- Same figure with reversed end and start -->
- <path
- android:pathData="M0, 0 m 0, -12 a 19,19 0 1,1 0,38 a 19,19 0 1,1 0,-38"
- android:strokeColor="#FFFF00"
- android:strokeLineCap="square"
- android:strokeLineJoin="miter"
- android:strokeWidth="1"
- android:trimPathEnd="0.3"
- android:trimPathStart="0.8" />
-
- <!--
- Draw a few partial quadratic segments
- -->
- <path
- android:strokeWidth="2"
- android:strokeColor="#FFFF00"
- android:pathData="M2,2 Q 5 30 15 0"
- android:trimPathStart="0.1"
- android:trimPathEnd="0.9"
- />
-
- <!--
- Draw a line
- -->
- <path
- android:strokeWidth="3"
- android:strokeColor="#00FFFF"
- android:pathData="M-10,-10 L 10, 10"
- android:trimPathStart="0.2"
- android:trimPathEnd="0.8"
- />
-
- <!--
- Draw a line with gradient stroke color
- -->
- <path
- android:strokeWidth="1"
- android:strokeColor="#FF00FF"
- android:fillColor="@color/gradient"
- android:pathData="M-20,-20 l0, 10 l10, 0 l0, -10 l-10,0 "
- />
-
- <!--
- Draw squares with different fill types
- -->
- <path
- android:fillType="evenOdd"
- android:strokeWidth="1"
- android:strokeColor="#AABBCC"
- android:fillColor="#AAEFCC"
- android:pathData="M-20,-40 l0, 10 l10, 0 l0, -10 l-10,0 m5,0 l0, 10 l10, 0 l0, -10 l-10,0"
- />
-
- <path
- android:fillType="nonZero"
- android:strokeWidth="1"
- android:strokeColor="#AABBCC"
- android:fillColor="#40AAEFCC"
- android:pathData="M0,-40 l0, 10 l10, 0 l0, -10 l-10,0 m5,0 l0, 10 l10, 0 l0, -10 l-10,0"
- />
- </group>
-
-</vector>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<font-family xmlns:android="http://schemas.android.com/apk/res/android">
- <font android:fontStyle="normal" android:fontWeight="400" android:font="@font/testfont" />
- <font android:fontStyle="italic" android:fontWeight="400" android:font="@font/testfont2" />
-</font-family>
\ No newline at end of file
+++ /dev/null
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingLeft="@dimen/activity_horizontal_margin"
- android:paddingRight="@dimen/activity_horizontal_margin"
- android:paddingTop="@dimen/activity_vertical_margin"
- android:paddingBottom="@dimen/activity_vertical_margin"
- tools:context=".MyActivity">
-
- <TextView
- android:text="@string/hello_world"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/text1"/>
-
- <include layout="@layout/layout"
- android:layout_below="@+id/text1"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content" />
-</RelativeLayout>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:ignore="HardcodedText,LabelFor,TextFields,ContentDescription,RtlHardcoded">
-
- <FrameLayout
- android:id="@id/frameLayout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
- android:layout_alignParentTop="true"
- android:layout_marginEnd="311dp">
-
- <TextView
- android:id="@id/textView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="left|top"
- android:text="New Text" />
- </FrameLayout>
-
- <TextView
- android:id="@id/textView2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_below="@id/frameLayout"
- android:text="Large Text"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:pointerIcon="hand" />
-
- <TextView
- android:id="@id/textView3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_toEndOf="@id/textView2"
- android:text="Medium Text"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@id/textView4"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignTop="@id/textView2"
- android:layout_toEndOf="@id/textView2"
- android:text="Small Text"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
- <Button
- android:id="@id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/textView3"
- android:layout_toEndOf="@id/textView4"
- android:text="New Button" />
-
- <Button
- android:id="@id/button2"
- style="?android:attr/buttonStyleSmall"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_toEndOf="@id/button"
- android:text="New Button" />
-
- <CheckBox
- android:id="@id/checkBox"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignEnd="@id/button"
- android:layout_below="@id/button"
- android:text="New CheckBox" />
-
- <Switch
- android:id="@id/switch1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_below="@id/textView2"
- android:text="New Switch" />
-
- <ImageButton
- android:id="@id/imageButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/button"
- android:layout_toEndOf="@id/switch1" />
-
- <ImageView
- android:id="@id/imageView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_launcher"
- android:layout_below="@id/button"
- android:layout_toEndOf="@id/imageButton" />
-
- <GridLayout
- android:id="@id/gridLayout"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_below="@id/imageButton"
- android:columnCount="2"
- android:rowCount="2">
-
- <ProgressBar
- android:id="@id/progressBar"
- style="?android:attr/progressBarStyleLarge"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_column="0"
- android:layout_row="0" />
-
- <ProgressBar
- android:id="@id/progressBar2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_column="1"
- android:layout_row="0" />
-
- <ProgressBar
- android:id="@id/progressBar3"
- style="?android:attr/progressBarStyleSmall"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_column="0"
- android:layout_row="1" />
-
- <ProgressBar
- android:id="@id/progressBar4"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_column="1"
- android:layout_row="1" />
- </GridLayout>
-
- <SeekBar
- android:id="@id/seekBar"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignTop="@id/gridLayout"
- android:layout_toEndOf="@id/gridLayout" />
-
- <RatingBar
- android:id="@id/ratingBar"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/switch2"
- android:layout_toEndOf="@id/gridLayout" />
-
- <Switch
- android:id="@id/switch2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/seekBar"
- android:layout_toEndOf="@id/switch1"
- android:checked="true" />
-
- <EditText
- android:id="@id/editText"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignBottom="@id/ratingBar"
- android:layout_alignParentStart="true"
- android:text="plain text" />
-
- <EditText
- android:id="@id/editText2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_below="@id/ratingBar"
- android:ems="3"
- android:inputType="textPersonName"
- android:text="Name" />
-
- <EditText
- android:id="@id/editText3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_toEndOf="@id/editText2"
- android:ems="2"
- android:inputType="textPassword"
- android:text="password" />
-
- <EditText
- android:id="@id/editText4"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignTop="@id/editText3"
- android:layout_toEndOf="@id/editText3"
- android:ems="3"
- android:inputType="numberPassword"
- android:text="numeric password" />
-
- <ToggleButton
- android:id="@+id/toggleButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignTop="@id/editText4"
- android:layout_toEndOf="@id/editText4"
- android:text="New ToggleButton" />
-
- <EditText
- android:id="@id/editText5"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/editText3"
- android:layout_toStartOf="@id/editText6"
- android:ems="7"
- android:inputType="textEmailAddress"
- android:text="email@domain.com" />
-
- <EditText
- android:id="@id/editText6"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
- android:layout_below="@id/editText4"
- android:ems="7"
- android:inputType="phone"
- android:text="+11235554344" />
-
- <EditText
- android:id="@id/editText7"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/editText"
- android:layout_toEndOf="@id/editText4"
- android:ems="10"
- android:inputType="textPostalAddress"
- android:text="1600 Amphitheatre" />
-
- <EditText
- android:id="@id/editText9"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/editText5"
- android:layout_alignParentStart="true"
- android:ems="3"
- android:inputType="time"
- android:text="12:12" />
-
- <RadioGroup
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/editText5"
- android:layout_toEndOf="@id/editText9"
- android:orientation="horizontal">
-
- <RadioButton
- android:id="@id/radioButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="New RadioButton" />
-
- <RadioButton
- android:id="@id/radioButton2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="New RadioButton"
- android:checked="true" />
-
- </RadioGroup>
-
- <CheckedTextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="CheckedTextView"
- android:id="@id/checkedTextView"
- android:layout_below="@id/button2"
- android:layout_alignParentEnd="true"
- android:layout_alignStart="@id/button2" />
-
- <DialerFilter
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/checkBox"
- android:layout_toStartOf="@id/quickContactBadge"
- android:id="@id/dialerFilter"
- android:layout_above="@id/ratingBar"
- android:layout_toEndOf="@id/seekBar">
-
- <EditText
- android:id="@android:id/hint"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="Hint" />
-
- <EditText
- android:id="@android:id/primary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@android:id/hint"
- android:text="Primary" />
- </DialerFilter>
-
- <QuickContactBadge
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@id/quickContactBadge"
- android:layout_below="@id/checkedTextView"
- android:layout_alignParentEnd="true" />
-
- <android.inputmethodservice.ExtractEditText
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="ExtractEditText"
- android:id="@id/extractEditText"
- android:layout_below="@id/editText9"
- android:layout_alignParentEnd="true"
- android:layout_alignStart="@id/checkedTextView" />
-
- <ZoomControls
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@id/zoomControls"
- android:layout_below="@id/editText9"
- android:layout_alignParentStart="true" />
-
- <TextureView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@id/textureView"
- android:layout_below="@id/zoomControls"
- android:layout_alignParentStart="true"
- android:layout_alignBottom="@id/extractEditText"
- android:layout_toStartOf="@id/editText3" />
-
- <ListView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@id/listView"
- android:layout_below="@id/textureView"
- android:layout_alignParentStart="true"
- android:layout_alignEnd="@id/textureView" />
-
- <GridView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@id/gridView"
- android:layout_below="@id/extractEditText"
- android:layout_alignParentEnd="true"
- android:layout_alignStart="@id/extractEditText" />
-
- <ScrollView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@id/scrollView"
- android:layout_below="@id/zoomControls"
- android:layout_toRightOf="@id/listView"
- android:layout_toLeftOf="@id/extractEditText">
-
- <TabHost
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:id="@id/tabHost">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <TabWidget
- android:id="@android:id/tabs"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
-
- <FrameLayout
- android:id="@android:id/tabcontent"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:id="@id/linearLayout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"/>
-
- <LinearLayout
- android:id="@id/linearLayout2"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"/>
-
- </FrameLayout>
- </LinearLayout>
- </TabHost>
-</ScrollView>
-
- <SearchView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@id/searchView"
- android:layout_alignBottom="@id/zoomControls"
- android:layout_toEndOf="@id/seekBar" />
-
-</RelativeLayout>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.layoutlib.test.myapplication.ArraysCheckWidget
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="match_parent"
- android:layout_height="match_parent">
-
-</com.android.layoutlib.test.myapplication.ArraysCheckWidget>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:padding="16dp"
- android:orientation="horizontal"
- android:background="#AAAAAA"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
-
- <include layout="@layout/expand_layout"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content" />
-
-</LinearLayout>
-
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <TextView
- android:background="#FF0000"
- android:textSize="200sp"
- android:layout_width="200dp"
- android:layout_height="200dp" />
- <TextView
- android:background="#00FF00"
- android:textSize="200sp"
- android:layout_width="200dp"
- android:layout_height="200dp" />
- <TextView
- android:background="#0000FF"
- android:textSize="200sp"
- android:layout_width="200dp"
- android:layout_height="200dp" />
- <TextView
- android:background="#FF00FF"
- android:textSize="200sp"
- android:layout_width="200dp"
- android:layout_height="200dp" />
- <TextView
- android:background="#00FFFF"
- android:textSize="200sp"
- android:layout_width="200dp"
- android:layout_height="200dp" />
-</merge>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:padding="16dp"
- android:orientation="vertical"
- android:background="#AAAAAA"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
-
- <include layout="@layout/expand_layout"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content" />
-
-</LinearLayout>
-
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="CONDENSED"
- android:textSize="50sp"
- android:fontFamily="sans-serif-condensed"
- />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="CONDENSED ITALIC"
- android:textSize="30sp"
- android:fontFamily="sans-serif-condensed"
- android:textStyle="italic"
- />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="MONOSPACE"
- android:textSize="50sp"
- android:fontFamily="monospace"/>
-
- <Space
- android:layout_width="wrap_content"
- android:layout_height="30dp" />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Custom"
- android:textSize="20sp"
- android:fontFamily="@font/testfont"/>
-
- <Space
- android:layout_width="wrap_content"
- android:layout_height="30dp" />
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Custom family"
- android:textSize="20sp"
- android:fontFamily="@font/testfamily"/>
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Custom family"
- android:textSize="20sp"
- android:fontFamily="@font/testfamily"
- android:textStyle="italic"/>
-
-</LinearLayout>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_centerHorizontal="true"
- android:textSize="40sp"
- android:text="Bottom Text" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
- android:textSize="40sp"
- android:text="Top text" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentStart="true"
- android:layout_centerVertical="true"
- android:textSize="40sp"
- android:text="Start text" />
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
- android:layout_centerVertical="true"
- android:textSize="40sp"
- android:text="End text" />
-</RelativeLayout>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-
-<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:columnCount="2"
- android:layout_height="match_parent">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Some text"/>
- <Switch
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:checked="true"
- android:layout_gravity="center"
- />
- <com.android.layoutlib.test.myapplication.widgets.CustomDate
- android:layout_width="100dp"
- android:layout_height="wrap_content"/>
- <com.android.layoutlib.test.myapplication.widgets.CustomCalendar
- android:layout_width="200dp"
- android:layout_gravity="center_horizontal"
- android:layout_height="200dp"/>
-</GridLayout>
\ No newline at end of file
+++ /dev/null
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:scrollX="30px"
- android:scrollY="90px">
- <LinearLayout
- android:layout_width="60dp"
- android:layout_height="60dp"
- android:background="#FF0000" />
- <LinearLayout
- android:layout_width="60dp"
- android:layout_height="30dp"
- android:background="#00FF00" />
- <LinearLayout
- android:layout_width="60dp"
- android:layout_height="60dp"
- android:background="#0000FF" />
- <LinearLayout
- android:layout_width="60dp"
- android:layout_height="30dp"
- android:background="#FF00FF" />
- <LinearLayout
- android:layout_width="60dp"
- android:layout_height="60dp"
- android:background="#00FFFF" />
-
- <LinearLayout
- android:layout_width="200dp"
- android:layout_height="400dp"
- android:orientation="vertical"
- android:scrollX="-90px"
- android:scrollY="450px">
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="60dp"
- android:background="#FF0000" />
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="30dp"
- android:background="#00FF00" />
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="60dp"
- android:background="#0000FF" />
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="30dp"
- android:background="#FF00FF" />
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="60dp"
- android:background="#00FFFF" />
- </LinearLayout>
-
-
-</LinearLayout>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2017 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1">
-
- <Button
- android:layout_marginLeft="40dp"
- android:layout_width="48dp"
- android:layout_height="40dp"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:elevation="48dp"
- android:stateListAnimator="@null"/>
-
- <Button
- android:layout_marginRight="40dp"
- android:layout_width="48dp"
- android:layout_height="40dp"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:elevation="48dp"
- android:stateListAnimator="@null"/>
-
- </RelativeLayout>
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1">
-
- <Button
- android:layout_marginLeft="40dp"
- android:layout_width="48dp"
- android:layout_height="40dp"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:elevation="0dp"
- android:stateListAnimator="@null"/>
-
- <Button
- android:layout_marginRight="40dp"
- android:layout_width="48dp"
- android:layout_height="40dp"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:elevation="108dp"
- android:stateListAnimator="@null"/>
-
- </RelativeLayout>
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1">
-
- <Button
- android:layout_marginLeft="40dp"
- android:layout_width="48dp"
- android:layout_height="40dp"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:elevation="12dp"
- android:stateListAnimator="@null"/>
-
- <Button
- android:layout_marginRight="40dp"
- android:layout_width="48dp"
- android:layout_height="40dp"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:elevation="108dp"
- android:stateListAnimator="@null"/>
-
- </RelativeLayout>
-</LinearLayout>
\ No newline at end of file
+++ /dev/null
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- tools:context=".MyActivity" >
- <item android:id="@+id/action_settings"
- android:title="@string/action_settings"
- android:orderInCategory="100"
- android:showAsAction="never" />
-</menu>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <array name="array">
- <item>first</item>
- <item>second</item>
- </array>
- <integer-array name="int_array">
- <item>1</item>
- <item>0xaB</item> <!-- hex entry (decimal 171) -->
- <item>010</item> <!-- octal entry -->
- <item>@integer/ten</item> <!-- value reference -->
- <item>?attr/myattr</item> <!-- theme attr reference -->
- </integer-array>
- <string-array name="string_array">
- <item>mystring</item>
- <item>@string/hello_world</item> <!-- string ref in appNs -->
- <!-- theme ref in android NS. value = @string/candidates_style = <u>candidates</u> -->
- <item>?android:attr/candidatesTextStyleSpans</item>
- <item>@android:string/unknownName</item> <!-- value = Unknown -->
- <item>?EC</item>
- </string-array>
-
- <!-- resources that the above array can refer to -->
- <integer name="ten">10</integer>
- <integer name="twelve">12</integer>
-</resources>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <attr name="myattr" format="integer" />
-</resources>
\ No newline at end of file
+++ /dev/null
-<resources>
- <!-- Default screen margins, per the Android Design guidelines. -->
- <dimen name="activity_horizontal_margin">16dp</dimen>
- <dimen name="activity_vertical_margin">16dp</dimen>
-</resources>
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <item type="id" name="button" />
- <item type="id" name="button2" />
- <item type="id" name="checkBox" />
- <item type="id" name="checkedTextView" />
- <item type="id" name="dialerFilter" />
- <item type="id" name="editText" />
- <item type="id" name="editText2" />
- <item type="id" name="editText3" />
- <item type="id" name="editText4" />
- <item type="id" name="editText5" />
- <item type="id" name="editText6" />
- <item type="id" name="editText7" />
- <item type="id" name="editText8" />
- <item type="id" name="editText9" />
- <item type="id" name="extractEditText" />
- <item type="id" name="frameLayout" />
- <item type="id" name="gridLayout" />
- <item type="id" name="gridView" />
- <item type="id" name="imageButton" />
- <item type="id" name="imageView" />
- <item type="id" name="linearLayout" />
- <item type="id" name="linearLayout2" />
- <item type="id" name="listView" />
- <item type="id" name="progressBar" />
- <item type="id" name="progressBar2" />
- <item type="id" name="progressBar3" />
- <item type="id" name="progressBar4" />
- <item type="id" name="quickContactBadge" />
- <item type="id" name="radioButton" />
- <item type="id" name="radioButton2" />
- <item type="id" name="ratingBar" />
- <item type="id" name="scrollView" />
- <item type="id" name="searchView" />
- <item type="id" name="seekBar" />
- <item type="id" name="spinner" />
- <item type="id" name="switch1" />
- <item type="id" name="switch2" />
- <item type="id" name="tabHost" />
- <item type="id" name="textView" />
- <item type="id" name="textView2" />
- <item type="id" name="textView3" />
- <item type="id" name="textView4" />
- <item type="id" name="textureView" />
- <item type="id" name="zoomControls" />
-</resources>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
- <string name="app_name">My Application</string>
- <string name="hello_world">Hello world!</string>
- <string name="action_settings">Settings</string>
-
-</resources>
+++ /dev/null
-<resources>
-
- <!-- Base application theme. -->
- <style name="AppTheme" parent="android:Theme.Material.Light.DarkActionBar">
- <item name="myattr">@integer/ten</item>
- </style>
-
-</resources>
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import org.junit.Test;
-
-import android.content.Context;
-import android.hardware.input.InputManager;
-import android.view.WindowManager;
-import android.view.accessibility.AccessibilityManager;
-
-import static org.junit.Assert.*;
-
-public class SystemServiceRegistry_AccessorTest {
- @Test
- public void testRegistry() {
- // Just check a few services to make sure we don't break the accessor
- assertEquals(Context.ACCESSIBILITY_SERVICE,
- SystemServiceRegistry_Accessor.getSystemServiceName(AccessibilityManager.class));
- assertEquals(Context.INPUT_SERVICE,
- SystemServiceRegistry_Accessor.getSystemServiceName(InputManager.class));
- assertEquals(Context.WINDOW_SERVICE,
- SystemServiceRegistry_Accessor.getSystemServiceName(WindowManager.class));
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.graphics;
-
-import junit.framework.TestCase;
-
-/**
- *
- */
-public class Matrix_DelegateTest extends TestCase {
-
- public void testIdentity() {
- Matrix m1 = new Matrix();
-
- assertTrue(m1.isIdentity());
-
- m1.setValues(new float[] { 1,0,0, 0,1,0, 0,0,1 });
- assertTrue(m1.isIdentity());
- }
-
- public void testCopyConstructor() {
- Matrix m1 = new Matrix();
- Matrix m2 = new Matrix(m1);
-
- float[] v1 = new float[9];
- float[] v2 = new float[9];
- m1.getValues(v1);
- m2.getValues(v2);
-
- for (int i = 0 ; i < 9; i++) {
- assertEquals(v1[i], v2[i]);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.util;
-
-import com.android.ide.common.rendering.api.RenderResources;
-import com.android.layoutlib.bridge.BridgeConstants;
-import com.android.layoutlib.bridge.android.BridgeContext;
-
-import org.junit.Test;
-import org.xmlpull.v1.XmlPullParser;
-
-import com.google.common.collect.ImmutableMap;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class BridgeXmlPullAttributesTest {
- @Test
- public void testGetAttributeIntValueForEnums() {
- RenderResources renderResources = new RenderResources();
-
- XmlPullParser parser = mock(XmlPullParser.class);
- when(parser.getAttributeValue(BridgeConstants.NS_RESOURCES, "layout_width"))
- .thenReturn("match_parent");
- when(parser.getAttributeName(0)).thenReturn("layout_width");
- when(parser.getAttributeNamespace(0)).thenReturn(BridgeConstants.NS_RESOURCES);
- // Return every value twice since there is one test using name and other using index
- when(parser.getAttributeValue("http://custom", "my_custom_attr"))
- .thenReturn("a", "a", "b", "b", "invalid", "invalid");
- when(parser.getAttributeName(1)).thenReturn("my_custom_attr");
- when(parser.getAttributeNamespace(1)).thenReturn("http://custom");
-
- BridgeContext context = mock(BridgeContext.class);
- when(context.getRenderResources()).thenReturn(renderResources);
-
- BridgeXmlPullAttributes attributes = new BridgeXmlPullAttributes(
- parser,
- context,
- false,
- attrName -> {
- if ("layout_width".equals(attrName)) {
- return ImmutableMap.of(
- "match_parent", 123);
- }
- return ImmutableMap.of();
- },
- attrName -> {
- if ("my_custom_attr".equals(attrName)) {
- return ImmutableMap.of(
- "a", 1,
- "b", 2
- );
- }
- return ImmutableMap.of();
- });
-
- // Test a framework defined enum attribute
- assertEquals(123, attributes.getAttributeIntValue(BridgeConstants.NS_RESOURCES,
- "layout_width", 500));
- assertEquals(123, attributes.getAttributeIntValue(0, 500));
- // Test non existing attribute (it should return the default value)
- assertEquals(500, attributes.getAttributeIntValue(BridgeConstants.NS_RESOURCES,
- "layout_height", 500));
- assertEquals(500, attributes.getAttributeIntValue(2, 500));
-
- // Test project defined enum attribute
- assertEquals(1, attributes.getAttributeIntValue("http://custom",
- "my_custom_attr", 500));
- assertEquals(1, attributes.getAttributeIntValue(1, 500));
- assertEquals(2, attributes.getAttributeIntValue("http://custom",
- "my_custom_attr", 500));
- assertEquals(2, attributes.getAttributeIntValue(1, 500));
- // Test an invalid enum
- boolean exception = false;
- try {
- attributes.getAttributeIntValue("http://custom", "my_custom_attr", 500);
- } catch(NumberFormatException e) {
- exception = true;
- }
- assertTrue(exception);
- exception = false;
- try {
- attributes.getAttributeIntValue(1, 500);
- } catch(NumberFormatException e) {
- exception = true;
- }
- assertTrue(exception);
-
- // Test non existing project attribute
- assertEquals(500, attributes.getAttributeIntValue("http://custom",
- "my_other_attr", 500));
- }
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge;
-
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.Result.Status;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-public class BridgeRenderSessionTest {
- @Test
- public void testNullSession() {
- BridgeRenderSession renderSession = new BridgeRenderSession(null, Status.ERROR_UNKNOWN
- .createResult("Test result"));
-
- assertNotNull(renderSession.getImage());
- assertNotNull(renderSession.getRootViews());
- assertNotNull(renderSession.getSystemRootViews());
- assertNotNull(renderSession.getDefaultProperties());
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (C) 2010 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;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-import com.android.tools.layoutlib.create.CreateInfo;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.List;
-
-import junit.framework.TestCase;
-
-/**
- * Tests that native delegate classes implement all the required methods.
- *
- * This looks at {@link CreateInfo#DELEGATE_CLASS_NATIVES} to get the list of classes that
- * have their native methods reimplemented through a delegate.
- *
- * Since the reimplemented methods are not native anymore, we look for the annotation
- * {@link LayoutlibDelegate}, and look for a matching method in the delegate (named the same
- * as the modified class with _Delegate added as a suffix).
- * If the original native method is not static, then we make sure the delegate method also
- * include the original class as first parameter (to access "this").
- *
- */
-public class TestDelegates extends TestCase {
-
- private List<String> mErrors = new ArrayList<String>();
-
- public void testNativeDelegates() {
-
- final String[] classes = CreateInfo.DELEGATE_CLASS_NATIVES;
- mErrors.clear();
- for (String clazz : classes) {
- loadAndCompareClasses(clazz, clazz + "_Delegate");
- }
- assertTrue(getErrors(), mErrors.isEmpty());
- }
-
- public void testMethodDelegates() {
- final String[] methods = CreateInfo.DELEGATE_METHODS;
- mErrors.clear();
- for (String methodName : methods) {
- // extract the class name
- String className = methodName.substring(0, methodName.indexOf('#'));
- String targetClassName = className.replace('$', '_') + "_Delegate";
-
- loadAndCompareClasses(className, targetClassName);
- }
- assertTrue(getErrors(), mErrors.isEmpty());
- }
-
- private void loadAndCompareClasses(String originalClassName, String delegateClassName) {
- // load the classes
- try {
- ClassLoader classLoader = TestDelegates.class.getClassLoader();
- Class<?> originalClass = classLoader.loadClass(originalClassName);
- Class<?> delegateClass = classLoader.loadClass(delegateClassName);
-
- compare(originalClass, delegateClass);
- } catch (ClassNotFoundException e) {
- mErrors.add("Failed to load class: " + e.getMessage());
- } catch (SecurityException e) {
- mErrors.add("Failed to load class: " + e.getMessage());
- }
- }
-
- private void compare(Class<?> originalClass, Class<?> delegateClass) throws SecurityException {
- List<Method> checkedDelegateMethods = new ArrayList<Method>();
-
- // loop on the methods of the original class, and for the ones that are annotated
- // with @LayoutlibDelegate, look for a matching method in the delegate class.
- // The annotation is automatically added by layoutlib_create when it replace a method
- // by a call to a delegate
- Method[] originalMethods = originalClass.getDeclaredMethods();
- for (Method originalMethod : originalMethods) {
- // look for methods that are delegated: they have the LayoutlibDelegate annotation
- if (originalMethod.getAnnotation(LayoutlibDelegate.class) == null) {
- continue;
- }
-
- // get the signature.
- Class<?>[] parameters = originalMethod.getParameterTypes();
-
- // if the method is not static, then the class is added as the first parameter
- // (for "this")
- if ((originalMethod.getModifiers() & Modifier.STATIC) == 0) {
-
- Class<?>[] newParameters = new Class<?>[parameters.length + 1];
- newParameters[0] = originalClass;
- System.arraycopy(parameters, 0, newParameters, 1, parameters.length);
- parameters = newParameters;
- }
-
- // if the original class is an inner class that's not static, then
- // we add this on the enclosing class at the beginning
- if (originalClass.getEnclosingClass() != null &&
- (originalClass.getModifiers() & Modifier.STATIC) == 0) {
- Class<?>[] newParameters = new Class<?>[parameters.length + 1];
- newParameters[0] = originalClass.getEnclosingClass();
- System.arraycopy(parameters, 0, newParameters, 1, parameters.length);
- parameters = newParameters;
- }
-
- try {
- // try to load the method with the given parameter types.
- Method delegateMethod = delegateClass.getDeclaredMethod(originalMethod.getName(),
- parameters);
-
- // check the return type of the methods match.
- if (delegateMethod.getReturnType() != originalMethod.getReturnType()) {
- mErrors.add(
- String.format("Delegate method %1$s.%2$s does not match the " +
- "corresponding framework method which returns %3$s",
- delegateClass.getName(),
- getMethodName(delegateMethod),
- originalMethod.getReturnType().getName()));
- }
-
- // check that the method has the annotation
- if (delegateMethod.getAnnotation(LayoutlibDelegate.class) == null) {
- mErrors.add(
- String.format("Delegate method %1$s for class %2$s does not have the " +
- "@LayoutlibDelegate annotation",
- delegateMethod.getName(),
- originalClass.getName()));
- }
-
- // check that the method is static
- if ((delegateMethod.getModifiers() & Modifier.STATIC) != Modifier.STATIC) {
- mErrors.add(
- String.format(
- "Delegate method %1$s for class %2$s is not static",
- delegateMethod.getName(),
- originalClass.getName())
- );
- }
-
- // add the method as checked.
- checkedDelegateMethods.add(delegateMethod);
- } catch (NoSuchMethodException e) {
- String name = getMethodName(originalMethod, parameters);
- mErrors.add(String.format("Missing %1$s.%2$s", delegateClass.getName(), name));
- }
- }
-
- // look for dead (delegate) code.
- // This looks for all methods in the delegate class, and if they have the
- // @LayoutlibDelegate annotation, make sure they have been previously found as a
- // match for a method in the original class.
- // If not, this means the method is a delegate for a method that either doesn't exist
- // anymore or is not delegated anymore.
- Method[] delegateMethods = delegateClass.getDeclaredMethods();
- for (Method delegateMethod : delegateMethods) {
- // look for methods that are delegates: they have the LayoutlibDelegate annotation
- if (delegateMethod.getAnnotation(LayoutlibDelegate.class) == null) {
- continue;
- }
-
- if (!checkedDelegateMethods.contains(delegateMethod)) {
- mErrors.add(String.format(
- "Delegate method %1$s.%2$s is not used anymore and must be removed",
- delegateClass.getName(),
- getMethodName(delegateMethod)));
- }
- }
-
- }
-
- private String getMethodName(Method method) {
- return getMethodName(method, method.getParameterTypes());
- }
-
- private String getMethodName(Method method, Class<?>[] parameters) {
- // compute a full class name that's long but not too long.
- StringBuilder sb = new StringBuilder(method.getName() + "(");
- for (int j = 0; j < parameters.length; j++) {
- Class<?> theClass = parameters[j];
- int dimensions = 0;
- while (theClass.isArray()) {
- dimensions++;
- theClass = theClass.getComponentType();
- }
- sb.append(theClass.getName());
- for (int i = 0; i < dimensions; i++) {
- sb.append("[]");
- }
- if (j < (parameters.length - 1)) {
- sb.append(",");
- }
- }
- sb.append(")");
-
- return sb.toString();
- }
-
- private String getErrors() {
- StringBuilder s = new StringBuilder();
- for (String error : mErrors) {
- s.append(error).append('\n');
- }
- return s.toString();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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 com.android.layoutlib.bridge.impl.ParserFactory;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.kxml2.io.KXmlParser;
-import org.w3c.dom.Node;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.NonNull;
-
-import static org.junit.Assert.assertEquals;
-
-public class BridgeXmlBlockParserTest {
-
- @BeforeClass
- public static void setUp() {
- ParserFactory.setParserFactory(new ParserFactoryImpl());
- }
-
- @Test
- public void testXmlBlockParser() throws Exception {
-
- XmlPullParser parser = ParserFactory.create(
- getClass().getResourceAsStream("/com/android/layoutlib/testdata/layout1.xml"),
- "layout1.xml");
-
- parser = new BridgeXmlBlockParser(parser, null, false /* platformResourceFlag */);
-
- assertEquals(XmlPullParser.START_DOCUMENT, parser.next());
-
- assertEquals(XmlPullParser.START_TAG, parser.next());
- assertEquals("LinearLayout", parser.getName());
-
- assertEquals(XmlPullParser.TEXT, parser.next());
-
- assertEquals(XmlPullParser.START_TAG, parser.next());
- assertEquals("Button", parser.getName());
- assertEquals(XmlPullParser.TEXT, parser.next());
- assertEquals(XmlPullParser.END_TAG, parser.next());
-
- assertEquals(XmlPullParser.TEXT, parser.next());
-
- assertEquals(XmlPullParser.START_TAG, parser.next());
- assertEquals("View", parser.getName());
- assertEquals(XmlPullParser.END_TAG, parser.next());
-
- assertEquals(XmlPullParser.TEXT, parser.next());
-
- assertEquals(XmlPullParser.START_TAG, parser.next());
- assertEquals("TextView", parser.getName());
- assertEquals(XmlPullParser.END_TAG, parser.next());
-
- assertEquals(XmlPullParser.TEXT, parser.next());
-
- assertEquals(XmlPullParser.END_TAG, parser.next());
- assertEquals(XmlPullParser.END_DOCUMENT, parser.next());
- }
-
- //------------
-
- /**
- * Quick 'n' dirty debug helper that dumps an XML structure to stdout.
- */
- @SuppressWarnings("unused")
- private void dump(Node node, String prefix) {
- Node n;
-
- String[] types = {
- "unknown",
- "ELEMENT_NODE",
- "ATTRIBUTE_NODE",
- "TEXT_NODE",
- "CDATA_SECTION_NODE",
- "ENTITY_REFERENCE_NODE",
- "ENTITY_NODE",
- "PROCESSING_INSTRUCTION_NODE",
- "COMMENT_NODE",
- "DOCUMENT_NODE",
- "DOCUMENT_TYPE_NODE",
- "DOCUMENT_FRAGMENT_NODE",
- "NOTATION_NODE"
- };
-
- String s = String.format("%s<%s> %s %s",
- prefix,
- types[node.getNodeType()],
- node.getNodeName(),
- node.getNodeValue() == null ? "" : node.getNodeValue().trim());
-
- System.out.println(s);
-
- n = node.getFirstChild();
- if (n != null) {
- dump(n, prefix + "- ");
- }
-
- n = node.getNextSibling();
- if (n != null) {
- dump(n, prefix);
- }
- }
-
- @AfterClass
- public static void tearDown() {
- ParserFactory.setParserFactory(null);
- }
-
- private static class ParserFactoryImpl
- extends com.android.ide.common.rendering.api.ParserFactory {
-
- @NonNull
- @Override
- public XmlPullParser createParser(String displayName) throws XmlPullParserException {
- return new KXmlParser();
- }
- }
-}
+++ /dev/null
-/*
- * 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.impl;
-
-import org.junit.Test;
-import org.kxml2.io.KXmlParser;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.StringReader;
-
-import static com.android.SdkConstants.NS_RESOURCES;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotSame;
-import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
-import static org.xmlpull.v1.XmlPullParser.END_TAG;
-import static org.xmlpull.v1.XmlPullParser.START_TAG;
-
-
-public class LayoutParserWrapperTest {
- @Test
- @SuppressWarnings("StatementWithEmptyBody") // some for loops need to be empty statements.
- public void testDataBindingLayout() throws Exception {
- LayoutParserWrapper parser = getParserFromString(sDataBindingLayout);
- parser.peekTillLayoutStart();
- assertEquals("Expected START_TAG", START_TAG, parser.next());
- assertEquals("RelativeLayout", parser.getName());
- for (int next = parser.next(); next != START_TAG && next != END_DOCUMENT;
- next = parser.next());
- assertEquals("Expected START_TAG", START_TAG, parser.getEventType());
- assertEquals("TextView", parser.getName());
- assertEquals("layout_width incorrect for first text view.", "wrap_content",
- parser.getAttributeValue(NS_RESOURCES, "layout_width"));
- // Ensure that data-binding part is stripped.
- assertEquals("Bound attribute android:text incorrect", "World",
- parser.getAttributeValue(NS_RESOURCES, "text"));
- assertEquals("resource attribute 'id' for first text view incorrect.", "@+id/first",
- parser.getAttributeValue(NS_RESOURCES, "id"));
- for (int next = parser.next();
- (next != END_TAG || !"RelativeLayout".equals(parser.getName())) && next != END_DOCUMENT;
- next = parser.next());
- assertNotSame("Unexpected end of document", END_DOCUMENT, parser.getEventType());
- assertEquals("Document didn't end when expected.", END_DOCUMENT, parser.next());
- }
-
- @Test
- @SuppressWarnings("StatementWithEmptyBody")
- public void testNonDataBindingLayout() throws Exception {
- LayoutParserWrapper parser = getParserFromString(sNonDataBindingLayout);
- parser.peekTillLayoutStart();
- assertEquals("Expected START_TAG", START_TAG, parser.next());
- assertEquals("RelativeLayout", parser.getName());
- for (int next = parser.next(); next != START_TAG && next != END_DOCUMENT;
- next = parser.next());
- assertEquals("Expected START_TAG", START_TAG, parser.getEventType());
- assertEquals("TextView", parser.getName());
- assertEquals("layout_width incorrect for first text view.", "wrap_content",
- parser.getAttributeValue(NS_RESOURCES, "layout_width"));
- // Ensure that value isn't modified.
- assertEquals("Bound attribute android:text incorrect", "@{user.firstName,default=World}",
- parser.getAttributeValue(NS_RESOURCES, "text"));
- assertEquals("resource attribute 'id' for first text view incorrect.", "@+id/first",
- parser.getAttributeValue(NS_RESOURCES, "id"));
- for (int next = parser.next();
- (next != END_TAG || !"RelativeLayout".equals(parser.getName())) && next != END_DOCUMENT;
- next = parser.next());
- assertNotSame("Unexpected end of document", END_DOCUMENT, parser.getEventType());
- assertEquals("Document didn't end when expected.", END_DOCUMENT, parser.next());
- }
-
- private static LayoutParserWrapper getParserFromString(String layoutContent) throws
- XmlPullParserException {
- XmlPullParser parser = new KXmlParser();
- parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
- parser.setInput(new StringReader(layoutContent));
- return new LayoutParserWrapper(parser);
- }
-
- private static final String sDataBindingLayout =
- //language=XML
- "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
- "<layout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
- " xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n" +
- " xmlns:tools=\"http://schemas.android.com/tools\"\n" +
- " tools:context=\".MainActivity\"\n" +
- " tools:showIn=\"@layout/activity_main\">\n" +
- "\n" +
- " <data>\n" +
- "\n" +
- " <variable\n" +
- " name=\"user\"\n" +
- " type=\"com.example.User\" />\n" +
- " <variable\n" +
- " name=\"activity\"\n" +
- " type=\"com.example.MainActivity\" />\n" +
- " </data>\n" +
- "\n" +
- " <RelativeLayout\n" +
- " android:layout_width=\"match_parent\"\n" +
- " android:layout_height=\"match_parent\"\n" +
- " android:paddingBottom=\"@dimen/activity_vertical_margin\"\n" +
- " android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n" +
- " android:paddingRight=\"@dimen/activity_horizontal_margin\"\n" +
- " android:paddingTop=\"@dimen/activity_vertical_margin\"\n" +
- " app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"\n" +
- " >\n" +
- "\n" +
- " <TextView\n" +
- " android:id=\"@+id/first\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:layout_alignParentStart=\"true\"\n" +
- " android:layout_alignParentLeft=\"true\"\n" +
- " android:layout_height=\"wrap_content\"\n" +
- " android:text=\"@{user.firstName,default=World}\" />\n" +
- "\n" +
- " <TextView\n" +
- " android:id=\"@+id/last\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:layout_height=\"wrap_content\"\n" +
- " android:layout_toEndOf=\"@id/first\"\n" +
- " android:layout_toRightOf=\"@id/first\"\n" +
- " android:text=\"@{user.lastName,default=Hello}\" />\n" +
- "\n" +
- " <Button\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:layout_height=\"wrap_content\"\n" +
- " android:layout_below=\"@id/last\"\n" +
- " android:text=\"Submit\"\n" +
- " android:onClick=\"@{activity.onClick}\"/>\n" +
- " </RelativeLayout>\n" +
- "</layout>";
-
- private static final String sNonDataBindingLayout =
- //language=XML
- "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
- " xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n" +
- " android:layout_width=\"match_parent\"\n" +
- " android:layout_height=\"match_parent\"\n" +
- " android:paddingBottom=\"@dimen/activity_vertical_margin\"\n" +
- " android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n" +
- " android:paddingRight=\"@dimen/activity_horizontal_margin\"\n" +
- " android:paddingTop=\"@dimen/activity_vertical_margin\"\n" +
- " app:layout_behavior=\"@string/appbar_scrolling_view_behavior\"\n" +
- ">\n" +
- "\n" +
- " <TextView\n" +
- " android:id=\"@+id/first\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:layout_alignParentStart=\"true\"\n" +
- " android:layout_alignParentLeft=\"true\"\n" +
- " android:layout_height=\"wrap_content\"\n" +
- " android:text=\"@{user.firstName,default=World}\" />\n" +
- "\n" +
- " <TextView\n" +
- " android:id=\"@+id/last\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:layout_height=\"wrap_content\"\n" +
- " android:layout_toEndOf=\"@id/first\"\n" +
- " android:layout_toRightOf=\"@id/first\"\n" +
- " android:text=\"@{user.lastName,default=Hello}\" />\n" +
- "\n" +
- " <Button\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:layout_height=\"wrap_content\"\n" +
- " android:layout_below=\"@id/last\"\n" +
- " android:text=\"Submit\"\n" +
- " android:onClick=\"@{activity.onClick}\"/>\n" +
- "</RelativeLayout>";
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive;
-
-import com.android.layoutlib.bridge.BridgeRenderSessionTest;
-import com.android.layoutlib.bridge.TestDelegates;
-import com.android.layoutlib.bridge.android.BridgeXmlBlockParserTest;
-import com.android.layoutlib.bridge.impl.LayoutParserWrapperTest;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-import org.junit.runners.Suite.SuiteClasses;
-
-import android.graphics.Matrix_DelegateTest;
-import android.util.BridgeXmlPullAttributesTest;
-
-/**
- * Suite used by the layoutlib build system
- */
-@RunWith(Suite.class)
-@SuiteClasses({
- RenderTests.class, LayoutParserWrapperTest.class,
- BridgeXmlBlockParserTest.class, BridgeXmlPullAttributesTest.class,
- Matrix_DelegateTest.class, TestDelegates.class, PerformanceTests.class,
- BridgeRenderSessionTest.class
-})
-public class Main {
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive;
-
-import com.android.ide.common.rendering.api.SessionParams;
-import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
-import com.android.layoutlib.bridge.intensive.util.perf.PerformanceRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import android.annotation.NonNull;
-
-import java.io.FileNotFoundException;
-
-/**
- * Set of render tests
- */
-@RunWith(PerformanceRunner.class)
-public class PerformanceTests extends RenderTestBase {
-
- @Before
- public void setUp() {
- ignoreAllLogging();
- }
-
-
- private void render(@NonNull String layoutFileName)
- throws ClassNotFoundException, FileNotFoundException {
- SessionParams params = createSessionParams(layoutFileName, ConfigGenerator.NEXUS_5);
- render(params, 250);
- }
-
- @Test
- public void testActivity() throws ClassNotFoundException, FileNotFoundException {
- render("activity.xml");
- }
-
- @Test
- public void testAllWidgets() throws ClassNotFoundException, FileNotFoundException {
- render("allwidgets.xml");
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive;
-
-import com.android.ide.common.rendering.api.RenderSession;
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.ViewInfo;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.awt.image.BufferedImage;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-class RenderResult {
- private final List<ViewInfo> mRootViews;
- private final List<ViewInfo> mSystemViews;
- private final Result mRenderResult;
- private BufferedImage mImage;
-
- private RenderResult(@Nullable Result result, @Nullable List<ViewInfo> systemViewInfoList,
- @Nullable List<ViewInfo> rootViewInfoList, @Nullable BufferedImage image) {
- mSystemViews = systemViewInfoList == null ? Collections.emptyList() : systemViewInfoList;
- mRootViews = rootViewInfoList == null ? Collections.emptyList() : rootViewInfoList;
- mRenderResult = result;
- mImage = image;
- }
-
- @NonNull
- static RenderResult getFromSession(@NonNull RenderSession session) {
- return new RenderResult(session.getResult(),
- new ArrayList<>(session.getSystemRootViews()),
- new ArrayList<>(session.getRootViews()),
- session.getImage());
- }
-
- @Nullable
- Result getResult() {
- return mRenderResult;
- }
-
- @NonNull
- public List<ViewInfo> getRootViews() {
- return mRootViews;
- }
-
- @NonNull
- public List<ViewInfo> getSystemViews() {
- return mSystemViews;
- }
-
- @Nullable
- public BufferedImage getImage() {
- return mImage;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.ide.common.rendering.api.RenderSession;
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.SessionParams;
-import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
-import com.android.ide.common.resources.FrameworkResources;
-import com.android.ide.common.resources.ResourceItem;
-import com.android.ide.common.resources.ResourceRepository;
-import com.android.ide.common.resources.ResourceResolver;
-import com.android.ide.common.resources.configuration.FolderConfiguration;
-import com.android.io.FolderWrapper;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.RenderParamsFlags;
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
-import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback;
-import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser;
-import com.android.layoutlib.bridge.intensive.util.ImageUtils;
-import com.android.layoutlib.bridge.intensive.util.ModuleClassLoader;
-import com.android.layoutlib.bridge.intensive.util.TestAssetRepository;
-import com.android.layoutlib.bridge.intensive.util.TestUtils;
-import com.android.tools.layoutlib.java.System_Delegate;
-import com.android.utils.ILogger;
-
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.rules.TestWatcher;
-import org.junit.runner.Description;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
-
-import com.google.android.collect.Lists;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-
-/**
- * Base class for render tests. The render tests load all the framework resources and a project
- * checked in this test's resources. The main dependencies
- * are:
- * 1. Fonts directory.
- * 2. Framework Resources.
- * 3. App resources.
- * 4. build.prop file
- * <p>
- * These are configured by two variables set in the system properties.
- * <p>
- * 1. platform.dir: This is the directory for the current platform in the built SDK
- * (.../sdk/platforms/android-<version>).
- * <p>
- * The fonts are platform.dir/data/fonts.
- * The Framework resources are platform.dir/data/res.
- * build.prop is at platform.dir/build.prop.
- * <p>
- * 2. test_res.dir: This is the directory for the resources of the test. If not specified, this
- * falls back to getClass().getProtectionDomain().getCodeSource().getLocation()
- * <p>
- * The app resources are at: test_res.dir/testApp/MyApplication/app/src/main/res
- */
-public class RenderTestBase {
-
- private static final String PLATFORM_DIR_PROPERTY = "platform.dir";
- private static final String RESOURCE_DIR_PROPERTY = "test_res.dir";
-
- private static final String PLATFORM_DIR;
- private static final String TEST_RES_DIR;
- /** Location of the app to test inside {@link #TEST_RES_DIR} */
- private static final String APP_TEST_DIR = "testApp/MyApplication";
- /** Location of the app's res dir inside {@link #TEST_RES_DIR} */
- private static final String APP_TEST_RES = APP_TEST_DIR + "/src/main/res";
- private static final String APP_CLASSES_LOCATION =
- APP_TEST_DIR + "/build/intermediates/classes/debug/";
- protected static Bridge sBridge;
- /** List of log messages generated by a render call. It can be used to find specific errors */
- protected static ArrayList<String> sRenderMessages = Lists.newArrayList();
- private static LayoutLog sLayoutLibLog;
- private static FrameworkResources sFrameworkRepo;
- private static ResourceRepository sProjectResources;
- private static ILogger sLogger;
-
- static {
- // Test that System Properties are properly set.
- PLATFORM_DIR = getPlatformDir();
- if (PLATFORM_DIR == null) {
- fail(String.format("System Property %1$s not properly set. The value is %2$s",
- PLATFORM_DIR_PROPERTY, System.getProperty(PLATFORM_DIR_PROPERTY)));
- }
-
- TEST_RES_DIR = getTestResDir();
- if (TEST_RES_DIR == null) {
- fail(String.format("System property %1$s.dir not properly set. The value is %2$s",
- RESOURCE_DIR_PROPERTY, System.getProperty(RESOURCE_DIR_PROPERTY)));
- }
- }
-
- @Rule
- public TestWatcher sRenderMessageWatcher = new TestWatcher() {
- @Override
- protected void succeeded(Description description) {
- // We only check error messages if the rest of the test case was successful.
- if (!sRenderMessages.isEmpty()) {
- fail(description.getMethodName() + " render error message: " +
- sRenderMessages.get(0));
- }
- }
- };
- // Default class loader with access to the app classes
- protected ClassLoader mDefaultClassLoader =
- new ModuleClassLoader(APP_CLASSES_LOCATION, getClass().getClassLoader());
-
- private static String getPlatformDir() {
- String platformDir = System.getProperty(PLATFORM_DIR_PROPERTY);
- if (platformDir != null && !platformDir.isEmpty() && new File(platformDir).isDirectory()) {
- return platformDir;
- }
- // System Property not set. Try to find the directory in the build directory.
- String androidHostOut = System.getenv("ANDROID_HOST_OUT");
- if (androidHostOut != null) {
- platformDir = getPlatformDirFromHostOut(new File(androidHostOut));
- if (platformDir != null) {
- return platformDir;
- }
- }
- String workingDirString = System.getProperty("user.dir");
- File workingDir = new File(workingDirString);
- // Test if workingDir is android checkout root.
- platformDir = getPlatformDirFromRoot(workingDir);
- if (platformDir != null) {
- return platformDir;
- }
-
- // Test if workingDir is platform/frameworks/base/tools/layoutlib/bridge.
- File currentDir = workingDir;
- if (currentDir.getName().equalsIgnoreCase("bridge")) {
- currentDir = currentDir.getParentFile();
- }
- // Test if currentDir is platform/frameworks/base/tools/layoutlib. That is, root should be
- // workingDir/../../../../ (4 levels up)
- for (int i = 0; i < 4; i++) {
- if (currentDir != null) {
- currentDir = currentDir.getParentFile();
- }
- }
- return currentDir == null ? null : getPlatformDirFromRoot(currentDir);
- }
-
- private static String getPlatformDirFromRoot(File root) {
- if (!root.isDirectory()) {
- return null;
- }
- File out = new File(root, "out");
- if (!out.isDirectory()) {
- return null;
- }
- File host = new File(out, "host");
- if (!host.isDirectory()) {
- return null;
- }
- File[] hosts = host.listFiles(path -> path.isDirectory() &&
- (path.getName().startsWith("linux-") || path.getName().startsWith("darwin-")));
- assert hosts != null;
- for (File hostOut : hosts) {
- String platformDir = getPlatformDirFromHostOut(hostOut);
- if (platformDir != null) {
- return platformDir;
- }
- }
- return null;
- }
-
- private static String getPlatformDirFromHostOut(File out) {
- if (!out.isDirectory()) {
- return null;
- }
- File sdkDir = new File(out, "sdk");
- if (!sdkDir.isDirectory()) {
- return null;
- }
- File[] sdkDirs = sdkDir.listFiles(path -> {
- // We need to search for $TARGET_PRODUCT (usually, sdk_phone_armv7)
- return path.isDirectory() && path.getName().startsWith("sdk");
- });
- assert sdkDirs != null;
- for (File dir : sdkDirs) {
- String platformDir = getPlatformDirFromHostOutSdkSdk(dir);
- if (platformDir != null) {
- return platformDir;
- }
- }
- return null;
- }
-
- private static String getPlatformDirFromHostOutSdkSdk(File sdkDir) {
- File[] possibleSdks = sdkDir.listFiles(
- path -> path.isDirectory() && path.getName().contains("android-sdk"));
- assert possibleSdks != null;
- for (File possibleSdk : possibleSdks) {
- File platformsDir = new File(possibleSdk, "platforms");
- File[] platforms = platformsDir.listFiles(
- path -> path.isDirectory() && path.getName().startsWith("android-"));
- if (platforms == null || platforms.length == 0) {
- continue;
- }
- Arrays.sort(platforms, (o1, o2) -> {
- final int MAX_VALUE = 1000;
- String suffix1 = o1.getName().substring("android-".length());
- String suffix2 = o2.getName().substring("android-".length());
- int suff1, suff2;
- try {
- suff1 = Integer.parseInt(suffix1);
- } catch (NumberFormatException e) {
- suff1 = MAX_VALUE;
- }
- try {
- suff2 = Integer.parseInt(suffix2);
- } catch (NumberFormatException e) {
- suff2 = MAX_VALUE;
- }
- if (suff1 != MAX_VALUE || suff2 != MAX_VALUE) {
- return suff2 - suff1;
- }
- return suffix2.compareTo(suffix1);
- });
- return platforms[0].getAbsolutePath();
- }
- return null;
- }
-
- private static String getTestResDir() {
- String resourceDir = System.getProperty(RESOURCE_DIR_PROPERTY);
- if (resourceDir != null && !resourceDir.isEmpty() && new File(resourceDir).isDirectory()) {
- return resourceDir;
- }
- // TEST_RES_DIR not explicitly set. Fallback to the class's source location.
- try {
- URL location = RenderTestBase.class.getProtectionDomain().getCodeSource().getLocation();
- return new File(location.getPath()).exists() ? location.getPath() : null;
- } catch (NullPointerException e) {
- // Prevent a lot of null checks by just catching the exception.
- return null;
- }
- }
-
- /**
- * Initialize the bridge and the resource maps.
- */
- @BeforeClass
- public static void beforeClass() {
- File data_dir = new File(PLATFORM_DIR, "data");
- File res = new File(data_dir, "res");
- sFrameworkRepo = new FrameworkResources(new FolderWrapper(res));
- sFrameworkRepo.loadResources();
- sFrameworkRepo.loadPublicResources(getLogger());
-
- sProjectResources =
- new ResourceRepository(new FolderWrapper(TEST_RES_DIR + "/" + APP_TEST_RES),
- false) {
- @NonNull
- @Override
- protected ResourceItem createResourceItem(@NonNull String name) {
- return new ResourceItem(name);
- }
- };
- sProjectResources.loadResources();
-
- File fontLocation = new File(data_dir, "fonts");
- File buildProp = new File(PLATFORM_DIR, "build.prop");
- File attrs = new File(res, "values" + File.separator + "attrs.xml");
- sBridge = new Bridge();
- sBridge.init(ConfigGenerator.loadProperties(buildProp), fontLocation,
- ConfigGenerator.getEnumMap(attrs), getLayoutLog());
- Bridge.getLock().lock();
- try {
- Bridge.setLog(getLayoutLog());
- } finally {
- Bridge.getLock().unlock();
- }
- }
-
- @AfterClass
- public static void tearDown() {
- sLayoutLibLog = null;
- sFrameworkRepo = null;
- sProjectResources = null;
- sLogger = null;
- sBridge = null;
-
- TestUtils.gc();
-
- System.out.println("Objects still linked from the DelegateManager:");
- DelegateManager.dump(System.out);
- }
-
- @NonNull
- protected static RenderResult render(SessionParams params, long frameTimeNanos) {
- // TODO: Set up action bar handler properly to test menu rendering.
- // Create session params.
- System_Delegate.setBootTimeNanos(TimeUnit.MILLISECONDS.toNanos(871732800000L));
- System_Delegate.setNanosTime(TimeUnit.MILLISECONDS.toNanos(871732800000L));
- RenderSession session = sBridge.createSession(params);
-
- try {
- if (frameTimeNanos != -1) {
- session.setElapsedFrameTimeNanos(frameTimeNanos);
- }
-
- if (!session.getResult().isSuccess()) {
- getLogger().error(session.getResult().getException(),
- session.getResult().getErrorMessage());
- }
- else {
- // Render the session with a timeout of 50s.
- Result renderResult = session.render(50000);
- if (!renderResult.isSuccess()) {
- getLogger().error(session.getResult().getException(),
- session.getResult().getErrorMessage());
- }
- }
-
- return RenderResult.getFromSession(session);
- } finally {
- session.dispose();
- }
- }
-
- /**
- * Create a new rendering session and test that rendering the given layout doesn't throw any
- * exceptions and matches the provided image.
- * <p>
- * If frameTimeNanos is >= 0 a frame will be executed during the rendering. The time indicates
- * how far in the future is.
- */
- @Nullable
- protected static RenderResult renderAndVerify(SessionParams params, String goldenFileName,
- long frameTimeNanos) throws ClassNotFoundException {
- RenderResult result = RenderTestBase.render(params, frameTimeNanos);
- try {
- String goldenImagePath = APP_TEST_DIR + "/golden/" + goldenFileName;
- assertNotNull(result.getImage());
- ImageUtils.requireSimilar(goldenImagePath, result.getImage());
- } catch (IOException e) {
- getLogger().error(e, e.getMessage());
- }
-
- return result;
- }
-
- /**
- * Create a new rendering session and test that rendering the given layout doesn't throw any
- * exceptions and matches the provided image.
- */
- @Nullable
- protected static RenderResult renderAndVerify(SessionParams params, String goldenFileName)
- throws ClassNotFoundException {
- return RenderTestBase.renderAndVerify(params, goldenFileName, -1);
- }
-
- private static LayoutLog getLayoutLog() {
- if (sLayoutLibLog == null) {
- sLayoutLibLog = new LayoutLog() {
- @Override
- public void warning(String tag, String message, Object data) {
- System.out.println("Warning " + tag + ": " + message);
- failWithMsg(message);
- }
-
- @Override
- 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 == null ? "" : message);
- }
-
- @Override
- public void error(String tag, String message, Object data) {
- System.out.println("Error " + tag + ": " + message);
- failWithMsg(message);
- }
-
- @Override
- public void error(String tag, String message, Throwable throwable, Object data) {
- System.out.println("Error " + tag + ": " + message);
- if (throwable != null) {
- throwable.printStackTrace();
- }
- failWithMsg(message);
- }
- };
- }
- return sLayoutLibLog;
- }
-
- protected static void ignoreAllLogging() {
- sLayoutLibLog = new LayoutLog();
- sLogger = new ILogger() {
- @Override
- public void error(Throwable t, String msgFormat, Object... args) {
- }
-
- @Override
- public void warning(String msgFormat, Object... args) {
- }
-
- @Override
- public void info(String msgFormat, Object... args) {
- }
-
- @Override
- public void verbose(String msgFormat, Object... args) {
- }
- };
- }
-
- protected static ILogger getLogger() {
- if (sLogger == null) {
- sLogger = new ILogger() {
- @Override
- public void error(Throwable t, @Nullable String msgFormat, Object... args) {
- if (t != null) {
- t.printStackTrace();
- }
- failWithMsg(msgFormat == null ? "" : msgFormat, args);
- }
-
- @Override
- public void warning(@NonNull String msgFormat, Object... args) {
- failWithMsg(msgFormat, args);
- }
-
- @Override
- public void info(@NonNull String msgFormat, Object... args) {
- // pass.
- }
-
- @Override
- public void verbose(@NonNull String msgFormat, Object... args) {
- // pass.
- }
- };
- }
- return sLogger;
- }
-
- private static void failWithMsg(@NonNull String msgFormat, Object... args) {
- sRenderMessages.add(args == null ? msgFormat : String.format(msgFormat, args));
- }
-
- @Before
- public void beforeTestCase() {
- sRenderMessages.clear();
- }
-
- @NonNull
- protected LayoutPullParser createParserFromPath(String layoutPath)
- throws FileNotFoundException {
- return LayoutPullParser.createFromPath(APP_TEST_RES + "/layout/" + layoutPath);
- }
-
- /**
- * Create a new rendering session and test that rendering the given layout on nexus 5
- * doesn't throw any exceptions and matches the provided image.
- */
- @Nullable
- protected RenderResult renderAndVerify(String layoutFileName, String goldenFileName)
- throws ClassNotFoundException, FileNotFoundException {
- return renderAndVerify(layoutFileName, goldenFileName, ConfigGenerator.NEXUS_5);
- }
-
- /**
- * Create a new rendering session and test that rendering the given layout on given device
- * doesn't throw any exceptions and matches the provided image.
- */
- @Nullable
- protected RenderResult renderAndVerify(String layoutFileName, String goldenFileName,
- ConfigGenerator deviceConfig) throws ClassNotFoundException, FileNotFoundException {
- SessionParams params = createSessionParams(layoutFileName, deviceConfig);
- return renderAndVerify(params, goldenFileName);
- }
-
- protected SessionParams createSessionParams(String layoutFileName, ConfigGenerator deviceConfig)
- throws ClassNotFoundException, FileNotFoundException {
- // Create the layout pull parser.
- LayoutPullParser parser = createParserFromPath(layoutFileName);
- // Create LayoutLibCallback.
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
- // TODO: Set up action bar handler properly to test menu rendering.
- // Create session params.
- return getSessionParams(parser, deviceConfig, layoutLibCallback, "AppTheme", true,
- RenderingMode.NORMAL, 22);
- }
-
- /**
- * Uses Theme.Material and Target sdk version as 22.
- */
- protected SessionParams getSessionParams(LayoutPullParser layoutParser,
- ConfigGenerator configGenerator, LayoutLibTestCallback layoutLibCallback,
- String themeName, boolean isProjectTheme, RenderingMode renderingMode,
- @SuppressWarnings("SameParameterValue") int targetSdk) {
- FolderConfiguration config = configGenerator.getFolderConfig();
- ResourceResolver resourceResolver =
- ResourceResolver.create(sProjectResources.getConfiguredResources(config),
- sFrameworkRepo.getConfiguredResources(config), themeName, isProjectTheme);
-
- SessionParams sessionParams =
- new SessionParams(layoutParser, renderingMode, null /*used for caching*/,
- configGenerator.getHardwareConfig(), resourceResolver, layoutLibCallback, 0,
- targetSdk, getLayoutLog());
- sessionParams.setFlag(RenderParamsFlags.FLAG_DO_NOT_RENDER_ON_CREATE, true);
- sessionParams.setAssetRepository(new TestAssetRepository());
- return sessionParams;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.intensive;
-
-import com.android.ide.common.rendering.api.RenderSession;
-import com.android.ide.common.rendering.api.SessionParams;
-import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
-import com.android.ide.common.rendering.api.ViewInfo;
-import com.android.layoutlib.bridge.android.BridgeContext;
-import com.android.layoutlib.bridge.android.RenderParamsFlags;
-import com.android.layoutlib.bridge.impl.RenderAction;
-import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
-import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback;
-import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser;
-import com.android.resources.Density;
-import com.android.resources.Navigation;
-import com.android.resources.ResourceType;
-
-import org.junit.Test;
-
-import android.content.res.AssetManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-
-import java.io.FileNotFoundException;
-import java.lang.reflect.Field;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Set of render tests
- */
-public class RenderTests extends RenderTestBase {
-
- @Test
- public void testActivity() throws ClassNotFoundException, FileNotFoundException {
- renderAndVerify("activity.xml", "activity.png");
- }
-
- @Test
- public void testActivityOnOldTheme() throws ClassNotFoundException, FileNotFoundException {
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
-
- LayoutPullParser parser = LayoutPullParser.createFromString(
- "<RelativeLayout xmlns:android=\"http://schemas" +
- ".android.com/apk/res/android\"\n" +
- " android:layout_width=\"match_parent\"\n" +
- " android:layout_height=\"match_parent\"\n" +
- " android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n" +
- " android:paddingRight=\"@dimen/activity_horizontal_margin\"\n" +
- " android:paddingTop=\"@dimen/activity_vertical_margin\"\n" +
- " android:paddingBottom=\"@dimen/activity_vertical_margin\">\n" +
- " <TextView\n" +
- " android:text=\"@string/hello_world\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:layout_height=\"200dp\"\n" +
- " android:background=\"#FF0000\"\n" +
- " android:id=\"@+id/text1\"/>\n" +
- "</RelativeLayout>");
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.NoTitleBar", false,
- RenderingMode.NORMAL, 22);
-
- renderAndVerify(params, "simple_activity-old-theme.png");
- }
-
- @Test
- public void testTranslucentBars() throws ClassNotFoundException, FileNotFoundException {
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
-
- LayoutPullParser parser = createParserFromPath("four_corners.xml");
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.Light.NoActionBar.TranslucentDecor", false,
- RenderingMode.NORMAL, 22);
- renderAndVerify(params, "four_corners_translucent.png");
-
- parser = createParserFromPath("four_corners.xml");
- params = getSessionParams(parser, ConfigGenerator.NEXUS_5_LAND,
- layoutLibCallback, "Theme.Material.Light.NoActionBar.TranslucentDecor", false,
- RenderingMode.NORMAL, 22);
- renderAndVerify(params, "four_corners_translucent_land.png");
-
- parser = createParserFromPath("four_corners.xml");
- params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.Light.NoActionBar", false,
- RenderingMode.NORMAL, 22);
- renderAndVerify(params, "four_corners.png");
- }
-
- @Test
- public void testAllWidgets() throws ClassNotFoundException, FileNotFoundException {
- renderAndVerify("allwidgets.xml", "allwidgets.png");
-
- // We expect fidelity warnings for Path.isConvex. Fail for anything else.
- sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported."));
- }
-
- @Test
- public void testArrayCheck() throws ClassNotFoundException, FileNotFoundException {
- renderAndVerify("array_check.xml", "array_check.png");
- }
-
- @Test
- public void testAllWidgetsTablet() throws ClassNotFoundException, FileNotFoundException {
- renderAndVerify("allwidgets.xml", "allwidgets_tab.png", ConfigGenerator.NEXUS_7_2012);
-
- // We expect fidelity warnings for Path.isConvex. Fail for anything else.
- sRenderMessages.removeIf(message -> message.equals("Path.isConvex is not supported."));
- }
-
- @Test
- public void testActivityActionBar() throws ClassNotFoundException {
- String simpleActivity =
- "<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
- " android:layout_width=\"match_parent\"\n" +
- " android:layout_height=\"match_parent\"\n" +
- " android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n" +
- " android:paddingRight=\"@dimen/activity_horizontal_margin\"\n" +
- " android:paddingTop=\"@dimen/activity_vertical_margin\"\n" +
- " android:paddingBottom=\"@dimen/activity_vertical_margin\">\n" +
- " <TextView\n" +
- " android:text=\"@string/hello_world\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:layout_height=\"200dp\"\n" +
- " android:background=\"#FF0000\"\n" +
- " android:id=\"@+id/text1\"/>\n" +
- "</RelativeLayout>";
-
- LayoutPullParser parser = LayoutPullParser.createFromString(simpleActivity);
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
-
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.Light.NoActionBar", false,
- RenderingMode.V_SCROLL, 22);
-
- renderAndVerify(params, "simple_activity_noactionbar.png");
-
- parser = LayoutPullParser.createFromString(simpleActivity);
- params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.Light", false,
- RenderingMode.V_SCROLL, 22);
-
- renderAndVerify(params, "simple_activity.png");
-
- // This also tests that a theme with "NoActionBar" DOES HAVE an action bar when we are
- // displaying menus.
- parser = LayoutPullParser.createFromString(simpleActivity);
- params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.Light.NoActionBar", false,
- RenderingMode.V_SCROLL, 22);
- params.setFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG, "menu");
- renderAndVerify(params, "simple_activity.png");
- }
-
- @Test
- public void testOnApplyInsetsCall()
- throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
- // We get the widget via reflection to avoid IntelliJ complaining about the class being
- // located in the wrong package. (From the Bridge tests point of view, it is)
- Class insetsWidgetClass = Class.forName("com.android.layoutlib.test.myapplication.widgets" +
- ".InsetsWidget");
- Field field = insetsWidgetClass.getDeclaredField("sApplyInsetsCalled");
- assertFalse((Boolean)field.get(null));
-
- LayoutPullParser parser = LayoutPullParser.createFromString(
- "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
- " android:padding=\"16dp\"\n" +
- " android:orientation=\"horizontal\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:layout_height=\"wrap_content\">\n" + "\n" +
- " <com.android.layoutlib.test.myapplication.widgets.InsetsWidget\n" +
- " android:text=\"Hello world\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:layout_height=\"wrap_content\"\n" +
- " android:id=\"@+id/text1\"/>\n" + "</LinearLayout>\n");
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.Light.NoActionBar", false,
- RenderingMode.NORMAL, 22);
-
- render(params, -1);
-
- assertTrue((Boolean)field.get(null));
- field.set(null, false);
- }
-
- /** Test expand_layout.xml */
- @Test
- public void testExpand() throws ClassNotFoundException, FileNotFoundException {
- // Create the layout pull parser.
- LayoutPullParser parser = createParserFromPath("expand_vert_layout.xml");
- // Create LayoutLibCallback.
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
-
- ConfigGenerator customConfigGenerator = new ConfigGenerator()
- .setScreenWidth(300)
- .setScreenHeight(20)
- .setDensity(Density.XHIGH)
- .setNavigation(Navigation.NONAV);
-
- SessionParams params = getSessionParams(parser, customConfigGenerator,
- layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false,
- RenderingMode.V_SCROLL, 22);
-
- renderAndVerify(params, "expand_vert_layout.png");
-
- customConfigGenerator = new ConfigGenerator()
- .setScreenWidth(20)
- .setScreenHeight(300)
- .setDensity(Density.XHIGH)
- .setNavigation(Navigation.NONAV);
- parser = createParserFromPath("expand_horz_layout.xml");
- params = getSessionParams(parser, customConfigGenerator,
- layoutLibCallback, "Theme.Material.Light.NoActionBar.Fullscreen", false,
- RenderingMode.H_SCROLL, 22);
-
- renderAndVerify(params, "expand_horz_layout.png");
- }
-
- /** Test indeterminate_progressbar.xml */
- @Test
- public void testVectorAnimation() throws ClassNotFoundException {
- String layout = "\n" +
- "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
- " android:padding=\"16dp\"\n" +
- " android:orientation=\"horizontal\"\n" +
- " android:layout_width=\"fill_parent\"\n" +
- " android:layout_height=\"fill_parent\">\n" + "\n" +
- " <ProgressBar\n" + " android:layout_height=\"fill_parent\"\n" +
- " android:layout_width=\"fill_parent\" />\n" + "\n" +
- "</LinearLayout>\n";
-
- // Create the layout pull parser.
- LayoutPullParser parser = LayoutPullParser.createFromString(layout);
- // Create LayoutLibCallback.
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
-
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
- RenderingMode.V_SCROLL, 22);
-
- renderAndVerify(params, "animated_vector.png", TimeUnit.SECONDS.toNanos(2));
-
- parser = LayoutPullParser.createFromString(layout);
- params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
- RenderingMode.V_SCROLL, 22);
- renderAndVerify(params, "animated_vector_1.png", TimeUnit.SECONDS.toNanos(3));
- }
-
- /**
- * Test a vector drawable that uses trimStart and trimEnd. It also tests all the primitives
- * for vector drawables (lines, moves and cubic and quadratic curves).
- */
- @Test
- public void testVectorDrawable() throws ClassNotFoundException {
- // Create the layout pull parser.
- LayoutPullParser parser = LayoutPullParser.createFromString(
- "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
- " android:padding=\"16dp\"\n" +
- " android:orientation=\"horizontal\"\n" +
- " android:layout_width=\"fill_parent\"\n" +
- " android:layout_height=\"fill_parent\">\n" +
- " <ImageView\n" +
- " android:layout_height=\"fill_parent\"\n" +
- " android:layout_width=\"fill_parent\"\n" +
- " android:src=\"@drawable/multi_path\" />\n" + "\n" +
- "</LinearLayout>");
- // Create LayoutLibCallback.
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
-
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
- RenderingMode.V_SCROLL, 22);
-
- renderAndVerify(params, "vector_drawable.png", TimeUnit.SECONDS.toNanos(2));
- }
-
- /**
- * Regression test for http://b.android.com/91383 and http://b.android.com/203797
- */
- @Test
- public void testVectorDrawable91383() throws ClassNotFoundException {
- // Create the layout pull parser.
- LayoutPullParser parser = LayoutPullParser.createFromString(
- "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
- " android:padding=\"16dp\"\n" +
- " android:orientation=\"vertical\"\n" +
- " android:layout_width=\"fill_parent\"\n" +
- " android:layout_height=\"fill_parent\">\n" +
- " <ImageView\n" +
- " android:layout_height=\"wrap_content\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:src=\"@drawable/android\"/>\n" +
- " <ImageView\n" +
- " android:layout_height=\"wrap_content\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:src=\"@drawable/headset\"/>\n" +
- "</LinearLayout>");
- // Create LayoutLibCallback.
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
-
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
- RenderingMode.V_SCROLL, 22);
-
- renderAndVerify(params, "vector_drawable_91383.png", TimeUnit.SECONDS.toNanos(2));
- }
-
- /** Test activity.xml */
- @Test
- public void testScrollingAndMeasure() throws ClassNotFoundException, FileNotFoundException {
- // Create the layout pull parser.
- LayoutPullParser parser = createParserFromPath("scrolled.xml");
- // Create LayoutLibCallback.
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
-
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
- RenderingMode.V_SCROLL, 22);
- params.setForceNoDecor();
- params.setExtendedViewInfoMode(true);
-
- // Do an only-measure pass
- RenderSession session = sBridge.createSession(params);
- session.measure();
- RenderResult result = RenderResult.getFromSession(session);
- assertNotNull(result);
- assertNotNull(result.getResult());
- assertTrue(result.getResult().isSuccess());
-
- ViewInfo rootLayout = result.getRootViews().get(0);
- // Check the first box in the main LinearLayout
- assertEquals(-90, rootLayout.getChildren().get(0).getTop());
- assertEquals(-30, rootLayout.getChildren().get(0).getLeft());
- assertEquals(90, rootLayout.getChildren().get(0).getBottom());
- assertEquals(150, rootLayout.getChildren().get(0).getRight());
-
- // Check the first box within the nested LinearLayout
- assertEquals(-450, rootLayout.getChildren().get(5).getChildren().get(0).getTop());
- assertEquals(90, rootLayout.getChildren().get(5).getChildren().get(0).getLeft());
- assertEquals(-270, rootLayout.getChildren().get(5).getChildren().get(0).getBottom());
- assertEquals(690, rootLayout.getChildren().get(5).getChildren().get(0).getRight());
-
- // Do a full render pass
- parser = createParserFromPath("scrolled.xml");
-
- params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
- RenderingMode.V_SCROLL, 22);
- params.setForceNoDecor();
- params.setExtendedViewInfoMode(true);
-
- result = renderAndVerify(params, "scrolled.png");
- assertNotNull(result);
- assertNotNull(result.getResult());
- assertTrue(result.getResult().isSuccess());
- }
-
- @Test
- public void testGetResourceNameVariants() throws Exception {
- // Setup
- // Create the layout pull parser for our resources (empty.xml can not be part of the test
- // app as it won't compile).
- LayoutPullParser parser = LayoutPullParser.createFromPath("/empty.xml");
- // Create LayoutLibCallback.
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_4,
- layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22);
- AssetManager assetManager = AssetManager.getSystem();
- DisplayMetrics metrics = new DisplayMetrics();
- Configuration configuration = RenderAction.getConfiguration(params);
- //noinspection deprecation
- Resources resources = new Resources(assetManager, metrics, configuration);
- resources.mLayoutlibCallback = params.getLayoutlibCallback();
- resources.mContext =
- new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
- params.getAssets(), params.getLayoutlibCallback(), configuration,
- params.getTargetSdkVersion(), params.isRtlSupported());
- // Test
- assertEquals("android:style/ButtonBar",
- resources.getResourceName(android.R.style.ButtonBar));
- assertEquals("android", resources.getResourcePackageName(android.R.style.ButtonBar));
- assertEquals("ButtonBar", resources.getResourceEntryName(android.R.style.ButtonBar));
- assertEquals("style", resources.getResourceTypeName(android.R.style.ButtonBar));
- int id = resources.mLayoutlibCallback.getResourceId(ResourceType.STRING, "app_name");
- assertEquals("com.android.layoutlib.test.myapplication:string/app_name",
- resources.getResourceName(id));
- assertEquals("com.android.layoutlib.test.myapplication",
- resources.getResourcePackageName(id));
- assertEquals("string", resources.getResourceTypeName(id));
- assertEquals("app_name", resources.getResourceEntryName(id));
- }
-
- @Test
- public void testStringEscaping() throws Exception {
- // Setup
- // Create the layout pull parser for our resources (empty.xml can not be part of the test
- // app as it won't compile).
- LayoutPullParser parser = LayoutPullParser.createFromPath("/empty.xml");
- // Create LayoutLibCallback.
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(RenderTestBase.getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_4,
- layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22);
- AssetManager assetManager = AssetManager.getSystem();
- DisplayMetrics metrics = new DisplayMetrics();
- Configuration configuration = RenderAction.getConfiguration(params);
- //noinspection deprecation
- Resources resources = new Resources(assetManager, metrics, configuration);
- resources.mLayoutlibCallback = params.getLayoutlibCallback();
- resources.mContext =
- new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
- params.getAssets(), params.getLayoutlibCallback(), configuration,
- params.getTargetSdkVersion(), params.isRtlSupported());
-
- int id = resources.mLayoutlibCallback.getResourceId(ResourceType.ARRAY, "string_array");
- String[] strings = resources.getStringArray(id);
- assertArrayEquals(
- new String[]{"mystring", "Hello world!", "candidates", "Unknown", "?EC"},
- strings);
- assertTrue(sRenderMessages.isEmpty());
- }
-
- @Test
- public void testFonts() throws ClassNotFoundException, FileNotFoundException {
- // TODO: styles seem to be broken in TextView
- renderAndVerify("fonts_test.xml", "font_test.png");
- }
-
- @Test
- public void testAdaptiveIcon() throws ClassNotFoundException, FileNotFoundException {
- // Create the layout pull parser.
- LayoutPullParser parser = LayoutPullParser.createFromString(
- "<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
- " android:padding=\"16dp\"\n" +
- " android:orientation=\"horizontal\"\n" +
- " android:layout_width=\"fill_parent\"\n" +
- " android:layout_height=\"fill_parent\">\n" +
- " <ImageView\n" +
- " android:layout_height=\"wrap_content\"\n" +
- " android:layout_width=\"wrap_content\"\n" +
- " android:src=\"@drawable/adaptive\" />\n" +
- "</LinearLayout>\n");
- // Create LayoutLibCallback.
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
-
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_5,
- layoutLibCallback, "Theme.Material.NoActionBar.Fullscreen", false,
- RenderingMode.V_SCROLL, 22);
-
- renderAndVerify(params, "adaptive_icon.png");
- }
-
- @Test
- public void testColorTypedValue() throws Exception {
- // Setup
- // Create the layout pull parser for our resources (empty.xml can not be part of the test
- // app as it won't compile).
- LayoutPullParser parser = LayoutPullParser.createFromPath("/empty.xml");
- // Create LayoutLibCallback.
- LayoutLibTestCallback layoutLibCallback =
- new LayoutLibTestCallback(RenderTestBase.getLogger(), mDefaultClassLoader);
- layoutLibCallback.initResources();
- SessionParams params = getSessionParams(parser, ConfigGenerator.NEXUS_4,
- layoutLibCallback, "AppTheme", true, RenderingMode.NORMAL, 22);
- AssetManager assetManager = AssetManager.getSystem();
- DisplayMetrics metrics = new DisplayMetrics();
- Configuration configuration = RenderAction.getConfiguration(params);
- //noinspection deprecation
- Resources resources = new Resources(assetManager, metrics, configuration);
- resources.mLayoutlibCallback = params.getLayoutlibCallback();
- resources.mContext =
- new BridgeContext(params.getProjectKey(), metrics, params.getResources(),
- params.getAssets(), params.getLayoutlibCallback(), configuration,
- params.getTargetSdkVersion(), params.isRtlSupported());
-
- TypedValue outValue = new TypedValue();
- resources.mContext.resolveThemeAttribute(android.R.attr.colorPrimary, outValue, true);
- assertEquals(TypedValue.TYPE_INT_COLOR_ARGB8, outValue.type);
- assertNotEquals(0, outValue.data);
- assertTrue(sRenderMessages.isEmpty());
- }
-
- @Test
- public void testRectangleShadow() throws Exception {
- renderAndVerify("shadows_test.xml", "shadows_test.png");
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.intensive.setup;
-
-import com.android.ide.common.rendering.api.HardwareConfig;
-import com.android.ide.common.resources.configuration.CountryCodeQualifier;
-import com.android.ide.common.resources.configuration.DensityQualifier;
-import com.android.ide.common.resources.configuration.FolderConfiguration;
-import com.android.ide.common.resources.configuration.KeyboardStateQualifier;
-import com.android.ide.common.resources.configuration.LayoutDirectionQualifier;
-import com.android.ide.common.resources.configuration.LocaleQualifier;
-import com.android.ide.common.resources.configuration.NavigationMethodQualifier;
-import com.android.ide.common.resources.configuration.NetworkCodeQualifier;
-import com.android.ide.common.resources.configuration.NightModeQualifier;
-import com.android.ide.common.resources.configuration.ScreenDimensionQualifier;
-import com.android.ide.common.resources.configuration.ScreenOrientationQualifier;
-import com.android.ide.common.resources.configuration.ScreenRatioQualifier;
-import com.android.ide.common.resources.configuration.ScreenSizeQualifier;
-import com.android.ide.common.resources.configuration.TextInputMethodQualifier;
-import com.android.ide.common.resources.configuration.TouchScreenQualifier;
-import com.android.ide.common.resources.configuration.UiModeQualifier;
-import com.android.ide.common.resources.configuration.VersionQualifier;
-import com.android.resources.Density;
-import com.android.resources.Keyboard;
-import com.android.resources.KeyboardState;
-import com.android.resources.Navigation;
-import com.android.resources.NightMode;
-import com.android.resources.ScreenOrientation;
-import com.android.resources.ScreenRatio;
-import com.android.resources.ScreenSize;
-import com.android.resources.TouchScreen;
-import com.android.resources.UiMode;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Properties;
-
-import com.google.android.collect.Maps;
-
-/**
- * Provides {@link FolderConfiguration} and {@link HardwareConfig} for various devices. Also
- * provides utility methods to parse build.prop and attrs.xml to generate the appropriate maps.
- */
-@SuppressWarnings("UnusedDeclaration") // For the pre-configured nexus generators.
-public class ConfigGenerator {
-
- public static final ConfigGenerator NEXUS_4 = new ConfigGenerator();
-
- public static final ConfigGenerator NEXUS_5 = new ConfigGenerator()
- .setScreenHeight(1920)
- .setScreenWidth(1080)
- .setXdpi(445)
- .setYdpi(445)
- .setOrientation(ScreenOrientation.PORTRAIT)
- .setDensity(Density.XXHIGH)
- .setRatio(ScreenRatio.NOTLONG)
- .setSize(ScreenSize.NORMAL)
- .setKeyboard(Keyboard.NOKEY)
- .setTouchScreen(TouchScreen.FINGER)
- .setKeyboardState(KeyboardState.SOFT)
- .setSoftButtons(true)
- .setNavigation(Navigation.NONAV);
-
- public static final ConfigGenerator NEXUS_7 = new ConfigGenerator()
- .setScreenHeight(1920)
- .setScreenWidth(1200)
- .setXdpi(323)
- .setYdpi(323)
- .setOrientation(ScreenOrientation.PORTRAIT)
- .setDensity(Density.XHIGH)
- .setRatio(ScreenRatio.NOTLONG)
- .setSize(ScreenSize.LARGE)
- .setKeyboard(Keyboard.NOKEY)
- .setTouchScreen(TouchScreen.FINGER)
- .setKeyboardState(KeyboardState.SOFT)
- .setSoftButtons(true)
- .setNavigation(Navigation.NONAV);
-
- public static final ConfigGenerator NEXUS_10 = new ConfigGenerator()
- .setScreenHeight(1600)
- .setScreenWidth(2560)
- .setXdpi(300)
- .setYdpi(300)
- .setOrientation(ScreenOrientation.LANDSCAPE)
- .setDensity(Density.XHIGH)
- .setRatio(ScreenRatio.NOTLONG)
- .setSize(ScreenSize.XLARGE)
- .setKeyboard(Keyboard.NOKEY)
- .setTouchScreen(TouchScreen.FINGER)
- .setKeyboardState(KeyboardState.SOFT)
- .setSoftButtons(true)
- .setNavigation(Navigation.NONAV);
-
- public static final ConfigGenerator NEXUS_5_LAND = new ConfigGenerator()
- .setScreenHeight(1080)
- .setScreenWidth(1920)
- .setXdpi(445)
- .setYdpi(445)
- .setOrientation(ScreenOrientation.LANDSCAPE)
- .setDensity(Density.XXHIGH)
- .setRatio(ScreenRatio.NOTLONG)
- .setSize(ScreenSize.NORMAL)
- .setKeyboard(Keyboard.NOKEY)
- .setTouchScreen(TouchScreen.FINGER)
- .setKeyboardState(KeyboardState.SOFT)
- .setSoftButtons(true)
- .setNavigation(Navigation.NONAV);
-
- public static final ConfigGenerator NEXUS_7_2012 = new ConfigGenerator()
- .setScreenHeight(1280)
- .setScreenWidth(800)
- .setXdpi(195)
- .setYdpi(200)
- .setOrientation(ScreenOrientation.PORTRAIT)
- .setDensity(Density.TV)
- .setRatio(ScreenRatio.NOTLONG)
- .setSize(ScreenSize.LARGE)
- .setKeyboard(Keyboard.NOKEY)
- .setTouchScreen(TouchScreen.FINGER)
- .setKeyboardState(KeyboardState.SOFT)
- .setSoftButtons(true)
- .setNavigation(Navigation.NONAV);
-
- private static final String TAG_ATTR = "attr";
- private static final String TAG_ENUM = "enum";
- private static final String TAG_FLAG = "flag";
- private static final String ATTR_NAME = "name";
- private static final String ATTR_VALUE = "value";
-
- // Device Configuration. Defaults are for a Nexus 4 device.
- private int mScreenHeight = 1280;
- private int mScreenWidth = 768;
- private int mXdpi = 320;
- private int mYdpi = 320;
- private ScreenOrientation mOrientation = ScreenOrientation.PORTRAIT;
- private Density mDensity = Density.XHIGH;
- private ScreenRatio mRatio = ScreenRatio.NOTLONG;
- private ScreenSize mSize = ScreenSize.NORMAL;
- private Keyboard mKeyboard = Keyboard.NOKEY;
- private TouchScreen mTouchScreen = TouchScreen.FINGER;
- private KeyboardState mKeyboardState = KeyboardState.SOFT;
- private boolean mSoftButtons = true;
- private Navigation mNavigation = Navigation.NONAV;
-
- public FolderConfiguration getFolderConfig() {
- FolderConfiguration config = new FolderConfiguration();
- config.createDefault();
- config.setDensityQualifier(new DensityQualifier(mDensity));
- config.setNavigationMethodQualifier(new NavigationMethodQualifier(mNavigation));
- if (mScreenWidth > mScreenHeight) {
- config.setScreenDimensionQualifier(new ScreenDimensionQualifier(mScreenWidth,
- mScreenHeight));
- } else {
- config.setScreenDimensionQualifier(new ScreenDimensionQualifier(mScreenHeight,
- mScreenWidth));
- }
- config.setScreenRatioQualifier(new ScreenRatioQualifier(mRatio));
- config.setScreenSizeQualifier(new ScreenSizeQualifier(mSize));
- config.setTextInputMethodQualifier(new TextInputMethodQualifier(mKeyboard));
- config.setTouchTypeQualifier(new TouchScreenQualifier(mTouchScreen));
- config.setKeyboardStateQualifier(new KeyboardStateQualifier(mKeyboardState));
- config.setScreenOrientationQualifier(new ScreenOrientationQualifier(mOrientation));
-
- config.updateScreenWidthAndHeight();
-
- // some default qualifiers.
- config.setUiModeQualifier(new UiModeQualifier(UiMode.NORMAL));
- config.setNightModeQualifier(new NightModeQualifier(NightMode.NOTNIGHT));
- config.setCountryCodeQualifier(new CountryCodeQualifier());
- config.setLayoutDirectionQualifier(new LayoutDirectionQualifier());
- config.setNetworkCodeQualifier(new NetworkCodeQualifier());
- config.setLocaleQualifier(new LocaleQualifier());
- config.setVersionQualifier(new VersionQualifier());
- return config;
- }
-
- public HardwareConfig getHardwareConfig() {
- return new HardwareConfig(mScreenWidth, mScreenHeight, mDensity, mXdpi, mYdpi, mSize,
- mOrientation, null, mSoftButtons);
- }
-
- public static Map<String, String> loadProperties(File path) {
- Properties p = new Properties();
- Map<String, String> map = Maps.newHashMap();
- try {
- p.load(new FileInputStream(path));
- for (String key : p.stringPropertyNames()) {
- map.put(key, p.getProperty(key));
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return map;
- }
-
- public static Map<String, Map<String, Integer>> getEnumMap(File path) {
- Map<String, Map<String, Integer>> map = Maps.newHashMap();
- try {
- XmlPullParser xmlPullParser = XmlPullParserFactory.newInstance().newPullParser();
- xmlPullParser.setInput(new FileInputStream(path), null);
- int eventType = xmlPullParser.getEventType();
- String attr = null;
- while (eventType != XmlPullParser.END_DOCUMENT) {
- if (eventType == XmlPullParser.START_TAG) {
- if (TAG_ATTR.equals(xmlPullParser.getName())) {
- attr = xmlPullParser.getAttributeValue(null, ATTR_NAME);
- } else if (TAG_ENUM.equals(xmlPullParser.getName())
- || TAG_FLAG.equals(xmlPullParser.getName())) {
- String name = xmlPullParser.getAttributeValue(null, ATTR_NAME);
- String value = xmlPullParser.getAttributeValue(null, ATTR_VALUE);
- // Integer.decode cannot handle "ffffffff", see JDK issue 6624867
- int i = (int) (long) Long.decode(value);
- assert attr != null;
- Map<String, Integer> attributeMap = map.get(attr);
- if (attributeMap == null) {
- attributeMap = Maps.newHashMap();
- map.put(attr, attributeMap);
- }
- attributeMap.put(name, i);
- }
- } else if (eventType == XmlPullParser.END_TAG) {
- if (TAG_ATTR.equals(xmlPullParser.getName())) {
- attr = null;
- }
- }
- eventType = xmlPullParser.next();
- }
- } catch (XmlPullParserException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return map;
- }
-
- // Methods to set the configuration values.
-
- public ConfigGenerator setScreenHeight(int height) {
- mScreenHeight = height;
- return this;
- }
-
- public ConfigGenerator setScreenWidth(int width) {
- mScreenWidth = width;
- return this;
- }
-
- public ConfigGenerator setXdpi(int xdpi) {
- mXdpi = xdpi;
- return this;
- }
-
- public ConfigGenerator setYdpi(int ydpi) {
- mYdpi = ydpi;
- return this;
- }
-
- public ConfigGenerator setOrientation(ScreenOrientation orientation) {
- mOrientation = orientation;
- return this;
- }
-
- public ConfigGenerator setDensity(Density density) {
- mDensity = density;
- return this;
- }
-
- public ConfigGenerator setRatio(ScreenRatio ratio) {
- mRatio = ratio;
- return this;
- }
-
- public ConfigGenerator setSize(ScreenSize size) {
- mSize = size;
- return this;
- }
-
- public ConfigGenerator setKeyboard(Keyboard keyboard) {
- mKeyboard = keyboard;
- return this;
- }
-
- public ConfigGenerator setTouchScreen(TouchScreen touchScreen) {
- mTouchScreen = touchScreen;
- return this;
- }
-
- public ConfigGenerator setKeyboardState(KeyboardState state) {
- mKeyboardState = state;
- return this;
- }
-
- public ConfigGenerator setSoftButtons(boolean softButtons) {
- mSoftButtons = softButtons;
- return this;
- }
-
- public ConfigGenerator setNavigation(Navigation navigation) {
- mNavigation = navigation;
- return this;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.intensive.setup;
-
-import com.android.SdkConstants;
-import com.android.ide.common.rendering.api.ActionBarCallback;
-import com.android.ide.common.rendering.api.AdapterBinding;
-import com.android.ide.common.rendering.api.ILayoutPullParser;
-import com.android.ide.common.rendering.api.LayoutlibCallback;
-import com.android.ide.common.rendering.api.ParserFactory;
-import com.android.ide.common.rendering.api.ResourceReference;
-import com.android.ide.common.rendering.api.ResourceValue;
-import com.android.ide.common.rendering.api.SessionParams.Key;
-import com.android.ide.common.resources.IntArrayWrapper;
-import com.android.layoutlib.bridge.android.RenderParamsFlags;
-import com.android.resources.ResourceType;
-import com.android.util.Pair;
-import com.android.utils.ILogger;
-
-import org.kxml2.io.KXmlParser;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.Map;
-
-import com.google.android.collect.Maps;
-
-import static org.junit.Assert.fail;
-
-@SuppressWarnings("deprecation") // For Pair
-public class LayoutLibTestCallback extends LayoutlibCallback {
-
- private static final String PROJECT_CLASSES_LOCATION = "/testApp/MyApplication/build/intermediates/classes/debug/";
- private static final String PACKAGE_NAME = "com.android.layoutlib.test.myapplication";
-
- private final Map<Integer, Pair<ResourceType, String>> mProjectResources = Maps.newHashMap();
- private final Map<IntArrayWrapper, String> mStyleableValueToNameMap = Maps.newHashMap();
- private final Map<ResourceType, Map<String, Integer>> mResources = Maps.newHashMap();
- private final ILogger mLog;
- private final ActionBarCallback mActionBarCallback = new ActionBarCallback();
- private final ClassLoader mModuleClassLoader;
-
- public LayoutLibTestCallback(ILogger logger, ClassLoader classLoader) {
- mLog = logger;
- mModuleClassLoader = classLoader;
- }
-
- public void initResources() throws ClassNotFoundException {
- Class<?> rClass = mModuleClassLoader.loadClass(PACKAGE_NAME + ".R");
- Class<?>[] nestedClasses = rClass.getDeclaredClasses();
- for (Class<?> resClass : nestedClasses) {
- final ResourceType resType = ResourceType.getEnum(resClass.getSimpleName());
-
- if (resType != null) {
- final Map<String, Integer> resName2Id = Maps.newHashMap();
- mResources.put(resType, resName2Id);
-
- for (Field field : resClass.getDeclaredFields()) {
- final int modifiers = field.getModifiers();
- if (Modifier.isStatic(modifiers)) { // May not be final in library projects
- final Class<?> type = field.getType();
- try {
- if (type.isArray() && type.getComponentType() == int.class) {
- mStyleableValueToNameMap.put(
- new IntArrayWrapper((int[]) field.get(null)),
- field.getName());
- } else if (type == int.class) {
- final Integer value = (Integer) field.get(null);
- mProjectResources.put(value, Pair.of(resType, field.getName()));
- resName2Id.put(field.getName(), value);
- } else {
- mLog.error(null, "Unknown field type in R class: %1$s", type);
- }
- } catch (IllegalAccessException ignored) {
- mLog.error(ignored, "Malformed R class: %1$s", PACKAGE_NAME + ".R");
- }
- }
- }
- }
- }
- }
-
-
- @Override
- public Object loadView(String name, Class[] constructorSignature, Object[] constructorArgs)
- throws Exception {
- Class<?> viewClass = mModuleClassLoader.loadClass(name);
- Constructor<?> viewConstructor = viewClass.getConstructor(constructorSignature);
- viewConstructor.setAccessible(true);
- return viewConstructor.newInstance(constructorArgs);
- }
-
- @Override
- public String getNamespace() {
- return String.format(SdkConstants.NS_CUSTOM_RESOURCES_S,
- PACKAGE_NAME);
- }
-
- @Override
- public Pair<ResourceType, String> resolveResourceId(int id) {
- return mProjectResources.get(id);
- }
-
- @Override
- public String resolveResourceId(int[] id) {
- return mStyleableValueToNameMap.get(new IntArrayWrapper(id));
- }
-
- @Override
- public Integer getResourceId(ResourceType type, String name) {
- Map<String, Integer> resName2Id = mResources.get(type);
- if (resName2Id == null) {
- return null;
- }
- return resName2Id.get(name);
- }
-
- @Override
- public ILayoutPullParser getParser(String layoutName) {
- fail("This method shouldn't be called by this version of LayoutLib.");
- return null;
- }
-
- @Override
- public ILayoutPullParser getParser(ResourceValue layoutResource) {
- try {
- return LayoutPullParser.createFromFile(new File(layoutResource.getValue()));
- } catch (FileNotFoundException e) {
- return null;
- }
- }
-
- @Override
- public Object getAdapterItemValue(ResourceReference adapterView, Object adapterCookie,
- ResourceReference itemRef, int fullPosition, int positionPerType,
- int fullParentPosition, int parentPositionPerType, ResourceReference viewRef,
- ViewAttribute viewAttribute, Object defaultValue) {
- return null;
- }
-
- @Override
- public AdapterBinding getAdapterBinding(ResourceReference adapterViewRef, Object adapterCookie,
- Object viewObject) {
- return null;
- }
-
- @Override
- public ActionBarCallback getActionBarCallback() {
- return mActionBarCallback;
- }
-
- @Override
- public boolean supports(int ideFeature) {
- return false;
- }
-
- @NonNull
- @Override
- public ParserFactory getParserFactory() {
- return new ParserFactory() {
- @NonNull
- @Override
- public XmlPullParser createParser(@Nullable String debugName)
- throws XmlPullParserException {
- return new KXmlParser();
- }
- };
- }
-
- @Override
- public <T> T getFlag(Key<T> key) {
- if (key.equals(RenderParamsFlags.FLAG_KEY_APPLICATION_PACKAGE)) {
- return (T) PACKAGE_NAME;
- }
- return null;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.layoutlib.bridge.intensive.setup;
-
-import com.android.ide.common.rendering.api.ILayoutPullParser;
-
-import org.kxml2.io.KXmlParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.annotation.NonNull;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOError;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.util.HashMap;
-import java.util.Map;
-
-import static com.android.SdkConstants.ATTR_IGNORE;
-import static com.android.SdkConstants.EXPANDABLE_LIST_VIEW;
-import static com.android.SdkConstants.GRID_VIEW;
-import static com.android.SdkConstants.LIST_VIEW;
-import static com.android.SdkConstants.SPINNER;
-import static com.android.SdkConstants.TOOLS_URI;
-
-public class LayoutPullParser extends KXmlParser implements ILayoutPullParser{
- @NonNull
- public static LayoutPullParser createFromFile(@NonNull File layoutFile)
- throws FileNotFoundException {
- return new LayoutPullParser(new FileInputStream(layoutFile));
- }
-
- /**
- * @param layoutPath Must start with '/' and be relative to test resources.
- */
- @NonNull
- public static LayoutPullParser createFromPath(@NonNull String layoutPath) {
- if (layoutPath.startsWith("/")) {
- layoutPath = layoutPath.substring(1);
- }
-
- return new LayoutPullParser(LayoutPullParser.class.getClassLoader().getResourceAsStream
- (layoutPath));
- }
-
- @NonNull
- public static LayoutPullParser createFromString(@NonNull String contents) {
- return new LayoutPullParser(new ByteArrayInputStream(
- contents.getBytes(Charset.forName("UTF-8"))));
- }
-
- private LayoutPullParser(@NonNull InputStream inputStream) {
- try {
- setFeature(FEATURE_PROCESS_NAMESPACES, true);
- setInput(inputStream, null);
- } catch (XmlPullParserException e) {
- throw new IOError(e);
- }
- }
-
- @Override
- public Object getViewCookie() {
- // TODO: Implement this properly.
- String name = super.getName();
- if (name == null) {
- return null;
- }
-
- // Store tools attributes if this looks like a layout we'll need adapter view
- // bindings for in the LayoutlibCallback.
- if (LIST_VIEW.equals(name) || EXPANDABLE_LIST_VIEW.equals(name) || GRID_VIEW.equals(name) || SPINNER.equals(name)) {
- Map<String, String> map = null;
- int count = getAttributeCount();
- for (int i = 0; i < count; i++) {
- String namespace = getAttributeNamespace(i);
- if (namespace != null && namespace.equals(TOOLS_URI)) {
- String attribute = getAttributeName(i);
- if (attribute.equals(ATTR_IGNORE)) {
- continue;
- }
- if (map == null) {
- map = new HashMap<String, String>(4);
- }
- map.put(attribute, getAttributeValue(i));
- }
- }
-
- return map;
- }
-
- return null;
- }
-
- @Override
- @Deprecated
- public ILayoutPullParser getParser(String layoutName) {
- // Studio returns null.
- return null;
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive.util;
-
-import android.annotation.NonNull;
-
-import java.awt.AlphaComposite;
-import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.imageio.ImageIO;
-
-import static java.awt.RenderingHints.*;
-import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
-import static java.io.File.separatorChar;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-
-// Adapted by taking the relevant pieces of code from the following classes:
-//
-// com.android.tools.idea.rendering.ImageUtils,
-// com.android.tools.idea.tests.gui.framework.fixture.layout.ImageFixture and
-// com.android.tools.idea.rendering.RenderTestBase
-/**
- * Utilities related to image processing.
- */
-public class ImageUtils {
- /**
- * Normally, this test will fail when there is a missing thumbnail. However, when
- * you create creating a new test, it's useful to be able to turn this off such that
- * you can generate all the missing thumbnails in one go, rather than having to run
- * the test repeatedly to get to each new render assertion generating its thumbnail.
- */
- private static final boolean FAIL_ON_MISSING_THUMBNAIL = true;
-
- private static final int THUMBNAIL_SIZE = 1000;
-
- private static final double MAX_PERCENT_DIFFERENCE = 0.3;
-
- public static void requireSimilar(@NonNull String relativePath, @NonNull BufferedImage image)
- throws IOException {
- int maxDimension = Math.max(image.getWidth(), image.getHeight());
- double scale = THUMBNAIL_SIZE / (double)maxDimension;
- BufferedImage thumbnail = scale(image, scale, scale);
-
- InputStream is = ImageUtils.class.getClassLoader().getResourceAsStream(relativePath);
- if (is == null) {
- String message = "Unable to load golden thumbnail: " + relativePath + "\n";
- message = saveImageAndAppendMessage(thumbnail, message, relativePath);
- if (FAIL_ON_MISSING_THUMBNAIL) {
- fail(message);
- } else {
- System.out.println(message);
- }
- }
- else {
- try {
- BufferedImage goldenImage = ImageIO.read(is);
- assertImageSimilar(relativePath, goldenImage, thumbnail, MAX_PERCENT_DIFFERENCE);
- } finally {
- is.close();
- }
- }
- }
-
- public static void assertImageSimilar(String relativePath, BufferedImage goldenImage,
- BufferedImage image, double maxPercentDifferent) throws IOException {
- assertEquals("Only TYPE_INT_ARGB image types are supported", TYPE_INT_ARGB, image.getType());
-
- if (goldenImage.getType() != TYPE_INT_ARGB) {
- BufferedImage temp = new BufferedImage(goldenImage.getWidth(), goldenImage.getHeight(),
- TYPE_INT_ARGB);
- temp.getGraphics().drawImage(goldenImage, 0, 0, null);
- goldenImage = temp;
- }
- assertEquals(TYPE_INT_ARGB, goldenImage.getType());
-
- int imageWidth = Math.min(goldenImage.getWidth(), image.getWidth());
- int imageHeight = Math.min(goldenImage.getHeight(), image.getHeight());
-
- // Blur the images to account for the scenarios where there are pixel
- // differences
- // in where a sharp edge occurs
- // goldenImage = blur(goldenImage, 6);
- // image = blur(image, 6);
-
- int width = 3 * imageWidth;
- @SuppressWarnings("UnnecessaryLocalVariable")
- int height = imageHeight; // makes code more readable
- BufferedImage deltaImage = new BufferedImage(width, height, TYPE_INT_ARGB);
- Graphics g = deltaImage.getGraphics();
-
- // Compute delta map
- long delta = 0;
- for (int y = 0; y < imageHeight; y++) {
- for (int x = 0; x < imageWidth; x++) {
- int goldenRgb = goldenImage.getRGB(x, y);
- int rgb = image.getRGB(x, y);
- if (goldenRgb == rgb) {
- deltaImage.setRGB(imageWidth + x, y, 0x00808080);
- continue;
- }
-
- // If the pixels have no opacity, don't delta colors at all
- if (((goldenRgb & 0xFF000000) == 0) && (rgb & 0xFF000000) == 0) {
- deltaImage.setRGB(imageWidth + x, y, 0x00808080);
- continue;
- }
-
- int deltaR = ((rgb & 0xFF0000) >>> 16) - ((goldenRgb & 0xFF0000) >>> 16);
- int newR = 128 + deltaR & 0xFF;
- int deltaG = ((rgb & 0x00FF00) >>> 8) - ((goldenRgb & 0x00FF00) >>> 8);
- int newG = 128 + deltaG & 0xFF;
- int deltaB = (rgb & 0x0000FF) - (goldenRgb & 0x0000FF);
- int newB = 128 + deltaB & 0xFF;
-
- int avgAlpha = ((((goldenRgb & 0xFF000000) >>> 24)
- + ((rgb & 0xFF000000) >>> 24)) / 2) << 24;
-
- int newRGB = avgAlpha | newR << 16 | newG << 8 | newB;
- deltaImage.setRGB(imageWidth + x, y, newRGB);
-
- delta += Math.abs(deltaR);
- delta += Math.abs(deltaG);
- delta += Math.abs(deltaB);
- }
- }
-
- // 3 different colors, 256 color levels
- long total = imageHeight * imageWidth * 3L * 256L;
- float percentDifference = (float) (delta * 100 / (double) total);
-
- String error = null;
- String imageName = getName(relativePath);
- if (percentDifference > maxPercentDifferent) {
- error = String.format("Images differ (by %.1f%%)", percentDifference);
- } else if (Math.abs(goldenImage.getWidth() - image.getWidth()) >= 2) {
- error = "Widths differ too much for " + imageName + ": " +
- goldenImage.getWidth() + "x" + goldenImage.getHeight() +
- "vs" + image.getWidth() + "x" + image.getHeight();
- } else if (Math.abs(goldenImage.getHeight() - image.getHeight()) >= 2) {
- error = "Heights differ too much for " + imageName + ": " +
- goldenImage.getWidth() + "x" + goldenImage.getHeight() +
- "vs" + image.getWidth() + "x" + image.getHeight();
- }
-
- assertEquals(TYPE_INT_ARGB, image.getType());
- if (error != null) {
- // Expected on the left
- // Golden on the right
- g.drawImage(goldenImage, 0, 0, null);
- g.drawImage(image, 2 * imageWidth, 0, null);
-
- // Labels
- if (imageWidth > 80) {
- g.setColor(Color.RED);
- g.drawString("Expected", 10, 20);
- g.drawString("Actual", 2 * imageWidth + 10, 20);
- }
-
- File output = new File(getFailureDir(), "delta-" + imageName);
- if (output.exists()) {
- boolean deleted = output.delete();
- assertTrue(deleted);
- }
- ImageIO.write(deltaImage, "PNG", output);
- error += " - see details in " + output.getPath() + "\n";
- error = saveImageAndAppendMessage(image, error, relativePath);
- System.out.println(error);
- fail(error);
- }
-
- g.dispose();
- }
-
- /**
- * Resize the given image
- *
- * @param source the image to be scaled
- * @param xScale x scale
- * @param yScale y scale
- * @return the scaled image
- */
- @NonNull
- public static BufferedImage scale(@NonNull BufferedImage source, double xScale, double yScale) {
-
- int sourceWidth = source.getWidth();
- int sourceHeight = source.getHeight();
- int destWidth = Math.max(1, (int) (xScale * sourceWidth));
- int destHeight = Math.max(1, (int) (yScale * sourceHeight));
- int imageType = source.getType();
- if (imageType == BufferedImage.TYPE_CUSTOM) {
- imageType = BufferedImage.TYPE_INT_ARGB;
- }
- if (xScale > 0.5 && yScale > 0.5) {
- BufferedImage scaled =
- new BufferedImage(destWidth, destHeight, imageType);
- Graphics2D g2 = scaled.createGraphics();
- g2.setComposite(AlphaComposite.Src);
- g2.setColor(new Color(0, true));
- g2.fillRect(0, 0, destWidth, destHeight);
- if (xScale == 1 && yScale == 1) {
- g2.drawImage(source, 0, 0, null);
- } else {
- setRenderingHints(g2);
- g2.drawImage(source, 0, 0, destWidth, destHeight, 0, 0, sourceWidth, sourceHeight,
- null);
- }
- g2.dispose();
- return scaled;
- } else {
- // When creating a thumbnail, using the above code doesn't work very well;
- // you get some visible artifacts, especially for text. Instead use the
- // technique of repeatedly scaling the image into half; this will cause
- // proper averaging of neighboring pixels, and will typically (for the kinds
- // of screen sizes used by this utility method in the layout editor) take
- // about 3-4 iterations to get the result since we are logarithmically reducing
- // the size. Besides, each successive pass in operating on much fewer pixels
- // (a reduction of 4 in each pass).
- //
- // However, we may not be resizing to a size that can be reached exactly by
- // successively diving in half. Therefore, once we're within a factor of 2 of
- // the final size, we can do a resize to the exact target size.
- // However, we can get even better results if we perform this final resize
- // up front. Let's say we're going from width 1000 to a destination width of 85.
- // The first approach would cause a resize from 1000 to 500 to 250 to 125, and
- // then a resize from 125 to 85. That last resize can distort/blur a lot.
- // Instead, we can start with the destination width, 85, and double it
- // successfully until we're close to the initial size: 85, then 170,
- // then 340, and finally 680. (The next one, 1360, is larger than 1000).
- // So, now we *start* the thumbnail operation by resizing from width 1000 to
- // width 680, which will preserve a lot of visual details such as text.
- // Then we can successively resize the image in half, 680 to 340 to 170 to 85.
- // We end up with the expected final size, but we've been doing an exact
- // divide-in-half resizing operation at the end so there is less distortion.
-
- int iterations = 0; // Number of halving operations to perform after the initial resize
- int nearestWidth = destWidth; // Width closest to source width that = 2^x, x is integer
- int nearestHeight = destHeight;
- while (nearestWidth < sourceWidth / 2) {
- nearestWidth *= 2;
- nearestHeight *= 2;
- iterations++;
- }
-
- BufferedImage scaled = new BufferedImage(nearestWidth, nearestHeight, imageType);
-
- Graphics2D g2 = scaled.createGraphics();
- setRenderingHints(g2);
- g2.drawImage(source, 0, 0, nearestWidth, nearestHeight, 0, 0, sourceWidth, sourceHeight,
- null);
- g2.dispose();
-
- sourceWidth = nearestWidth;
- sourceHeight = nearestHeight;
- source = scaled;
-
- for (int iteration = iterations - 1; iteration >= 0; iteration--) {
- int halfWidth = sourceWidth / 2;
- int halfHeight = sourceHeight / 2;
- scaled = new BufferedImage(halfWidth, halfHeight, imageType);
- g2 = scaled.createGraphics();
- setRenderingHints(g2);
- g2.drawImage(source, 0, 0, halfWidth, halfHeight, 0, 0, sourceWidth, sourceHeight,
- null);
- g2.dispose();
-
- sourceWidth = halfWidth;
- sourceHeight = halfHeight;
- source = scaled;
- iterations--;
- }
- return scaled;
- }
- }
-
- private static void setRenderingHints(@NonNull Graphics2D g2) {
- g2.setRenderingHint(KEY_INTERPOLATION,VALUE_INTERPOLATION_BILINEAR);
- g2.setRenderingHint(KEY_RENDERING, VALUE_RENDER_QUALITY);
- g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
- }
-
- /**
- * Directory where to write the thumbnails and deltas.
- */
- @NonNull
- private static File getFailureDir() {
- String workingDirString = System.getProperty("user.dir");
- File failureDir = new File(workingDirString, "out/failures");
-
- //noinspection ResultOfMethodCallIgnored
- failureDir.mkdirs();
- return failureDir; //$NON-NLS-1$
- }
-
- /**
- * Saves the generated thumbnail image and appends the info message to an initial message
- */
- @NonNull
- private static String saveImageAndAppendMessage(@NonNull BufferedImage image,
- @NonNull String initialMessage, @NonNull String relativePath) throws IOException {
- File output = new File(getFailureDir(), getName(relativePath));
- if (output.exists()) {
- boolean deleted = output.delete();
- assertTrue(deleted);
- }
- ImageIO.write(image, "PNG", output);
- initialMessage += "Thumbnail for current rendering stored at " + output.getPath();
-// initialMessage += "\nRun the following command to accept the changes:\n";
-// initialMessage += String.format("mv %1$s %2$s", output.getPath(),
-// ImageUtils.class.getResource(relativePath).getPath());
- // The above has been commented out, since the destination path returned is in out dir
- // and it makes the tests pass without the code being actually checked in.
- return initialMessage;
- }
-
- private static String getName(@NonNull String relativePath) {
- return relativePath.substring(relativePath.lastIndexOf(separatorChar) + 1);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive.util;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import libcore.io.Streams;
-
-/**
- * Module class loader that loads classes from the test project.
- */
-public class ModuleClassLoader extends ClassLoader {
- private final Map<String, Class<?>> mClasses = new HashMap<>();
- private String myModuleRoot;
-
- /**
- * @param moduleRoot The path to the module root
- * @param parent The parent class loader
- */
- public ModuleClassLoader(String moduleRoot, ClassLoader parent) {
- super(parent);
- myModuleRoot = moduleRoot + (moduleRoot.endsWith("/") ? "" : "/");
- }
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- try {
- return super.findClass(name);
- } catch (ClassNotFoundException ignored) {
- }
-
- Class<?> clazz = mClasses.get(name);
- if (clazz == null) {
- String path = name.replace('.', '/').concat(".class");
- try {
- byte[] b = Streams.readFully(getResourceAsStream(myModuleRoot + path));
- clazz = defineClass(name, b, 0, b.length);
- mClasses.put(name, clazz);
- } catch (IOException ignore) {
- throw new ClassNotFoundException(name + " not found");
- }
- }
-
- return clazz;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive.util;
-
-import com.android.ide.common.rendering.api.AssetRepository;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * {@link AssetRepository} used for render tests.
- */
-public class TestAssetRepository extends AssetRepository {
- private static InputStream open(String path) throws FileNotFoundException {
- File asset = new File(path);
- if (asset.isFile()) {
- return new FileInputStream(asset);
- }
-
- return null;
- }
-
- @Override
- public boolean isSupported() {
- return true;
- }
-
- @Override
- public InputStream openAsset(String path, int mode) throws IOException {
- return open(path);
- }
-
- @Override
- public InputStream openNonAsset(int cookie, String path, int mode) throws IOException {
- return open(path);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive.util;
-
-import java.lang.ref.WeakReference;
-
-public class TestUtils {
- public static void gc() {
- // See RuntimeUtil#gc in jlibs (http://jlibs.in/)
- Object obj = new Object();
- WeakReference ref = new WeakReference<>(obj);
- //noinspection UnusedAssignment
- obj = null;
- while (ref.get() != null) {
- System.gc();
- System.runFinalization();
- }
-
- System.gc();
- System.runFinalization();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive.util.perf;
-
-import android.annotation.NonNull;
-import android.util.LongArray;
-
-import java.util.Arrays;
-import java.util.function.LongConsumer;
-
-/**
- * Class that collect a series of longs and produces the median, min and max values.
- */
-public class LongStatsCollector implements LongConsumer {
- private final LongArray mAllValues;
- private long mMin = Long.MAX_VALUE;
- private long mMax = Long.MIN_VALUE;
- public LongStatsCollector(int estimatedRuns) {
- mAllValues = new LongArray(estimatedRuns);
- }
-
- public int size() {
- return mAllValues.size();
- }
-
- @NonNull
- public Stats getStats() {
- if (mAllValues.size() == 0) {
- throw new IndexOutOfBoundsException("No data");
- }
-
- double median;
- int size = mAllValues.size();
- long[] buffer = new long[size];
- for (int i = 0; i < size; i++) {
- buffer[i] = mAllValues.get(i);
- }
-
- Arrays.sort(buffer);
-
- int midPoint = size / 2;
- median = (size % 2 == 0) ? (buffer[midPoint - 1] + buffer[midPoint]) / 2 : buffer[midPoint];
-
- return new Stats(mAllValues.size(), mMin, mMax, median);
- }
-
- @Override
- public void accept(long value) {
- mMin = Math.min(mMin, value);
- mMax = Math.max(mMax, value);
- mAllValues.add(value);
- }
-
- public static class Stats {
- private final int mSamples;
- private final long mMin;
- private final long mMax;
- private final double mMedian;
-
- private Stats(int samples, long min, long max, double median) {
- mSamples = samples;
- mMin = min;
- mMax = max;
- mMedian = median;
- }
-
- public int getSampleCount() {
- return mSamples;
- }
-
- public long getMin() {
- return mMin;
- }
-
- public long getMax() {
- return mMax;
- }
-
- public double getMedian() {
- return mMedian;
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive.util.perf;
-
-import org.junit.runner.Runner;
-import org.junit.runner.notification.RunNotifier;
-import org.junit.runners.BlockJUnit4ClassRunner;
-import org.junit.runners.model.FrameworkMethod;
-import org.junit.runners.model.InitializationError;
-import org.junit.runners.model.Statement;
-
-import java.lang.annotation.Inherited;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * JUnit {@link Runner} that times the test execution and produces some stats.
- */
-public class PerformanceRunner extends BlockJUnit4ClassRunner {
- private static final int DEFAULT_WARMUP_ITERATIONS = 50;
- private static final int DEFAULT_RUNS = 100;
-
- private final int mWarmUpIterations;
- private final int mRuns;
-
- public PerformanceRunner(Class<?> testClass) throws InitializationError {
- super(testClass);
-
- Configuration classConfig = testClass.getAnnotation(Configuration.class);
- mWarmUpIterations = classConfig != null && classConfig.warmUpIterations() != -1 ?
- classConfig.warmUpIterations() :
- DEFAULT_WARMUP_ITERATIONS;
- mRuns = classConfig != null && classConfig.runs() != -1 ?
- classConfig.runs() :
- DEFAULT_RUNS;
- }
-
- @Override
- protected Statement methodInvoker(FrameworkMethod method, Object test) {
- int warmUpIterations;
- int runs;
-
- Configuration methodConfig = method.getAnnotation(Configuration.class);
- warmUpIterations = methodConfig != null && methodConfig.warmUpIterations() != -1 ?
- methodConfig.warmUpIterations() :
- mWarmUpIterations;
- runs = methodConfig != null && methodConfig.runs() != -1 ?
- methodConfig.runs() :
- mRuns;
- return new TimedStatement(super.methodInvoker(method, test), warmUpIterations, runs,
- (result) -> System.out.println(result.toString()));
- }
-
- @Override
- public void run(RunNotifier notifier) {
- super.run(notifier);
- }
-
- @Retention(RetentionPolicy.RUNTIME)
- @Inherited
- public @interface Configuration {
- int warmUpIterations() default -1;
-
- int runs() default -1;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive.util.perf;
-
-import com.android.layoutlib.bridge.intensive.util.TestUtils;
-
-import org.junit.runners.model.Statement;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Random;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
-
-import com.google.common.hash.HashCode;
-import com.google.common.hash.HashFunction;
-import com.google.common.hash.Hashing;
-
-/**
- * JUnit {@link Statement} used to measure some statistics about the test method.
- */
-public class TimedStatement extends Statement {
- private static final int CALIBRATION_WARMUP_ITERATIONS = 50;
- private static final int CALIBRATION_RUNS = 100;
-
- private static boolean sIsCalibrated;
- private static double sCalibrated;
-
- private final Statement mStatement;
- private final int mWarmUpIterations;
- private final int mRuns;
- private final Runtime mRuntime = Runtime.getRuntime();
- private final Consumer<TimedStatementResult> mCallback;
-
- TimedStatement(Statement statement, int warmUpIterations, int runs,
- Consumer<TimedStatementResult> finishedCallback) {
- mStatement = statement;
- mWarmUpIterations = warmUpIterations;
- mRuns = runs;
- mCallback = finishedCallback;
- }
-
- /**
- * The calibrate method tries to do some work that involves IO, memory allocations and some
- * operations on the randomly generated data to calibrate the speed of the machine with
- * something that resembles the execution of a test case.
- */
- private static void calibrateMethod() throws IOException {
- File tmpFile = File.createTempFile("test", "file");
- Random rnd = new Random();
- HashFunction hashFunction = Hashing.sha512();
- for (int i = 0; i < 5 + rnd.nextInt(5); i++) {
- FileOutputStream stream = new FileOutputStream(tmpFile);
- int bytes = 30000 + rnd.nextInt(60000);
- byte[] buffer = new byte[bytes];
-
- rnd.nextBytes(buffer);
- byte acc = 0;
- for (int j = 0; j < bytes; j++) {
- acc += buffer[i];
- }
- buffer[0] = acc;
- stream.write(buffer);
- System.gc();
- stream.close();
- FileInputStream input = new FileInputStream(tmpFile);
- byte[] readBuffer = new byte[bytes];
- //noinspection ResultOfMethodCallIgnored
- input.read(readBuffer);
- buffer = readBuffer;
- HashCode code1 = hashFunction.hashBytes(buffer);
- Arrays.sort(buffer);
- HashCode code2 = hashFunction.hashBytes(buffer);
- input.close();
-
- FileOutputStream hashStream = new FileOutputStream(tmpFile);
- hashStream.write(code1.asBytes());
- hashStream.write(code2.asBytes());
- hashStream.close();
- }
- }
-
- /**
- * Runs the calibration process and sets the calibration measure in {@link #sCalibrated}
- */
- private static void doCalibration() throws IOException {
- System.out.println("Calibrating ...");
- TestUtils.gc();
- for (int i = 0; i < CALIBRATION_WARMUP_ITERATIONS; i++) {
- calibrateMethod();
- }
-
- LongStatsCollector stats = new LongStatsCollector(CALIBRATION_RUNS);
- for (int i = 0; i < CALIBRATION_RUNS; i++) {
- TestUtils.gc();
- long start = System.currentTimeMillis();
- calibrateMethod();
- stats.accept(System.currentTimeMillis() - start);
- }
-
- sCalibrated = stats.getStats().getMedian();
- sIsCalibrated = true;
- System.out.printf(" DONE %fms\n", sCalibrated);
- }
-
- private long getUsedMemory() {
- return mRuntime.totalMemory() - mRuntime.freeMemory();
- }
-
-
- @Override
- public void evaluate() throws Throwable {
- if (!sIsCalibrated) {
- doCalibration();
- }
-
- for (int i = 0; i < mWarmUpIterations; i++) {
- mStatement.evaluate();
- }
-
- LongStatsCollector timeStats = new LongStatsCollector(mRuns);
- LongStatsCollector memoryUseStats = new LongStatsCollector(mRuns);
- AtomicBoolean collectSamples = new AtomicBoolean(false);
-
- ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
- TestUtils.gc();
- executorService.scheduleAtFixedRate(() -> {
- if (!collectSamples.get()) {
- return;
- }
- memoryUseStats.accept(getUsedMemory());
- }, 0, 200, TimeUnit.MILLISECONDS);
-
- try {
- for (int i = 0; i < mRuns; i++) {
- TestUtils.gc();
- collectSamples.set(true);
- long startTimeMs = System.currentTimeMillis();
- mStatement.evaluate();
- long stopTimeMs = System.currentTimeMillis();
- collectSamples.set(true);
- timeStats.accept(stopTimeMs - startTimeMs);
-
- }
- } finally {
- executorService.shutdownNow();
- }
-
- TimedStatementResult result = new TimedStatementResult(
- mWarmUpIterations,
- mRuns,
- sCalibrated,
- timeStats.getStats(),
- memoryUseStats.getStats());
- mCallback.accept(result);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.intensive.util.perf;
-
-import com.android.layoutlib.bridge.intensive.util.perf.LongStatsCollector.Stats;
-
-import java.text.DecimalFormat;
-
-/**
- * Result value of a {@link TimedStatement}
- */
-public class TimedStatementResult {
- private static final DecimalFormat UNITS_FORMAT = new DecimalFormat("#.##");
-
- private final int mWarmUpIterations;
- private final int mRuns;
- private final double mCalibrationTimeMs;
- private final Stats mTimeStats;
- private final Stats mMemoryStats;
-
- TimedStatementResult(int warmUpIterations, int runs,
- double calibrationTimeMs,
- Stats timeStats,
- Stats memoryStats) {
- mWarmUpIterations = warmUpIterations;
- mRuns = runs;
- mCalibrationTimeMs = calibrationTimeMs;
- mTimeStats = timeStats;
- mMemoryStats = memoryStats;
- }
-
- @Override
- public String toString() {
- return String.format(
- "Warm up %d. Runs %d\n" + "Time: %s ms (min: %s, max %s)\n" +
- "Calibration Time: %f ms\n" +
- "Calibrated Time: %s units (min: %s, max %s)\n" +
- "Sampled %d times\n" +
- " Memory used: %d bytes (max %d)\n\n",
- mWarmUpIterations, mRuns,
- mTimeStats.getMedian(), mTimeStats.getMin(), mTimeStats.getMax(),
- mCalibrationTimeMs,
- UNITS_FORMAT.format((mTimeStats.getMedian() / mCalibrationTimeMs) * 100000),
- UNITS_FORMAT.format((mTimeStats.getMin() / mCalibrationTimeMs) * 100000),
- UNITS_FORMAT.format((mTimeStats.getMax() / mCalibrationTimeMs) * 100000),
- mMemoryStats.getSampleCount(),
- (long)mMemoryStats.getMedian() - mMemoryStats.getMin(),
- mMemoryStats.getMax() - mMemoryStats.getMin());
- }
-}
+++ /dev/null
-#!/bin/sh
-
-# copies the navigation bar icons from system ui code to layoutlib.
-# to run, simply execute the script. (if not using bash, cd to the dir
-# containing this script and then run by ./update_nav_icons.sh)
-
-# Try to get the location of this script.
-if [ -n $BASH ]; then
- # see http://stackoverflow.com/a/246128/1546000
- MY_LOCATION=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
- cd $MY_LOCATION
-else
- # Let's assume script was run from the same dir.
- MY_LOCATION=$(pwd)
-fi
-
-# Check mac or linux to get sed argument to enable extended regex.
-case $(uname -s) in
- Darwin)
- EXT_REGEX="-E"
- ;;
- *)
- EXT_REGEX="-r"
- ;;
-esac
-
-
-FB="frameworks/base"
-# frameworks/base relative to current location
-FB=$(echo $MY_LOCATION | sed $EXT_REGEX -e "s,.*$FB[^/]*/,," -e "s,[^/]+,..,g")
-CURRENT_API=21 # update only if icons change from this api version.
-DENSITIES="ldpi mdpi hdpi xhdpi xxhdpi"
-ICONS="ic_sysbar_back.png ic_sysbar_home.png ic_sysbar_recent.png"
-BARS="./resources/bars/"
-
-for icon in $ICONS
-do
- for density in $DENSITIES
- do
- destination="$BARS/v$CURRENT_API/$density/"
- mkdir -p "$destination" # create if not present.
- cp -v "$FB/packages/SystemUI/res/drawable-$density/$icon" "$destination"
- done
-
- for density in $DENSITIES
- do
- destination="$BARS/v$CURRENT_API/ldrtl-$density/"
- mkdir -p "$destination"
- cp -v "$FB/packages/SystemUI/res/drawable-ldrtl-$density/$icon" "$destination"
- done
-done
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry excluding="mock_data/" kind="src" path="tests"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
- <classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilts/misc/common/asm/asm-4.0.jar" sourcepath="/ANDROID_PLAT_SRC/prebuilts/misc/common/asm/src.zip"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>layoutlib_create</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-Copy this in eclipse project as a .settings folder at the root.
-This ensure proper compilation compliance and warning/error levels.
\ No newline at end of file
+++ /dev/null
-eclipse.preferences.version=1
-org.eclipse.jdt.core.compiler.annotation.nonnull=com.android.annotations.NonNull
-org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=com.android.annotations.NonNullByDefault
-org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled
-org.eclipse.jdt.core.compiler.annotation.nullable=com.android.annotations.Nullable
-org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled
-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
-org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.6
-org.eclipse.jdt.core.compiler.debug.lineNumber=generate
-org.eclipse.jdt.core.compiler.debug.localVariable=generate
-org.eclipse.jdt.core.compiler.debug.sourceFile=generate
-org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
-org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
-org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
-org.eclipse.jdt.core.compiler.problem.deadCode=warning
-org.eclipse.jdt.core.compiler.problem.deprecation=warning
-org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
-org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
-org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
-org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
-org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
-org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
-org.eclipse.jdt.core.compiler.problem.fieldHiding=warning
-org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
-org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
-org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
-org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
-org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled
-org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
-org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
-org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
-org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning
-org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
-org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error
-org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
-org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
-org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
-org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
-org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
-org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
-org.eclipse.jdt.core.compiler.problem.nullReference=error
-org.eclipse.jdt.core.compiler.problem.nullSpecInsufficientInfo=warning
-org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
-org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
-org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
-org.eclipse.jdt.core.compiler.problem.potentialNullSpecViolation=error
-org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning
-org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
-org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
-org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
-org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
-org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
-org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
-org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
-org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
-org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
-org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled
-org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
-org.eclipse.jdt.core.compiler.problem.unclosedCloseable=error
-org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
-org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
-org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
-org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
-org.eclipse.jdt.core.compiler.problem.unusedImport=warning
-org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
-org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
-org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning
-org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
-org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
-org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
-org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
-org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
-org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.6
+++ /dev/null
-#
-# Copyright (C) 2008 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.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-
-LOCAL_JAR_MANIFEST := manifest.txt
-LOCAL_STATIC_JAVA_LIBRARIES := \
- asm-5.2
-
-LOCAL_MODULE := layoutlib_create
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-# Build all sub-directories
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
+++ /dev/null
-# Copyright (C) 2008 The Android Open Source Project
-
-
-- Description -
----------------
-
-Layoutlib_create generates a JAR library used by the Eclipse graphical layout editor to perform
-layout.
-
-
-- Usage -
----------
-
- ./layoutlib_create destination.jar path/to/android1.jar path/to/android2.jar
-
-
-- Design Overview -
--------------------
-
-Layoutlib_create uses a few jars from the framework containing the Java code used by Android as
-generated by the Android build, right before the classes are converted to a DEX format.
-
-These jars can't be used directly in Eclipse as:
-- they contains references to native code (which we want to avoid in Eclipse),
-- some classes need to be overridden, for example all the drawing code that is replaced by Java 2D
- calls in Eclipse.
-- some of the classes that need to be changed are final and/or we need access to their private
- internal state.
-
-Consequently this tool:
-- parses the input JAR,
-- modifies some of the classes directly using some bytecode manipulation,
-- filters some packages and removes those we don't want in the output JAR,
-- injects some new classes,
-- generates a modified JAR file that is suitable for the Android plugin for Eclipse to perform
- rendering.
-
-The ASM library is used to do the bytecode modification using its visitor pattern API.
-
-The layoutlib_create is *NOT* generic. There is no configuration file. Instead all the configuration
-is done in the main() method and the CreateInfo structure is expected to change with the Android
-platform as new classes are added, changed or removed. Some configuration that may be platform
-dependent is also present elsewhere in code.
-
-The resulting JAR is used by layoutlib_bridge (a.k.a. "the bridge"), also part of the platform, that
-provides all the necessary missing implementation for rendering graphics in Eclipse.
-
-
-
-- Implementation Notes -
-------------------------
-
-The tool works in two phases:
-- first analyze the input jar (AsmAnalyzer class)
-- then generate the output jar (AsmGenerator class),
-
-
-- Analyzer
-----------
-
-The goal of the analyzer is to create a graph of all the classes from the input JAR with their
-dependencies and then only keep the ones we want.
-
-To do that, the analyzer is created with a list of base classes to keep -- everything that derives
-from these is kept. Currently the one such class is android.view.View: since we want to render
-layouts, anything that is sort of a view needs to be kept.
-
-The analyzer is also given a list of class names to keep in the output. This is done using
-shell-like glob patterns that filter on the fully-qualified class names, for example "android.*.R**"
-("*" does not matches dots whilst "**" does, and "." and "$" are interpreted as-is). In practice we
-almost but not quite request the inclusion of full packages.
-
-The analyzer is also given a list of classes to exclude. A fake implementation of these classes is
-injected by the Generator.
-
-With this information, the analyzer parses the input zip to find all the classes. All classes
-deriving from the requested bases classes are kept. All classes whose name match the glob pattern
-are kept. The analysis then finds all the dependencies of the classes that are to be kept using an
-ASM visitor on the class, the field types, the method types and annotations types. Classes that
-belong to the current JRE are excluded.
-
-The output of the analyzer is a set of ASM ClassReader instances which are then fed to the
-generator.
-
-
-- Generator
------------
-
-The generator is constructed from a CreateInfo struct that acts as a config file and lists:
-- the classes to inject in the output JAR -- these classes are directly implemented in
- layoutlib_create and will be used to interface with the renderer in Eclipse.
-- specific methods to override (see method stubs details below).
-- specific methods for which to delegate calls.
-- specific methods to remove based on their return type.
-- specific classes to rename.
-- specific classes to refactor.
-
-Each of these are specific strategies we use to be able to modify the Android code to fit within the
-Eclipse renderer. These strategies are explained below.
-
-The core method of the generator is transform(): it takes an input ASM ClassReader and modifies it
-to produce a byte array suitable for the final JAR file.
-
-The first step of the transformation is to implement the method delegates.
-
-The TransformClassAdapter is then used to process the potentially renamed class. All protected or
-private classes are market as public. All classes are made non-final. Interfaces are left as-is.
-
-If a method has a return type that must be erased, the whole method is skipped. Methods are also
-changed from protected/private to public. The code of the methods is then kept as-is, except for
-native methods which are replaced by a stub. Methods that are to be overridden are also replaced by
-a stub.
-
-Finally fields are also visited and changed from protected/private to public.
-
-The next step of the transformation is changing the name of the class in case we requested the class
-to be renamed. This uses the RenameClassAdapter to also rename all inner classes and references in
-methods and types. Note that other classes are not transformed and keep referencing the original
-name.
-
-The class is then fed to RefactorClassAdapter which is like RenameClassAdapter but updates the
-references in all classes. This is used to update the references of classes in the java package that
-were added in the Dalvik VM but are not a part of the Desktop VM. The existing classes are
-modified to update all references to these non-desktop classes. An alternate implementation of
-these (com.android.tools.layoutlib.java.*) is injected.
-
-RenameClassAdapter and RefactorClassAdapter both inherit from AbstractClassAdapter which changes the
-class version (version of the JDK used to compile the class) to 50 (corresponding to Java 6), if the
-class was originally compiled with Java 7 (version 51). This is because we don't currently generate
-the StackMapTable correctly and Java 7 VM enforces that classes with version greater than 51 have
-valid StackMapTable. As a side benefit of this, we can continue to support Java 6 because Java 7 on
-Mac has horrible font rendering support.
-
-ReplaceMethodCallsAdapter replaces calls to certain methods. This is different from the
-DelegateMethodAdapter since it doesn't preserve the original copy of the method and more importantly
-changes the calls to a method in each class instead of changing the implementation of the method.
-This is useful for methods in the Java namespace where we cannot add delegates. The configuration
-for this is not done through the CreateInfo class, but done in the ReplaceMethodAdapter.
-
-The ClassAdapters are chained together to achieve the desired output. (Look at section 2.2.7
-Transformation chains in the asm user guide, link in the References.) The order of execution of
-these is:
-ClassReader -> [DelegateClassAdapter] -> TransformClassAdapter -> [RenameClassAdapter] ->
-RefactorClassAdapter -> [ReplaceMethodCallsAdapter] -> ClassWriter
-
-- Method stubs
---------------
-
-As indicated above, all native and overridden methods are replaced by a stub. We don't have the
-code to replace with in layoutlib_create. Instead the StubMethodAdapter replaces the code of the
-method by a call to OverrideMethod.invokeX(). When using the final JAR, the bridge can register
-listeners from these overridden method calls based on the method signatures.
-
-The listeners are currently pretty basic: we only pass the signature of the method being called, its
-caller object and a flag indicating whether the method was native. We do not currently provide the
-parameters. The listener can however specify the return value of the overridden method.
-
-This strategy is now obsolete and replaced by the method delegates.
-
-
-- Strategies
-------------
-
-We currently have 6 strategies to deal with overriding the rendering code and make it run in
-Eclipse. Most of these strategies are implemented hand-in-hand by the bridge (which runs in Eclipse)
-and the generator.
-
-
-1- Class Injection
-
-This is the easiest: we currently inject the following classes:
-- OverrideMethod and its associated MethodListener and MethodAdapter are used to intercept calls to
- some specific methods that are stubbed out and change their return value.
-- CreateInfo class, which configured the generator. Not used yet, but could in theory help us track
- what the generator changed.
-- AutoCloseable and Objects are part of Java 7. To enable us to still run on Java 6, new classes are
- injected. The implementation for these classes has been taken from Android's libcore
- (platform/libcore/luni/src/main/java/java/...).
-- Charsets, IntegralToString and UnsafeByteSequence are not part of the Desktop VM. They are
- added to the Dalvik VM for performance reasons. An implementation that is very close to the
- original (which is at platform/libcore/luni/src/main/java/...) is injected. Since these classees
- were in part of the java package, where we can't inject classes, all references to these have been
- updated (See strategy 4- Refactoring Classes).
-
-
-2- Overriding methods
-
-As explained earlier, the creator doesn't have any replacement code for methods to override. Instead
-it removes the original code and replaces it by a call to a specific OveriddeMethod.invokeX(). The
-bridge then registers a listener on the method signature and can provide an implementation.
-
-This strategy is now obsolete and replaced by the method delegates (See strategy 6- Method
-Delegates).
-
-
-3- Renaming classes
-
-This simply changes the name of a class in its definition, as well as all its references in internal
-inner classes and methods. Calls from other classes are not modified -- they keep referencing the
-original class name. This allows the bridge to literally replace an implementation.
-
-An example will make this easier: android.graphics.Paint is the main drawing class that we need to
-replace. To do so, the generator renames Paint to _original_Paint. Later the bridge provides its own
-replacement version of Paint which will be used by the rest of the Android stack. The replacement
-version of Paint can still use (either by inheritance or delegation) all the original non-native
-code of _original_Paint if it so desires.
-
-Some of the Android classes are basically wrappers over native objects and since we don't have the
-native code in Eclipse, we need to provide a full alternate implementation. Sub-classing doesn't
-work as some native methods are static and we don't control object creation.
-
-This won't rename/replace the inner static methods of a given class.
-
-
-4- Refactoring classes
-
-This is very similar to the Renaming classes except that it also updates the reference in all
-classes. This is done for classes which are added to the Dalvik VM for performance reasons but are
-not present in the Desktop VM. An implementation for these classes is also injected.
-
-
-5- Method erasure based on return type
-
-This is mostly an implementation detail of the bridge: in the Paint class mentioned above, some
-inner static classes are used to pass around attributes (e.g. FontMetrics, or the Style enum) and
-all the original implementation is native.
-
-In this case we have a strategy that tells the generator that anything returning, for example, the
-inner class Paint$Style in the Paint class should be discarded and the bridge will provide its own
-implementation.
-
-
-6- Method Delegates
-
-This strategy is used to override method implementations. Given a method SomeClass.MethodName(), 1
-or 2 methods are generated:
-a- A copy of the original method named SomeClass.MethodName_Original(). The content is the original
-method as-is from the reader. This step is omitted if the method is native, since it has no Java
-implementation.
-b- A brand new implementation of SomeClass.MethodName() which calls to a non-existing static method
-named SomeClass_Delegate.MethodName(). The implementation of this 'delegate' method is done in
-layoutlib_bridge.
-
-The delegate method is a static method. If the original method is non-static, the delegate method
-receives the original 'this' as its first argument. If the original method is an inner non-static
-method, it also receives the inner 'this' as the second argument.
-
-
-
-- References -
---------------
-
-
-The JVM Specification 2nd edition:
- http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html
-
-Understanding bytecode:
- http://www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/
-
-Bytecode opcode list:
- http://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
-
-ASM user guide:
- http://download.forge.objectweb.org/asm/asm4-guide.pdf
-
-
---
-end
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$">
- <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
- <sourceFolder url="file://$MODULE_DIR$/tests/data" type="java-test-resource" />
- <sourceFolder url="file://$MODULE_DIR$/tests/mock_data" type="java-test-resource" />
- <excludeFolder url="file://$MODULE_DIR$/.settings" />
- </content>
- <orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="module-library">
- <library name="asm-5.2">
- <CLASSES>
- <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/asm/asm-5.2.jar!/" />
- </CLASSES>
- <JAVADOC />
- <SOURCES>
- <root url="jar://$MODULE_DIR$/../../../../../prebuilts/misc/common/asm/src.zip!/" />
- </SOURCES>
- </library>
- </orderEntry>
- <orderEntry type="library" scope="TEST" name="junit" level="project" />
- </component>
-</module>
\ No newline at end of file
+++ /dev/null
-Main-Class: com.android.tools.layoutlib.create.Main
+++ /dev/null
-/*
- * Copyright (C) 2010 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.annotations;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Denotes a method that has been converted to a delegate by layoutlib_create.
- */
-@Retention(RetentionPolicy.RUNTIME)
-public @interface LayoutlibDelegate {
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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.annotations;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Denotes a parameter or field can be null.
- * <p/>
- * When decorating a method call parameter, this denotes the parameter can
- * legitimately be null and the method will gracefully deal with it. Typically used
- * on optional parameters.
- * <p/>
- * When decorating a method, this denotes the method might legitimately return null.
- * <p/>
- * This is a marker annotation and it has no specific attributes.
- */
-@Retention(RetentionPolicy.SOURCE)
-public @interface Nullable {
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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.annotations;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Denotes that the class, method or field has its visibility relaxed so
- * that unit tests can access it.
- * <p/>
- * The <code>visibility</code> argument can be used to specific what the original
- * visibility should have been if it had not been made public or package-private for testing.
- * The default is to consider the element private.
- */
-@Retention(RetentionPolicy.SOURCE)
-public @interface VisibleForTesting {
- /**
- * Intended visibility if the element had not been made public or package-private for
- * testing.
- */
- enum Visibility {
- /** The element should be considered protected. */
- PROTECTED,
- /** The element should be considered package-private. */
- PACKAGE,
- /** The element should be considered private. */
- PRIVATE
- }
-
- /**
- * Intended visibility if the element had not been made public or package-private for testing.
- * If not specified, one should assume the element originally intended to be private.
- */
- Visibility visibility() default Visibility.PRIVATE;
-}
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.create;
-
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.signature.SignatureReader;
-import org.objectweb.asm.signature.SignatureVisitor;
-import org.objectweb.asm.signature.SignatureWriter;
-
-/**
- * Provides the common code for RenameClassAdapter and RefactorClassAdapter. It
- * goes through the complete class and finds references to other classes. It
- * then calls {@link #renameInternalType(String)} to convert the className to
- * the new value, if need be.
- */
-public abstract class AbstractClassAdapter extends ClassVisitor {
-
- /**
- * Returns the new FQCN for the class, if the reference to this class needs
- * to be updated. Else, it returns the same string.
- * @param name Old FQCN
- * @return New FQCN if it needs to be renamed, else the old FQCN
- */
- abstract String renameInternalType(String name);
-
- public AbstractClassAdapter(ClassVisitor cv) {
- super(Main.ASM_VERSION, cv);
- }
-
- /**
- * Renames a type descriptor, e.g. "Lcom.package.MyClass;"
- * If the type doesn't need to be renamed, returns the input string as-is.
- */
- String renameTypeDesc(String desc) {
- if (desc == null) {
- return null;
- }
-
- return renameType(Type.getType(desc));
- }
-
- /**
- * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an
- * object element, e.g. "[Lcom.package.MyClass;"
- * If the type doesn't need to be renamed, returns the internal name of the input type.
- */
- String renameType(Type type) {
- if (type == null) {
- return null;
- }
-
- if (type.getSort() == Type.OBJECT) {
- String in = type.getInternalName();
- return "L" + renameInternalType(in) + ";";
- } else if (type.getSort() == Type.ARRAY) {
- StringBuilder sb = new StringBuilder();
- for (int n = type.getDimensions(); n > 0; n--) {
- sb.append('[');
- }
- sb.append(renameType(type.getElementType()));
- return sb.toString();
- }
- return type.getDescriptor();
- }
-
- /**
- * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an
- * object element, e.g. "[Lcom.package.MyClass;".
- * This is like renameType() except that it returns a Type object.
- * If the type doesn't need to be renamed, returns the input type object.
- */
- Type renameTypeAsType(Type type) {
- if (type == null) {
- return null;
- }
-
- if (type.getSort() == Type.OBJECT) {
- String in = type.getInternalName();
- String newIn = renameInternalType(in);
- if (!newIn.equals(in)) {
- return Type.getType("L" + newIn + ";");
- }
- } else if (type.getSort() == Type.ARRAY) {
- StringBuilder sb = new StringBuilder();
- for (int n = type.getDimensions(); n > 0; n--) {
- sb.append('[');
- }
- sb.append(renameType(type.getElementType()));
- return Type.getType(sb.toString());
- }
- return type;
- }
-
- /**
- * Renames a method descriptor, i.e. applies renameType to all arguments and to the
- * return value.
- */
- String renameMethodDesc(String desc) {
- if (desc == null) {
- return null;
- }
-
- Type[] args = Type.getArgumentTypes(desc);
-
- StringBuilder sb = new StringBuilder("(");
- for (Type arg : args) {
- String name = renameType(arg);
- sb.append(name);
- }
- sb.append(')');
-
- Type ret = Type.getReturnType(desc);
- String name = renameType(ret);
- sb.append(name);
-
- return sb.toString();
- }
-
-
- /**
- * Renames the ClassSignature handled by ClassVisitor.visit
- * or the MethodTypeSignature handled by ClassVisitor.visitMethod.
- */
- String renameTypeSignature(String sig) {
- if (sig == null) {
- return null;
- }
- SignatureReader reader = new SignatureReader(sig);
- SignatureWriter writer = new SignatureWriter();
- reader.accept(new RenameSignatureAdapter(writer));
- sig = writer.toString();
- return sig;
- }
-
-
- /**
- * Renames the FieldTypeSignature handled by ClassVisitor.visitField
- * or MethodVisitor.visitLocalVariable.
- */
- String renameFieldSignature(String sig) {
- return renameTypeSignature(sig);
- }
-
-
- //----------------------------------
- // Methods from the ClassAdapter
-
- @Override
- public void visit(int version, int access, String name, String signature,
- String superName, String[] interfaces) {
- name = renameInternalType(name);
- superName = renameInternalType(superName);
- signature = renameTypeSignature(signature);
- if (interfaces != null) {
- for (int i = 0; i < interfaces.length; ++i) {
- interfaces[i] = renameInternalType(interfaces[i]);
- }
- }
-
- super.visit(version, access, name, signature, superName, interfaces);
- }
-
- @Override
- public void visitInnerClass(String name, String outerName, String innerName, int access) {
- name = renameInternalType(name);
- outerName = renameInternalType(outerName);
- super.visitInnerClass(name, outerName, innerName, access);
- }
-
- @Override
- public void visitOuterClass(String owner, String name, String desc) {
- super.visitOuterClass(renameInternalType(owner), name, renameTypeDesc(desc));
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- desc = renameMethodDesc(desc);
- signature = renameTypeSignature(signature);
- MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
- return new RenameMethodAdapter(mw);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- desc = renameTypeDesc(desc);
- return super.visitAnnotation(desc, visible);
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc,
- String signature, Object value) {
- desc = renameTypeDesc(desc);
- return super.visitField(access, name, desc, signature, value);
- }
-
-
- //----------------------------------
-
- /**
- * A method visitor that renames all references from an old class name to a new class name.
- */
- public class RenameMethodAdapter extends MethodVisitor {
-
- /**
- * Creates a method visitor that renames all references from a given old name to a given new
- * name. The method visitor will also rename all inner classes.
- * The names must be full qualified internal ASM names (e.g. com/blah/MyClass$InnerClass).
- */
- public RenameMethodAdapter(MethodVisitor mv) {
- super(Main.ASM_VERSION, mv);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- desc = renameTypeDesc(desc);
-
- return super.visitAnnotation(desc, visible);
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
- desc = renameTypeDesc(desc);
-
- return super.visitParameterAnnotation(parameter, desc, visible);
- }
-
- @Override
- public void visitTypeInsn(int opcode, String type) {
- // The type sometimes turns out to be a type descriptor. We try to detect it and fix.
- if (type.indexOf(';') > 0) {
- type = renameTypeDesc(type);
- } else {
- type = renameInternalType(type);
- }
- super.visitTypeInsn(opcode, type);
- }
-
- @Override
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- owner = renameInternalType(owner);
- desc = renameTypeDesc(desc);
-
- super.visitFieldInsn(opcode, owner, name, desc);
- }
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc,
- boolean itf) {
- // The owner sometimes turns out to be a type descriptor. We try to detect it and fix.
- if (owner.indexOf(';') > 0) {
- owner = renameTypeDesc(owner);
- } else {
- owner = renameInternalType(owner);
- }
- desc = renameMethodDesc(desc);
-
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- }
-
- @Override
- public void visitLdcInsn(Object cst) {
- // If cst is a Type, this means the code is trying to pull the .class constant
- // for this class, so it needs to be renamed too.
- if (cst instanceof Type) {
- cst = renameTypeAsType((Type) cst);
- }
- super.visitLdcInsn(cst);
- }
-
- @Override
- public void visitMultiANewArrayInsn(String desc, int dims) {
- desc = renameTypeDesc(desc);
-
- super.visitMultiANewArrayInsn(desc, dims);
- }
-
- @Override
- public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
- type = renameInternalType(type);
-
- super.visitTryCatchBlock(start, end, handler, type);
- }
-
- @Override
- public void visitLocalVariable(String name, String desc, String signature,
- Label start, Label end, int index) {
- desc = renameTypeDesc(desc);
- signature = renameFieldSignature(signature);
-
- super.visitLocalVariable(name, desc, signature, start, end, index);
- }
-
- }
-
- //----------------------------------
-
- public class RenameSignatureAdapter extends SignatureVisitor {
-
- private final SignatureVisitor mSv;
-
- public RenameSignatureAdapter(SignatureVisitor sv) {
- super(Main.ASM_VERSION);
- mSv = sv;
- }
-
- @Override
- public void visitClassType(String name) {
- name = renameInternalType(name);
- mSv.visitClassType(name);
- }
-
- @Override
- public void visitInnerClassType(String name) {
- name = renameInternalType(name);
- mSv.visitInnerClassType(name);
- }
-
- @Override
- public SignatureVisitor visitArrayType() {
- SignatureVisitor sv = mSv.visitArrayType();
- return new RenameSignatureAdapter(sv);
- }
-
- @Override
- public void visitBaseType(char descriptor) {
- mSv.visitBaseType(descriptor);
- }
-
- @Override
- public SignatureVisitor visitClassBound() {
- SignatureVisitor sv = mSv.visitClassBound();
- return new RenameSignatureAdapter(sv);
- }
-
- @Override
- public void visitEnd() {
- mSv.visitEnd();
- }
-
- @Override
- public SignatureVisitor visitExceptionType() {
- SignatureVisitor sv = mSv.visitExceptionType();
- return new RenameSignatureAdapter(sv);
- }
-
- @Override
- public void visitFormalTypeParameter(String name) {
- mSv.visitFormalTypeParameter(name);
- }
-
- @Override
- public SignatureVisitor visitInterface() {
- SignatureVisitor sv = mSv.visitInterface();
- return new RenameSignatureAdapter(sv);
- }
-
- @Override
- public SignatureVisitor visitInterfaceBound() {
- SignatureVisitor sv = mSv.visitInterfaceBound();
- return new RenameSignatureAdapter(sv);
- }
-
- @Override
- public SignatureVisitor visitParameterType() {
- SignatureVisitor sv = mSv.visitParameterType();
- return new RenameSignatureAdapter(sv);
- }
-
- @Override
- public SignatureVisitor visitReturnType() {
- SignatureVisitor sv = mSv.visitReturnType();
- return new RenameSignatureAdapter(sv);
- }
-
- @Override
- public SignatureVisitor visitSuperclass() {
- SignatureVisitor sv = mSv.visitSuperclass();
- return new RenameSignatureAdapter(sv);
- }
-
- @Override
- public void visitTypeArgument() {
- mSv.visitTypeArgument();
- }
-
- @Override
- public SignatureVisitor visitTypeArgument(char wildcard) {
- SignatureVisitor sv = mSv.visitTypeArgument(wildcard);
- return new RenameSignatureAdapter(sv);
- }
-
- @Override
- public void visitTypeVariable(String name) {
- mSv.visitTypeVariable(name);
- }
-
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.signature.SignatureReader;
-import org.objectweb.asm.signature.SignatureVisitor;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.regex.Pattern;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-/**
- * Analyzes the input JAR using the ASM java bytecode manipulation library
- * to list the desired classes and their dependencies.
- */
-public class AsmAnalyzer {
-
- // Note: a bunch of stuff has package-level access for unit tests. Consider it private.
-
- /** Output logger. */
- private final Log mLog;
- /** The input source JAR to parse. */
- private final List<String> mOsSourceJar;
- /** The generator to fill with the class list and dependency list. */
- private final AsmGenerator mGen;
- /** Keep all classes that derive from these one (these included). */
- private final String[] mDeriveFrom;
- /** Glob patterns of classes to keep, e.g. "com.foo.*" */
- private final String[] mIncludeGlobs;
- /** The set of classes to exclude.*/
- private final Set<String> mExcludedClasses;
- /** Glob patterns of files to keep as is. */
- private final String[] mIncludeFileGlobs;
- /** Internal names of classes that contain method calls that need to be rewritten. */
- private final Set<String> mReplaceMethodCallClasses = new HashSet<>();
-
- /**
- * Creates a new analyzer.
- *
- * @param log The log output.
- * @param osJarPath The input source JARs to parse.
- * @param gen The generator to fill with the class list and dependency list.
- * @param deriveFrom Keep all classes that derive from these one (these included).
- * @param includeGlobs Glob patterns of classes to keep, e.g. "com.foo.*"
- * ("*" does not matches dots whilst "**" does, "." and "$" are interpreted as-is)
- * @param includeFileGlobs Glob patterns of files which are kept as is. This is only for files
- * not ending in .class.
- */
- public AsmAnalyzer(Log log, List<String> osJarPath, AsmGenerator gen,
- String[] deriveFrom, String[] includeGlobs, Set<String> excludeClasses,
- String[] includeFileGlobs) {
- mLog = log;
- mGen = gen;
- mOsSourceJar = osJarPath != null ? osJarPath : new ArrayList<String>();
- mDeriveFrom = deriveFrom != null ? deriveFrom : new String[0];
- mIncludeGlobs = includeGlobs != null ? includeGlobs : new String[0];
- mExcludedClasses = excludeClasses;
- mIncludeFileGlobs = includeFileGlobs != null ? includeFileGlobs : new String[0];
- }
-
- /**
- * Starts the analysis using parameters from the constructor.
- * Fills the generator with classes & dependencies found.
- */
- public void analyze() throws IOException, LogAbortException {
-
- TreeMap<String, ClassReader> zipClasses = new TreeMap<>();
- Map<String, InputStream> filesFound = new TreeMap<>();
-
- parseZip(mOsSourceJar, zipClasses, filesFound);
- mLog.info("Found %d classes in input JAR%s.", zipClasses.size(),
- mOsSourceJar.size() > 1 ? "s" : "");
-
- Map<String, ClassReader> found = findIncludes(zipClasses);
- Map<String, ClassReader> deps = findDeps(zipClasses, found);
-
- if (mGen != null) {
- mGen.setKeep(found);
- mGen.setDeps(deps);
- mGen.setCopyFiles(filesFound);
- mGen.setRewriteMethodCallClasses(mReplaceMethodCallClasses);
- }
- }
-
- /**
- * Parses a JAR file and adds all the classes found to <code>classes</code>
- * and all other files to <code>filesFound</code>.
- *
- * @param classes The map of class name => ASM ClassReader. Class names are
- * in the form "android.view.View".
- * @param filesFound The map of file name => InputStream. The file name is
- * in the form "android/data/dataFile".
- */
- void parseZip(List<String> jarPathList, Map<String, ClassReader> classes,
- Map<String, InputStream> filesFound) throws IOException {
- if (classes == null || filesFound == null) {
- return;
- }
-
- Pattern[] includeFilePatterns = new Pattern[mIncludeFileGlobs.length];
- for (int i = 0; i < mIncludeFileGlobs.length; ++i) {
- includeFilePatterns[i] = getPatternFromGlob(mIncludeFileGlobs[i]);
- }
-
- for (String jarPath : jarPathList) {
- ZipFile zip = new ZipFile(jarPath);
- Enumeration<? extends ZipEntry> entries = zip.entries();
- ZipEntry entry;
- while (entries.hasMoreElements()) {
- entry = entries.nextElement();
- if (entry.getName().endsWith(".class")) {
- ClassReader cr = new ClassReader(zip.getInputStream(entry));
- String className = classReaderToClassName(cr);
- classes.put(className, cr);
- } else {
- for (Pattern includeFilePattern : includeFilePatterns) {
- if (includeFilePattern.matcher(entry.getName()).matches()) {
- filesFound.put(entry.getName(), zip.getInputStream(entry));
- break;
- }
- }
- }
- }
- }
-
- }
-
- /**
- * Utility that returns the fully qualified binary class name for a ClassReader.
- * E.g. it returns something like android.view.View.
- */
- static String classReaderToClassName(ClassReader classReader) {
- if (classReader == null) {
- return null;
- } else {
- return classReader.getClassName().replace('/', '.');
- }
- }
-
- /**
- * Utility that returns the fully qualified binary class name from a path-like FQCN.
- * E.g. it returns android.view.View from android/view/View.
- */
- static String internalToBinaryClassName(String className) {
- if (className == null) {
- return null;
- } else {
- return className.replace('/', '.');
- }
- }
-
- /**
- * Process the "includes" arrays.
- * <p/>
- * This updates the in_out_found map.
- */
- Map<String, ClassReader> findIncludes(Map<String, ClassReader> zipClasses)
- throws LogAbortException {
- TreeMap<String, ClassReader> found = new TreeMap<>();
-
- mLog.debug("Find classes to include.");
-
- for (String s : mIncludeGlobs) {
- findGlobs(s, zipClasses, found);
- }
- for (String s : mDeriveFrom) {
- findClassesDerivingFrom(s, zipClasses, found);
- }
-
- return found;
- }
-
-
- /**
- * Uses ASM to find the class reader for the given FQCN class name.
- * If found, insert it in the in_out_found map.
- * Returns the class reader object.
- */
- ClassReader findClass(String className, Map<String, ClassReader> zipClasses,
- Map<String, ClassReader> inOutFound) throws LogAbortException {
- ClassReader classReader = zipClasses.get(className);
- if (classReader == null) {
- throw new LogAbortException("Class %s not found by ASM in %s",
- className, mOsSourceJar);
- }
-
- inOutFound.put(className, classReader);
- return classReader;
- }
-
- /**
- * Insert in the inOutFound map all classes found in zipClasses that match the
- * given glob pattern.
- * <p/>
- * The glob pattern is not a regexp. It only accepts the "*" keyword to mean
- * "anything but a period". The "." and "$" characters match themselves.
- * The "**" keyword means everything including ".".
- * <p/>
- * Examples:
- * <ul>
- * <li>com.foo.* matches all classes in the package com.foo but NOT sub-packages.
- * <li>com.foo*.*$Event matches all internal Event classes in a com.foo*.* class.
- * </ul>
- */
- void findGlobs(String globPattern, Map<String, ClassReader> zipClasses,
- Map<String, ClassReader> inOutFound) throws LogAbortException {
-
- Pattern regexp = getPatternFromGlob(globPattern);
-
- for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
- String class_name = entry.getKey();
- if (regexp.matcher(class_name).matches() &&
- !mExcludedClasses.contains(getOuterClassName(class_name))) {
- findClass(class_name, zipClasses, inOutFound);
- }
- }
- }
-
- Pattern getPatternFromGlob(String globPattern) {
- // transforms the glob pattern in a regexp:
- // - escape "." with "\."
- // - replace "*" by "[^.]*"
- // - escape "$" with "\$"
- // - add end-of-line match $
- globPattern = globPattern.replaceAll("\\$", "\\\\\\$");
- globPattern = globPattern.replaceAll("\\.", "\\\\.");
- // prevent ** from being altered by the next rule, then process the * rule and finally
- // the real ** rule (which is now @)
- globPattern = globPattern.replaceAll("\\*\\*", "@");
- globPattern = globPattern.replaceAll("\\*", "[^.]*");
- globPattern = globPattern.replaceAll("@", ".*");
- globPattern += "$";
-
- return Pattern.compile(globPattern);
- }
-
- /**
- * Checks all the classes defined in the JarClassName instance and uses BCEL to
- * determine if they are derived from the given FQCN super class name.
- * Inserts the super class and all the class objects found in the map.
- */
- void findClassesDerivingFrom(String super_name, Map<String, ClassReader> zipClasses,
- Map<String, ClassReader> inOutFound) throws LogAbortException {
- if (mExcludedClasses.contains(getOuterClassName(super_name))) {
- return;
- }
- findClass(super_name, zipClasses, inOutFound);
-
- for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
- String className = entry.getKey();
- if (super_name.equals(className)) {
- continue;
- }
- ClassReader classReader = entry.getValue();
- ClassReader parent_cr = classReader;
- while (parent_cr != null) {
- String parent_name = internalToBinaryClassName(parent_cr.getSuperName());
- if (parent_name == null) {
- // not found
- break;
- } else if (super_name.equals(parent_name)) {
- inOutFound.put(className, classReader);
- break;
- }
- parent_cr = zipClasses.get(parent_name);
- }
- }
- }
-
- /**
- * Instantiates a new DependencyVisitor. Useful for unit tests.
- */
- DependencyVisitor getVisitor(Map<String, ClassReader> zipClasses,
- Map<String, ClassReader> inKeep,
- Map<String, ClassReader> outKeep,
- Map<String, ClassReader> inDeps,
- Map<String, ClassReader> outDeps) {
- return new DependencyVisitor(zipClasses, inKeep, outKeep, inDeps, outDeps);
- }
-
- /**
- * Finds all dependencies for all classes in keepClasses which are also
- * listed in zipClasses. Returns a map of all the dependencies found.
- */
- Map<String, ClassReader> findDeps(Map<String, ClassReader> zipClasses,
- Map<String, ClassReader> inOutKeepClasses) {
-
- TreeMap<String, ClassReader> deps = new TreeMap<>();
- TreeMap<String, ClassReader> new_deps = new TreeMap<>();
- TreeMap<String, ClassReader> new_keep = new TreeMap<>();
- TreeMap<String, ClassReader> temp = new TreeMap<>();
-
- DependencyVisitor visitor = getVisitor(zipClasses,
- inOutKeepClasses, new_keep,
- deps, new_deps);
-
- for (ClassReader cr : inOutKeepClasses.values()) {
- visitor.setClassName(cr.getClassName());
- cr.accept(visitor, 0 /* flags */);
- }
-
- while (new_deps.size() > 0 || new_keep.size() > 0) {
- deps.putAll(new_deps);
- inOutKeepClasses.putAll(new_keep);
-
- temp.clear();
- temp.putAll(new_deps);
- temp.putAll(new_keep);
- new_deps.clear();
- new_keep.clear();
- mLog.debug("Found %1$d to keep, %2$d dependencies.",
- inOutKeepClasses.size(), deps.size());
-
- for (ClassReader cr : temp.values()) {
- visitor.setClassName(cr.getClassName());
- cr.accept(visitor, 0 /* flags */);
- }
- }
-
- mLog.info("Found %1$d classes to keep, %2$d class dependencies.",
- inOutKeepClasses.size(), deps.size());
-
- return deps;
- }
-
- private String getOuterClassName(String className) {
- int pos = className.indexOf('$');
- if (pos > 0) {
- return className.substring(0, pos);
- }
- return className;
- }
-
- // ----------------------------------
-
- /**
- * Visitor to collect all the type dependencies from a class.
- */
- public class DependencyVisitor extends ClassVisitor {
-
- /** All classes found in the source JAR. */
- private final Map<String, ClassReader> mZipClasses;
- /** Classes from which dependencies are to be found. */
- private final Map<String, ClassReader> mInKeep;
- /** Dependencies already known. */
- private final Map<String, ClassReader> mInDeps;
- /** New dependencies found by this visitor. */
- private final Map<String, ClassReader> mOutDeps;
- /** New classes to keep as-is found by this visitor. */
- private final Map<String, ClassReader> mOutKeep;
-
- private String mClassName;
-
- /**
- * Creates a new visitor that will find all the dependencies for the visited class.
- * Types which are already in the zipClasses, keepClasses or inDeps are not marked.
- * New dependencies are marked in outDeps.
- *
- * @param zipClasses All classes found in the source JAR.
- * @param inKeep Classes from which dependencies are to be found.
- * @param inDeps Dependencies already known.
- * @param outDeps New dependencies found by this visitor.
- */
- public DependencyVisitor(Map<String, ClassReader> zipClasses,
- Map<String, ClassReader> inKeep,
- Map<String, ClassReader> outKeep,
- Map<String,ClassReader> inDeps,
- Map<String,ClassReader> outDeps) {
- super(Main.ASM_VERSION);
- mZipClasses = zipClasses;
- mInKeep = inKeep;
- mOutKeep = outKeep;
- mInDeps = inDeps;
- mOutDeps = outDeps;
- }
-
- private void setClassName(String className) {
- mClassName = className;
- }
-
- /**
- * Considers the given class name as a dependency.
- * If it does, add to the mOutDeps map.
- */
- public void considerName(String className) {
- if (className == null) {
- return;
- }
-
- className = internalToBinaryClassName(className);
-
- // exclude classes that have already been found or are marked to be excluded
- if (mInKeep.containsKey(className) ||
- mOutKeep.containsKey(className) ||
- mInDeps.containsKey(className) ||
- mOutDeps.containsKey(className) ||
- mExcludedClasses.contains(getOuterClassName(className))) {
- return;
- }
-
- // exclude classes that are not part of the JAR file being examined
- ClassReader cr = mZipClasses.get(className);
- if (cr == null) {
- return;
- }
-
- try {
- // exclude classes that are part of the default JRE (the one executing this program)
- if (className.startsWith("java.") ||
- getClass().getClassLoader().loadClass(className) != null) {
- return;
- }
- } catch (ClassNotFoundException e) {
- // ignore
- }
-
- // accept this class:
- // - android classes are added to dependencies
- // - non-android classes are added to the list of classes to keep as-is (they don't need
- // to be stubbed).
- if (className.contains("android")) { // TODO make configurable
- mOutDeps.put(className, cr);
- } else {
- mOutKeep.put(className, cr);
- }
- }
-
- /**
- * Considers this array of names using considerName().
- */
- public void considerNames(String[] classNames) {
- if (classNames != null) {
- for (String className : classNames) {
- considerName(className);
- }
- }
- }
-
- /**
- * Considers this signature or type signature by invoking the {@link SignatureVisitor}
- * on it.
- */
- public void considerSignature(String signature) {
- if (signature != null) {
- SignatureReader sr = new SignatureReader(signature);
- // SignatureReader.accept will call accessType so we don't really have
- // to differentiate where the signature comes from.
- sr.accept(new MySignatureVisitor());
- }
- }
-
- /**
- * Considers this {@link Type}. For arrays, the element type is considered.
- * If the type is an object, it's internal name is considered.
- */
- public void considerType(Type t) {
- if (t != null) {
- if (t.getSort() == Type.ARRAY) {
- t = t.getElementType();
- }
- if (t.getSort() == Type.OBJECT) {
- considerName(t.getInternalName());
- }
- }
- }
-
- /**
- * Considers a descriptor string. The descriptor is converted to a {@link Type}
- * and then considerType() is invoked.
- */
- public void considerDesc(String desc) {
- if (desc != null) {
- try {
- Type t = Type.getType(desc);
- considerType(t);
- } catch (ArrayIndexOutOfBoundsException e) {
- // ignore, not a valid type.
- }
- }
- }
-
- // ---------------------------------------------------
- // --- ClassVisitor, FieldVisitor
- // ---------------------------------------------------
-
- // Visits a class header
- @Override
- public void visit(int version, int access, String name,
- String signature, String superName, String[] interfaces) {
- // signature is the signature of this class. May be null if the class is not a generic
- // one, and does not extend or implement generic classes or interfaces.
-
- if (signature != null) {
- considerSignature(signature);
- }
-
- // superName is the internal of name of the super class (see getInternalName).
- // For interfaces, the super class is Object. May be null but only for the Object class.
- considerName(superName);
-
- // interfaces is the internal names of the class's interfaces (see getInternalName).
- // May be null.
- considerNames(interfaces);
- }
-
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- // desc is the class descriptor of the annotation class.
- considerDesc(desc);
- return new MyAnnotationVisitor();
- }
-
- @Override
- public void visitAttribute(Attribute attr) {
- // pass
- }
-
- // Visits the end of a class
- @Override
- public void visitEnd() {
- // pass
- }
-
- private class MyFieldVisitor extends FieldVisitor {
-
- public MyFieldVisitor() {
- super(Main.ASM_VERSION);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- // desc is the class descriptor of the annotation class.
- considerDesc(desc);
- return new MyAnnotationVisitor();
- }
-
- @Override
- public void visitAttribute(Attribute attr) {
- // pass
- }
-
- // Visits the end of a class
- @Override
- public void visitEnd() {
- // pass
- }
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc,
- String signature, Object value) {
- // desc is the field's descriptor (see Type).
- considerDesc(desc);
-
- // signature is the field's signature. May be null if the field's type does not use
- // generic types.
- considerSignature(signature);
-
- return new MyFieldVisitor();
- }
-
- @Override
- public void visitInnerClass(String name, String outerName, String innerName, int access) {
- // name is the internal name of an inner class (see getInternalName).
- considerName(name);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- // desc is the method's descriptor (see Type).
- considerDesc(desc);
- // signature is the method's signature. May be null if the method parameters, return
- // type and exceptions do not use generic types.
- considerSignature(signature);
-
- return new MyMethodVisitor(mClassName);
- }
-
- @Override
- public void visitOuterClass(String owner, String name, String desc) {
- // pass
- }
-
- @Override
- public void visitSource(String source, String debug) {
- // pass
- }
-
-
- // ---------------------------------------------------
- // --- MethodVisitor
- // ---------------------------------------------------
-
- private class MyMethodVisitor extends MethodVisitor {
-
- private String mOwnerClass;
-
- public MyMethodVisitor(String ownerClass) {
- super(Main.ASM_VERSION);
- mOwnerClass = ownerClass;
- }
-
-
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- return new MyAnnotationVisitor();
- }
-
- @Override
- public void visitCode() {
- // pass
- }
-
- // field instruction
- @Override
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- // owner is the class that declares the field.
- considerName(owner);
- // desc is the field's descriptor (see Type).
- considerDesc(desc);
- }
-
- @Override
- public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) {
- // pass
- }
-
- @Override
- public void visitIincInsn(int var, int increment) {
- // pass -- an IINC instruction
- }
-
- @Override
- public void visitInsn(int opcode) {
- // pass -- a zero operand instruction
- }
-
- @Override
- public void visitIntInsn(int opcode, int operand) {
- // pass -- a single int operand instruction
- }
-
- @Override
- public void visitJumpInsn(int opcode, Label label) {
- // pass -- a jump instruction
- }
-
- @Override
- public void visitLabel(Label label) {
- // pass -- a label target
- }
-
- // instruction to load a constant from the stack
- @Override
- public void visitLdcInsn(Object cst) {
- if (cst instanceof Type) {
- considerType((Type) cst);
- }
- }
-
- @Override
- public void visitLineNumber(int line, Label start) {
- // pass
- }
-
- @Override
- public void visitLocalVariable(String name, String desc,
- String signature, Label start, Label end, int index) {
- // desc is the type descriptor of this local variable.
- considerDesc(desc);
- // signature is the type signature of this local variable. May be null if the local
- // variable type does not use generic types.
- considerSignature(signature);
- }
-
- @Override
- public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
- // pass -- a lookup switch instruction
- }
-
- @Override
- public void visitMaxs(int maxStack, int maxLocals) {
- // pass
- }
-
- // instruction that invokes a method
- @Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc,
- boolean itf) {
-
- // owner is the internal name of the method's owner class
- considerName(owner);
- // desc is the method's descriptor (see Type).
- considerDesc(desc);
-
-
- // Check if method needs to replaced by a call to a different method.
- if (ReplaceMethodCallsAdapter.isReplacementNeeded(owner, name, desc, mOwnerClass)) {
- mReplaceMethodCallClasses.add(mOwnerClass);
- }
- }
-
- // instruction multianewarray, whatever that is
- @Override
- public void visitMultiANewArrayInsn(String desc, int dims) {
-
- // desc an array type descriptor.
- considerDesc(desc);
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
- boolean visible) {
- // desc is the class descriptor of the annotation class.
- considerDesc(desc);
- return new MyAnnotationVisitor();
- }
-
- @Override
- public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
- // pass -- table switch instruction
-
- }
-
- @Override
- public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
- // type is the internal name of the type of exceptions handled by the handler,
- // or null to catch any exceptions (for "finally" blocks).
- considerName(type);
- }
-
- // type instruction
- @Override
- public void visitTypeInsn(int opcode, String type) {
- // type is the operand of the instruction to be visited. This operand must be the
- // internal name of an object or array class.
- considerName(type);
- }
-
- @Override
- public void visitVarInsn(int opcode, int var) {
- // pass -- local variable instruction
- }
- }
-
- private class MySignatureVisitor extends SignatureVisitor {
-
- public MySignatureVisitor() {
- super(Main.ASM_VERSION);
- }
-
- // ---------------------------------------------------
- // --- SignatureVisitor
- // ---------------------------------------------------
-
- private String mCurrentSignatureClass = null;
-
- // Starts the visit of a signature corresponding to a class or interface type
- @Override
- public void visitClassType(String name) {
- mCurrentSignatureClass = name;
- considerName(name);
- }
-
- // Visits an inner class
- @Override
- public void visitInnerClassType(String name) {
- if (mCurrentSignatureClass != null) {
- mCurrentSignatureClass += "$" + name;
- considerName(mCurrentSignatureClass);
- }
- }
-
- @Override
- public SignatureVisitor visitArrayType() {
- return new MySignatureVisitor();
- }
-
- @Override
- public void visitBaseType(char descriptor) {
- // pass -- a primitive type, ignored
- }
-
- @Override
- public SignatureVisitor visitClassBound() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitExceptionType() {
- return new MySignatureVisitor();
- }
-
- @Override
- public void visitFormalTypeParameter(String name) {
- // pass
- }
-
- @Override
- public SignatureVisitor visitInterface() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitInterfaceBound() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitParameterType() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitReturnType() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitSuperclass() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitTypeArgument(char wildcard) {
- return new MySignatureVisitor();
- }
-
- @Override
- public void visitTypeVariable(String name) {
- // pass
- }
-
- @Override
- public void visitTypeArgument() {
- // pass
- }
- }
-
-
- // ---------------------------------------------------
- // --- AnnotationVisitor
- // ---------------------------------------------------
-
- private class MyAnnotationVisitor extends AnnotationVisitor {
-
- public MyAnnotationVisitor() {
- super(Main.ASM_VERSION);
- }
-
- // Visits a primitive value of an annotation
- @Override
- public void visit(String name, Object value) {
- // value is the actual value, whose type must be Byte, Boolean, Character, Short,
- // Integer, Long, Float, Double, String or Type
- if (value instanceof Type) {
- considerType((Type) value);
- }
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String name, String desc) {
- // desc is the class descriptor of the nested annotation class.
- considerDesc(desc);
- return new MyAnnotationVisitor();
- }
-
- @Override
- public AnnotationVisitor visitArray(String name) {
- return new MyAnnotationVisitor();
- }
-
- @Override
- public void visitEnum(String name, String desc, String value) {
- // desc is the class descriptor of the enumeration class.
- considerDesc(desc);
- }
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.ClassWriter;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * Class that generates a new JAR from a list of classes, some of which are to be kept as-is
- * and some of which are to be stubbed partially or totally.
- */
-public class AsmGenerator {
-
- /** Output logger. */
- private final Log mLog;
- /** The path of the destination JAR to create. */
- private final String mOsDestJar;
- /** List of classes to inject in the final JAR from _this_ archive. */
- private final Class<?>[] mInjectClasses;
- /** All classes to output as-is, except if they have native methods. */
- private Map<String, ClassReader> mKeep;
- /** All dependencies that must be completely stubbed. */
- private Map<String, ClassReader> mDeps;
- /** All files that are to be copied as-is. */
- private Map<String, InputStream> mCopyFiles;
- /** All classes where certain method calls need to be rewritten. */
- private Set<String> mReplaceMethodCallsClasses;
- /** Counter of number of classes renamed during transform. */
- private int mRenameCount;
- /** FQCN Names of the classes to rename: map old-FQCN => new-FQCN */
- private final HashMap<String, String> mRenameClasses;
- /** FQCN Names of "old" classes that were NOT renamed. This starts with the full list of
- * old-FQCN to rename and they get erased as they get renamed. At the end, classes still
- * left here are not in the code base anymore and thus were not renamed. */
- private HashSet<String> mClassesNotRenamed;
- /** A map { FQCN => set { list of return types to delete from the FQCN } }. */
- private HashMap<String, Set<String>> mDeleteReturns;
- /** A map { FQCN => set { method names } } of methods to rewrite as delegates.
- * The special name {@link DelegateClassAdapter#ALL_NATIVES} can be used as in internal set. */
- private final HashMap<String, Set<String>> mDelegateMethods;
- /** FQCN Names of classes to refactor. All reference to old-FQCN will be updated to new-FQCN.
- * map old-FQCN => new-FQCN */
- private final HashMap<String, String> mRefactorClasses;
- /** 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 map { FQCN => set { field names } } which should be promoted to public visibility */
- private final Map<String, Set<String>> mPromotedFields;
- /** A list of classes to be promoted to public visibility */
- private final Set<String> mPromotedClasses;
-
- /**
- * Creates a new generator that can generate the output JAR with the stubbed classes.
- *
- * @param log Output logger.
- * @param osDestJar The path of the destination JAR to create.
- * @param createInfo Creation parameters. Must not be null.
- */
- public AsmGenerator(Log log, String osDestJar, ICreateInfo createInfo) {
- mLog = log;
- mOsDestJar = osDestJar;
- ArrayList<Class<?>> injectedClasses =
- new ArrayList<>(Arrays.asList(createInfo.getInjectedClasses()));
- // Search for and add anonymous inner classes also.
- ListIterator<Class<?>> iter = injectedClasses.listIterator();
- while (iter.hasNext()) {
- Class<?> clazz = iter.next();
- try {
- int i = 1;
- while(i < 100) {
- iter.add(Class.forName(clazz.getName() + "$" + i));
- i++;
- }
- } catch (ClassNotFoundException ignored) {
- // Expected.
- }
- }
- mInjectClasses = injectedClasses.toArray(new Class<?>[0]);
-
- // Create the map/set of methods to change to delegates
- mDelegateMethods = new HashMap<>();
- addToMap(createInfo.getDelegateMethods(), mDelegateMethods);
-
- for (String className : createInfo.getDelegateClassNatives()) {
- className = binaryToInternalClassName(className);
- Set<String> methods = mDelegateMethods.get(className);
- if (methods == null) {
- methods = new HashSet<>();
- mDelegateMethods.put(className, methods);
- }
- methods.add(DelegateClassAdapter.ALL_NATIVES);
- }
-
- // Create the map of classes to rename.
- mRenameClasses = new HashMap<>();
- mClassesNotRenamed = new HashSet<>();
- String[] renameClasses = Stream.concat(
- Arrays.stream(createInfo.getRenamedClasses()),
- Arrays.stream(createInfo.getRefactoredClasses()))
- .toArray(String[]::new);
- int n = renameClasses.length;
- for (int i = 0; i < n; i += 2) {
- assert i + 1 < n;
- // The ASM class names uses "/" separators, whereas regular FQCN use "."
- String oldFqcn = binaryToInternalClassName(renameClasses[i]);
- String newFqcn = binaryToInternalClassName(renameClasses[i + 1]);
- mRenameClasses.put(oldFqcn, newFqcn);
- mClassesNotRenamed.add(oldFqcn);
- }
-
- // Create a map of classes to be refactored.
- mRefactorClasses = new HashMap<>();
- String[] refactorClasses = Stream.concat(
- Arrays.stream(createInfo.getJavaPkgClasses()),
- Arrays.stream(createInfo.getRefactoredClasses()))
- .toArray(String[]::new);
- n = refactorClasses.length;
- for (int i = 0; i < n; i += 2) {
- assert i + 1 < n;
- String oldFqcn = binaryToInternalClassName(refactorClasses[i]);
- String newFqcn = binaryToInternalClassName(refactorClasses[i + 1]);
- mRefactorClasses.put(oldFqcn, newFqcn);
- }
-
- // create the map of renamed class -> return type of method to delete.
- mDeleteReturns = new HashMap<>();
- String[] deleteReturns = createInfo.getDeleteReturns();
- Set<String> returnTypes = null;
- String renamedClass = null;
- for (String className : deleteReturns) {
- // if we reach the end of a section, add it to the main map
- if (className == null) {
- if (returnTypes != null) {
- mDeleteReturns.put(renamedClass, returnTypes);
- }
-
- renamedClass = null;
- continue;
- }
-
- // if the renamed class is null, this is the beginning of a section
- if (renamedClass == null) {
- renamedClass = binaryToInternalClassName(className);
- continue;
- }
-
- // just a standard return type, we add it to the list.
- if (returnTypes == null) {
- returnTypes = new HashSet<>();
- }
- returnTypes.add(binaryToInternalClassName(className));
- }
-
- mPromotedFields = new HashMap<>();
- addToMap(createInfo.getPromotedFields(), mPromotedFields);
-
- mInjectedMethodsMap = createInfo.getInjectedMethodsMap();
-
- mPromotedClasses =
- Arrays.stream(createInfo.getPromotedClasses()).collect(Collectors.toSet());
- }
-
- /**
- * 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<>();
- 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 "."
- * as package separators.
- */
- public Set<String> getClassesNotRenamed() {
- return mClassesNotRenamed;
- }
-
- /**
- * 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.
- */
- String binaryToInternalClassName(String className) {
- if (className == null) {
- return null;
- } else {
- return className.replace('.', '/');
- }
- }
-
- /** Sets the map of classes to output as-is, except if they have native methods */
- public void setKeep(Map<String, ClassReader> keep) {
- mKeep = keep;
- }
-
- /** Sets the map of dependencies that must be completely stubbed */
- public void setDeps(Map<String, ClassReader> deps) {
- mDeps = deps;
- }
-
- /** Sets the map of files to output as-is. */
- public void setCopyFiles(Map<String, InputStream> copyFiles) {
- mCopyFiles = copyFiles;
- }
-
- public void setRewriteMethodCallClasses(Set<String> rewriteMethodCallClasses) {
- mReplaceMethodCallsClasses = rewriteMethodCallClasses;
- }
-
- /** Generates the final JAR */
- public void generate() throws IOException {
- TreeMap<String, byte[]> all = new TreeMap<>();
-
- for (Class<?> clazz : mInjectClasses) {
- String name = classToEntryPath(clazz);
- InputStream is = ClassLoader.getSystemResourceAsStream(name);
- ClassReader cr = new ClassReader(is);
- byte[] b = transform(cr, true);
- name = classNameToEntryPath(transformName(cr.getClassName()));
- all.put(name, b);
- }
-
- for (Entry<String, ClassReader> entry : mDeps.entrySet()) {
- ClassReader cr = entry.getValue();
- byte[] b = transform(cr, true);
- String name = classNameToEntryPath(transformName(cr.getClassName()));
- all.put(name, b);
- }
-
- for (Entry<String, ClassReader> entry : mKeep.entrySet()) {
- ClassReader cr = entry.getValue();
- byte[] b = transform(cr, true);
- String name = classNameToEntryPath(transformName(cr.getClassName()));
- all.put(name, b);
- }
-
- for (Entry<String, InputStream> entry : mCopyFiles.entrySet()) {
- try {
- byte[] b = inputStreamToByteArray(entry.getValue());
- all.put(entry.getKey(), b);
- } catch (IOException e) {
- // Ignore.
- }
-
- }
- mLog.info("# deps classes: %d", mDeps.size());
- mLog.info("# keep classes: %d", mKeep.size());
- mLog.info("# renamed : %d", mRenameCount);
-
- createJar(new FileOutputStream(mOsDestJar), all);
- mLog.info("Created JAR file %s", mOsDestJar);
- }
-
- /**
- * Writes the JAR file.
- *
- * @param outStream The file output stream were to write the JAR.
- * @param all The map of all classes to output.
- * @throws IOException if an I/O error has occurred
- */
- void createJar(FileOutputStream outStream, Map<String,byte[]> all) throws IOException {
- JarOutputStream jar = new JarOutputStream(outStream);
- for (Entry<String, byte[]> entry : all.entrySet()) {
- String name = entry.getKey();
- JarEntry jar_entry = new JarEntry(name);
- jar.putNextEntry(jar_entry);
- jar.write(entry.getValue());
- jar.closeEntry();
- }
- jar.flush();
- jar.close();
- }
-
- /**
- * Utility method that converts a fully qualified java name into a JAR entry path
- * e.g. for the input "android.view.View" it returns "android/view/View.class"
- */
- String classNameToEntryPath(String className) {
- return className.replace('.', '/').concat(".class");
- }
-
- /**
- * Utility method to get the JAR entry path from a Class name.
- * e.g. it returns something like "com/foo/OuterClass$InnerClass1$InnerClass2.class"
- */
- private String classToEntryPath(Class<?> clazz) {
- return classNameToEntryPath(clazz.getName());
- }
-
- /**
- * Transforms a class.
- * <p/>
- * There are 3 kind of transformations:
- *
- * 1- For "mock" dependencies classes, we want to remove all code from methods and replace
- * by a stub. Native methods must be implemented with this stub too. Abstract methods are
- * left intact. Modified classes must be overridable (non-private, non-final).
- * Native methods must be made non-final, non-private.
- *
- * 2- For "keep" classes, we want to rewrite all native methods as indicated above.
- * If a class has native methods, it must also be made non-private, non-final.
- *
- * Note that unfortunately static methods cannot be changed to non-static (since static and
- * non-static are invoked differently.)
- */
- byte[] transform(ClassReader cr, boolean stubNativesOnly) {
-
- boolean hasNativeMethods = hasNativeMethods(cr);
-
- // Get the class name, as an internal name (e.g. com/android/SomeClass$InnerClass)
- String className = cr.getClassName();
-
- String newName = transformName(className);
- // transformName returns its input argument if there's no need to rename the class
- if (!newName.equals(className)) {
- mRenameCount++;
- // This class is being renamed, so remove it from the list of classes not renamed.
- mClassesNotRenamed.remove(className);
- }
-
- mLog.debug("Transform %s%s%s%s", className,
- newName.equals(className) ? "" : " (renamed to " + newName + ")",
- hasNativeMethods ? " -- has natives" : "",
- stubNativesOnly ? " -- stub natives only" : "");
-
- // Rewrite the new class from scratch, without reusing the constant pool from the
- // original class reader.
- ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
-
- ClassVisitor cv = cw;
-
- // FIXME Generify
- if ("android/content/res/Resources".equals(className)) {
- cv = new FieldInjectorAdapter(cv);
- }
- if (mReplaceMethodCallsClasses.contains(className)) {
- cv = new ReplaceMethodCallsAdapter(cv, className);
- }
-
- cv = new RefactorClassAdapter(cv, mRefactorClasses);
- if (!newName.equals(className)) {
- cv = new RenameClassAdapter(cv, className, newName);
- }
-
- String binaryNewName = newName.replace('/', '.');
- if (mInjectedMethodsMap.keySet().contains(binaryNewName)) {
- cv = new InjectMethodsAdapter(cv, mInjectedMethodsMap.get(binaryNewName));
- }
- cv = new TransformClassAdapter(mLog, Collections.emptySet(), mDeleteReturns.get(className),
- newName, cv, stubNativesOnly);
-
- Set<String> delegateMethods = mDelegateMethods.get(className);
- if (delegateMethods != null && !delegateMethods.isEmpty()) {
- // If delegateMethods only contains one entry ALL_NATIVES and the class is
- // known to have no native methods, just skip this step.
- if (hasNativeMethods ||
- !(delegateMethods.size() == 1 &&
- delegateMethods.contains(DelegateClassAdapter.ALL_NATIVES))) {
- cv = new DelegateClassAdapter(mLog, cv, className, delegateMethods);
- }
- }
-
- Set<String> promoteFields = mPromotedFields.get(className);
- if (promoteFields != null && !promoteFields.isEmpty()) {
- cv = new PromoteFieldClassAdapter(cv, promoteFields);
- }
- if (!mPromotedClasses.isEmpty()) {
- cv = new PromoteClassClassAdapter(cv, mPromotedClasses);
- }
- cr.accept(cv, 0);
-
- return cw.toByteArray();
- }
-
- /**
- * Should this class be renamed, this returns the new name. Otherwise it returns the
- * original name.
- *
- * @param className The internal ASM name of the class that may have to be renamed
- * @return A new transformed name or the original input argument.
- */
- String transformName(String className) {
- String newName = mRenameClasses.get(className);
- if (newName != null) {
- return newName;
- }
- int pos = className.indexOf('$');
- if (pos > 0) {
- // Is this an inner class of a renamed class?
- String base = className.substring(0, pos);
- newName = mRenameClasses.get(base);
- if (newName != null) {
- return newName + className.substring(pos);
- }
- }
-
- return className;
- }
-
- /**
- * Returns true if a class has any native methods.
- */
- boolean hasNativeMethods(ClassReader cr) {
- ClassHasNativeVisitor cv = new ClassHasNativeVisitor();
- cr.accept(cv, 0);
- return cv.hasNativeMethods();
- }
-
- private byte[] inputStreamToByteArray(InputStream is) throws IOException {
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- byte[] data = new byte[8192]; // 8KB
- int n;
- while ((n = is.read(data, 0, data.length)) != -1) {
- buffer.write(data, 0, n);
- }
- return buffer.toByteArray();
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create;
-
-import com.android.tools.layoutlib.annotations.VisibleForTesting;
-import com.android.tools.layoutlib.annotations.VisibleForTesting.Visibility;
-
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-
-/**
- * Indicates if a class contains any native methods.
- */
-public class ClassHasNativeVisitor extends ClassVisitor {
- public ClassHasNativeVisitor() {
- super(Main.ASM_VERSION);
- }
-
- private boolean mHasNativeMethods = false;
-
- public boolean hasNativeMethods() {
- return mHasNativeMethods;
- }
-
- @VisibleForTesting(visibility=Visibility.PRIVATE)
- protected void setHasNativeMethods(boolean hasNativeMethods, String methodName) {
- mHasNativeMethods = hasNativeMethods;
- }
-
- @Override
- public void visit(int version, int access, String name, String signature,
- String superName, String[] interfaces) {
- // pass
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- // pass
- return null;
- }
-
- @Override
- public void visitAttribute(Attribute attr) {
- // pass
- }
-
- @Override
- public void visitEnd() {
- // pass
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc,
- String signature, Object value) {
- // pass
- return null;
- }
-
- @Override
- public void visitInnerClass(String name, String outerName,
- String innerName, int access) {
- // pass
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- if ((access & Opcodes.ACC_NATIVE) != 0) {
- setHasNativeMethods(true, name);
- }
- return null;
- }
-
- @Override
- public void visitOuterClass(String owner, String name, String desc) {
- // pass
- }
-
- @Override
- public void visitSource(String source, String debug) {
- // pass
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-import com.android.tools.layoutlib.java.AutoCloseable;
-import com.android.tools.layoutlib.java.Charsets;
-import com.android.tools.layoutlib.java.IntegralToString;
-import com.android.tools.layoutlib.java.LinkedHashMap_Delegate;
-import com.android.tools.layoutlib.java.Objects;
-import com.android.tools.layoutlib.java.System_Delegate;
-import com.android.tools.layoutlib.java.UnsafeByteSequence;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Describes the work to be done by {@link AsmGenerator}.
- */
-public final class CreateInfo implements ICreateInfo {
-
- @Override
- public Class<?>[] getInjectedClasses() {
- return INJECTED_CLASSES;
- }
-
- @Override
- public String[] getDelegateMethods() {
- return DELEGATE_METHODS;
- }
-
- @Override
- public String[] getDelegateClassNatives() {
- return DELEGATE_CLASS_NATIVES;
- }
-
- @Override
- public String[] getRenamedClasses() {
- return RENAMED_CLASSES;
- }
-
- @Override
- public String[] getDeleteReturns() {
- return DELETE_RETURNS;
- }
-
- @Override
- public String[] getJavaPkgClasses() {
- return JAVA_PKG_CLASSES;
- }
-
- @Override
- public String[] getRefactoredClasses() {
- return REFACTOR_CLASSES;
- }
-
- @Override
- public Set<String> getExcludedClasses() {
- String[] refactoredClasses = getJavaPkgClasses();
- int count = refactoredClasses.length / 2 + EXCLUDED_CLASSES.length;
- Set<String> excludedClasses = new HashSet<>(count);
- for (int i = 0; i < refactoredClasses.length; i+=2) {
- excludedClasses.add(refactoredClasses[i]);
- }
- excludedClasses.addAll(Arrays.asList(EXCLUDED_CLASSES));
- return excludedClasses;
- }
-
- @Override
- public String[] getPromotedFields() {
- return PROMOTED_FIELDS;
- }
-
- @Override
- public String[] getPromotedClasses() {
- return PROMOTED_CLASSES;
- }
-
- @Override
- public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
- return INJECTED_METHODS;
- }
-
- //-----
-
- /**
- * The list of class from layoutlib_create to inject in layoutlib.
- */
- private final static Class<?>[] INJECTED_CLASSES = new Class<?>[] {
- OverrideMethod.class,
- MethodListener.class,
- MethodAdapter.class,
- ICreateInfo.class,
- CreateInfo.class,
- LayoutlibDelegate.class,
- InjectMethodRunnable.class,
- InjectMethodRunnables.class,
- /* Java package classes */
- IntegralToString.class,
- UnsafeByteSequence.class,
- System_Delegate.class,
- LinkedHashMap_Delegate.class,
- };
-
- /**
- * The list of methods to rewrite as delegates.
- */
- public final static String[] DELEGATE_METHODS = new String[] {
- "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
- "android.content.res.Resources#getAnimation",
- "android.content.res.Resources#getBoolean",
- "android.content.res.Resources#getColor",
- "android.content.res.Resources#getColorStateList",
- "android.content.res.Resources#getDimension",
- "android.content.res.Resources#getDimensionPixelOffset",
- "android.content.res.Resources#getDimensionPixelSize",
- "android.content.res.Resources#getDrawable",
- "android.content.res.Resources#getFont",
- "android.content.res.Resources#getIntArray",
- "android.content.res.Resources#getInteger",
- "android.content.res.Resources#getLayout",
- "android.content.res.Resources#getQuantityString",
- "android.content.res.Resources#getQuantityText",
- "android.content.res.Resources#getResourceEntryName",
- "android.content.res.Resources#getResourceName",
- "android.content.res.Resources#getResourcePackageName",
- "android.content.res.Resources#getResourceTypeName",
- "android.content.res.Resources#getString",
- "android.content.res.Resources#getStringArray",
- "android.content.res.Resources#getText",
- "android.content.res.Resources#getTextArray",
- "android.content.res.Resources#getValue",
- "android.content.res.Resources#getXml",
- "android.content.res.Resources#loadXmlResourceParser",
- "android.content.res.Resources#obtainAttributes",
- "android.content.res.Resources#obtainTypedArray",
- "android.content.res.Resources#openRawResource",
- "android.content.res.Resources#openRawResourceFd",
- "android.content.res.Resources$Theme#obtainStyledAttributes",
- "android.content.res.Resources$Theme#resolveAttribute",
- "android.content.res.Resources$Theme#resolveAttributes",
- "android.content.res.AssetManager#newTheme",
- "android.content.res.AssetManager#deleteTheme",
- "android.content.res.AssetManager#getAssignedPackageIdentifiers",
- "android.content.res.TypedArray#getValueAt",
- "android.content.res.TypedArray#obtain",
- "android.graphics.BitmapFactory#finishDecode",
- "android.graphics.BitmapFactory#setDensityFromOptions",
- "android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#useLastSeenTarget",
- "android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#onDraw",
- "android.graphics.drawable.GradientDrawable#buildRing",
- "android.graphics.FontFamily#addFont",
- "android.graphics.Typeface#getSystemFontConfigLocation",
- "android.graphics.Typeface#makeFamilyFromParsed",
- "android.os.Handler#sendMessageAtTime",
- "android.os.HandlerThread#run",
- "android.preference.Preference#getView",
- "android.text.format.DateFormat#is24HourFormat",
- "android.text.Hyphenator#getSystemHyphenatorLocation",
- "android.util.Xml#newPullParser",
- "android.view.Choreographer#getInstance",
- "android.view.Choreographer#getRefreshRate",
- "android.view.Choreographer#scheduleVsyncLocked",
- "android.view.Display#updateDisplayInfoLocked",
- "android.view.Display#getWindowManager",
- "android.view.HandlerActionQueue#postDelayed",
- "android.view.LayoutInflater#rInflate",
- "android.view.LayoutInflater#parseInclude",
- "android.view.View#getWindowToken",
- "android.view.View#isInEditMode",
- "android.view.ViewRootImpl#isInTouchMode",
- "android.view.WindowManagerGlobal#getWindowManagerService",
- "android.view.inputmethod.InputMethodManager#getInstance",
- "android.view.MenuInflater#registerMenu",
- "android.view.RenderNode#getMatrix",
- "android.view.RenderNode#nCreate",
- "android.view.RenderNode#nGetNativeFinalizer",
- "android.view.RenderNode#nSetElevation",
- "android.view.RenderNode#nGetElevation",
- "android.view.RenderNode#nSetTranslationX",
- "android.view.RenderNode#nGetTranslationX",
- "android.view.RenderNode#nSetTranslationY",
- "android.view.RenderNode#nGetTranslationY",
- "android.view.RenderNode#nSetTranslationZ",
- "android.view.RenderNode#nGetTranslationZ",
- "android.view.RenderNode#nSetRotation",
- "android.view.RenderNode#nGetRotation",
- "android.view.RenderNode#nSetLeft",
- "android.view.RenderNode#nSetTop",
- "android.view.RenderNode#nSetRight",
- "android.view.RenderNode#nSetBottom",
- "android.view.RenderNode#nSetLeftTopRightBottom",
- "android.view.RenderNode#nSetPivotX",
- "android.view.RenderNode#nGetPivotX",
- "android.view.RenderNode#nSetPivotY",
- "android.view.RenderNode#nGetPivotY",
- "android.view.RenderNode#nSetScaleX",
- "android.view.RenderNode#nGetScaleX",
- "android.view.RenderNode#nSetScaleY",
- "android.view.RenderNode#nGetScaleY",
- "android.view.RenderNode#nIsPivotExplicitlySet",
- "android.view.PointerIcon#loadResource",
- "android.view.ViewGroup#drawChild",
- "com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
- "com.android.internal.util.XmlUtils#convertValueToInt",
- "dalvik.system.VMRuntime#newUnpaddedArray",
- "libcore.io.MemoryMappedFile#mmapRO",
- "libcore.io.MemoryMappedFile#close",
- "libcore.io.MemoryMappedFile#bigEndianIterator",
- "libcore.util.NativeAllocationRegistry#applyFreeFunction",
- };
-
- /**
- * The list of classes on which to delegate all native methods.
- */
- public final static String[] DELEGATE_CLASS_NATIVES = new String[] {
- "android.animation.PropertyValuesHolder",
- "android.graphics.BaseCanvas",
- "android.graphics.Bitmap",
- "android.graphics.BitmapFactory",
- "android.graphics.BitmapShader",
- "android.graphics.BlurMaskFilter",
- "android.graphics.Canvas",
- "android.graphics.ColorFilter",
- "android.graphics.ColorMatrixColorFilter",
- "android.graphics.ComposePathEffect",
- "android.graphics.ComposeShader",
- "android.graphics.CornerPathEffect",
- "android.graphics.DashPathEffect",
- "android.graphics.DiscretePathEffect",
- "android.graphics.DrawFilter",
- "android.graphics.EmbossMaskFilter",
- "android.graphics.FontFamily",
- "android.graphics.LightingColorFilter",
- "android.graphics.LinearGradient",
- "android.graphics.MaskFilter",
- "android.graphics.Matrix",
- "android.graphics.NinePatch",
- "android.graphics.Paint",
- "android.graphics.PaintFlagsDrawFilter",
- "android.graphics.Path",
- "android.graphics.PathDashPathEffect",
- "android.graphics.PathEffect",
- "android.graphics.PathMeasure",
- "android.graphics.PorterDuffColorFilter",
- "android.graphics.RadialGradient",
- "android.graphics.Region",
- "android.graphics.Shader",
- "android.graphics.SumPathEffect",
- "android.graphics.SweepGradient",
- "android.graphics.Typeface",
- "android.graphics.drawable.AnimatedVectorDrawable",
- "android.graphics.drawable.VectorDrawable",
- "android.os.SystemClock",
- "android.os.SystemProperties",
- "android.text.AndroidBidi",
- "android.text.StaticLayout",
- "android.util.PathParser",
- "android.view.Display",
- "com.android.internal.util.VirtualRefBasePtr",
- "com.android.internal.view.animation.NativeInterpolatorFactoryHelper",
- "libcore.icu.ICU",
- };
-
- /**
- * The list of classes to rename, must be an even list: the binary FQCN
- * of class to replace followed by the new FQCN.
- */
- private final static String[] RENAMED_CLASSES =
- new String[] {
- "android.os.ServiceManager", "android.os._Original_ServiceManager",
- "android.view.textservice.TextServicesManager", "android.view.textservice._Original_TextServicesManager",
- "android.util.LruCache", "android.util._Original_LruCache",
- "android.view.SurfaceView", "android.view._Original_SurfaceView",
- "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
- "android.webkit.WebView", "android.webkit._Original_WebView",
- };
-
- /**
- * The list of class references to update, must be an even list: the binary
- * FQCN of class to replace followed by the new FQCN. The classes to
- * replace are to be excluded from the output.
- */
- private final static String[] JAVA_PKG_CLASSES =
- new String[] {
- "java.nio.charset.Charsets", "java.nio.charset.StandardCharsets",
- "java.lang.IntegralToString", "com.android.tools.layoutlib.java.IntegralToString",
- "java.lang.UnsafeByteSequence", "com.android.tools.layoutlib.java.UnsafeByteSequence",
- // Use android.icu.text versions of DateFormat and SimpleDateFormat since the
- // original ones do not match the Android implementation
- "java.text.DateFormat", "android.icu.text.DateFormat",
- "java.text.SimpleDateFormat", "android.icu.text.SimpleDateFormat",
- };
-
- /**
- * List of classes to refactor. This is similar to combining {@link #getRenamedClasses()} and
- * {@link #getJavaPkgClasses()}.
- * Classes included here will be renamed and then all their references in any other classes
- * will be also modified.
- * FQCN of class to refactor followed by its new FQCN.
- */
- private final static String[] REFACTOR_CLASSES =
- new String[] {
- "android.os.Build", "android.os._Original_Build",
- };
-
- private final static String[] EXCLUDED_CLASSES =
- new String[] {
- "android.preference.PreferenceActivity",
- "org.kxml2.io.KXmlParser",
- };
-
- /**
- * List of fields for which we will update the visibility to be public. This is sometimes
- * needed when access from the delegate classes is needed.
- */
- private final static String[] PROMOTED_FIELDS = new String[] {
- "android.graphics.drawable.VectorDrawable#mVectorState",
- "android.view.Choreographer#mLastFrameTimeNanos",
- "android.graphics.FontFamily#mBuilderPtr",
- "android.graphics.Typeface#sDynamicTypefaceCache"
- };
-
- /**
- * List of classes to be promoted to public visibility. Prefer using PROMOTED_FIELDS to this
- * if possible.
- */
- private final static String[] PROMOTED_CLASSES = new String[] {
- };
-
- /**
- * 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
- * to rename in which the methods are deleted, followed by a list of return types identifying
- * the methods to delete.
- */
- private final static String[] DELETE_RETURNS =
- new String[] {
- null }; // separator, for next class/methods list.
-
- private final static Map<String, InjectMethodRunnable> INJECTED_METHODS =
- new HashMap<String, InjectMethodRunnable>(1) {{
- put("android.content.Context",
- InjectMethodRunnables.CONTEXT_GET_FRAMEWORK_CLASS_LOADER);
- }};
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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 java.util.Set;
-
-/**
- * A {@link DelegateClassAdapter} can transform some methods from a class into
- * delegates that defer the call to an associated delegate class.
- * <p/>
- * This is used to override specific methods and or all native methods in classes.
- */
-public class DelegateClassAdapter extends ClassVisitor {
-
- /** Suffix added to original methods. */
- private static final String ORIGINAL_SUFFIX = "_Original";
- private static final String CONSTRUCTOR = "<init>";
- private static final String CLASS_INIT = "<clinit>";
-
- public static final String ALL_NATIVES = "<<all_natives>>";
-
- private final String mClassName;
- private final Set<String> mDelegateMethods;
- private final Log mLog;
- private boolean mIsStaticInnerClass;
-
- /**
- * Creates a new {@link DelegateClassAdapter} that can transform some methods
- * from a class into delegates that defer the call to an associated delegate class.
- * <p/>
- * This is used to override specific methods and or all native methods in classes.
- *
- * @param log The logger object. Must not be null.
- * @param cv the class visitor to which this adapter must delegate calls.
- * @param className The internal class name of the class to visit,
- * e.g. <code>com/android/SomeClass$InnerClass</code>.
- * @param delegateMethods The set of method names to modify and/or the
- * special constant {@link #ALL_NATIVES} to convert all native methods.
- */
- public DelegateClassAdapter(Log log,
- ClassVisitor cv,
- String className,
- Set<String> delegateMethods) {
- super(Main.ASM_VERSION, cv);
- mLog = log;
- mClassName = className;
- mDelegateMethods = delegateMethods;
- // If this is an inner class, by default, we assume it's static. If it's not we will detect
- // by looking at the fields (see visitField)
- mIsStaticInnerClass = className.contains("$");
- }
-
- //----------------------------------
- // Methods from the ClassAdapter
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc, String signature,
- Object value) {
- if (mIsStaticInnerClass && "this$0".equals(name)) {
- // Having a "this$0" field, proves that this class is not a static inner class.
- mIsStaticInnerClass = false;
- }
-
- return super.visitField(access, name, desc, signature, value);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
-
- boolean isStaticMethod = (access & Opcodes.ACC_STATIC) != 0;
- boolean isNative = (access & Opcodes.ACC_NATIVE) != 0;
-
- boolean useDelegate = (isNative && mDelegateMethods.contains(ALL_NATIVES)) ||
- mDelegateMethods.contains(name);
-
- if (!useDelegate) {
- // Not creating a delegate for this method, pass it as-is from the reader to the writer.
- return super.visitMethod(access, name, desc, signature, exceptions);
- }
-
- if (CONSTRUCTOR.equals(name) || CLASS_INIT.equals(name)) {
- // We don't currently support generating delegates for constructors.
- throw new UnsupportedOperationException(
- String.format(
- "Delegate doesn't support overriding constructor %1$s:%2$s(%3$s)", //$NON-NLS-1$
- mClassName, name, desc));
- }
-
- if (isNative) {
- // Remove native flag
- access = access & ~Opcodes.ACC_NATIVE;
- MethodVisitor mwDelegate = super.visitMethod(access, name, desc, signature, exceptions);
-
- DelegateMethodAdapter a = new DelegateMethodAdapter(
- mLog, null, mwDelegate, mClassName, name, desc, isStaticMethod,
- mIsStaticInnerClass);
-
- // A native has no code to visit, so we need to generate it directly.
- a.generateDelegateCode();
-
- return mwDelegate;
- }
-
- // Given a non-native SomeClass.MethodName(), we want to generate 2 methods:
- // - A copy of the original method named SomeClass.MethodName_Original().
- // The content is the original method as-is from the reader.
- // - A brand new implementation of SomeClass.MethodName() which calls to a
- // non-existing method named SomeClass_Delegate.MethodName().
- // The implementation of this 'delegate' method is done in layoutlib_bridge.
-
- int accessDelegate = access;
- access = access & ~Opcodes.ACC_PRIVATE; // If private, make it package protected.
-
- MethodVisitor mwOriginal = super.visitMethod(access, name + ORIGINAL_SUFFIX,
- desc, signature, exceptions);
- MethodVisitor mwDelegate = super.visitMethod(accessDelegate, name,
- desc, signature, exceptions);
-
- return new DelegateMethodAdapter(
- mLog, mwOriginal, mwDelegate, mClassName, name, desc, isStaticMethod,
- mIsStaticInnerClass);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create;
-
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-import java.util.ArrayList;
-
-/**
- * This method adapter generates delegate methods.
- * <p/>
- * Given a method {@code SomeClass.MethodName()}, this generates 1 or 2 methods:
- * <ul>
- * <li> A copy of the original method named {@code SomeClass.MethodName_Original()}.
- * The content is the original method as-is from the reader.
- * This step is omitted if the method is native, since it has no Java implementation.
- * <li> A brand new implementation of {@code SomeClass.MethodName()} which calls to a
- * non-existing method named {@code SomeClass_Delegate.MethodName()}.
- * The implementation of this 'delegate' method is done in layoutlib_brigde.
- * </ul>
- * A method visitor is generally constructed to generate a single method; however
- * here we might want to generate one or two depending on the context. To achieve
- * that, the visitor here generates the 'original' method and acts as a no-op if
- * no such method exists (e.g. when the original is a native method).
- * The delegate method is generated after the {@code visitEnd} of the original method
- * or by having the class adapter <em>directly</em> call {@link #generateDelegateCode()}
- * for native methods.
- * <p/>
- * When generating the 'delegate', the implementation generates a call to a class
- * class named <code><className>_Delegate</code> with static methods matching
- * the methods to be overridden here. The methods have the same return type.
- * The argument type list is the same except the "this" reference is passed first
- * for non-static methods.
- * <p/>
- * A new annotation is added to these 'delegate' methods so that we can easily find them
- * for automated testing.
- * <p/>
- * This class isn't intended to be generic or reusable.
- * It is called by {@link DelegateClassAdapter}, which takes care of properly initializing
- * the two method writers for the original and the delegate class, as needed, with their
- * expected names.
- * <p/>
- * The class adapter also takes care of calling {@link #generateDelegateCode()} directly for
- * a native and use the visitor pattern for non-natives.
- * Note that native methods have, by definition, no code so there's nothing a visitor
- * can visit.
- * <p/>
- * Instances of this class are not re-usable.
- * The class adapter creates a new instance for each method.
- */
-class DelegateMethodAdapter extends MethodVisitor {
-
- /** Suffix added to delegate classes. */
- public static final String DELEGATE_SUFFIX = "_Delegate";
-
- /** The parent method writer to copy of the original method.
- * Null when dealing with a native original method. */
- private MethodVisitor mOrgWriter;
- /** The parent method writer to generate the delegating method. Never null. */
- private MethodVisitor mDelWriter;
- /** The original method descriptor (return type + argument types.) */
- private String mDesc;
- /** True if the original method is static. */
- private final boolean mIsStatic;
- /** True if the method is contained in a static inner class */
- private final boolean mIsStaticInnerClass;
- /** The internal class name (e.g. <code>com/android/SomeClass$InnerClass</code>.) */
- private final String mClassName;
- /** The method name. */
- private final String mMethodName;
- /** Logger object. */
- private final Log mLog;
-
- /** Array used to capture the first line number information from the original method
- * and duplicate it in the delegate. */
- private Object[] mDelegateLineNumber;
-
- /**
- * Creates a new {@link DelegateMethodAdapter} that will transform this method
- * into a delegate call.
- * <p/>
- * See {@link DelegateMethodAdapter} for more details.
- *
- * @param log The logger object. Must not be null.
- * @param mvOriginal The parent method writer to copy of the original method.
- * Must be {@code null} when dealing with a native original method.
- * @param mvDelegate The parent method writer to generate the delegating method.
- * Must never be null.
- * @param className The internal class name of the class to visit,
- * e.g. <code>com/android/SomeClass$InnerClass</code>.
- * @param methodName The simple name of the method.
- * @param desc A method descriptor (c.f. {@link Type#getReturnType(String)} +
- * {@link Type#getArgumentTypes(String)})
- * @param isStatic True if the method is declared static.
- */
- public DelegateMethodAdapter(Log log,
- MethodVisitor mvOriginal,
- MethodVisitor mvDelegate,
- String className,
- String methodName,
- String desc,
- boolean isStatic,
- boolean isStaticClass) {
- super(Main.ASM_VERSION);
- mLog = log;
- mOrgWriter = mvOriginal;
- mDelWriter = mvDelegate;
- mClassName = className;
- mMethodName = methodName;
- mDesc = desc;
- mIsStatic = isStatic;
- mIsStaticInnerClass = isStaticClass;
- }
-
- /**
- * Generates the new code for the method.
- * <p/>
- * For native methods, this must be invoked directly by {@link DelegateClassAdapter}
- * (since they have no code to visit).
- * <p/>
- * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to
- * return this instance of {@link DelegateMethodAdapter} and let the normal visitor pattern
- * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then
- * this method will be invoked from {@link MethodVisitor#visitEnd()}.
- */
- public void generateDelegateCode() {
- /*
- * The goal is to generate a call to a static delegate method.
- * If this method is non-static, the first parameter will be 'this'.
- * All the parameters must be passed and then the eventual return type returned.
- *
- * Example, let's say we have a method such as
- * public void myMethod(int a, Object b, ArrayList<String> c) { ... }
- *
- * We'll want to create a body that calls a delegate method like this:
- * TheClass_Delegate.myMethod(this, a, b, c);
- *
- * If the method is non-static and the class name is an inner class (e.g. has $ in its
- * last segment), we want to push the 'this' of the outer class first:
- * OuterClass_InnerClass_Delegate.myMethod(
- * OuterClass.this,
- * OuterClass$InnerClass.this,
- * a, b, c);
- *
- * Only one level of inner class is supported right now, for simplicity and because
- * we don't need more.
- *
- * The generated class name is the current class name with "_Delegate" appended to it.
- * One thing to realize is that we don't care about generics -- since generic types
- * are erased at build time, they have no influence on the method name being called.
- */
-
- // Add our annotation
- AnnotationVisitor aw = mDelWriter.visitAnnotation(
- Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(),
- true); // visible at runtime
- if (aw != null) {
- aw.visitEnd();
- }
-
- mDelWriter.visitCode();
-
- if (mDelegateLineNumber != null) {
- Object[] p = mDelegateLineNumber;
- mDelWriter.visitLineNumber((Integer) p[0], (Label) p[1]);
- }
-
- ArrayList<Type> paramTypes = new ArrayList<>();
- String delegateClassName = mClassName + DELEGATE_SUFFIX;
- boolean pushedArg0 = false;
- int maxStack = 0;
-
- // Check if the last segment of the class name has inner an class.
- // Right now we only support one level of inner classes.
- Type outerType = null;
- int slash = mClassName.lastIndexOf('/');
- int dol = mClassName.lastIndexOf('$');
- if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
- String outerClass = mClassName.substring(0, dol);
- outerType = Type.getObjectType(outerClass);
-
- // Change a delegate class name to "com/foo/Outer_Inner_Delegate"
- delegateClassName = delegateClassName.replace('$', '_');
- }
-
- // For an instance method (e.g. non-static), push the 'this' preceded
- // by the 'this' of any outer class, if any.
- if (!mIsStatic) {
-
- if (outerType != null && !mIsStaticInnerClass) {
- // The first-level inner class has a package-protected member called 'this$0'
- // that points to the outer class.
-
- // Push this.getField("this$0") on the call stack.
- mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this
- mDelWriter.visitFieldInsn(Opcodes.GETFIELD,
- mClassName, // class where the field is defined
- "this$0", // field name
- outerType.getDescriptor()); // type of the field
- maxStack++;
- paramTypes.add(outerType);
-
- }
-
- // Push "this" for the instance method, which is always ALOAD 0
- mDelWriter.visitVarInsn(Opcodes.ALOAD, 0);
- maxStack++;
- pushedArg0 = true;
- paramTypes.add(Type.getObjectType(mClassName));
- }
-
- // Push all other arguments. Start at arg 1 if we already pushed 'this' above.
- Type[] argTypes = Type.getArgumentTypes(mDesc);
- int maxLocals = pushedArg0 ? 1 : 0;
- for (Type t : argTypes) {
- int size = t.getSize();
- mDelWriter.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals);
- maxLocals += size;
- maxStack += size;
- paramTypes.add(t);
- }
-
- // Construct the descriptor of the delegate based on the parameters
- // we pushed on the call stack. The return type remains unchanged.
- String desc = Type.getMethodDescriptor(
- Type.getReturnType(mDesc),
- paramTypes.toArray(new Type[paramTypes.size()]));
-
- // Invoke the static delegate
- mDelWriter.visitMethodInsn(Opcodes.INVOKESTATIC,
- delegateClassName,
- mMethodName,
- desc,
- false);
-
- Type returnType = Type.getReturnType(mDesc);
- mDelWriter.visitInsn(returnType.getOpcode(Opcodes.IRETURN));
-
- mDelWriter.visitMaxs(maxStack, maxLocals);
- mDelWriter.visitEnd();
-
- // For debugging now. Maybe we should collect these and store them in
- // a text file for helping create the delegates. We could also compare
- // the text file to a golden and break the build on unsupported changes
- // or regressions. Even better we could fancy-print something that looks
- // like the expected Java method declaration.
- mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc);
- }
-
- /* Pass down to visitor writer. In this implementation, either do nothing. */
- @Override
- public void visitCode() {
- if (mOrgWriter != null) {
- mOrgWriter.visitCode();
- }
- }
-
- /*
- * visitMaxs is called just before visitEnd if there was any code to rewrite.
- */
- @Override
- public void visitMaxs(int maxStack, int maxLocals) {
- if (mOrgWriter != null) {
- mOrgWriter.visitMaxs(maxStack, maxLocals);
- }
- }
-
- /** End of visiting. Generate the delegating code. */
- @Override
- public void visitEnd() {
- if (mOrgWriter != null) {
- mOrgWriter.visitEnd();
- }
- generateDelegateCode();
- }
-
- /* Writes all annotation from the original method. */
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- if (mOrgWriter != null) {
- return mOrgWriter.visitAnnotation(desc, visible);
- } else {
- return null;
- }
- }
-
- /* Writes all annotation default values from the original method. */
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- if (mOrgWriter != null) {
- return mOrgWriter.visitAnnotationDefault();
- } else {
- return null;
- }
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
- boolean visible) {
- if (mOrgWriter != null) {
- return mOrgWriter.visitParameterAnnotation(parameter, desc, visible);
- } else {
- return null;
- }
- }
-
- /* Writes all attributes from the original method. */
- @Override
- public void visitAttribute(Attribute attr) {
- if (mOrgWriter != null) {
- mOrgWriter.visitAttribute(attr);
- }
- }
-
- /*
- * Only writes the first line number present in the original code so that source
- * viewers can direct to the correct method, even if the content doesn't match.
- */
- @Override
- public void visitLineNumber(int line, Label start) {
- // Capture the first line values for the new delegate method
- if (mDelegateLineNumber == null) {
- mDelegateLineNumber = new Object[] { line, start };
- }
- if (mOrgWriter != null) {
- mOrgWriter.visitLineNumber(line, start);
- }
- }
-
- @Override
- public void visitInsn(int opcode) {
- if (mOrgWriter != null) {
- mOrgWriter.visitInsn(opcode);
- }
- }
-
- @Override
- public void visitLabel(Label label) {
- if (mOrgWriter != null) {
- mOrgWriter.visitLabel(label);
- }
- }
-
- @Override
- public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
- if (mOrgWriter != null) {
- mOrgWriter.visitTryCatchBlock(start, end, handler, type);
- }
- }
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
- if (mOrgWriter != null) {
- mOrgWriter.visitMethodInsn(opcode, owner, name, desc, itf);
- }
- }
-
- @Override
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- if (mOrgWriter != null) {
- mOrgWriter.visitFieldInsn(opcode, owner, name, desc);
- }
- }
-
- @Override
- public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
- if (mOrgWriter != null) {
- mOrgWriter.visitFrame(type, nLocal, local, nStack, stack);
- }
- }
-
- @Override
- public void visitIincInsn(int var, int increment) {
- if (mOrgWriter != null) {
- mOrgWriter.visitIincInsn(var, increment);
- }
- }
-
- @Override
- public void visitIntInsn(int opcode, int operand) {
- if (mOrgWriter != null) {
- mOrgWriter.visitIntInsn(opcode, operand);
- }
- }
-
- @Override
- public void visitJumpInsn(int opcode, Label label) {
- if (mOrgWriter != null) {
- mOrgWriter.visitJumpInsn(opcode, label);
- }
- }
-
- @Override
- public void visitLdcInsn(Object cst) {
- if (mOrgWriter != null) {
- mOrgWriter.visitLdcInsn(cst);
- }
- }
-
- @Override
- public void visitLocalVariable(String name, String desc, String signature,
- Label start, Label end, int index) {
- if (mOrgWriter != null) {
- mOrgWriter.visitLocalVariable(name, desc, signature, start, end, index);
- }
- }
-
- @Override
- public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
- if (mOrgWriter != null) {
- mOrgWriter.visitLookupSwitchInsn(dflt, keys, labels);
- }
- }
-
- @Override
- public void visitMultiANewArrayInsn(String desc, int dims) {
- if (mOrgWriter != null) {
- mOrgWriter.visitMultiANewArrayInsn(desc, dims);
- }
- }
-
- @Override
- public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
- if (mOrgWriter != null) {
- mOrgWriter.visitTableSwitchInsn(min, max, dflt, labels);
- }
- }
-
- @Override
- public void visitTypeInsn(int opcode, String type) {
- if (mOrgWriter != null) {
- mOrgWriter.visitTypeInsn(opcode, type);
- }
- }
-
- @Override
- public void visitVarInsn(int opcode, int var) {
- if (mOrgWriter != null) {
- mOrgWriter.visitVarInsn(opcode, var);
- }
- }
-
-}
+++ /dev/null
-/*
- * 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.tools.layoutlib.create;
-
-import com.android.tools.layoutlib.annotations.VisibleForTesting;
-import com.android.tools.layoutlib.annotations.VisibleForTesting.Visibility;
-
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Type;
-import org.objectweb.asm.signature.SignatureReader;
-import org.objectweb.asm.signature.SignatureVisitor;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-/**
- * Analyzes the input JAR using the ASM java bytecode manipulation library
- * to list the classes and their dependencies. A "dependency" is a class
- * used by another class.
- */
-public class DependencyFinder {
-
- // Note: a bunch of stuff has package-level access for unit tests. Consider it private.
-
- /** Output logger. */
- private final Log mLog;
-
- /**
- * Creates a new analyzer.
- *
- * @param log The log output.
- */
- public DependencyFinder(Log log) {
- mLog = log;
- }
-
- /**
- * Starts the analysis using parameters from the constructor.
- *
- * @param osJarPath The input source JARs to parse.
- * @return A pair: [0]: map { class FQCN => set of FQCN class dependencies }.
- * [1]: map { missing class FQCN => set of FQCN class that uses it. }
- */
- public List<Map<String, Set<String>>> findDeps(List<String> osJarPath) throws IOException {
-
- Map<String, ClassReader> zipClasses = parseZip(osJarPath);
- mLog.info("Found %d classes in input JAR%s.",
- zipClasses.size(),
- osJarPath.size() > 1 ? "s" : "");
-
- Map<String, Set<String>> deps = findClassesDeps(zipClasses);
-
- Map<String, Set<String>> missing = findMissingClasses(deps, zipClasses.keySet());
-
- List<Map<String, Set<String>>> result = new ArrayList<>(2);
- result.add(deps);
- result.add(missing);
- return result;
- }
-
- /**
- * Prints dependencies to the current logger, found stuff and missing stuff.
- */
- public void printAllDeps(List<Map<String, Set<String>>> result) {
- assert result.size() == 2;
- Map<String, Set<String>> deps = result.get(0);
- Map<String, Set<String>> missing = result.get(1);
-
- // Print all dependences found in the format:
- // +Found: <FQCN from zip>
- // uses: FQCN
-
- mLog.info("++++++ %d Entries found in source JARs", deps.size());
- mLog.info("");
-
- for (Entry<String, Set<String>> entry : deps.entrySet()) {
- mLog.info( "+Found : %s", entry.getKey());
- for (String dep : entry.getValue()) {
- mLog.info(" uses: %s", dep);
- }
-
- mLog.info("");
- }
-
-
- // Now print all missing dependences in the format:
- // -Missing <FQCN>:
- // used by: <FQCN>
-
- mLog.info("");
- mLog.info("------ %d Entries missing from source JARs", missing.size());
- mLog.info("");
-
- for (Entry<String, Set<String>> entry : missing.entrySet()) {
- mLog.info( "-Missing : %s", entry.getKey());
- for (String dep : entry.getValue()) {
- mLog.info(" used by: %s", dep);
- }
-
- mLog.info("");
- }
- }
-
- /**
- * Prints only a summary of the missing dependencies to the current logger.
- */
- public void printMissingDeps(List<Map<String, Set<String>>> result) {
- assert result.size() == 2;
- @SuppressWarnings("unused") Map<String, Set<String>> deps = result.get(0);
- Map<String, Set<String>> missing = result.get(1);
-
- for (String fqcn : missing.keySet()) {
- mLog.info("%s", fqcn);
- }
- }
-
- // ----------------
-
- /**
- * Parses a JAR file and returns a list of all classes founds using a map
- * class name => ASM ClassReader. Class names are in the form "android.view.View".
- */
- Map<String,ClassReader> parseZip(List<String> jarPathList) throws IOException {
- TreeMap<String, ClassReader> classes = new TreeMap<>();
-
- for (String jarPath : jarPathList) {
- ZipFile zip = new ZipFile(jarPath);
- Enumeration<? extends ZipEntry> entries = zip.entries();
- ZipEntry entry;
- while (entries.hasMoreElements()) {
- entry = entries.nextElement();
- if (entry.getName().endsWith(".class")) {
- ClassReader cr = new ClassReader(zip.getInputStream(entry));
- String className = classReaderToClassName(cr);
- classes.put(className, cr);
- }
- }
- }
-
- return classes;
- }
-
- /**
- * Utility that returns the fully qualified binary class name for a ClassReader.
- * E.g. it returns something like android.view.View.
- */
- static String classReaderToClassName(ClassReader classReader) {
- if (classReader == null) {
- return null;
- } else {
- return classReader.getClassName().replace('/', '.');
- }
- }
-
- /**
- * Utility that returns the fully qualified binary class name from a path-like FQCN.
- * E.g. it returns android.view.View from android/view/View.
- */
- static String internalToBinaryClassName(String className) {
- if (className == null) {
- return null;
- } else {
- return className.replace('/', '.');
- }
- }
-
- /**
- * Finds all dependencies for all classes in keepClasses which are also
- * listed in zipClasses. Returns a map of all the dependencies found.
- */
- Map<String, Set<String>> findClassesDeps(Map<String, ClassReader> zipClasses) {
-
- // The dependencies that we'll collect.
- // It's a map Class name => uses class names.
- Map<String, Set<String>> dependencyMap = new TreeMap<>();
-
- DependencyVisitor visitor = getVisitor();
-
- int count = 0;
- try {
- for (Entry<String, ClassReader> entry : zipClasses.entrySet()) {
- String name = entry.getKey();
-
- TreeSet<String> set = new TreeSet<>();
- dependencyMap.put(name, set);
- visitor.setDependencySet(set);
-
- ClassReader cr = entry.getValue();
- cr.accept(visitor, 0 /* flags */);
-
- visitor.setDependencySet(null);
-
- mLog.debugNoln("Visited %d classes\r", ++count);
- }
- } finally {
- mLog.debugNoln("\n");
- }
-
- return dependencyMap;
- }
-
- /**
- * Computes which classes FQCN were found as dependencies that are NOT listed
- * in the original JAR classes.
- *
- * @param deps The map { FQCN => dependencies[] } returned by {@link #findClassesDeps(Map)}.
- * @param zipClasses The set of all classes FQCN found in the JAR files.
- * @return A map { FQCN not found in the zipClasses => classes using it }
- */
- private Map<String, Set<String>> findMissingClasses(
- Map<String, Set<String>> deps,
- Set<String> zipClasses) {
- Map<String, Set<String>> missing = new TreeMap<>();
-
- for (Entry<String, Set<String>> entry : deps.entrySet()) {
- String name = entry.getKey();
-
- for (String dep : entry.getValue()) {
- if (!zipClasses.contains(dep)) {
- // This dependency doesn't exist in the zip classes.
- Set<String> set = missing.get(dep);
- if (set == null) {
- set = new TreeSet<>();
- missing.put(dep, set);
- }
- set.add(name);
- }
- }
-
- }
-
- return missing;
- }
-
-
- // ----------------------------------
-
- /**
- * Instantiates a new DependencyVisitor. Useful for unit tests.
- */
- @VisibleForTesting(visibility=Visibility.PRIVATE)
- DependencyVisitor getVisitor() {
- return new DependencyVisitor();
- }
-
- /**
- * Visitor to collect all the type dependencies from a class.
- */
- public class DependencyVisitor extends ClassVisitor {
-
- private Set<String> mCurrentDepSet;
-
- /**
- * Creates a new visitor that will find all the dependencies for the visited class.
- */
- public DependencyVisitor() {
- super(Main.ASM_VERSION);
- }
-
- /**
- * Sets the {@link Set} where to record direct dependencies for this class.
- * This will change before each {@link ClassReader#accept(ClassVisitor, int)} call.
- */
- public void setDependencySet(Set<String> set) {
- mCurrentDepSet = set;
- }
-
- /**
- * Considers the given class name as a dependency.
- */
- public void considerName(String className) {
- if (className == null) {
- return;
- }
-
- className = internalToBinaryClassName(className);
-
- try {
- // exclude classes that are part of the default JRE (the one executing this program)
- // or in java package (we won't be able to load them anyway).
- if (className.startsWith("java.") ||
- getClass().getClassLoader().loadClass(className) != null) {
- return;
- }
- } catch (ClassNotFoundException e) {
- // ignore
- }
-
- // Add it to the dependency set for the currently visited class, as needed.
- assert mCurrentDepSet != null;
- mCurrentDepSet.add(className);
- }
-
- /**
- * Considers this array of names using considerName().
- */
- public void considerNames(String[] classNames) {
- if (classNames != null) {
- for (String className : classNames) {
- considerName(className);
- }
- }
- }
-
- /**
- * Considers this signature or type signature by invoking the {@link SignatureVisitor}
- * on it.
- */
- public void considerSignature(String signature) {
- if (signature != null) {
- SignatureReader sr = new SignatureReader(signature);
- // SignatureReader.accept will call accessType so we don't really have
- // to differentiate where the signature comes from.
- sr.accept(new MySignatureVisitor());
- }
- }
-
- /**
- * Considers this {@link Type}. For arrays, the element type is considered.
- * If the type is an object, it's internal name is considered.
- */
- public void considerType(Type t) {
- if (t != null) {
- if (t.getSort() == Type.ARRAY) {
- t = t.getElementType();
- }
- if (t.getSort() == Type.OBJECT) {
- considerName(t.getInternalName());
- }
- }
- }
-
- /**
- * Considers a descriptor string. The descriptor is converted to a {@link Type}
- * and then considerType() is invoked.
- */
- public boolean considerDesc(String desc) {
- if (desc != null) {
- try {
- if (desc.length() > 0 && desc.charAt(0) == '(') {
- // This is a method descriptor with arguments and a return type.
- Type t = Type.getReturnType(desc);
- considerType(t);
-
- for (Type arg : Type.getArgumentTypes(desc)) {
- considerType(arg);
- }
-
- } else {
- Type t = Type.getType(desc);
- considerType(t);
- }
- return true;
- } catch (ArrayIndexOutOfBoundsException e) {
- // ignore, not a valid type.
- }
- }
- return false;
- }
-
-
- // ---------------------------------------------------
- // --- ClassVisitor, FieldVisitor
- // ---------------------------------------------------
-
- // Visits a class header
- @Override
- public void visit(int version, int access, String name,
- String signature, String superName, String[] interfaces) {
- // signature is the signature of this class. May be null if the class is not a generic
- // one, and does not extend or implement generic classes or interfaces.
-
- if (signature != null) {
- considerSignature(signature);
- }
-
- // superName is the internal of name of the super class (see getInternalName).
- // For interfaces, the super class is Object. May be null but only for the Object class.
- considerName(superName);
-
- // interfaces is the internal names of the class's interfaces (see getInternalName).
- // May be null.
- considerNames(interfaces);
- }
-
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- // desc is the class descriptor of the annotation class.
- considerDesc(desc);
- return new MyAnnotationVisitor();
- }
-
- @Override
- public void visitAttribute(Attribute attr) {
- // pass
- }
-
- // Visits the end of a class
- @Override
- public void visitEnd() {
- // pass
- }
-
- private class MyFieldVisitor extends FieldVisitor {
-
- public MyFieldVisitor() {
- super(Main.ASM_VERSION);
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- // desc is the class descriptor of the annotation class.
- considerDesc(desc);
- return new MyAnnotationVisitor();
- }
-
- @Override
- public void visitAttribute(Attribute attr) {
- // pass
- }
-
- // Visits the end of a class
- @Override
- public void visitEnd() {
- // pass
- }
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc,
- String signature, Object value) {
- // desc is the field's descriptor (see Type).
- considerDesc(desc);
-
- // signature is the field's signature. May be null if the field's type does not use
- // generic types.
- considerSignature(signature);
-
- return new MyFieldVisitor();
- }
-
- @Override
- public void visitInnerClass(String name, String outerName, String innerName, int access) {
- // name is the internal name of an inner class (see getInternalName).
- // Note: outerName/innerName seems to be null when we're reading the
- // _Original_ClassName classes generated by layoutlib_create.
- if (outerName != null) {
- considerName(name);
- }
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
- // desc is the method's descriptor (see Type).
- considerDesc(desc);
- // signature is the method's signature. May be null if the method parameters, return
- // type and exceptions do not use generic types.
- considerSignature(signature);
-
- return new MyMethodVisitor();
- }
-
- @Override
- public void visitOuterClass(String owner, String name, String desc) {
- // pass
- }
-
- @Override
- public void visitSource(String source, String debug) {
- // pass
- }
-
-
- // ---------------------------------------------------
- // --- MethodVisitor
- // ---------------------------------------------------
-
- private class MyMethodVisitor extends MethodVisitor {
-
- public MyMethodVisitor() {
- super(Main.ASM_VERSION);
- }
-
-
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- return new MyAnnotationVisitor();
- }
-
- @Override
- public void visitCode() {
- // pass
- }
-
- // field instruction
- @Override
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- // owner is the class that declares the field.
- considerName(owner);
- // desc is the field's descriptor (see Type).
- considerDesc(desc);
- }
-
- @Override
- public void visitFrame(int type, int local, Object[] local2, int stack, Object[] stack2) {
- // pass
- }
-
- @Override
- public void visitIincInsn(int var, int increment) {
- // pass -- an IINC instruction
- }
-
- @Override
- public void visitInsn(int opcode) {
- // pass -- a zero operand instruction
- }
-
- @Override
- public void visitIntInsn(int opcode, int operand) {
- // pass -- a single int operand instruction
- }
-
- @Override
- public void visitJumpInsn(int opcode, Label label) {
- // pass -- a jump instruction
- }
-
- @Override
- public void visitLabel(Label label) {
- // pass -- a label target
- }
-
- // instruction to load a constant from the stack
- @Override
- public void visitLdcInsn(Object cst) {
- if (cst instanceof Type) {
- considerType((Type) cst);
- }
- }
-
- @Override
- public void visitLineNumber(int line, Label start) {
- // pass
- }
-
- @Override
- public void visitLocalVariable(String name, String desc,
- String signature, Label start, Label end, int index) {
- // desc is the type descriptor of this local variable.
- considerDesc(desc);
- // signature is the type signature of this local variable. May be null if the local
- // variable type does not use generic types.
- considerSignature(signature);
- }
-
- @Override
- public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
- // pass -- a lookup switch instruction
- }
-
- @Override
- public void visitMaxs(int maxStack, int maxLocals) {
- // pass
- }
-
- // instruction that invokes a method
- @Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc,
- boolean itf) {
-
- // owner is the internal name of the method's owner class
- if (!considerDesc(owner) && owner.indexOf('/') != -1) {
- considerName(owner);
- }
- // desc is the method's descriptor (see Type).
- considerDesc(desc);
- }
-
- // instruction multianewarray, whatever that is
- @Override
- public void visitMultiANewArrayInsn(String desc, int dims) {
-
- // desc an array type descriptor.
- considerDesc(desc);
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
- boolean visible) {
- // desc is the class descriptor of the annotation class.
- considerDesc(desc);
- return new MyAnnotationVisitor();
- }
-
- @Override
- public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
- // pass -- table switch instruction
-
- }
-
- @Override
- public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
- // type is the internal name of the type of exceptions handled by the handler,
- // or null to catch any exceptions (for "finally" blocks).
- considerName(type);
- }
-
- // type instruction
- @Override
- public void visitTypeInsn(int opcode, String type) {
- // type is the operand of the instruction to be visited. This operand must be the
- // internal name of an object or array class.
- considerName(type);
- }
-
- @Override
- public void visitVarInsn(int opcode, int var) {
- // pass -- local variable instruction
- }
- }
-
- private class MySignatureVisitor extends SignatureVisitor {
-
- public MySignatureVisitor() {
- super(Main.ASM_VERSION);
- }
-
- // ---------------------------------------------------
- // --- SignatureVisitor
- // ---------------------------------------------------
-
- private String mCurrentSignatureClass = null;
-
- // Starts the visit of a signature corresponding to a class or interface type
- @Override
- public void visitClassType(String name) {
- mCurrentSignatureClass = name;
- considerName(name);
- }
-
- // Visits an inner class
- @Override
- public void visitInnerClassType(String name) {
- if (mCurrentSignatureClass != null) {
- mCurrentSignatureClass += "$" + name;
- considerName(mCurrentSignatureClass);
- }
- }
-
- @Override
- public SignatureVisitor visitArrayType() {
- return new MySignatureVisitor();
- }
-
- @Override
- public void visitBaseType(char descriptor) {
- // pass -- a primitive type, ignored
- }
-
- @Override
- public SignatureVisitor visitClassBound() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitExceptionType() {
- return new MySignatureVisitor();
- }
-
- @Override
- public void visitFormalTypeParameter(String name) {
- // pass
- }
-
- @Override
- public SignatureVisitor visitInterface() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitInterfaceBound() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitParameterType() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitReturnType() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitSuperclass() {
- return new MySignatureVisitor();
- }
-
- @Override
- public SignatureVisitor visitTypeArgument(char wildcard) {
- return new MySignatureVisitor();
- }
-
- @Override
- public void visitTypeVariable(String name) {
- // pass
- }
-
- @Override
- public void visitTypeArgument() {
- // pass
- }
- }
-
-
- // ---------------------------------------------------
- // --- AnnotationVisitor
- // ---------------------------------------------------
-
- private class MyAnnotationVisitor extends AnnotationVisitor {
-
- public MyAnnotationVisitor() {
- super(Main.ASM_VERSION);
- }
-
- // Visits a primitive value of an annotation
- @Override
- public void visit(String name, Object value) {
- // value is the actual value, whose type must be Byte, Boolean, Character, Short,
- // Integer, Long, Float, Double, String or Type
- if (value instanceof Type) {
- considerType((Type) value);
- }
- }
-
- @Override
- public AnnotationVisitor visitAnnotation(String name, String desc) {
- // desc is the class descriptor of the nested annotation class.
- considerDesc(desc);
- return new MyAnnotationVisitor();
- }
-
- @Override
- public AnnotationVisitor visitArray(String name) {
- return new MyAnnotationVisitor();
- }
-
- @Override
- public void visitEnum(String name, String desc, String value) {
- // desc is the class descriptor of the enumeration class.
- considerDesc(desc);
- }
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create;
-
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.Opcodes;
-
-/**
- * Injects fields in a class.
- * <p>
- * TODO: Generify
- */
-public class FieldInjectorAdapter extends ClassVisitor {
- public FieldInjectorAdapter(ClassVisitor cv) {
- super(Opcodes.ASM4, cv);
- }
-
- @Override
- public void visitEnd() {
- super.visitField(Opcodes.ACC_PUBLIC, "mLayoutlibCallback",
- "Lcom/android/ide/common/rendering/api/LayoutlibCallback;", null, null);
- super.visitField(Opcodes.ACC_PUBLIC, "mContext",
- "Lcom/android/layoutlib/bridge/android/BridgeContext;", null, null);
- super.visitEnd();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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 java.util.Map;
-import java.util.Set;
-
-/**
- * Interface describing the work to be done by {@link AsmGenerator}.
- */
-public interface ICreateInfo {
-
- /**
- * Returns the list of class from layoutlib_create to inject in layoutlib.
- * The list can be empty but must not be null.
- */
- Class<?>[] getInjectedClasses();
-
- /**
- * Returns the list of methods to rewrite as delegates.
- * The list can be empty but must not be null.
- */
- String[] getDelegateMethods();
-
- /**
- * Returns the list of classes on which to delegate all native methods.
- * The list can be empty but must not be null.
- */
- String[] getDelegateClassNatives();
-
- /**
- * Returns the list of classes to rename, must be an even list: the binary FQCN
- * of class to replace followed by the new FQCN.
- * The list can be empty but must not be null.
- */
- String[] getRenamedClasses();
-
- /**
- * List of classes to refactor. This is similar to combining {@link #getRenamedClasses()} and
- * {@link #getJavaPkgClasses()}.
- * Classes included here will be renamed and then all their references in any other classes
- * will be also modified.
- * FQCN of class to refactor followed by its new FQCN.
- */
- String[] getRefactoredClasses();
-
- /**
- * Returns the 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
- * to rename in which the methods are deleted, followed by a list of return types identifying
- * the methods to delete.
- * The list can be empty but must not be null.
- */
- String[] getDeleteReturns();
-
- /**
- * Returns the list of classes to refactor, must be an even list: the
- * binary FQCN of class to replace followed by the new FQCN. All references
- * to the old class should be updated to the new class.
- * The list can be empty but must not be null.
- */
- String[] getJavaPkgClasses();
-
- 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 list of classes to be promoted to public visibility.
- */
- String[] getPromotedClasses();
-
- /**
- * 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.
- */
- Map<String, InjectMethodRunnable> getInjectedMethodsMap();
-
- abstract class InjectMethodRunnable {
- /**
- * @param cv Must be {@link ClassVisitor}. However, the param type is object so that when
- * loading the class, ClassVisitor is not loaded. This is because when injecting
- * CreateInfo in LayoutLib (see {@link #getInjectedClasses()}, we don't want to inject
- * asm classes also, but still keep CreateInfo loadable.
- */
- public abstract void generateMethods(Object cv);
- }
-}
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.create.ICreateInfo.InjectMethodRunnable;
-
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.MethodVisitor;
-
-import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
-import static org.objectweb.asm.Opcodes.ALOAD;
-import static org.objectweb.asm.Opcodes.ARETURN;
-import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
-
-public class InjectMethodRunnables {
- public static final ICreateInfo.InjectMethodRunnable CONTEXT_GET_FRAMEWORK_CLASS_LOADER
- = new InjectMethodRunnable() {
- @Override
- public void generateMethods(Object classVisitor) {
- assert classVisitor instanceof ClassVisitor;
- ClassVisitor cv = (ClassVisitor) classVisitor;
- // generated by compiling the class:
- // class foo { public ClassLoader getFrameworkClassLoader() { return getClass().getClassLoader(); } }
- // and then running ASMifier on it:
- // java -classpath asm-debug-all-5.0.2.jar:. org.objectweb.asm.util.ASMifier foo
- MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "getFrameworkClassLoader",
- "()Ljava/lang/ClassLoader;", null, null);
- mv.visitCode();
- mv.visitVarInsn(ALOAD, 0);
- mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "getClass",
- "()Ljava/lang/Class;", false);
- mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getClassLoader",
- "()Ljava/lang/ClassLoader;", false);
- mv.visitInsn(ARETURN);
- mv.visitMaxs(1, 1);
- mv.visitEnd();
- // generated code ends.
- }
- };
-}
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.create.ICreateInfo.InjectMethodRunnable;
-
-import org.objectweb.asm.ClassVisitor;
-
-/**
- * Injects methods into some classes.
- */
-public class InjectMethodsAdapter extends ClassVisitor {
-
- private final ICreateInfo.InjectMethodRunnable mRunnable;
-
- public InjectMethodsAdapter(ClassVisitor cv, InjectMethodRunnable runnable) {
- super(Main.ASM_VERSION, cv);
- mRunnable = runnable;
- }
-
- @Override
- public void visitEnd() {
- mRunnable.generateMethods(this);
- super.visitEnd();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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 java.io.PrintWriter;
-import java.io.StringWriter;
-
-public class Log {
-
- private boolean mVerbose = false;
-
- public void setVerbose(boolean verbose) {
- mVerbose = verbose;
- }
-
- public void debug(String format, Object... args) {
- if (mVerbose) {
- info(format, args);
- }
- }
-
- /** Similar to debug() but doesn't do a \n automatically. */
- public void debugNoln(String format, Object... args) {
- if (mVerbose) {
- String s = String.format(format, args);
- System.out.print(s);
- }
- }
-
- public void info(String format, Object... args) {
- String s = String.format(format, args);
- outPrintln(s);
- }
-
- public void error(String format, Object... args) {
- String s = String.format(format, args);
- errPrintln(s);
- }
-
- public void exception(Throwable t, String format, Object... args) {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- t.printStackTrace(pw);
- pw.flush();
- error(format + "\n" + sw.toString(), args);
- }
-
- /** for unit testing */
- protected void errPrintln(String msg) {
- System.err.println(msg);
- }
-
- /** for unit testing */
- protected void outPrintln(String msg) {
- System.out.println(msg);
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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;
-
-public class LogAbortException extends Exception {
-
- private final String mFormat;
- private final Object[] mArgs;
-
- public LogAbortException(String format, Object... args) {
- mFormat = format;
- mArgs = args;
- }
-
- public void error(Log log) {
- log.error(mFormat, mArgs);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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.Opcodes;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-
-/**
- * Entry point for the layoutlib_create tool.
- * <p/>
- * The tool does not currently rely on any external configuration file.
- * Instead the configuration is mostly done via the {@link CreateInfo} class.
- * <p/>
- * For a complete description of the tool and its implementation, please refer to
- * the "README.txt" file at the root of this project.
- * <p/>
- * For a quick test, invoke this as follows:
- * <pre>
- * $ make layoutlib
- * </pre>
- * which does:
- * <pre>
- * $ make layoutlib_create <bunch of framework jars>
- * $ java -jar out/host/linux-x86/framework/layoutlib_create.jar \
- * out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar \
- * out/target/common/obj/JAVA_LIBRARIES/core_intermediates/classes.jar \
- * out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
- * </pre>
- */
-public class Main {
-
- public static class Options {
- public boolean listAllDeps = false;
- public boolean listOnlyMissingDeps = false;
- }
-
- public static final int ASM_VERSION = Opcodes.ASM5;
-
- public static final Options sOptions = new Options();
-
- public static void main(String[] args) {
-
- Log log = new Log();
-
- ArrayList<String> osJarPath = new ArrayList<>();
- String[] osDestJar = { null };
-
- if (!processArgs(log, args, osJarPath, osDestJar)) {
- log.error("Usage: layoutlib_create [-v] output.jar input.jar ...");
- log.error("Usage: layoutlib_create [-v] [--list-deps|--missing-deps] input.jar ...");
- System.exit(1);
- }
-
- if (sOptions.listAllDeps || sOptions.listOnlyMissingDeps) {
- System.exit(listDeps(osJarPath, log));
-
- } else {
- System.exit(createLayoutLib(osDestJar[0], osJarPath, log));
- }
-
-
- System.exit(1);
- }
-
- private static int createLayoutLib(String osDestJar, ArrayList<String> osJarPath, Log log) {
- log.info("Output: %1$s", osDestJar);
- for (String path : osJarPath) {
- log.info("Input : %1$s", path);
- }
-
- try {
- CreateInfo info = new CreateInfo();
- Set<String> excludeClasses = info.getExcludedClasses();
- AsmGenerator agen = new AsmGenerator(log, osDestJar, info);
-
- AsmAnalyzer aa = new AsmAnalyzer(log, osJarPath, agen,
- new String[] { // derived from
- "android.view.View",
- "android.app.Fragment"
- },
- new String[] { // include classes
- "android.*", // for android.R
- "android.util.*",
- "com.android.internal.util.*",
- "android.view.*",
- "android.widget.*",
- "com.android.internal.widget.*",
- "android.text.**",
- "android.graphics.*",
- "android.graphics.drawable.**",
- "android.content.*",
- "android.content.res.*",
- "android.preference.*",
- "org.apache.harmony.xml.*",
- "com.android.internal.R**",
- "android.pim.*", // for datepicker
- "android.os.*", // for android.os.Handler
- "android.database.ContentObserver", // for Digital clock
- "com.android.i18n.phonenumbers.*", // for TextView with autolink attribute
- "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",
- "com.android.internal.graphics.drawable.AnimationScaleListDrawable",
- },
- excludeClasses,
- new String[] {
- "com/android/i18n/phonenumbers/data/*",
- "android/icu/impl/data/**"
- });
- aa.analyze();
- agen.generate();
-
- // Throw an error if any class failed to get renamed by the generator
- //
- // IMPORTANT: if you're building the platform and you get this error message,
- // it means the renameClasses[] array in AsmGenerator needs to be updated: some
- // class should have been renamed but it was not found in the input JAR files.
- Set<String> notRenamed = agen.getClassesNotRenamed();
- if (notRenamed.size() > 0) {
- // (80-column guide below for error formatting)
- // 01234567890123456789012345678901234567890123456789012345678901234567890123456789
- log.error(
- "ERROR when running layoutlib_create: the following classes are referenced\n" +
- "by tools/layoutlib/create but were not actually found in the input JAR files.\n" +
- "This may be due to some platform classes having been renamed.");
- for (String fqcn : notRenamed) {
- log.error("- Class not found: %s", fqcn.replace('/', '.'));
- }
- for (String path : osJarPath) {
- log.info("- Input JAR : %1$s", path);
- }
- return 1;
- }
-
- return 0;
- } catch (IOException e) {
- log.exception(e, "Failed to load jar");
- } catch (LogAbortException e) {
- e.error(log);
- }
-
- return 1;
- }
-
- private static int listDeps(ArrayList<String> osJarPath, Log log) {
- DependencyFinder df = new DependencyFinder(log);
- try {
- List<Map<String, Set<String>>> result = df.findDeps(osJarPath);
- if (sOptions.listAllDeps) {
- df.printAllDeps(result);
- } else if (sOptions.listOnlyMissingDeps) {
- df.printMissingDeps(result);
- }
- } catch (IOException e) {
- log.exception(e, "Failed to load jar");
- }
-
- return 0;
- }
-
- /**
- * Returns true if args where properly parsed.
- * Returns false if program should exit with command-line usage.
- * <p/>
- * Note: the String[0] is an output parameter wrapped in an array, since there is no
- * "out" parameter support.
- */
- private static boolean processArgs(Log log, String[] args,
- ArrayList<String> osJarPath, String[] osDestJar) {
- boolean needs_dest = true;
- for (String s : args) {
- if (s.equals("-v")) {
- log.setVerbose(true);
- } else if (s.equals("--list-deps")) {
- sOptions.listAllDeps = true;
- needs_dest = false;
- } else if (s.equals("--missing-deps")) {
- sOptions.listOnlyMissingDeps = true;
- needs_dest = false;
- } else if (!s.startsWith("-")) {
- if (needs_dest && osDestJar[0] == null) {
- osDestJar[0] = s;
- } else {
- osJarPath.add(s);
- }
- } else {
- log.error("Unknown argument: %s", s);
- return false;
- }
- }
-
- if (osJarPath.isEmpty()) {
- log.error("Missing parameter: path to input jar");
- return false;
- }
- if (needs_dest && osDestJar[0] == null) {
- log.error("Missing parameter: path to output jar");
- return false;
- }
-
- return true;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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;
-
-
-/**
- * An adapter to make it easier to use {@link MethodListener}.
- * <p/>
- * The adapter calls the void {@link #onInvokeV(String, boolean, Object)} listener
- * for all types (I, L, F, D and A), returning 0 or null as appropriate.
- */
-public class MethodAdapter implements MethodListener {
- /**
- * A stub method is being invoked.
- * <p/>
- * Known limitation: caller arguments are not available.
- *
- * @param signature The signature of the method being invoked, composed of the
- * binary class name followed by the method descriptor (aka argument
- * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V".
- * @param isNative True if the method was a native method.
- * @param caller The calling object. Null for static methods, "this" for instance methods.
- */
- @Override
- public void onInvokeV(String signature, boolean isNative, Object caller) {
- }
-
- /**
- * Same as {@link #onInvokeV(String, boolean, Object)} but returns an integer or similar.
- * @see #onInvokeV(String, boolean, Object)
- * @return an integer, or a boolean, or a short or a byte.
- */
- @Override
- public int onInvokeI(String signature, boolean isNative, Object caller) {
- onInvokeV(signature, isNative, caller);
- return 0;
- }
-
- /**
- * Same as {@link #onInvokeV(String, boolean, Object)} but returns a long.
- * @see #onInvokeV(String, boolean, Object)
- * @return a long.
- */
- @Override
- public long onInvokeL(String signature, boolean isNative, Object caller) {
- onInvokeV(signature, isNative, caller);
- return 0;
- }
-
- /**
- * Same as {@link #onInvokeV(String, boolean, Object)} but returns a float.
- * @see #onInvokeV(String, boolean, Object)
- * @return a float.
- */
- @Override
- public float onInvokeF(String signature, boolean isNative, Object caller) {
- onInvokeV(signature, isNative, caller);
- return 0;
- }
-
- /**
- * Same as {@link #onInvokeV(String, boolean, Object)} but returns a double.
- * @see #onInvokeV(String, boolean, Object)
- * @return a double.
- */
- @Override
- public double onInvokeD(String signature, boolean isNative, Object caller) {
- onInvokeV(signature, isNative, caller);
- return 0;
- }
-
- /**
- * Same as {@link #onInvokeV(String, boolean, Object)} but returns an object.
- * @see #onInvokeV(String, boolean, Object)
- * @return an object.
- */
- @Override
- public Object onInvokeA(String signature, boolean isNative, Object caller) {
- onInvokeV(signature, isNative, caller);
- return null;
- }
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2008 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;
-
-
-/**
- * Interface to allow a method invocation to be listened upon.
- * <p/>
- * This is used by {@link OverrideMethod} to register a listener for methods that
- * have been stubbed by the {@link AsmGenerator}. At runtime the stub will call either a
- * default global listener or a specific listener based on the method signature.
- */
-public interface MethodListener {
- /**
- * A stub method is being invoked.
- * <p/>
- * Known limitation: caller arguments are not available.
- *
- * @param signature The signature of the method being invoked, composed of the
- * binary class name followed by the method descriptor (aka argument
- * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V".
- * @param isNative True if the method was a native method.
- * @param caller The calling object. Null for static methods, "this" for instance methods.
- */
- void onInvokeV(String signature, boolean isNative, Object caller);
-
- /**
- * Same as {@link #onInvokeV(String, boolean, Object)} but returns an integer or similar.
- * @see #onInvokeV(String, boolean, Object)
- * @return an integer, or a boolean, or a short or a byte.
- */
- int onInvokeI(String signature, boolean isNative, Object caller);
-
- /**
- * Same as {@link #onInvokeV(String, boolean, Object)} but returns a long.
- * @see #onInvokeV(String, boolean, Object)
- * @return a long.
- */
- long onInvokeL(String signature, boolean isNative, Object caller);
-
- /**
- * Same as {@link #onInvokeV(String, boolean, Object)} but returns a float.
- * @see #onInvokeV(String, boolean, Object)
- * @return a float.
- */
- float onInvokeF(String signature, boolean isNative, Object caller);
-
- /**
- * Same as {@link #onInvokeV(String, boolean, Object)} but returns a double.
- * @see #onInvokeV(String, boolean, Object)
- * @return a double.
- */
- double onInvokeD(String signature, boolean isNative, Object caller);
-
- /**
- * Same as {@link #onInvokeV(String, boolean, Object)} but returns an object.
- * @see #onInvokeV(String, boolean, Object)
- * @return an object.
- */
- Object onInvokeA(String signature, boolean isNative, Object caller);
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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 java.util.HashMap;
-
-/**
- * Allows stub methods from LayoutLib to be overriden at runtime.
- * <p/>
- * Implementation note: all types required by this class(inner/outer classes & interfaces)
- * must be referenced by the injectClass argument to {@link AsmGenerator} in Main.java;
- * Otherwise they won't be accessible in layoutlib.jar at runtime.
- */
-public final class OverrideMethod {
-
- /** Map of method overridden. */
- private static HashMap<String, MethodListener> sMethods = new HashMap<>();
- /** Default listener for all method not listed in sMethods. Nothing if null. */
- private static MethodListener sDefaultListener = null;
-
- /**
- * Sets the default listener for all methods not specifically handled.
- * Null means to do nothing.
- */
- @SuppressWarnings("UnusedDeclaration") // Used by Bridge by reflection for debug purposes.
- public static void setDefaultListener(MethodListener listener) {
- sDefaultListener = listener;
- }
-
- /**
- * Defines or reset a listener for the given method signature.
- *
- * @param signature The signature of the method being invoked, composed of the
- * binary class name followed by the method descriptor (aka argument
- * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V"
- * @param listener The new listener. Removes it if null.
- */
- public static void setMethodListener(String signature, MethodListener listener) {
- if (listener == null) {
- sMethods.remove(signature);
- } else {
- sMethods.put(signature, listener);
- }
- }
-
- /**
- * Invokes the specific listener for the given signature or the default one if defined.
- * <p/>
- * This version invokes the method listener for the void return type.
- * <p/>
- * Note: this is not intended to be used by the LayoutLib Bridge. It is intended to be called
- * by the stubbed methods generated by the LayoutLib_create tool.
- *
- * @param signature The signature of the method being invoked, composed of the
- * binary class name followed by the method descriptor (aka argument
- * types). Example: "com/foo/MyClass/InnerClass/printInt(I)V".
- * @param isNative True if the method was a native method.
- * @param caller The calling object. Null for static methods, "this" for instance methods.
- */
- public static void invokeV(String signature, boolean isNative, Object caller) {
- MethodListener i = sMethods.get(signature);
- if (i != null) {
- i.onInvokeV(signature, isNative, caller);
- } else if (sDefaultListener != null) {
- sDefaultListener.onInvokeV(signature, isNative, caller);
- }
- }
-
- /**
- * Invokes the specific listener for the int return type.
- * @see #invokeV(String, boolean, Object)
- */
- public static int invokeI(String signature, boolean isNative, Object caller) {
- MethodListener i = sMethods.get(signature);
- if (i != null) {
- return i.onInvokeI(signature, isNative, caller);
- } else if (sDefaultListener != null) {
- return sDefaultListener.onInvokeI(signature, isNative, caller);
- }
- return 0;
- }
-
- /**
- * Invokes the specific listener for the long return type.
- * @see #invokeV(String, boolean, Object)
- */
- public static long invokeL(String signature, boolean isNative, Object caller) {
- MethodListener i = sMethods.get(signature);
- if (i != null) {
- return i.onInvokeL(signature, isNative, caller);
- } else if (sDefaultListener != null) {
- return sDefaultListener.onInvokeL(signature, isNative, caller);
- }
- return 0;
- }
-
- /**
- * Invokes the specific listener for the float return type.
- * @see #invokeV(String, boolean, Object)
- */
- public static float invokeF(String signature, boolean isNative, Object caller) {
- MethodListener i = sMethods.get(signature);
- if (i != null) {
- return i.onInvokeF(signature, isNative, caller);
- } else if (sDefaultListener != null) {
- return sDefaultListener.onInvokeF(signature, isNative, caller);
- }
- return 0;
- }
-
- /**
- * Invokes the specific listener for the double return type.
- * @see #invokeV(String, boolean, Object)
- */
- public static double invokeD(String signature, boolean isNative, Object caller) {
- MethodListener i = sMethods.get(signature);
- if (i != null) {
- return i.onInvokeD(signature, isNative, caller);
- } else if (sDefaultListener != null) {
- return sDefaultListener.onInvokeD(signature, isNative, caller);
- }
- return 0;
- }
-
- /**
- * Invokes the specific listener for the object return type.
- * @see #invokeV(String, boolean, Object)
- */
- public static Object invokeA(String signature, boolean isNative, Object caller) {
- MethodListener i = sMethods.get(signature);
- if (i != null) {
- return i.onInvokeA(signature, isNative, caller);
- } else if (sDefaultListener != null) {
- return sDefaultListener.onInvokeA(signature, isNative, caller);
- }
- return null;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create;
-
-import org.objectweb.asm.ClassVisitor;
-
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
-import static org.objectweb.asm.Opcodes.ACC_PROTECTED;
-import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
-
-/**
- * Promotes given classes to public visibility.
- */
-public class PromoteClassClassAdapter extends ClassVisitor {
-
- private final Set<String> mClassNames;
- private static final int CLEAR_PRIVATE_MASK = ~(ACC_PRIVATE | ACC_PROTECTED);
-
- public PromoteClassClassAdapter(ClassVisitor cv, Set<String> classNames) {
- super(Main.ASM_VERSION, cv);
- mClassNames =
- classNames.stream().map(name -> name.replace(".", "/")).collect(Collectors.toSet());
- }
-
- @Override
- public void visit(int version, int access, String name, String signature, String superName,
- String[] interfaces) {
- if (mClassNames.contains(name)) {
- if ((access & ACC_PUBLIC) == 0) {
- access = (access & CLEAR_PRIVATE_MASK) | ACC_PUBLIC;
- }
- }
-
- super.visit(version, access, name, signature, superName, interfaces);
- }
-
- @Override
- public void visitInnerClass(String name, String outerName, String innerName, int access) {
- if (mClassNames.contains(name)) {
- if ((access & ACC_PUBLIC) == 0) {
- access = (access & CLEAR_PRIVATE_MASK) | ACC_PUBLIC;
- }
- }
-
- super.visitInnerClass(name, outerName, innerName, access);
- }
-}
+++ /dev/null
-/*
- * 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;
-
-/**
- * Promotes given fields to public visibility.
- */
-public class PromoteFieldClassAdapter extends ClassVisitor {
-
- private final Set<String> mFieldNames;
- private static final int CLEAR_PRIVATE_MASK = ~(ACC_PRIVATE | ACC_PROTECTED);
-
- public PromoteFieldClassAdapter(ClassVisitor cv, Set<String> fieldNames) {
- super(Main.ASM_VERSION, 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 & CLEAR_PRIVATE_MASK) | ACC_PUBLIC;
- }
- }
- return super.visitField(access, name, desc, signature, value);
- }
-}
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.create;
-
-import java.util.Arrays;
-import java.util.HashMap;
-
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.MethodVisitor;
-
-public class RefactorClassAdapter extends AbstractClassAdapter {
-
- private final HashMap<String, String> mRefactorClasses;
-
- RefactorClassAdapter(ClassVisitor cv, HashMap<String, String> refactorClasses) {
- super(cv);
- mRefactorClasses = refactorClasses;
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc, String signature,
- String[] exceptions) {
- MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
-
- return new RefactorStackMapAdapter(mw);
- }
-
- @Override
- protected String renameInternalType(String oldClassName) {
- if (oldClassName != null) {
- String newName = mRefactorClasses.get(oldClassName);
- if (newName != null) {
- return newName;
- }
- int pos = oldClassName.indexOf('$');
- if (pos > 0) {
- newName = mRefactorClasses.get(oldClassName.substring(0, pos));
- if (newName != null) {
- return newName + oldClassName.substring(pos);
- }
- }
- }
- return oldClassName;
- }
-
- /**
- * A method visitor that renames all references from an old class name to a new class name in
- * the stackmap of the method.
- */
- private class RefactorStackMapAdapter extends MethodVisitor {
-
- private RefactorStackMapAdapter(MethodVisitor mv) {
- super(Main.ASM_VERSION, mv);
- }
-
-
- private Object[] renameFrame(Object[] elements) {
- if (elements == null) {
- return null;
- }
-
- // The input array cannot be modified. We only copy the source array on write
- boolean copied = false;
- for (int i = 0; i < elements.length; i++) {
- if (!(elements[i] instanceof String)) {
- continue;
- }
-
- if (!copied) {
- elements = Arrays.copyOf(elements, elements.length);
- copied = true;
- }
-
- String type = (String)elements[i];
- if (type.indexOf(';') > 0) {
- elements[i] = renameTypeDesc(type);
- } else {
- elements[i] = renameInternalType(type);
- }
- }
-
- return elements;
- }
-
- @Override
- public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
- super.visitFrame(type, nLocal, renameFrame(local), nStack, renameFrame(stack));
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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;
-
-/**
- * This class visitor renames a class from a given old name to a given new name.
- * The class visitor will also rename all inner classes and references in the methods.
- * <p/>
- *
- * For inner classes, this handles only the case where the outer class name changes.
- * The inner class name should remain the same.
- */
-public class RenameClassAdapter extends AbstractClassAdapter {
-
-
- private final String mOldName;
- private final String mNewName;
- private String mOldBase;
- private String mNewBase;
-
- /**
- * Creates a class visitor that renames a class from a given old name to a given new name.
- * The class visitor will also rename all inner classes and references in the methods.
- * The names must be full qualified internal ASM names (e.g. com/blah/MyClass$InnerClass).
- */
- public RenameClassAdapter(ClassVisitor cv, String oldName, String newName) {
- super(cv);
- mOldBase = mOldName = oldName;
- mNewBase = mNewName = newName;
-
- int pos = mOldName.indexOf('$');
- if (pos > 0) {
- mOldBase = mOldName.substring(0, pos);
- }
- pos = mNewName.indexOf('$');
- if (pos > 0) {
- mNewBase = mNewName.substring(0, pos);
- }
-
- assert (mOldBase == null && mNewBase == null) || (mOldBase != null && mNewBase != null);
- }
-
- /**
- * Renames an internal type name, e.g. "com.package.MyClass".
- * If the type doesn't need to be renamed, returns the input string as-is.
- * <p/>
- * The internal type of some of the MethodVisitor turns out to be a type
- descriptor sometimes so descriptors are renamed too.
- */
- @Override
- protected String renameInternalType(String type) {
- if (type == null) {
- return null;
- }
-
- if (type.equals(mOldName)) {
- return mNewName;
- }
-
- if (!mOldBase.equals(mOldName) && type.equals(mOldBase)) {
- return mNewBase;
- }
-
- int pos = type.indexOf('$');
- if (pos == mOldBase.length() && type.startsWith(mOldBase)) {
- return mNewBase + type.substring(pos);
- }
- return type;
- }
-
-}
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.create;
-
-import com.android.tools.layoutlib.java.LinkedHashMap_Delegate;
-import com.android.tools.layoutlib.java.System_Delegate;
-
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Replaces calls to certain methods that do not exist in the Desktop VM. Useful for methods in the
- * "java" package.
- */
-public class ReplaceMethodCallsAdapter extends ClassVisitor {
-
- /**
- * Descriptors for specialized versions {@link System#arraycopy} that are not present on the
- * Desktop VM.
- */
- private static Set<String> ARRAYCOPY_DESCRIPTORS = new HashSet<>(Arrays.asList(
- "([CI[CII)V", "([BI[BII)V", "([SI[SII)V", "([II[III)V",
- "([JI[JII)V", "([FI[FII)V", "([DI[DII)V", "([ZI[ZII)V"));
-
- private static final List<MethodReplacer> METHOD_REPLACERS = new ArrayList<>(5);
-
- private static final String ANDROID_LOCALE_CLASS =
- "com/android/layoutlib/bridge/android/AndroidLocale";
-
- private static final String JAVA_LOCALE_CLASS = Type.getInternalName(java.util.Locale.class);
- private static final Type STRING = Type.getType(String.class);
-
- private static final String JAVA_LANG_SYSTEM = Type.getInternalName(System.class);
-
- // Static initialization block to initialize METHOD_REPLACERS.
- static {
- // Case 1: java.lang.System.arraycopy()
- METHOD_REPLACERS.add(new MethodReplacer() {
- @Override
- public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
- return JAVA_LANG_SYSTEM.equals(owner) && "arraycopy".equals(name) &&
- ARRAYCOPY_DESCRIPTORS.contains(desc);
- }
-
- @Override
- public void replace(MethodInformation mi) {
- mi.desc = "(Ljava/lang/Object;ILjava/lang/Object;II)V";
- }
- });
-
- // Case 2: java.util.Locale.toLanguageTag() and java.util.Locale.getScript()
- METHOD_REPLACERS.add(new MethodReplacer() {
-
- private final String LOCALE_TO_STRING =
- Type.getMethodDescriptor(STRING, Type.getType(Locale.class));
-
- @Override
- public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
- return JAVA_LOCALE_CLASS.equals(owner) && "()Ljava/lang/String;".equals(desc) &&
- ("toLanguageTag".equals(name) || "getScript".equals(name));
- }
-
- @Override
- public void replace(MethodInformation mi) {
- mi.opcode = Opcodes.INVOKESTATIC;
- mi.owner = ANDROID_LOCALE_CLASS;
- mi.desc = LOCALE_TO_STRING;
- }
- });
-
- // 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) ||
- "getDefault".equals(name) && desc.equals(VOID_TO_LOCALE));
- }
-
- @Override
- public void replace(MethodInformation mi) {
- mi.owner = ANDROID_LOCALE_CLASS;
- }
- });
-
- // Case 4: java.lang.System.log?()
- METHOD_REPLACERS.add(new MethodReplacer() {
- @Override
- public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
- return JAVA_LANG_SYSTEM.equals(owner) && name.length() == 4
- && name.startsWith("log");
- }
-
- @Override
- public void replace(MethodInformation mi) {
- assert mi.desc.equals("(Ljava/lang/String;Ljava/lang/Throwable;)V")
- || mi.desc.equals("(Ljava/lang/String;)V");
- mi.name = "log";
- mi.owner = Type.getInternalName(System_Delegate.class);
- }
- });
-
- // Case 5: java.lang.System time calls
- METHOD_REPLACERS.add(new MethodReplacer() {
- @Override
- public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
- return JAVA_LANG_SYSTEM.equals(owner) && name.equals("nanoTime");
- }
-
- @Override
- public void replace(MethodInformation mi) {
- mi.name = "nanoTime";
- mi.owner = Type.getInternalName(System_Delegate.class);
- }
- });
- METHOD_REPLACERS.add(new MethodReplacer() {
- @Override
- public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
- return JAVA_LANG_SYSTEM.equals(owner) && name.equals("currentTimeMillis");
- }
-
- @Override
- public void replace(MethodInformation mi) {
- mi.name = "currentTimeMillis";
- mi.owner = Type.getInternalName(System_Delegate.class);
- }
- });
-
- // Case 6: java.util.LinkedHashMap.eldest()
- METHOD_REPLACERS.add(new MethodReplacer() {
-
- private final String VOID_TO_MAP_ENTRY =
- Type.getMethodDescriptor(Type.getType(Map.Entry.class));
- private final String LINKED_HASH_MAP = Type.getInternalName(LinkedHashMap.class);
-
- @Override
- public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
- return LINKED_HASH_MAP.equals(owner) &&
- "eldest".equals(name) &&
- VOID_TO_MAP_ENTRY.equals(desc);
- }
-
- @Override
- public void replace(MethodInformation mi) {
- mi.opcode = Opcodes.INVOKESTATIC;
- mi.owner = Type.getInternalName(LinkedHashMap_Delegate.class);
- mi.desc = Type.getMethodDescriptor(
- Type.getType(Map.Entry.class), Type.getType(LinkedHashMap.class));
- }
- });
-
- // Case 7: android.content.Context.getClassLoader() in LayoutInflater
- METHOD_REPLACERS.add(new MethodReplacer() {
- // When LayoutInflater asks for a class loader, we must return the class loader that
- // cannot return app's custom views/classes. This is so that in case of any failure
- // or exception when instantiating the views, the IDE can replace it with a mock view
- // and have proper error handling. However, if a custom view asks for the class
- // loader, we must return a class loader that can find app's custom views as well.
- // Thus, we rewrite the call to get class loader in LayoutInflater to
- // getFrameworkClassLoader and inject a new method in Context. This leaves the normal
- // method: Context.getClassLoader() free to be used by the apps.
- private final String VOID_TO_CLASS_LOADER =
- Type.getMethodDescriptor(Type.getType(ClassLoader.class));
-
- @Override
- public boolean isNeeded(String owner, String name, String desc, String sourceClass) {
- return owner.equals("android/content/Context") &&
- sourceClass.equals("android/view/LayoutInflater") &&
- name.equals("getClassLoader") &&
- desc.equals(VOID_TO_CLASS_LOADER);
- }
-
- @Override
- public void replace(MethodInformation mi) {
- mi.name = "getFrameworkClassLoader";
- }
- });
- }
-
- /**
- * If a method some.package.Class.Method(args) is called from some.other.Class,
- * @param owner some/package/Class
- * @param name Method
- * @param desc (args)returnType
- * @param sourceClass some/other/Class
- * @return if the method invocation needs to be replaced by some other class.
- */
- public static boolean isReplacementNeeded(String owner, String name, String desc,
- String sourceClass) {
- for (MethodReplacer replacer : METHOD_REPLACERS) {
- if (replacer.isNeeded(owner, name, desc, sourceClass)) {
- return true;
- }
- }
- return false;
- }
-
- private final String mOriginalClassName;
-
- public ReplaceMethodCallsAdapter(ClassVisitor cv, String originalClassName) {
- super(Main.ASM_VERSION, cv);
- mOriginalClassName = originalClassName;
- }
-
- @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 class MyMethodVisitor extends MethodVisitor {
-
- public MyMethodVisitor(MethodVisitor mv) {
- super(Main.ASM_VERSION, mv);
- }
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc,
- boolean itf) {
- for (MethodReplacer replacer : METHOD_REPLACERS) {
- if (replacer.isNeeded(owner, name, desc, mOriginalClassName)) {
- MethodInformation mi = new MethodInformation(opcode, owner, name, desc);
- replacer.replace(mi);
- opcode = mi.opcode;
- owner = mi.owner;
- name = mi.name;
- desc = mi.desc;
- break;
- }
- }
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- }
- }
-
- private static class MethodInformation {
- public int opcode;
- public String owner;
- public String name;
- public String desc;
-
- public MethodInformation(int opcode, String owner, String name, String desc) {
- this.opcode = opcode;
- this.owner = owner;
- this.name = name;
- this.desc = desc;
- }
- }
-
- private interface MethodReplacer {
- boolean isNeeded(String owner, String name, String desc, String sourceClass);
-
- /**
- * Updates the MethodInformation with the new values of the method attributes -
- * opcode, owner, name and desc.
- */
- void replace(MethodInformation mi);
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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.AnnotationVisitor;
-import org.objectweb.asm.Attribute;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-/**
- * This method adapter rewrites a method by discarding the original code and generating
- * a stub depending on the return type. Original annotations are passed along unchanged.
- */
-class StubMethodAdapter extends MethodVisitor {
-
- private static final String CONSTRUCTOR = "<init>";
- private static final String CLASS_INIT = "<clinit>";
-
- /** The parent method writer */
- private MethodVisitor mParentVisitor;
- /** The method return type. Can be null. */
- private Type mReturnType;
- /** Message to be printed by stub methods. */
- private String mInvokeSignature;
- /** Flag to output the first line number. */
- private boolean mOutputFirstLineNumber = true;
- /** Flag that is true when implementing a constructor, to accept all original
- * code calling the original super constructor. */
- private boolean mIsInitMethod = false;
-
- private boolean mMessageGenerated;
- private final boolean mIsStatic;
- private final boolean mIsNative;
-
- public StubMethodAdapter(MethodVisitor mv, String methodName, Type returnType,
- String invokeSignature, boolean isStatic, boolean isNative) {
- super(Main.ASM_VERSION);
- mParentVisitor = mv;
- mReturnType = returnType;
- mInvokeSignature = invokeSignature;
- mIsStatic = isStatic;
- mIsNative = isNative;
-
- if (CONSTRUCTOR.equals(methodName) || CLASS_INIT.equals(methodName)) {
- mIsInitMethod = true;
- }
- }
-
- private void generateInvoke() {
- /* Generates the code:
- * OverrideMethod.invoke("signature", mIsNative ? true : false, null or this);
- */
- mParentVisitor.visitLdcInsn(mInvokeSignature);
- // push true or false
- mParentVisitor.visitInsn(mIsNative ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
- // push null or this
- if (mIsStatic) {
- mParentVisitor.visitInsn(Opcodes.ACONST_NULL);
- } else {
- mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0);
- }
-
- int sort = mReturnType != null ? mReturnType.getSort() : Type.VOID;
- switch(sort) {
- case Type.VOID:
- mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
- "com/android/tools/layoutlib/create/OverrideMethod",
- "invokeV",
- "(Ljava/lang/String;ZLjava/lang/Object;)V",
- false);
- mParentVisitor.visitInsn(Opcodes.RETURN);
- break;
- case Type.BOOLEAN:
- case Type.CHAR:
- case Type.BYTE:
- case Type.SHORT:
- case Type.INT:
- mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
- "com/android/tools/layoutlib/create/OverrideMethod",
- "invokeI",
- "(Ljava/lang/String;ZLjava/lang/Object;)I",
- false);
- switch(sort) {
- case Type.BOOLEAN:
- Label l1 = new Label();
- mParentVisitor.visitJumpInsn(Opcodes.IFEQ, l1);
- mParentVisitor.visitInsn(Opcodes.ICONST_1);
- mParentVisitor.visitInsn(Opcodes.IRETURN);
- mParentVisitor.visitLabel(l1);
- mParentVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
- mParentVisitor.visitInsn(Opcodes.ICONST_0);
- break;
- case Type.CHAR:
- mParentVisitor.visitInsn(Opcodes.I2C);
- break;
- case Type.BYTE:
- mParentVisitor.visitInsn(Opcodes.I2B);
- break;
- case Type.SHORT:
- mParentVisitor.visitInsn(Opcodes.I2S);
- break;
- }
- mParentVisitor.visitInsn(Opcodes.IRETURN);
- break;
- case Type.LONG:
- mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
- "com/android/tools/layoutlib/create/OverrideMethod",
- "invokeL",
- "(Ljava/lang/String;ZLjava/lang/Object;)J",
- false);
- mParentVisitor.visitInsn(Opcodes.LRETURN);
- break;
- case Type.FLOAT:
- mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
- "com/android/tools/layoutlib/create/OverrideMethod",
- "invokeF",
- "(Ljava/lang/String;ZLjava/lang/Object;)F",
- false);
- mParentVisitor.visitInsn(Opcodes.FRETURN);
- break;
- case Type.DOUBLE:
- mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
- "com/android/tools/layoutlib/create/OverrideMethod",
- "invokeD",
- "(Ljava/lang/String;ZLjava/lang/Object;)D",
- false);
- mParentVisitor.visitInsn(Opcodes.DRETURN);
- break;
- case Type.ARRAY:
- case Type.OBJECT:
- mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
- "com/android/tools/layoutlib/create/OverrideMethod",
- "invokeA",
- "(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;",
- false);
- mParentVisitor.visitTypeInsn(Opcodes.CHECKCAST, mReturnType.getInternalName());
- mParentVisitor.visitInsn(Opcodes.ARETURN);
- break;
- }
-
- }
-
- private void generatePop() {
- /* Pops the stack, depending on the return type.
- */
- switch(mReturnType != null ? mReturnType.getSort() : Type.VOID) {
- case Type.VOID:
- break;
- case Type.BOOLEAN:
- case Type.CHAR:
- case Type.BYTE:
- case Type.SHORT:
- case Type.INT:
- case Type.FLOAT:
- case Type.ARRAY:
- case Type.OBJECT:
- mParentVisitor.visitInsn(Opcodes.POP);
- break;
- case Type.LONG:
- case Type.DOUBLE:
- mParentVisitor.visitInsn(Opcodes.POP2);
- break;
- }
- }
-
- /* Pass down to visitor writer. In this implementation, either do nothing. */
- @Override
- public void visitCode() {
- mParentVisitor.visitCode();
- }
-
- /*
- * visitMaxs is called just before visitEnd if there was any code to rewrite.
- * For non-constructor, generate the messaging code and the return statement
- * if it hasn't been done before.
- */
- @Override
- public void visitMaxs(int maxStack, int maxLocals) {
- if (!mIsInitMethod && !mMessageGenerated) {
- generateInvoke();
- mMessageGenerated = true;
- }
- mParentVisitor.visitMaxs(maxStack, maxLocals);
- }
-
- /**
- * End of visiting.
- * For non-constructor, generate the messaging code and the return statement
- * if it hasn't been done before.
- */
- @Override
- public void visitEnd() {
- if (!mIsInitMethod && !mMessageGenerated) {
- generateInvoke();
- mMessageGenerated = true;
- mParentVisitor.visitMaxs(1, 1);
- }
- mParentVisitor.visitEnd();
- }
-
- /* Writes all annotation from the original method. */
- @Override
- public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
- return mParentVisitor.visitAnnotation(desc, visible);
- }
-
- /* Writes all annotation default values from the original method. */
- @Override
- public AnnotationVisitor visitAnnotationDefault() {
- return mParentVisitor.visitAnnotationDefault();
- }
-
- @Override
- public AnnotationVisitor visitParameterAnnotation(int parameter, String desc,
- boolean visible) {
- return mParentVisitor.visitParameterAnnotation(parameter, desc, visible);
- }
-
- /* Writes all attributes from the original method. */
- @Override
- public void visitAttribute(Attribute attr) {
- mParentVisitor.visitAttribute(attr);
- }
-
- /*
- * Only writes the first line number present in the original code so that source
- * viewers can direct to the correct method, even if the content doesn't match.
- */
- @Override
- public void visitLineNumber(int line, Label start) {
- if (mIsInitMethod || mOutputFirstLineNumber) {
- mParentVisitor.visitLineNumber(line, start);
- mOutputFirstLineNumber = false;
- }
- }
-
- /**
- * For non-constructor, rewrite existing "return" instructions to write the message.
- */
- @Override
- public void visitInsn(int opcode) {
- if (mIsInitMethod) {
- switch (opcode) {
- case Opcodes.RETURN:
- case Opcodes.ARETURN:
- case Opcodes.DRETURN:
- case Opcodes.FRETURN:
- case Opcodes.IRETURN:
- case Opcodes.LRETURN:
- // Pop the last word from the stack since invoke will generate its own return.
- generatePop();
- generateInvoke();
- mMessageGenerated = true;
- //$FALL-THROUGH$
- default:
- mParentVisitor.visitInsn(opcode);
- }
- }
- }
-
- @Override
- public void visitLabel(Label label) {
- if (mIsInitMethod) {
- mParentVisitor.visitLabel(label);
- }
- }
-
- @Override
- public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
- if (mIsInitMethod) {
- mParentVisitor.visitTryCatchBlock(start, end, handler, type);
- }
- }
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
- if (mIsInitMethod) {
- mParentVisitor.visitMethodInsn(opcode, owner, name, desc, itf);
- }
- }
-
- @Override
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- if (mIsInitMethod) {
- mParentVisitor.visitFieldInsn(opcode, owner, name, desc);
- }
- }
-
- @Override
- public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
- if (mIsInitMethod) {
- mParentVisitor.visitFrame(type, nLocal, local, nStack, stack);
- }
- }
-
- @Override
- public void visitIincInsn(int var, int increment) {
- if (mIsInitMethod) {
- mParentVisitor.visitIincInsn(var, increment);
- }
- }
-
- @Override
- public void visitIntInsn(int opcode, int operand) {
- if (mIsInitMethod) {
- mParentVisitor.visitIntInsn(opcode, operand);
- }
- }
-
- @Override
- public void visitJumpInsn(int opcode, Label label) {
- if (mIsInitMethod) {
- mParentVisitor.visitJumpInsn(opcode, label);
- }
- }
-
- @Override
- public void visitLdcInsn(Object cst) {
- if (mIsInitMethod) {
- mParentVisitor.visitLdcInsn(cst);
- }
- }
-
- @Override
- public void visitLocalVariable(String name, String desc, String signature,
- Label start, Label end, int index) {
- if (mIsInitMethod) {
- mParentVisitor.visitLocalVariable(name, desc, signature, start, end, index);
- }
- }
-
- @Override
- public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
- if (mIsInitMethod) {
- mParentVisitor.visitLookupSwitchInsn(dflt, keys, labels);
- }
- }
-
- @Override
- public void visitMultiANewArrayInsn(String desc, int dims) {
- if (mIsInitMethod) {
- mParentVisitor.visitMultiANewArrayInsn(desc, dims);
- }
- }
-
- @Override
- public void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels) {
- if (mIsInitMethod) {
- mParentVisitor.visitTableSwitchInsn(min, max, dflt, labels);
- }
- }
-
- @Override
- public void visitTypeInsn(int opcode, String type) {
- if (mIsInitMethod) {
- mParentVisitor.visitTypeInsn(opcode, type);
- }
- }
-
- @Override
- public void visitVarInsn(int opcode, int var) {
- if (mIsInitMethod) {
- mParentVisitor.visitVarInsn(opcode, var);
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-import java.util.Set;
-
-/**
- * Class adapter that can stub some or all of the methods of the class.
- */
-class TransformClassAdapter extends ClassVisitor {
-
- /** True if all methods should be stubbed, false if only native ones must be stubbed. */
- private final boolean mStubAll;
- /** True if the class is an interface. */
- private boolean mIsInterface;
- private final String mClassName;
- private final Log mLog;
- private final Set<String> mStubMethods;
- private Set<String> mDeleteReturns;
-
- /**
- * Creates a new class adapter that will stub some or all methods.
- * @param stubMethods list of method signatures to always stub out
- * @param deleteReturns list of types that trigger the deletion of methods returning them.
- * @param className The name of the class being modified
- * @param cv The parent class writer visitor
- * @param stubNativesOnly True if only native methods should be stubbed. False if all
- * methods should be stubbed.
- */
- public TransformClassAdapter(Log logger, Set<String> stubMethods,
- Set<String> deleteReturns, String className, ClassVisitor cv,
- boolean stubNativesOnly) {
- super(Main.ASM_VERSION, cv);
- mLog = logger;
- mStubMethods = stubMethods;
- mClassName = className;
- mStubAll = !stubNativesOnly;
- mIsInterface = false;
- mDeleteReturns = deleteReturns;
- }
-
- /* Visits the class header. */
- @Override
- public void visit(int version, int access, String name,
- String signature, String superName, String[] interfaces) {
-
- // This class might be being renamed.
- name = mClassName;
-
- // remove final
- access = access & ~Opcodes.ACC_FINAL;
- // note: leave abstract classes as such
- // don't try to implement stub for interfaces
-
- mIsInterface = ((access & Opcodes.ACC_INTERFACE) != 0);
- super.visit(version, access, name, signature, superName, interfaces);
- }
-
- /* Visits the header of an inner class. */
- @Override
- public void visitInnerClass(String name, String outerName, String innerName, int access) {
- // remove final
- access = access & ~Opcodes.ACC_FINAL;
- // note: leave abstract classes as such
- // don't try to implement stub for interfaces
-
- super.visitInnerClass(name, outerName, innerName, access);
- }
-
- /* Visits a method. */
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc,
- String signature, String[] exceptions) {
-
- if (mDeleteReturns != null) {
- Type t = Type.getReturnType(desc);
- if (t.getSort() == Type.OBJECT) {
- String returnType = t.getInternalName();
- if (returnType != null) {
- if (mDeleteReturns.contains(returnType)) {
- return null;
- }
- }
- }
- }
-
- String methodSignature = mClassName.replace('/', '.') + "#" + name;
-
- // remove final
- access = access & ~Opcodes.ACC_FINAL;
-
- // stub this method if they are all to be stubbed or if it is a native method
- // and don't try to stub interfaces nor abstract non-native methods.
- if (!mIsInterface &&
- ((access & (Opcodes.ACC_ABSTRACT | Opcodes.ACC_NATIVE)) != Opcodes.ACC_ABSTRACT) &&
- (mStubAll ||
- (access & Opcodes.ACC_NATIVE) != 0) ||
- mStubMethods.contains(methodSignature)) {
-
- boolean isStatic = (access & Opcodes.ACC_STATIC) != 0;
- boolean isNative = (access & Opcodes.ACC_NATIVE) != 0;
-
- // remove abstract, final and native
- access = access & ~(Opcodes.ACC_ABSTRACT | Opcodes.ACC_FINAL | Opcodes.ACC_NATIVE);
-
- String invokeSignature = methodSignature + desc;
- mLog.debug(" Stub: %s (%s)", invokeSignature, isNative ? "native" : "");
-
- MethodVisitor mw = super.visitMethod(access, name, desc, signature, exceptions);
- return new StubMethodAdapter(mw, name, returnType(desc), invokeSignature,
- isStatic, isNative);
-
- } else {
- mLog.debug(" Keep: %s %s", name, desc);
- return super.visitMethod(access, name, desc, signature, exceptions);
- }
- }
-
- /**
- * Extracts the return {@link Type} of this descriptor.
- */
- Type returnType(String desc) {
- if (desc != null) {
- try {
- return Type.getReturnType(desc);
- } catch (ArrayIndexOutOfBoundsException e) {
- // ignore, not a valid type.
- }
- }
- return null;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.java;
-
-/**
- * Defines the same interface as the java.lang.AutoCloseable which was added in
- * Java 7. This hack makes it possible to run the Android code which uses Java 7
- * features (API 18 and beyond) to run on Java 6.
- * <p/>
- * Extracted from API level 18, file:
- * platform/libcore/luni/src/main/java/java/lang/AutoCloseable.java
- */
-public interface AutoCloseable {
- /**
- * Closes the object and release any system resources it holds.
- */
- void close() throws Exception;
-}
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.java;
-
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-
-/**
- * Defines the same class as the java.nio.charset.Charsets which was added in
- * Dalvik VM. This hack, provides a replacement for that class which can't be
- * loaded in the standard JVM since it's in the java package and standard JVM
- * doesn't have it. An implementation of the native methods in the original
- * class has been added.
- * <p/>
- * Extracted from API level 18, file:
- * platform/libcore/luni/src/main/java/java/nio/charset/Charsets
- */
-public final class Charsets {
- /**
- * A cheap and type-safe constant for the ISO-8859-1 Charset.
- */
- public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
-
- /**
- * A cheap and type-safe constant for the US-ASCII Charset.
- */
- public static final Charset US_ASCII = Charset.forName("US-ASCII");
-
- /**
- * A cheap and type-safe constant for the UTF-8 Charset.
- */
- public static final Charset UTF_8 = Charset.forName("UTF-8");
-
- /**
- * Returns a new byte array containing the bytes corresponding to the given characters,
- * encoded in US-ASCII. Unrepresentable characters are replaced by (byte) '?'.
- */
- public static byte[] toAsciiBytes(char[] chars, int offset, int length) {
- CharBuffer cb = CharBuffer.allocate(length);
- cb.put(chars, offset, length);
- return US_ASCII.encode(cb).array();
- }
-
- /**
- * Returns a new byte array containing the bytes corresponding to the given characters,
- * encoded in ISO-8859-1. Unrepresentable characters are replaced by (byte) '?'.
- */
- public static byte[] toIsoLatin1Bytes(char[] chars, int offset, int length) {
- CharBuffer cb = CharBuffer.allocate(length);
- cb.put(chars, offset, length);
- return ISO_8859_1.encode(cb).array();
- }
-
- /**
- * Returns a new byte array containing the bytes corresponding to the given characters,
- * encoded in UTF-8. All characters are representable in UTF-8.
- */
- public static byte[] toUtf8Bytes(char[] chars, int offset, int length) {
- CharBuffer cb = CharBuffer.allocate(length);
- cb.put(chars, offset, length);
- return UTF_8.encode(cb).array();
- }
-
- /**
- * Returns a new byte array containing the bytes corresponding to the given characters,
- * encoded in UTF-16BE. All characters are representable in UTF-16BE.
- */
- public static byte[] toBigEndianUtf16Bytes(char[] chars, int offset, int length) {
- byte[] result = new byte[length * 2];
- int end = offset + length;
- int resultIndex = 0;
- for (int i = offset; i < end; ++i) {
- char ch = chars[i];
- result[resultIndex++] = (byte) (ch >> 8);
- result[resultIndex++] = (byte) ch;
- }
- return result;
- }
-
- /**
- * Decodes the given US-ASCII bytes into the given char[]. Equivalent to but faster than:
- *
- * for (int i = 0; i < count; ++i) {
- * char ch = (char) (data[start++] & 0xff);
- * value[i] = (ch <= 0x7f) ? ch : REPLACEMENT_CHAR;
- * }
- */
- public static void asciiBytesToChars(byte[] bytes, int offset, int length, char[] chars) {
- if (bytes == null || chars == null) {
- return;
- }
- final char REPLACEMENT_CHAR = (char)0xffd;
- int start = offset;
- for (int i = 0; i < length; ++i) {
- char ch = (char) (bytes[start++] & 0xff);
- chars[i] = (ch <= 0x7f) ? ch : REPLACEMENT_CHAR;
- }
- }
-
- /**
- * Decodes the given ISO-8859-1 bytes into the given char[]. Equivalent to but faster than:
- *
- * for (int i = 0; i < count; ++i) {
- * value[i] = (char) (data[start++] & 0xff);
- * }
- */
- public static void isoLatin1BytesToChars(byte[] bytes, int offset, int length, char[] chars) {
- if (bytes == null || chars == null) {
- return;
- }
- int start = offset;
- for (int i = 0; i < length; ++i) {
- chars[i] = (char) (bytes[start++] & 0xff);
- }
- }
-
- private Charsets() {
- }
-}
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.java;
-
-/**
- * Defines the same class as the java.lang.IntegralToString which was added in
- * Dalvik VM. This hack, provides a replacement for that class which can't be
- * loaded in the standard JVM since it's in the java package and standard JVM
- * doesn't have it. Since it's no longer in java.lang, access to package
- * private methods and classes has been replaced by the closes matching public
- * implementation.
- * <p/>
- * Extracted from API level 18, file:
- * platform/libcore/luni/src/main/java/java/lang/IntegralToString.java
- */
-public final class IntegralToString {
- /**
- * When appending to an AbstractStringBuilder, this thread-local char[] lets us avoid
- * allocation of a temporary array. (We can't write straight into the AbstractStringBuilder
- * because it's almost as expensive to work out the exact length of the result as it is to
- * do the formatting. We could try being conservative and "delete"-ing the unused space
- * afterwards, but then we'd need to duplicate convertInt and convertLong rather than share
- * the code.)
- */
- private static final ThreadLocal<char[]> BUFFER = new ThreadLocal<char[]>() {
- @Override protected char[] initialValue() {
- return new char[20]; // Maximum length of a base-10 long.
- }
- };
-
- /**
- * These tables are used to special-case toString computation for
- * small values. This serves three purposes: it reduces memory usage;
- * it increases performance for small values; and it decreases the
- * number of comparisons required to do the length computation.
- * Elements of this table are lazily initialized on first use.
- * No locking is necessary, i.e., we use the non-volatile, racy
- * single-check idiom.
- */
- private static final String[] SMALL_NONNEGATIVE_VALUES = new String[100];
- private static final String[] SMALL_NEGATIVE_VALUES = new String[100];
-
- /** TENS[i] contains the tens digit of the number i, 0 <= i <= 99. */
- private static final char[] TENS = {
- '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
- '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
- '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
- '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
- '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
- '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
- '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
- '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
- '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
- '9', '9', '9', '9', '9', '9', '9', '9', '9', '9'
- };
-
- /** Ones [i] contains the tens digit of the number i, 0 <= i <= 99. */
- private static final char[] ONES = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- };
-
- /**
- * Table for MOD / DIV 10 computation described in Section 10-21
- * of Hank Warren's "Hacker's Delight" online addendum.
- * http://www.hackersdelight.org/divcMore.pdf
- */
- private static final char[] MOD_10_TABLE = {
- 0, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 0
- };
-
- /**
- * The digits for every supported radix.
- */
- private static final char[] DIGITS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
- 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
- 'u', 'v', 'w', 'x', 'y', 'z'
- };
-
- private static final char[] UPPER_CASE_DIGITS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
- 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
- 'U', 'V', 'W', 'X', 'Y', 'Z'
- };
-
- private IntegralToString() {
- }
-
- /**
- * Equivalent to Integer.toString(i, radix).
- */
- public static String intToString(int i, int radix) {
- if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
- radix = 10;
- }
- if (radix == 10) {
- return intToString(i);
- }
-
- /*
- * If i is positive, negate it. This is the opposite of what one might
- * expect. It is necessary because the range of the negative values is
- * strictly larger than that of the positive values: there is no
- * positive value corresponding to Integer.MIN_VALUE.
- */
- boolean negative = false;
- if (i < 0) {
- negative = true;
- } else {
- i = -i;
- }
-
- int bufLen = radix < 8 ? 33 : 12; // Max chars in result (conservative)
- char[] buf = new char[bufLen];
- int cursor = bufLen;
-
- do {
- int q = i / radix;
- buf[--cursor] = DIGITS[radix * q - i];
- i = q;
- } while (i != 0);
-
- if (negative) {
- buf[--cursor] = '-';
- }
-
- return new String(buf, cursor, bufLen - cursor);
- }
-
- /**
- * Equivalent to Integer.toString(i).
- */
- public static String intToString(int i) {
- return convertInt(null, i);
- }
-
- /**
- * Equivalent to sb.append(Integer.toString(i)).
- */
- public static void appendInt(StringBuilder sb, int i) {
- convertInt(sb, i);
- }
-
- /**
- * Returns the string representation of i and leaves sb alone if sb is null.
- * Returns null and appends the string representation of i to sb if sb is non-null.
- */
- private static String convertInt(StringBuilder sb, int i) {
- boolean negative = false;
- String quickResult = null;
- if (i < 0) {
- negative = true;
- i = -i;
- if (i < 100) {
- if (i < 0) {
- // If -n is still negative, n is Integer.MIN_VALUE
- quickResult = "-2147483648";
- } else {
- quickResult = SMALL_NEGATIVE_VALUES[i];
- if (quickResult == null) {
- SMALL_NEGATIVE_VALUES[i] = quickResult =
- i < 10 ? stringOf('-', ONES[i]) : stringOf('-', TENS[i], ONES[i]);
- }
- }
- }
- } else {
- if (i < 100) {
- quickResult = SMALL_NONNEGATIVE_VALUES[i];
- if (quickResult == null) {
- SMALL_NONNEGATIVE_VALUES[i] = quickResult =
- i < 10 ? stringOf(ONES[i]) : stringOf(TENS[i], ONES[i]);
- }
- }
- }
- if (quickResult != null) {
- if (sb != null) {
- sb.append(quickResult);
- return null;
- }
- return quickResult;
- }
-
- int bufLen = 11; // Max number of chars in result
- char[] buf = (sb != null) ? BUFFER.get() : new char[bufLen];
- int cursor = bufLen;
-
- // Calculate digits two-at-a-time till remaining digits fit in 16 bits
- while (i >= (1 << 16)) {
- // Compute q = n/100 and r = n % 100 as per "Hacker's Delight" 10-8
- int q = (int) ((0x51EB851FL * i) >>> 37);
- int r = i - 100*q;
- buf[--cursor] = ONES[r];
- buf[--cursor] = TENS[r];
- i = q;
- }
-
- // Calculate remaining digits one-at-a-time for performance
- while (i != 0) {
- // Compute q = n/10 and r = n % 10 as per "Hacker's Delight" 10-8
- int q = (0xCCCD * i) >>> 19;
- int r = i - 10*q;
- buf[--cursor] = DIGITS[r];
- i = q;
- }
-
- if (negative) {
- buf[--cursor] = '-';
- }
-
- if (sb != null) {
- sb.append(buf, cursor, bufLen - cursor);
- return null;
- } else {
- return new String(buf, cursor, bufLen - cursor);
- }
- }
-
- /**
- * Equivalent to Long.toString(v, radix).
- */
- public static String longToString(long v, int radix) {
- int i = (int) v;
- if (i == v) {
- return intToString(i, radix);
- }
-
- if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
- radix = 10;
- }
- if (radix == 10) {
- return longToString(v);
- }
-
- /*
- * If v is positive, negate it. This is the opposite of what one might
- * expect. It is necessary because the range of the negative values is
- * strictly larger than that of the positive values: there is no
- * positive value corresponding to Integer.MIN_VALUE.
- */
- boolean negative = false;
- if (v < 0) {
- negative = true;
- } else {
- v = -v;
- }
-
- int bufLen = radix < 8 ? 65 : 23; // Max chars in result (conservative)
- char[] buf = new char[bufLen];
- int cursor = bufLen;
-
- do {
- long q = v / radix;
- buf[--cursor] = DIGITS[(int) (radix * q - v)];
- v = q;
- } while (v != 0);
-
- if (negative) {
- buf[--cursor] = '-';
- }
-
- return new String(buf, cursor, bufLen - cursor);
- }
-
- /**
- * Equivalent to Long.toString(l).
- */
- public static String longToString(long l) {
- return convertLong(null, l);
- }
-
- /**
- * Equivalent to sb.append(Long.toString(l)).
- */
- public static void appendLong(StringBuilder sb, long l) {
- convertLong(sb, l);
- }
-
- /**
- * Returns the string representation of n and leaves sb alone if sb is null.
- * Returns null and appends the string representation of n to sb if sb is non-null.
- */
- private static String convertLong(StringBuilder sb, long n) {
- int i = (int) n;
- if (i == n) {
- return convertInt(sb, i);
- }
-
- boolean negative = (n < 0);
- if (negative) {
- n = -n;
- if (n < 0) {
- // If -n is still negative, n is Long.MIN_VALUE
- String quickResult = "-9223372036854775808";
- if (sb != null) {
- sb.append(quickResult);
- return null;
- }
- return quickResult;
- }
- }
-
- int bufLen = 20; // Maximum number of chars in result
- char[] buf = (sb != null) ? BUFFER.get() : new char[bufLen];
-
- int low = (int) (n % 1000000000); // Extract low-order 9 digits
- int cursor = intIntoCharArray(buf, bufLen, low);
-
- // Zero-pad Low order part to 9 digits
- while (cursor != (bufLen - 9)) {
- buf[--cursor] = '0';
- }
-
- /*
- * The remaining digits are (n - low) / 1,000,000,000. This
- * "exact division" is done as per the online addendum to Hank Warren's
- * "Hacker's Delight" 10-20, http://www.hackersdelight.org/divcMore.pdf
- */
- n = ((n - low) >>> 9) * 0x8E47CE423A2E9C6DL;
-
- /*
- * If the remaining digits fit in an int, emit them using a
- * single call to intIntoCharArray. Otherwise, strip off the
- * low-order digit, put it in buf, and then call intIntoCharArray
- * on the remaining digits (which now fit in an int).
- */
- if ((n & (-1L << 32)) == 0) {
- cursor = intIntoCharArray(buf, cursor, (int) n);
- } else {
- /*
- * Set midDigit to n % 10
- */
- int lo32 = (int) n;
- int hi32 = (int) (n >>> 32);
-
- // midDigit = ((unsigned) low32) % 10, per "Hacker's Delight" 10-21
- int midDigit = MOD_10_TABLE[(0x19999999 * lo32 + (lo32 >>> 1) + (lo32 >>> 3)) >>> 28];
-
- // Adjust midDigit for hi32. (assert hi32 == 1 || hi32 == 2)
- midDigit -= hi32 << 2; // 1L << 32 == -4 MOD 10
- if (midDigit < 0) {
- midDigit += 10;
- }
- buf[--cursor] = DIGITS[midDigit];
-
- // Exact division as per Warren 10-20
- int rest = ((int) ((n - midDigit) >>> 1)) * 0xCCCCCCCD;
- cursor = intIntoCharArray(buf, cursor, rest);
- }
-
- if (negative) {
- buf[--cursor] = '-';
- }
- if (sb != null) {
- sb.append(buf, cursor, bufLen - cursor);
- return null;
- } else {
- return new String(buf, cursor, bufLen - cursor);
- }
- }
-
- /**
- * Inserts the unsigned decimal integer represented by n into the specified
- * character array starting at position cursor. Returns the index after
- * the last character inserted (i.e., the value to pass in as cursor the
- * next time this method is called). Note that n is interpreted as a large
- * positive integer (not a negative integer) if its sign bit is set.
- */
- private static int intIntoCharArray(char[] buf, int cursor, int n) {
- // Calculate digits two-at-a-time till remaining digits fit in 16 bits
- while ((n & 0xffff0000) != 0) {
- /*
- * Compute q = n/100 and r = n % 100 as per "Hacker's Delight" 10-8.
- * This computation is slightly different from the corresponding
- * computation in intToString: the shifts before and after
- * multiply can't be combined, as that would yield the wrong result
- * if n's sign bit were set.
- */
- int q = (int) ((0x51EB851FL * (n >>> 2)) >>> 35);
- int r = n - 100*q;
- buf[--cursor] = ONES[r];
- buf[--cursor] = TENS[r];
- n = q;
- }
-
- // Calculate remaining digits one-at-a-time for performance
- while (n != 0) {
- // Compute q = n / 10 and r = n % 10 as per "Hacker's Delight" 10-8
- int q = (0xCCCD * n) >>> 19;
- int r = n - 10*q;
- buf[--cursor] = DIGITS[r];
- n = q;
- }
- return cursor;
- }
-
- public static String intToBinaryString(int i) {
- int bufLen = 32; // Max number of binary digits in an int
- char[] buf = new char[bufLen];
- int cursor = bufLen;
-
- do {
- buf[--cursor] = DIGITS[i & 1];
- } while ((i >>>= 1) != 0);
-
- return new String(buf, cursor, bufLen - cursor);
- }
-
- public static String longToBinaryString(long v) {
- int i = (int) v;
- if (v >= 0 && i == v) {
- return intToBinaryString(i);
- }
-
- int bufLen = 64; // Max number of binary digits in a long
- char[] buf = new char[bufLen];
- int cursor = bufLen;
-
- do {
- buf[--cursor] = DIGITS[((int) v) & 1];
- } while ((v >>>= 1) != 0);
-
- return new String(buf, cursor, bufLen - cursor);
- }
-
- public static StringBuilder appendByteAsHex(StringBuilder sb, byte b, boolean upperCase) {
- char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
- sb.append(digits[(b >> 4) & 0xf]);
- sb.append(digits[b & 0xf]);
- return sb;
- }
-
- public static String byteToHexString(byte b, boolean upperCase) {
- char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
- char[] buf = new char[2]; // We always want two digits.
- buf[0] = digits[(b >> 4) & 0xf];
- buf[1] = digits[b & 0xf];
- return new String(buf, 0, 2);
- }
-
- public static String bytesToHexString(byte[] bytes, boolean upperCase) {
- char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
- char[] buf = new char[bytes.length * 2];
- int c = 0;
- for (byte b : bytes) {
- buf[c++] = digits[(b >> 4) & 0xf];
- buf[c++] = digits[b & 0xf];
- }
- return new String(buf);
- }
-
- public static String intToHexString(int i, boolean upperCase, int minWidth) {
- int bufLen = 8; // Max number of hex digits in an int
- char[] buf = new char[bufLen];
- int cursor = bufLen;
-
- char[] digits = upperCase ? UPPER_CASE_DIGITS : DIGITS;
- do {
- buf[--cursor] = digits[i & 0xf];
- } while ((i >>>= 4) != 0 || (bufLen - cursor < minWidth));
-
- return new String(buf, cursor, bufLen - cursor);
- }
-
- public static String longToHexString(long v) {
- int i = (int) v;
- if (v >= 0 && i == v) {
- return intToHexString(i, false, 0);
- }
-
- int bufLen = 16; // Max number of hex digits in a long
- char[] buf = new char[bufLen];
- int cursor = bufLen;
-
- do {
- buf[--cursor] = DIGITS[((int) v) & 0xF];
- } while ((v >>>= 4) != 0);
-
- return new String(buf, cursor, bufLen - cursor);
- }
-
- public static String intToOctalString(int i) {
- int bufLen = 11; // Max number of octal digits in an int
- char[] buf = new char[bufLen];
- int cursor = bufLen;
-
- do {
- buf[--cursor] = DIGITS[i & 7];
- } while ((i >>>= 3) != 0);
-
- return new String(buf, cursor, bufLen - cursor);
- }
-
- public static String longToOctalString(long v) {
- int i = (int) v;
- if (v >= 0 && i == v) {
- return intToOctalString(i);
- }
- int bufLen = 22; // Max number of octal digits in a long
- char[] buf = new char[bufLen];
- int cursor = bufLen;
-
- do {
- buf[--cursor] = DIGITS[((int) v) & 7];
- } while ((v >>>= 3) != 0);
-
- return new String(buf, cursor, bufLen - cursor);
- }
-
- private static String stringOf(char... args) {
- return new String(args, 0, args.length);
- }
-}
+++ /dev/null
-/*
- * 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.java;
-
-import com.android.tools.layoutlib.create.ReplaceMethodCallsAdapter;
-
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Provides alternate implementation to java.util.LinkedHashMap#eldest(), which is present as a
- * non-public method in the Android VM, but not present on the host VM. This is injected in the
- * layoutlib using {@link ReplaceMethodCallsAdapter}.
- */
-public class LinkedHashMap_Delegate {
- public static <K,V> Map.Entry<K,V> eldest(LinkedHashMap<K,V> map) {
- Iterator<Entry<K, V>> iterator = map.entrySet().iterator();
- return iterator.hasNext() ? iterator.next() : null;
- }
-}
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.java;
-
-import java.util.Arrays;
-import java.util.Comparator;
-
-/**
- * Defines the same class as the java.util.Objects which is added in Java 7.
- * This hack makes it possible to run the Android code which uses Java 7 features
- * (API 18 and beyond) to run on Java 6.
- * <p/>
- * Extracted from API level 19, file:
- * platform/libcore/luni/src/main/java/java/util/Objects.java
- */
-public final class Objects {
- private Objects() {}
-
- /**
- * Returns 0 if {@code a == b}, or {@code c.compare(a, b)} otherwise.
- * That is, this makes {@code c} null-safe.
- */
- public static <T> int compare(T a, T b, Comparator<? super T> c) {
- if (a == b) {
- return 0;
- }
- return c.compare(a, b);
- }
-
- /**
- * Returns true if both arguments are null,
- * the result of {@link Arrays#equals} if both arguments are primitive arrays,
- * the result of {@link Arrays#deepEquals} if both arguments are arrays of reference types,
- * and the result of {@link #equals} otherwise.
- */
- public static boolean deepEquals(Object a, Object b) {
- if (a == null || b == null) {
- return a == b;
- } else if (a instanceof Object[] && b instanceof Object[]) {
- return Arrays.deepEquals((Object[]) a, (Object[]) b);
- } else if (a instanceof boolean[] && b instanceof boolean[]) {
- return Arrays.equals((boolean[]) a, (boolean[]) b);
- } else if (a instanceof byte[] && b instanceof byte[]) {
- return Arrays.equals((byte[]) a, (byte[]) b);
- } else if (a instanceof char[] && b instanceof char[]) {
- return Arrays.equals((char[]) a, (char[]) b);
- } else if (a instanceof double[] && b instanceof double[]) {
- return Arrays.equals((double[]) a, (double[]) b);
- } else if (a instanceof float[] && b instanceof float[]) {
- return Arrays.equals((float[]) a, (float[]) b);
- } else if (a instanceof int[] && b instanceof int[]) {
- return Arrays.equals((int[]) a, (int[]) b);
- } else if (a instanceof long[] && b instanceof long[]) {
- return Arrays.equals((long[]) a, (long[]) b);
- } else if (a instanceof short[] && b instanceof short[]) {
- return Arrays.equals((short[]) a, (short[]) b);
- }
- return a.equals(b);
- }
-
- /**
- * Null-safe equivalent of {@code a.equals(b)}.
- */
- public static boolean equals(Object a, Object b) {
- return (a == null) ? (b == null) : a.equals(b);
- }
-
- /**
- * Convenience wrapper for {@link Arrays#hashCode}, adding varargs.
- * This can be used to compute a hash code for an object's fields as follows:
- * {@code Objects.hash(a, b, c)}.
- */
- public static int hash(Object... values) {
- return Arrays.hashCode(values);
- }
-
- /**
- * Returns 0 for null or {@code o.hashCode()}.
- */
- public static int hashCode(Object o) {
- return (o == null) ? 0 : o.hashCode();
- }
-
- /**
- * Returns {@code o} if non-null, or throws {@code NullPointerException}.
- */
- public static <T> T requireNonNull(T o) {
- if (o == null) {
- throw new NullPointerException();
- }
- return o;
- }
-
- /**
- * Returns {@code o} if non-null, or throws {@code NullPointerException}
- * with the given detail message.
- */
- public static <T> T requireNonNull(T o, String message) {
- if (o == null) {
- throw new NullPointerException(message);
- }
- return o;
- }
-
- /**
- * Returns "null" for null or {@code o.toString()}.
- */
- public static String toString(Object o) {
- return (o == null) ? "null" : o.toString();
- }
-
- /**
- * Returns {@code nullString} for null or {@code o.toString()}.
- */
- public static String toString(Object o, String nullString) {
- return (o == null) ? nullString : o.toString();
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.java;
-
-import com.android.tools.layoutlib.create.ReplaceMethodCallsAdapter;
-
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Provides dummy implementation of methods that don't exist on the host VM.
- * This also providers a time control that allows to set a specific system time.
- *
- * @see ReplaceMethodCallsAdapter
- */
-@SuppressWarnings("unused")
-public class System_Delegate {
- // Current system time
- private static AtomicLong mNanosTime = new AtomicLong(System.nanoTime());
- // Time that the system booted up in nanos
- private static AtomicLong mBootNanosTime = new AtomicLong(System.nanoTime());
-
- public static void log(String message) {
- // ignore.
- }
-
- public static void log(String message, Throwable th) {
- // ignore.
- }
-
- public static void setNanosTime(long nanos) {
- mNanosTime.set(nanos);
- }
-
- public static void setBootTimeNanos(long nanos) {
- mBootNanosTime.set(nanos);
- }
-
- public static long nanoTime() {
- return mNanosTime.get();
- }
-
- public static long currentTimeMillis() {
- return TimeUnit.NANOSECONDS.toMillis(mNanosTime.get());
- }
-
- public static long bootTime() {
- return mBootNanosTime.get();
- }
-
- public static long bootTimeMillis() {
- return TimeUnit.NANOSECONDS.toMillis(mBootNanosTime.get());
- }
-}
+++ /dev/null
-/*
- * 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 com.android.tools.layoutlib.java;
-
-import java.nio.charset.Charset;
-
-/**
- * Defines the same class as the java.lang.UnsafeByteSequence which was added in
- * Dalvik VM. This hack, provides a replacement for that class which can't be
- * loaded in the standard JVM since it's in the java package and standard JVM
- * doesn't have it.
- * <p/>
- * Extracted from API level 18, file:
- * platform/libcore/luni/src/main/java/java/lang/UnsafeByteSequence.java
- */
-public class UnsafeByteSequence {
- private byte[] bytes;
- private int count;
-
- public UnsafeByteSequence(int initialCapacity) {
- this.bytes = new byte[initialCapacity];
- }
-
- public int size() {
- return count;
- }
-
- /**
- * Moves the write pointer back to the beginning of the sequence,
- * but without resizing or reallocating the buffer.
- */
- public void rewind() {
- count = 0;
- }
-
- public void write(byte[] buffer, int offset, int length) {
- if (count + length >= bytes.length) {
- byte[] newBytes = new byte[(count + length) * 2];
- System.arraycopy(bytes, 0, newBytes, 0, count);
- bytes = newBytes;
- }
- System.arraycopy(buffer, offset, bytes, count, length);
- count += length;
- }
-
- public void write(int b) {
- if (count == bytes.length) {
- byte[] newBytes = new byte[count * 2];
- System.arraycopy(bytes, 0, newBytes, 0, count);
- bytes = newBytes;
- }
- bytes[count++] = (byte) b;
- }
-
- public byte[] toByteArray() {
- if (count == bytes.length) {
- return bytes;
- }
- byte[] result = new byte[count];
- System.arraycopy(bytes, 0, result, 0, count);
- return result;
- }
-
- public String toString(Charset cs) {
- return new String(bytes, 0, count, cs);
- }
-}
+++ /dev/null
-# 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.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Only compile source java files in this lib.
-LOCAL_SRC_FILES := $(call all-java-files-under, com)
-
-LOCAL_JAVA_RESOURCE_DIRS := data mock_data
-
-LOCAL_MODULE := layoutlib-create-tests
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_JAVA_LIBRARIES := layoutlib_create junit-host
-LOCAL_STATIC_JAVA_LIBRARIES := asm-5.2
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-# Copy the jar to DIST_DIR for sdk builds
-$(call dist-for-goals, sdk win_sdk, $(LOCAL_INSTALLED_MODULE))
-
-# Build all sub-directories
-include $(call all-makefiles-under,$(LOCAL_PATH))
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package com.android.tools.layoutlib.create;
-
-import com.android.tools.layoutlib.create.AsmAnalyzer.DependencyVisitor;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.objectweb.asm.ClassReader;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * Unit tests for some methods of {@link AsmAnalyzer}.
- */
-public class AsmAnalyzerTest {
-
- private MockLog mLog;
- private ArrayList<String> mOsJarPath;
- private AsmAnalyzer mAa;
-
- @Before
- public void setUp() throws Exception {
- mLog = new MockLog();
- URL url = this.getClass().getClassLoader().getResource("data/mock_android.jar");
-
- mOsJarPath = new ArrayList<>();
- //noinspection ConstantConditions
- mOsJarPath.add(url.getFile());
-
- Set<String> excludeClasses = Collections.singleton("java.lang.JavaClass");
-
- String[] includeFiles = new String[]{"mock_android/data/data*"};
- mAa = new AsmAnalyzer(mLog, mOsJarPath, null /* gen */, null /* deriveFrom */,
- null /* includeGlobs */, excludeClasses, includeFiles);
- }
-
- @Test
- public void testParseZip() throws IOException {
-
- Map<String, ClassReader> map = new TreeMap<>();
- Map<String, InputStream> filesFound = new TreeMap<>();
-
- mAa.parseZip(mOsJarPath, map, filesFound);
-
- assertArrayEquals(new String[] {
- "java.lang.JavaClass",
- "mock_android.dummy.InnerTest",
- "mock_android.dummy.InnerTest$DerivingClass",
- "mock_android.dummy.InnerTest$MyGenerics1",
- "mock_android.dummy.InnerTest$MyIntEnum",
- "mock_android.dummy.InnerTest$MyStaticInnerClass",
- "mock_android.dummy.InnerTest$NotStaticInner1",
- "mock_android.dummy.InnerTest$NotStaticInner2",
- "mock_android.util.EmptyArray",
- "mock_android.view.View",
- "mock_android.view.ViewGroup",
- "mock_android.view.ViewGroup$LayoutParams",
- "mock_android.view.ViewGroup$MarginLayoutParams",
- "mock_android.widget.LinearLayout",
- "mock_android.widget.LinearLayout$LayoutParams",
- "mock_android.widget.TableLayout",
- "mock_android.widget.TableLayout$LayoutParams"
- },
- map.keySet().toArray());
- assertArrayEquals(new String[] {"mock_android/data/dataFile"},
- filesFound.keySet().toArray());
- }
-
- @Test
- public void testFindClass() throws IOException, LogAbortException {
-
- Map<String, ClassReader> zipClasses = new TreeMap<>();
- Map<String, InputStream> filesFound = new TreeMap<>();
-
- mAa.parseZip(mOsJarPath, zipClasses, filesFound);
- TreeMap<String, ClassReader> found = new TreeMap<>();
-
- ClassReader cr = mAa.findClass("mock_android.view.ViewGroup$LayoutParams",
- zipClasses, found);
-
- assertNotNull(cr);
- assertEquals("mock_android/view/ViewGroup$LayoutParams", cr.getClassName());
- assertArrayEquals(new String[] { "mock_android.view.ViewGroup$LayoutParams" },
- found.keySet().toArray());
- assertArrayEquals(new ClassReader[] { cr }, found.values().toArray());
- }
-
- @Test
- public void testFindGlobs() throws IOException, LogAbortException {
-
- Map<String, ClassReader> zipClasses = new TreeMap<>();
- Map<String, InputStream> filesFound = new TreeMap<>();
-
- mAa.parseZip(mOsJarPath, zipClasses, filesFound);
- TreeMap<String, ClassReader> found = new TreeMap<>();
-
- // this matches classes, a package match returns nothing
- found.clear();
- mAa.findGlobs("mock_android.view", zipClasses, found);
-
- assertArrayEquals(new String[] { },
- found.keySet().toArray());
-
- // a complex glob search. * is a search pattern that matches names, not dots
- mAa.findGlobs("mock_android.*.*Group$*Layout*", zipClasses, found);
-
- assertArrayEquals(new String[] {
- "mock_android.view.ViewGroup$LayoutParams",
- "mock_android.view.ViewGroup$MarginLayoutParams"
- },
- found.keySet().toArray());
-
- // a complex glob search. ** is a search pattern that matches names including dots
- mAa.findGlobs("mock_android.**Group*", zipClasses, found);
-
- assertArrayEquals(new String[] {
- "mock_android.view.ViewGroup",
- "mock_android.view.ViewGroup$LayoutParams",
- "mock_android.view.ViewGroup$MarginLayoutParams"
- },
- found.keySet().toArray());
-
- // matches a single class
- found.clear();
- mAa.findGlobs("mock_android.view.View", zipClasses, found);
-
- assertArrayEquals(new String[] {
- "mock_android.view.View"
- },
- found.keySet().toArray());
-
- // matches everyting inside the given package but not sub-packages
- found.clear();
- mAa.findGlobs("mock_android.view.*", zipClasses, found);
-
- assertArrayEquals(new String[] {
- "mock_android.view.View",
- "mock_android.view.ViewGroup",
- "mock_android.view.ViewGroup$LayoutParams",
- "mock_android.view.ViewGroup$MarginLayoutParams"
- },
- found.keySet().toArray());
-
- for (String key : found.keySet()) {
- ClassReader value = found.get(key);
- assertNotNull("No value for " + key, value);
- assertEquals(key, AsmAnalyzer.classReaderToClassName(value));
- }
- }
-
- @Test
- public void testFindClassesDerivingFrom() throws LogAbortException, IOException {
-
- Map<String, ClassReader> zipClasses = new TreeMap<>();
- Map<String, InputStream> filesFound = new TreeMap<>();
-
- mAa.parseZip(mOsJarPath, zipClasses, filesFound);
- TreeMap<String, ClassReader> found = new TreeMap<>();
-
- mAa.findClassesDerivingFrom("mock_android.view.View", zipClasses, found);
-
- assertArrayEquals(new String[] {
- "mock_android.view.View",
- "mock_android.view.ViewGroup",
- "mock_android.widget.LinearLayout",
- "mock_android.widget.TableLayout",
- },
- found.keySet().toArray());
-
- for (String key : found.keySet()) {
- ClassReader value = found.get(key);
- assertNotNull("No value for " + key, value);
- assertEquals(key, AsmAnalyzer.classReaderToClassName(value));
- }
- }
-
- @Test
- public void testDependencyVisitor() throws IOException, LogAbortException {
-
- Map<String, ClassReader> zipClasses = new TreeMap<>();
- Map<String, InputStream> filesFound = new TreeMap<>();
-
- mAa.parseZip(mOsJarPath, zipClasses, filesFound);
- TreeMap<String, ClassReader> keep = new TreeMap<>();
- TreeMap<String, ClassReader> new_keep = new TreeMap<>();
- TreeMap<String, ClassReader> in_deps = new TreeMap<>();
- TreeMap<String, ClassReader> out_deps = new TreeMap<>();
-
- ClassReader cr = mAa.findClass("mock_android.widget.LinearLayout", zipClasses, keep);
- DependencyVisitor visitor = mAa.getVisitor(zipClasses, keep, new_keep, in_deps, out_deps);
-
- // get first level dependencies
- cr.accept(visitor, 0 /* flags */);
-
- assertArrayEquals(new String[] {
- "mock_android.util.EmptyArray",
- "mock_android.view.ViewGroup",
- "mock_android.widget.LinearLayout$LayoutParams",
- },
- out_deps.keySet().toArray());
-
- in_deps.putAll(out_deps);
- out_deps.clear();
-
- // get second level dependencies
- for (ClassReader cr2 : in_deps.values()) {
- cr2.accept(visitor, 0 /* flags */);
- }
-
- assertArrayEquals(new String[] {
- "mock_android.view.View",
- "mock_android.view.ViewGroup$LayoutParams",
- "mock_android.view.ViewGroup$MarginLayoutParams",
- },
- out_deps.keySet().toArray());
-
- in_deps.putAll(out_deps);
- out_deps.clear();
-
- // get third level dependencies (there are none)
- for (ClassReader cr2 : in_deps.values()) {
- cr2.accept(visitor, 0 /* flags */);
- }
- keep.putAll(new_keep);
-
- assertArrayEquals(new String[] { }, out_deps.keySet().toArray());
- assertArrayEquals(new String[] {
- "mock_android.widget.LinearLayout",
- }, keep.keySet().toArray());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Type;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Unit tests for some methods of {@link AsmGenerator}.
- */
-public class AsmGeneratorTest {
- private MockLog mLog;
- private ArrayList<String> mOsJarPath;
- private String mOsDestJar;
- private File mTempFile;
-
- // ASM internal name for the the class in java package that should be refactored.
- private static final String JAVA_CLASS_NAME = "java/lang/JavaClass";
-
- @Before
- public void setUp() throws Exception {
- mLog = new MockLog();
- URL url = this.getClass().getClassLoader().getResource("data/mock_android.jar");
-
- mOsJarPath = new ArrayList<>();
- //noinspection ConstantConditions
- mOsJarPath.add(url.getFile());
-
- mTempFile = File.createTempFile("mock", ".jar");
- mOsDestJar = mTempFile.getAbsolutePath();
- mTempFile.deleteOnExit();
- }
-
- @After
- public void tearDown() throws Exception {
- if (mTempFile != null) {
- //noinspection ResultOfMethodCallIgnored
- mTempFile.delete();
- mTempFile = null;
- }
- }
-
- @Test
- public void testClassRenaming() throws IOException, LogAbortException {
-
- ICreateInfo ci = new CreateInfoAdapter() {
- @Override
- public String[] getRenamedClasses() {
- // classes to rename (so that we can replace them)
- return new String[] {
- "mock_android.view.View", "mock_android.view._Original_View",
- "not.an.actual.ClassName", "anoter.fake.NewClassName",
- };
- }
- };
-
- AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
-
- AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
- null, // derived from
- new String[] { // include classes
- "**"
- },
- Collections.emptySet() /* excluded classes */,
- new String[]{} /* include files */);
- aa.analyze();
- agen.generate();
-
- Set<String> notRenamed = agen.getClassesNotRenamed();
- assertArrayEquals(new String[] { "not/an/actual/ClassName" }, notRenamed.toArray());
-
- }
-
- @Test
- public void testJavaClassRefactoring() throws IOException, LogAbortException {
- ICreateInfo ci = new CreateInfoAdapter() {
- @Override
- public Class<?>[] getInjectedClasses() {
- // classes to inject in the final JAR
- return new Class<?>[] {
- com.android.tools.layoutlib.create.dataclass.JavaClass.class
- };
- }
-
- @Override
- public String[] getJavaPkgClasses() {
- // classes to refactor (so that we can replace them)
- return new String[] {
- "java.lang.JavaClass", "com.android.tools.layoutlib.create.dataclass.JavaClass",
- };
- }
-
- @Override
- public Set<String> getExcludedClasses() {
- return Collections.singleton("java.lang.JavaClass");
- }
- };
-
- AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
-
- AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
- null, // derived from
- new String[] { // include classes
- "**"
- },
- Collections.emptySet(),
- new String[] { /* include files */
- "mock_android/data/data*"
- });
- aa.analyze();
- agen.generate();
- Map<String, ClassReader> output = new TreeMap<>();
- Map<String, InputStream> filesFound = new TreeMap<>();
- parseZip(mOsDestJar, output, filesFound);
- RecordingClassVisitor cv = new RecordingClassVisitor();
- for (ClassReader cr: output.values()) {
- cr.accept(cv, 0);
- }
- assertTrue(cv.mVisitedClasses.contains(
- "com/android/tools/layoutlib/create/dataclass/JavaClass"));
- assertFalse(cv.mVisitedClasses.contains(
- JAVA_CLASS_NAME));
- assertArrayEquals(new String[] {"mock_android/data/dataFile"},
- filesFound.keySet().toArray());
- }
-
- @Test
- public void testClassRefactoring() throws IOException, LogAbortException {
- ICreateInfo ci = new CreateInfoAdapter() {
- @Override
- public Class<?>[] getInjectedClasses() {
- // classes to inject in the final JAR
- return new Class<?>[] {
- com.android.tools.layoutlib.create.dataclass.JavaClass.class
- };
- }
-
- @Override
- public String[] getRefactoredClasses() {
- // classes to refactor (so that we can replace them)
- return new String[] {
- "mock_android.view.View", "mock_android.view._Original_View",
- };
- }
- };
-
- AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
-
- AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
- null, // derived from
- new String[] { // include classes
- "**"
- },
- Collections.emptySet(),
- new String[] {});
- aa.analyze();
- agen.generate();
- Map<String, ClassReader> output = new TreeMap<>();
- parseZip(mOsDestJar, output, new TreeMap<>());
- RecordingClassVisitor cv = new RecordingClassVisitor();
- for (ClassReader cr: output.values()) {
- cr.accept(cv, 0);
- }
- assertTrue(cv.mVisitedClasses.contains(
- "mock_android/view/_Original_View"));
- assertFalse(cv.mVisitedClasses.contains(
- "mock_android/view/View"));
- }
-
- @Test
- public void testClassExclusion() throws IOException, LogAbortException {
- ICreateInfo ci = new CreateInfoAdapter() {
- @Override
- public Set<String> getExcludedClasses() {
- Set<String> set = new HashSet<>(2);
- set.add("mock_android.dummy.InnerTest");
- set.add("java.lang.JavaClass");
- return set;
- }
- };
-
- AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
- Set<String> excludedClasses = ci.getExcludedClasses();
- AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
- null, // derived from
- new String[] { // include classes
- "**"
- },
- excludedClasses,
- new String[] { /* include files */
- "mock_android/data/data*"
- });
- aa.analyze();
- agen.generate();
- Map<String, ClassReader> output = new TreeMap<>();
- Map<String, InputStream> filesFound = new TreeMap<>();
- parseZip(mOsDestJar, output, filesFound);
- for (String s : output.keySet()) {
- assertFalse(excludedClasses.contains(s));
- }
- assertArrayEquals(new String[] {"mock_android/data/dataFile"},
- filesFound.keySet().toArray());
- }
-
- @Test
- public void testMethodInjection() throws IOException, LogAbortException,
- ClassNotFoundException, IllegalAccessException, InstantiationException,
- NoSuchMethodException, InvocationTargetException {
- ICreateInfo ci = new CreateInfoAdapter() {
- @Override
- public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
- return Collections.singletonMap("mock_android.util.EmptyArray",
- InjectMethodRunnables.CONTEXT_GET_FRAMEWORK_CLASS_LOADER);
- }
- };
-
- AsmGenerator agen = new AsmGenerator(mLog, mOsDestJar, ci);
- AsmAnalyzer aa = new AsmAnalyzer(mLog, mOsJarPath, agen,
- null, // derived from
- new String[] { // include classes
- "**"
- },
- ci.getExcludedClasses(),
- new String[] { /* include files */
- "mock_android/data/data*"
- });
- aa.analyze();
- agen.generate();
- Map<String, ClassReader> output = new TreeMap<>();
- Map<String, InputStream> filesFound = new TreeMap<>();
- parseZip(mOsDestJar, output, filesFound);
- final String modifiedClass = "mock_android.util.EmptyArray";
- final String modifiedClassPath = modifiedClass.replace('.', '/').concat(".class");
- ZipFile zipFile = new ZipFile(mOsDestJar);
- ZipEntry entry = zipFile.getEntry(modifiedClassPath);
- assertNotNull(entry);
- final byte[] bytes;
- try (InputStream inputStream = zipFile.getInputStream(entry)) {
- bytes = getByteArray(inputStream);
- }
- ClassLoader classLoader = new ClassLoader(getClass().getClassLoader()) {
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- if (name.equals(modifiedClass)) {
- return defineClass(null, bytes, 0, bytes.length);
- }
- throw new ClassNotFoundException(name + " not found.");
- }
- };
- Class<?> emptyArrayClass = classLoader.loadClass(modifiedClass);
- Object emptyArrayInstance = emptyArrayClass.newInstance();
- Method method = emptyArrayClass.getMethod("getFrameworkClassLoader");
- Object cl = method.invoke(emptyArrayInstance);
- assertEquals(classLoader, cl);
- }
-
- private static byte[] getByteArray(InputStream stream) throws IOException {
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- byte[] buffer = new byte[1024];
- int read;
- while ((read = stream.read(buffer, 0, buffer.length)) > -1) {
- bos.write(buffer, 0, read);
- }
- return bos.toByteArray();
- }
-
- private void parseZip(String jarPath,
- Map<String, ClassReader> classes,
- Map<String, InputStream> filesFound) throws IOException {
-
- ZipFile zip = new ZipFile(jarPath);
- Enumeration<? extends ZipEntry> entries = zip.entries();
- ZipEntry entry;
- while (entries.hasMoreElements()) {
- entry = entries.nextElement();
- if (entry.getName().endsWith(".class")) {
- ClassReader cr = new ClassReader(zip.getInputStream(entry));
- String className = classReaderToClassName(cr);
- classes.put(className, cr);
- } else {
- filesFound.put(entry.getName(), zip.getInputStream(entry));
- }
- }
-
- }
-
- private String classReaderToClassName(ClassReader classReader) {
- if (classReader == null) {
- return null;
- } else {
- return classReader.getClassName().replace('/', '.');
- }
- }
-
- /**
- * {@link ClassVisitor} that records every class that sees.
- */
- private static class RecordingClassVisitor extends ClassVisitor {
- private Set<String> mVisitedClasses = new HashSet<>();
-
- private RecordingClassVisitor() {
- super(Main.ASM_VERSION);
- }
-
- private void addClass(String className) {
- if (className == null) {
- return;
- }
-
- int pos = className.indexOf('$');
- if (pos > 0) {
- // For inner classes, add also the base class
- mVisitedClasses.add(className.substring(0, pos));
- }
- mVisitedClasses.add(className);
- }
-
- @Override
- public void visit(int version, int access, String name, String signature, String superName,
- String[] interfaces) {
- addClass(superName);
- Arrays.stream(interfaces).forEach(this::addClass);
- }
-
- private void processType(Type type) {
- switch (type.getSort()) {
- case Type.OBJECT:
- addClass(type.getInternalName());
- break;
- case Type.ARRAY:
- addClass(type.getElementType().getInternalName());
- break;
- case Type.METHOD:
- processType(type.getReturnType());
- Arrays.stream(type.getArgumentTypes()).forEach(this::processType);
- break;
- }
- }
-
- @Override
- public FieldVisitor visitField(int access, String name, String desc, String signature,
- Object value) {
- processType(Type.getType(desc));
- return super.visitField(access, name, desc, signature, value);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc, String signature,
- String[] exceptions) {
- MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
- return new MethodVisitor(Main.ASM_VERSION, mv) {
-
- @Override
- public void visitFieldInsn(int opcode, String owner, String name, String desc) {
- addClass(owner);
- processType(Type.getType(desc));
- super.visitFieldInsn(opcode, owner, name, desc);
- }
-
- @Override
- public void visitLdcInsn(Object cst) {
- if (cst instanceof Type) {
- processType((Type) cst);
- }
- super.visitLdcInsn(cst);
- }
-
- @Override
- public void visitTypeInsn(int opcode, String type) {
- addClass(type);
- super.visitTypeInsn(opcode, type);
- }
-
- @Override
- public void visitMethodInsn(int opcode, String owner, String name, String desc,
- boolean itf) {
- addClass(owner);
- processType(Type.getType(desc));
- super.visitMethodInsn(opcode, owner, name, desc, itf);
- }
-
- };
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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 static org.junit.Assert.*;
-
-import org.junit.Test;
-import org.objectweb.asm.ClassReader;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-
-/**
- * Tests {@link ClassHasNativeVisitor}.
- */
-public class ClassHasNativeVisitorTest {
-
- @Test
- public void testHasNative() throws IOException {
- MockClassHasNativeVisitor cv = new MockClassHasNativeVisitor();
- String className =
- this.getClass().getCanonicalName() + "$" + ClassWithNative.class.getSimpleName();
- ClassReader cr = new ClassReader(className);
-
- cr.accept(cv, 0 /* flags */);
- assertArrayEquals(new String[] { "native_method" }, cv.getMethodsFound());
- assertTrue(cv.hasNativeMethods());
- }
-
- @Test
- public void testHasNoNative() throws IOException {
- MockClassHasNativeVisitor cv = new MockClassHasNativeVisitor();
- String className =
- this.getClass().getCanonicalName() + "$" + ClassWithoutNative.class.getSimpleName();
- ClassReader cr = new ClassReader(className);
-
- cr.accept(cv, 0 /* flags */);
- assertArrayEquals(new String[0], cv.getMethodsFound());
- assertFalse(cv.hasNativeMethods());
- }
-
- //-------
-
- /**
- * Overrides {@link ClassHasNativeVisitor} to collec the name of the native methods found.
- */
- private static class MockClassHasNativeVisitor extends ClassHasNativeVisitor {
- private ArrayList<String> mMethodsFound = new ArrayList<>();
-
- public String[] getMethodsFound() {
- return mMethodsFound.toArray(new String[mMethodsFound.size()]);
- }
-
- @Override
- protected void setHasNativeMethods(boolean hasNativeMethods, String methodName) {
- if (hasNativeMethods) {
- mMethodsFound.add(methodName);
- }
- super.setHasNativeMethods(hasNativeMethods, methodName);
- }
- }
-
- /**
- * Dummy test class with a native method.
- */
- public static class ClassWithNative {
- public ClassWithNative() {
- }
-
- public void callTheNativeMethod() {
- native_method();
- }
-
- private native void native_method();
- }
-
- /**
- * Dummy test class with no native method.
- */
- public static class ClassWithoutNative {
- public ClassWithoutNative() {
- }
-
- public void someMethod() {
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create;
-
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-class CreateInfoAdapter implements ICreateInfo {
- private static final String[] EMPTY_STRING_ARRAY = new String[0];
-
- @Override
- public Class<?>[] getInjectedClasses() {
- return new Class<?>[0];
- }
-
- @Override
- public String[] getDelegateMethods() {
- return EMPTY_STRING_ARRAY;
- }
-
- @Override
- public String[] getDelegateClassNatives() {
- return EMPTY_STRING_ARRAY;
- }
-
- @Override
- public String[] getRenamedClasses() {
- return EMPTY_STRING_ARRAY;
- }
-
- @Override
- public String[] getRefactoredClasses() {
- return EMPTY_STRING_ARRAY;
- }
-
- @Override
- public String[] getDeleteReturns() {
- return EMPTY_STRING_ARRAY;
- }
-
- @Override
- public String[] getJavaPkgClasses() {
- return EMPTY_STRING_ARRAY;
- }
-
- @Override
- public Set<String> getExcludedClasses() {
- return Collections.emptySet();
- }
-
- @Override
- public String[] getPromotedFields() {
- return EMPTY_STRING_ARRAY;
- }
-
- @Override
- public String[] getPromotedClasses() {
- return EMPTY_STRING_ARRAY;
- }
-
- @Override
- public Map<String, InjectMethodRunnable> getInjectedMethodsMap() {
- return Collections.emptyMap();
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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 static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import com.android.tools.layoutlib.create.dataclass.ClassWithNative;
-import com.android.tools.layoutlib.create.dataclass.OuterClass;
-import com.android.tools.layoutlib.create.dataclass.OuterClass.InnerClass;
-import com.android.tools.layoutlib.create.dataclass.OuterClass.StaticInnerClass;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.ClassWriter;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-public class DelegateClassAdapterTest {
-
- private MockLog mLog;
-
- private static final String NATIVE_CLASS_NAME = ClassWithNative.class.getName();
- private static final String OUTER_CLASS_NAME = OuterClass.class.getName();
- private static final String INNER_CLASS_NAME = InnerClass.class.getName();
- private static final String STATIC_INNER_CLASS_NAME = StaticInnerClass.class.getName();
-
- @Before
- public void setUp() throws Exception {
- mLog = new MockLog();
- mLog.setVerbose(true); // capture debug error too
- }
-
- /**
- * Tests that a class not being modified still works.
- */
- @Test
- public void testNoOp() throws Throwable {
- // create an instance of the class that will be modified
- // (load the class in a distinct class loader so that we can trash its definition later)
- ClassLoader cl1 = new ClassLoader(this.getClass().getClassLoader()) { };
- @SuppressWarnings("unchecked")
- Class<ClassWithNative> clazz1 = (Class<ClassWithNative>) cl1.loadClass(NATIVE_CLASS_NAME);
- ClassWithNative instance1 = clazz1.newInstance();
- assertEquals(42, instance1.add(20, 22));
- try {
- instance1.callNativeInstance(10, 3.1415, new Object[0] );
- fail("Test should have failed to invoke callTheNativeMethod [1]");
- } catch (UnsatisfiedLinkError e) {
- // This is expected to fail since the native method is not implemented.
- }
-
- // Now process it but tell the delegate to not modify any method
- ClassWriter cw = new ClassWriter(0 /*flags*/);
-
- HashSet<String> delegateMethods = new HashSet<>();
- String internalClassName = NATIVE_CLASS_NAME.replace('.', '/');
- DelegateClassAdapter cv = new DelegateClassAdapter(
- mLog, cw, internalClassName, delegateMethods);
-
- ClassReader cr = new ClassReader(NATIVE_CLASS_NAME);
- cr.accept(cv, 0 /* flags */);
-
- // Load the generated class in a different class loader and try it again
-
- ClassLoader2 cl2 = null;
- try {
- cl2 = new ClassLoader2() {
- @Override
- public void testModifiedInstance() throws Exception {
- Class<?> clazz2 = loadClass(NATIVE_CLASS_NAME);
- Object i2 = clazz2.newInstance();
- assertNotNull(i2);
- assertEquals(42, callAdd(i2, 20, 22));
-
- try {
- callCallNativeInstance(i2, 10, 3.1415, new Object[0]);
- fail("Test should have failed to invoke callTheNativeMethod [2]");
- } catch (InvocationTargetException e) {
- // This is expected to fail since the native method has NOT been
- // overridden here.
- assertEquals(UnsatisfiedLinkError.class, e.getCause().getClass());
- }
-
- // Check that the native method does NOT have the new annotation
- Method[] m = clazz2.getDeclaredMethods();
- Method nativeInstanceMethod = null;
- for (Method method : m) {
- if ("native_instance".equals(method.getName())) {
- nativeInstanceMethod = method;
- break;
- }
- }
- assertNotNull(nativeInstanceMethod);
- assertTrue(Modifier.isNative(nativeInstanceMethod.getModifiers()));
- Annotation[] a = nativeInstanceMethod.getAnnotations();
- assertEquals(0, a.length);
- }
- };
- cl2.add(NATIVE_CLASS_NAME, cw);
- cl2.testModifiedInstance();
- } catch (Throwable t) {
- throw dumpGeneratedClass(t, cl2);
- }
- }
-
- /**
- * {@link DelegateMethodAdapter} does not support overriding constructors yet,
- * so this should fail with an {@link UnsupportedOperationException}.
- *
- * Although not tested here, the message of the exception should contain the
- * constructor signature.
- */
- @Test(expected=UnsupportedOperationException.class)
- public void testConstructorsNotSupported() throws IOException {
- ClassWriter cw = new ClassWriter(0 /*flags*/);
-
- String internalClassName = NATIVE_CLASS_NAME.replace('.', '/');
-
- HashSet<String> delegateMethods = new HashSet<>();
- delegateMethods.add("<init>");
- DelegateClassAdapter cv = new DelegateClassAdapter(
- mLog, cw, internalClassName, delegateMethods);
-
- ClassReader cr = new ClassReader(NATIVE_CLASS_NAME);
- cr.accept(cv, 0 /* flags */);
- }
-
- @Test
- public void testDelegateNative() throws Throwable {
- ClassWriter cw = new ClassWriter(0 /*flags*/);
- String internalClassName = NATIVE_CLASS_NAME.replace('.', '/');
-
- HashSet<String> delegateMethods = new HashSet<>();
- delegateMethods.add(DelegateClassAdapter.ALL_NATIVES);
- DelegateClassAdapter cv = new DelegateClassAdapter(
- mLog, cw, internalClassName, delegateMethods);
-
- ClassReader cr = new ClassReader(NATIVE_CLASS_NAME);
- cr.accept(cv, 0 /* flags */);
-
- // Load the generated class in a different class loader and try it
- ClassLoader2 cl2 = null;
- try {
- cl2 = new ClassLoader2() {
- @Override
- public void testModifiedInstance() throws Exception {
- Class<?> clazz2 = loadClass(NATIVE_CLASS_NAME);
- Object i2 = clazz2.newInstance();
- assertNotNull(i2);
-
- // Use reflection to access inner methods
- assertEquals(42, callAdd(i2, 20, 22));
-
- Object[] objResult = new Object[] { null };
- int result = callCallNativeInstance(i2, 10, 3.1415, objResult);
- assertEquals((int)(10 + 3.1415), result);
- assertSame(i2, objResult[0]);
-
- // Check that the native method now has the new annotation and is not native
- Method[] m = clazz2.getDeclaredMethods();
- Method nativeInstanceMethod = null;
- for (Method method : m) {
- if ("native_instance".equals(method.getName())) {
- nativeInstanceMethod = method;
- break;
- }
- }
- assertNotNull(nativeInstanceMethod);
- assertFalse(Modifier.isNative(nativeInstanceMethod.getModifiers()));
- Annotation[] a = nativeInstanceMethod.getAnnotations();
- assertEquals("LayoutlibDelegate", a[0].annotationType().getSimpleName());
- }
- };
- cl2.add(NATIVE_CLASS_NAME, cw);
- cl2.testModifiedInstance();
- } catch (Throwable t) {
- throw dumpGeneratedClass(t, cl2);
- }
- }
-
- @Test
- public void testDelegateInner() throws Throwable {
- // We'll delegate the "get" method of both the inner and outer class.
- HashSet<String> delegateMethods = new HashSet<>();
- delegateMethods.add("get");
- delegateMethods.add("privateMethod");
-
- // Generate the delegate for the outer class.
- ClassWriter cwOuter = new ClassWriter(0 /*flags*/);
- String outerClassName = OUTER_CLASS_NAME.replace('.', '/');
- DelegateClassAdapter cvOuter = new DelegateClassAdapter(
- mLog, cwOuter, outerClassName, delegateMethods);
- ClassReader cr = new ClassReader(OUTER_CLASS_NAME);
- cr.accept(cvOuter, 0 /* flags */);
-
- // Generate the delegate for the inner class.
- ClassWriter cwInner = new ClassWriter(0 /*flags*/);
- String innerClassName = INNER_CLASS_NAME.replace('.', '/');
- DelegateClassAdapter cvInner = new DelegateClassAdapter(
- mLog, cwInner, innerClassName, delegateMethods);
- cr = new ClassReader(INNER_CLASS_NAME);
- cr.accept(cvInner, 0 /* flags */);
-
- // Load the generated classes in a different class loader and try them
- ClassLoader2 cl2 = null;
- try {
- cl2 = new ClassLoader2() {
- @Override
- public void testModifiedInstance() throws Exception {
-
- // Check the outer class
- Class<?> outerClazz2 = loadClass(OUTER_CLASS_NAME);
- Object o2 = outerClazz2.newInstance();
- assertNotNull(o2);
-
- // The original Outer.get returns 1+10+20,
- // but the delegate makes it return 4+10+20
- assertEquals(4+10+20, callGet(o2, 10, 20));
- assertEquals(1+10+20, callGet_Original(o2, 10, 20));
-
- // The original Outer has a private method,
- // so by default we can't access it.
- boolean gotIllegalAccessException = false;
- try {
- callMethod(o2, "privateMethod", false /*makePublic*/);
- } catch(IllegalAccessException e) {
- gotIllegalAccessException = true;
- }
- assertTrue(gotIllegalAccessException);
-
- // The private method from original Outer has been
- // delegated. The delegate generated should have the
- // same access.
- gotIllegalAccessException = false;
- try {
- assertEquals("outerPrivateMethod",
- callMethod(o2, "privateMethod_Original", false /*makePublic*/));
- } catch (IllegalAccessException e) {
- gotIllegalAccessException = true;
- }
- assertTrue(gotIllegalAccessException);
-
- // Check the inner class. Since it's not a static inner class, we need
- // to use the hidden constructor that takes the outer class as first parameter.
- Class<?> innerClazz2 = loadClass(INNER_CLASS_NAME);
- Constructor<?> innerCons = innerClazz2.getConstructor(outerClazz2);
- Object i2 = innerCons.newInstance(o2);
- assertNotNull(i2);
-
- // The original Inner.get returns 3+10+20,
- // but the delegate makes it return 6+10+20
- assertEquals(6+10+20, callGet(i2, 10, 20));
- assertEquals(3+10+20, callGet_Original(i2, 10, 20));
- }
- };
- cl2.add(OUTER_CLASS_NAME, cwOuter.toByteArray());
- cl2.add(INNER_CLASS_NAME, cwInner.toByteArray());
- cl2.testModifiedInstance();
- } catch (Throwable t) {
- throw dumpGeneratedClass(t, cl2);
- }
- }
-
- @Test
- public void testDelegateStaticInner() throws Throwable {
- // We'll delegate the "get" method of both the inner and outer class.
- HashSet<String> delegateMethods = new HashSet<>();
- delegateMethods.add("get");
-
- // Generate the delegate for the outer class.
- ClassWriter cwOuter = new ClassWriter(0 /*flags*/);
- String outerClassName = OUTER_CLASS_NAME.replace('.', '/');
- DelegateClassAdapter cvOuter = new DelegateClassAdapter(
- mLog, cwOuter, outerClassName, delegateMethods);
- ClassReader cr = new ClassReader(OUTER_CLASS_NAME);
- cr.accept(cvOuter, 0 /* flags */);
-
- // Generate the delegate for the static inner class.
- ClassWriter cwInner = new ClassWriter(0 /*flags*/);
- String innerClassName = STATIC_INNER_CLASS_NAME.replace('.', '/');
- DelegateClassAdapter cvInner = new DelegateClassAdapter(
- mLog, cwInner, innerClassName, delegateMethods);
- cr = new ClassReader(STATIC_INNER_CLASS_NAME);
- cr.accept(cvInner, 0 /* flags */);
-
- // Load the generated classes in a different class loader and try them
- ClassLoader2 cl2 = null;
- try {
- cl2 = new ClassLoader2() {
- @Override
- public void testModifiedInstance() throws Exception {
-
- // Check the outer class
- Class<?> outerClazz2 = loadClass(OUTER_CLASS_NAME);
- Object o2 = outerClazz2.newInstance();
- assertNotNull(o2);
-
- // Check the inner class. Since it's not a static inner class, we need
- // to use the hidden constructor that takes the outer class as first parameter.
- Class<?> innerClazz2 = loadClass(STATIC_INNER_CLASS_NAME);
- Constructor<?> innerCons = innerClazz2.getConstructor();
- Object i2 = innerCons.newInstance();
- assertNotNull(i2);
-
- // The original StaticInner.get returns 100+10+20,
- // but the delegate makes it return 6+10+20
- assertEquals(6+10+20, callGet(i2, 10, 20));
- assertEquals(100+10+20, callGet_Original(i2, 10, 20));
- }
- };
- cl2.add(OUTER_CLASS_NAME, cwOuter.toByteArray());
- cl2.add(STATIC_INNER_CLASS_NAME, cwInner.toByteArray());
- cl2.testModifiedInstance();
- } catch (Throwable t) {
- throw dumpGeneratedClass(t, cl2);
- }
- }
-
- //-------
-
- /**
- * A class loader than can define and instantiate our modified classes.
- * <p/>
- * The trick here is that this class loader will test our <em>modified</em> version
- * of the classes, the one with the delegate calls.
- * <p/>
- * Trying to do so in the original class loader generates all sort of link issues because
- * there are 2 different definitions of the same class name. This class loader will
- * define and load the class when requested by name and provide helpers to access the
- * instance methods via reflection.
- */
- private abstract class ClassLoader2 extends ClassLoader {
-
- private final Map<String, byte[]> mClassDefs = new HashMap<>();
-
- public ClassLoader2() {
- super(null);
- }
-
- public ClassLoader2 add(String className, byte[] definition) {
- mClassDefs.put(className, definition);
- return this;
- }
-
- public ClassLoader2 add(String className, ClassWriter rewrittenClass) {
- mClassDefs.put(className, rewrittenClass.toByteArray());
- return this;
- }
-
- private Set<Entry<String, byte[]>> getByteCode() {
- return mClassDefs.entrySet();
- }
-
- @SuppressWarnings("unused")
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- try {
- return super.findClass(name);
- } catch (ClassNotFoundException e) {
-
- byte[] def = mClassDefs.get(name);
- if (def != null) {
- // Load the modified ClassWithNative from its bytes representation.
- return defineClass(name, def, 0, def.length);
- }
-
- try {
- // Load everything else from the original definition into the new class loader.
- ClassReader cr = new ClassReader(name);
- ClassWriter cw = new ClassWriter(0);
- cr.accept(cw, 0);
- byte[] bytes = cw.toByteArray();
- return defineClass(name, bytes, 0, bytes.length);
-
- } catch (IOException ioe) {
- throw new RuntimeException(ioe);
- }
- }
- }
-
- /**
- * Accesses {@link OuterClass#get} or {@link InnerClass#get}via reflection.
- */
- public int callGet(Object instance, int a, long b) throws Exception {
- Method m = instance.getClass().getMethod("get",
- int.class, long.class);
-
- Object result = m.invoke(instance, a, b);
- return (Integer) result;
- }
-
- /**
- * Accesses the "_Original" methods for {@link OuterClass#get}
- * or {@link InnerClass#get}via reflection.
- */
- public int callGet_Original(Object instance, int a, long b) throws Exception {
- Method m = instance.getClass().getMethod("get_Original",
- int.class, long.class);
-
- Object result = m.invoke(instance, a, b);
- return (Integer) result;
- }
-
- /**
- * Accesses the any declared method that takes no parameter via reflection.
- */
- @SuppressWarnings("unchecked")
- public <T> T callMethod(Object instance, String methodName, boolean makePublic) throws Exception {
- Method m = instance.getClass().getDeclaredMethod(methodName, (Class<?>[])null);
-
- boolean wasAccessible = m.isAccessible();
- if (makePublic && !wasAccessible) {
- m.setAccessible(true);
- }
-
- Object result = m.invoke(instance, (Object[])null);
-
- if (makePublic && !wasAccessible) {
- m.setAccessible(false);
- }
-
- return (T) result;
- }
-
- /**
- * Accesses {@link ClassWithNative#add(int, int)} via reflection.
- */
- public int callAdd(Object instance, int a, int b) throws Exception {
- Method m = instance.getClass().getMethod("add",
- int.class, int.class);
-
- Object result = m.invoke(instance, a, b);
- return (Integer) result;
- }
-
- /**
- * Accesses {@link ClassWithNative#callNativeInstance(int, double, Object[])}
- * via reflection.
- */
- public int callCallNativeInstance(Object instance, int a, double d, Object[] o)
- throws Exception {
- Method m = instance.getClass().getMethod("callNativeInstance",
- int.class, double.class, Object[].class);
-
- Object result = m.invoke(instance, a, d, o);
- return (Integer) result;
- }
-
- public abstract void testModifiedInstance() throws Exception;
- }
-
- /**
- * For debugging, it's useful to dump the content of the generated classes
- * along with the exception that was generated.
- *
- * However to make it work you need to pull in the org.objectweb.asm.util.TraceClassVisitor
- * class and associated utilities which are found in the ASM source jar. Since we don't
- * want that dependency in the source code, we only put it manually for development and
- * access the TraceClassVisitor via reflection if present.
- *
- * @param t The exception thrown by {@link ClassLoader2#testModifiedInstance()}
- * @param cl2 The {@link ClassLoader2} instance with the generated bytecode.
- * @return Either original {@code t} or a new wrapper {@link Throwable}
- */
- private Throwable dumpGeneratedClass(Throwable t, ClassLoader2 cl2) {
- try {
- // For debugging, dump the bytecode of the class in case of unexpected error
- // if we can find the TraceClassVisitor class.
- Class<?> tcvClass = Class.forName("org.objectweb.asm.util.TraceClassVisitor");
-
- StringBuilder sb = new StringBuilder();
- sb.append('\n').append(t.getClass().getCanonicalName());
- if (t.getMessage() != null) {
- sb.append(": ").append(t.getMessage());
- }
-
- for (Entry<String, byte[]> entry : cl2.getByteCode()) {
- String className = entry.getKey();
- byte[] bytes = entry.getValue();
-
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- // next 2 lines do: TraceClassVisitor tcv = new TraceClassVisitor(pw);
- Constructor<?> cons = tcvClass.getConstructor(pw.getClass());
- Object tcv = cons.newInstance(pw);
- ClassReader cr2 = new ClassReader(bytes);
- cr2.accept((ClassVisitor) tcv, 0 /* flags */);
-
- sb.append("\nBytecode dump: <").append(className).append(">:\n")
- .append(sw.toString());
- }
-
- // Re-throw exception with new message
- return new RuntimeException(sb.toString(), t);
- } catch (Throwable ignore) {
- // In case of problem, just throw the original exception as-is.
- return t;
- }
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 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 static org.junit.Assert.*;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class LogTest {
-
- private MockLog mLog;
-
- @Before
- public void setUp() throws Exception {
- mLog = new MockLog();
- }
-
- @After
- public void tearDown() throws Exception {
- // pass
- }
-
- @Test
- public void testDebug() {
- assertEquals("", mLog.getOut());
- assertEquals("", mLog.getErr());
-
- mLog.setVerbose(false);
- mLog.debug("Test %d", 42);
- assertEquals("", mLog.getOut());
-
- mLog.setVerbose(true);
- mLog.debug("Test %d", 42);
-
- assertEquals("Test 42\n", mLog.getOut());
- assertEquals("", mLog.getErr());
- }
-
- @Test
- public void testInfo() {
- assertEquals("", mLog.getOut());
- assertEquals("", mLog.getErr());
-
- mLog.info("Test %d", 43);
-
- assertEquals("Test 43\n", mLog.getOut());
- assertEquals("", mLog.getErr());
- }
-
- @Test
- public void testError() {
- assertEquals("", mLog.getOut());
- assertEquals("", mLog.getErr());
-
- mLog.error("Test %d", 44);
-
- assertEquals("", mLog.getOut());
- assertEquals("Test 44\n", mLog.getErr());
- }
-
- @Test
- public void testException() {
- assertEquals("", mLog.getOut());
- assertEquals("", mLog.getErr());
-
- Exception e = new Exception("My Exception");
- mLog.exception(e, "Test %d", 44);
-
- assertEquals("", mLog.getOut());
- assertTrue(mLog.getErr().startsWith("Test 44\njava.lang.Exception: My Exception"));
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 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;
-
-
-public class MockLog extends Log {
- StringBuilder mOut = new StringBuilder();
- StringBuilder mErr = new StringBuilder();
-
- public String getOut() {
- return mOut.toString();
- }
-
- public String getErr() {
- return mErr.toString();
- }
-
- @Override
- protected void outPrintln(String msg) {
- mOut.append(msg);
- mOut.append('\n');
- }
-
- @Override
- protected void errPrintln(String msg) {
- mErr.append(msg);
- mErr.append('\n');
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create;
-
-import org.junit.Test;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.Opcodes;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.StringJoiner;
-
-import static org.junit.Assert.assertTrue;
-
-/**
- * {@link ClassVisitor} that logs all the calls to the different visit methods so they can be later
- * inspected.
- */
-class LoggingClassVisitor extends ClassVisitor {
- List<String> mLog = new LinkedList<String>();
-
- public LoggingClassVisitor() {
- super(Main.ASM_VERSION);
- }
-
- public LoggingClassVisitor(ClassVisitor cv) {
- super(Main.ASM_VERSION, cv);
- }
-
- private static String formatAccess(int access) {
- StringJoiner modifiers = new StringJoiner(",");
-
- if ((access & Opcodes.ACC_PUBLIC) != 0) {
- modifiers.add("public");
- }
- if ((access & Opcodes.ACC_PRIVATE) != 0) {
- modifiers.add("private");
- }
- if ((access & Opcodes.ACC_PROTECTED) != 0) {
- modifiers.add("protected");
- }
- if ((access & Opcodes.ACC_STATIC) != 0) {
- modifiers.add("static");
- }
- if ((access & Opcodes.ACC_FINAL) != 0) {
- modifiers.add("static");
- }
-
- return "[" + modifiers.toString() + "]";
- }
-
- private void log(String method, String format, Object...args) {
- mLog.add(
- String.format("[%s] - %s", method, String.format(format, (Object[]) args))
- );
- }
-
- @Override
- public void visitOuterClass(String owner, String name, String desc) {
- log(
- "visitOuterClass",
- "owner=%s, name=%s, desc=%s",
- owner, name, desc
- );
-
- super.visitOuterClass(owner, name, desc);
- }
-
- @Override
- public void visitInnerClass(String name, String outerName, String innerName, int access) {
- log(
- "visitInnerClass",
- "name=%s, outerName=%s, innerName=%s, access=%s",
- name, outerName, innerName, formatAccess(access)
- );
-
- super.visitInnerClass(name, outerName, innerName, access);
- }
-
- @Override
- public void visit(int version, int access, String name, String signature, String superName,
- String[] interfaces) {
- log(
- "visit",
- "version=%d, access=%s, name=%s, signature=%s, superName=%s, interfaces=%s",
- version, formatAccess(access), name, signature, superName, Arrays.toString(interfaces)
- );
-
- super.visit(version, access, name, signature, superName, interfaces);
- }
-}
-
-class PackageProtectedClass {}
-
-public class PromoteClassClassAdapterTest {
- private static class PrivateClass {}
- private static class ClassWithPrivateInnerClass {
- private class InnerPrivateClass {}
- }
-
- @Test
- public void testInnerClassPromotion() throws IOException {
- ClassReader reader = new ClassReader(PrivateClass.class.getName());
- LoggingClassVisitor log = new LoggingClassVisitor();
-
- PromoteClassClassAdapter adapter = new PromoteClassClassAdapter(log, new HashSet<String>() {
- {
- add("com.android.tools.layoutlib.create.PromoteClassClassAdapterTest$PrivateClass");
- add("com.android.tools.layoutlib.create" +
- ".PromoteClassClassAdapterTest$ClassWithPrivateInnerClass$InnerPrivateClass");
- }
- });
- reader.accept(adapter, 0);
- assertTrue(log.mLog.contains(
- "[visitInnerClass] - " +
- "name=com/android/tools/layoutlib/create" +
- "/PromoteClassClassAdapterTest$PrivateClass, " +
- "outerName=com/android/tools/layoutlib/create" +
- "/PromoteClassClassAdapterTest, innerName=PrivateClass, access=[public,static]"));
-
- // Test inner of inner class
- log.mLog.clear();
- reader = new ClassReader(ClassWithPrivateInnerClass.class.getName());
- reader.accept(adapter, 0);
-
- assertTrue(log.mLog.contains("[visitInnerClass] - " +
- "name=com/android/tools/layoutlib/create" +
- "/PromoteClassClassAdapterTest$ClassWithPrivateInnerClass$InnerPrivateClass, " +
- "outerName=com/android/tools/layoutlib/create" +
- "/PromoteClassClassAdapterTest$ClassWithPrivateInnerClass, " +
- "innerName=InnerPrivateClass, access=[public]"));
-
- }
-
- @Test
- public void testProtectedClassPromotion() throws IOException {
- ClassReader reader = new ClassReader(PackageProtectedClass.class.getName());
- LoggingClassVisitor log = new LoggingClassVisitor();
-
- PromoteClassClassAdapter adapter = new PromoteClassClassAdapter(log, new HashSet<String>() {
- {
- add("com.android.tools.layoutlib.create.PackageProtectedClass");
- }
- });
-
- reader.accept(adapter, 0);
- assertTrue(log.mLog.contains("[visit] - version=52, access=[public], " +
- "name=com/android/tools/layoutlib/create/PackageProtectedClass, signature=null, " +
- "superName=java/lang/Object, interfaces=[]"));
-
- }
-}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (C) 2008 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 static org.junit.Assert.*;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- *
- */
-public class RenameClassAdapterTest {
-
- private RenameClassAdapter mOuter;
- private RenameClassAdapter mInner;
-
- @Before
- public void setUp() throws Exception {
- mOuter = new RenameClassAdapter(null, // cv
- "com.pack.Old",
- "org.blah.New");
-
- mInner = new RenameClassAdapter(null, // cv
- "com.pack.Old$Inner",
- "org.blah.New$Inner");
- }
-
- @After
- public void tearDown() throws Exception {
- }
-
- /**
- * Renames a type, e.g. "Lcom.package.My;"
- * If the type doesn't need to be renamed, returns the input string as-is.
- */
- @Test
- public void testRenameTypeDesc() {
-
- // primitive types are left untouched
- assertEquals("I", mOuter.renameTypeDesc("I"));
- assertEquals("D", mOuter.renameTypeDesc("D"));
- assertEquals("V", mOuter.renameTypeDesc("V"));
-
- // object types that need no renaming are left untouched
- assertEquals("Lcom.package.MyClass;", mOuter.renameTypeDesc("Lcom.package.MyClass;"));
- assertEquals("Lcom.package.MyClass;", mInner.renameTypeDesc("Lcom.package.MyClass;"));
-
- // object types that match the requirements
- assertEquals("Lorg.blah.New;", mOuter.renameTypeDesc("Lcom.pack.Old;"));
- assertEquals("Lorg.blah.New$Inner;", mInner.renameTypeDesc("Lcom.pack.Old$Inner;"));
- // inner classes match the base type which is being renamed
- assertEquals("Lorg.blah.New$Other;", mOuter.renameTypeDesc("Lcom.pack.Old$Other;"));
- assertEquals("Lorg.blah.New$Other;", mInner.renameTypeDesc("Lcom.pack.Old$Other;"));
-
- // arrays
- assertEquals("[Lorg.blah.New;", mOuter.renameTypeDesc("[Lcom.pack.Old;"));
- assertEquals("[[Lorg.blah.New;", mOuter.renameTypeDesc("[[Lcom.pack.Old;"));
-
- assertEquals("[Lorg.blah.New;", mInner.renameTypeDesc("[Lcom.pack.Old;"));
- assertEquals("[[Lorg.blah.New;", mInner.renameTypeDesc("[[Lcom.pack.Old;"));
- }
-
- /**
- * Renames an object type, e.g. "Lcom.package.MyClass;" or an array type that has an
- * object element, e.g. "[Lcom.package.MyClass;"
- * If the type doesn't need to be renamed, returns the internal name of the input type.
- */
- @Test
- public void testRenameType() {
- // Skip. This is actually tested by testRenameTypeDesc above.
- }
-
- /**
- * Renames an internal type name, e.g. "com.package.MyClass".
- * If the type doesn't need to be renamed, returns the input string as-is.
- */
- @Test
- public void testRenameInternalType() {
- // an actual FQCN
- assertEquals("org.blah.New", mOuter.renameInternalType("com.pack.Old"));
- assertEquals("org.blah.New$Inner", mOuter.renameInternalType("com.pack.Old$Inner"));
-
- assertEquals("org.blah.New$Other", mInner.renameInternalType("com.pack.Old$Other"));
- assertEquals("org.blah.New$Other", mInner.renameInternalType("com.pack.Old$Other"));
- }
-
- /**
- * Renames a method descriptor, i.e. applies renameType to all arguments and to the
- * return value.
- */
- @Test
- public void testRenameMethodDesc() {
- assertEquals("(IDLorg.blah.New;[Lorg.blah.New$Inner;)Lorg.blah.New$Other;",
- mOuter.renameMethodDesc("(IDLcom.pack.Old;[Lcom.pack.Old$Inner;)Lcom.pack.Old$Other;"));
- }
-
-
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create;
-
-import com.android.tools.layoutlib.create.dataclass.StubClass;
-
-import org.junit.Assert;
-import org.junit.Test;
-import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-import java.lang.reflect.Method;
-import java.util.function.BiPredicate;
-import java.util.function.Consumer;
-
-import static org.junit.Assert.*;
-
-public class StubMethodAdapterTest {
-
- private static final String STUB_CLASS_NAME = StubClass.class.getName();
-
- /**
- * Load a dummy class, stub one of its method and ensure that the modified class works as
- * intended.
- */
- @Test
- public void testBoolean() throws Exception {
- final String methodName = "returnTrue";
- // First don't change the method and assert that it returns true
- testBoolean((name, type) -> false, Assert::assertTrue, methodName);
- // Change the method now and assert that it returns false.
- testBoolean((name, type) -> methodName.equals(name) &&
- Type.BOOLEAN_TYPE.equals(type.getReturnType()), Assert::assertFalse, methodName);
- }
-
- /**
- * @param methodPredicate tests if the method should be replaced
- */
- private void testBoolean(BiPredicate<String, Type> methodPredicate, Consumer<Boolean> assertion,
- String methodName) throws Exception {
- ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
- // Always rename the class to avoid conflict with the original class.
- String newClassName = STUB_CLASS_NAME + '_';
- new ClassReader(STUB_CLASS_NAME).accept(
- new ClassAdapter(newClassName, writer, methodPredicate), 0);
- MyClassLoader myClassLoader = new MyClassLoader(newClassName, writer.toByteArray());
- Class<?> aClass = myClassLoader.loadClass(newClassName);
- assertTrue("StubClass not loaded by the classloader. Likely a bug in the test.",
- myClassLoader.findClassCalled);
- Method method = aClass.getMethod(methodName);
- Object o = aClass.newInstance();
- assertion.accept((Boolean) method.invoke(o));
- }
-
- private static class ClassAdapter extends ClassVisitor {
-
- private final String mClassName;
- private final BiPredicate<String, Type> mMethodPredicate;
-
- private ClassAdapter(String className, ClassVisitor cv,
- BiPredicate<String, Type> methodPredicate) {
- super(Main.ASM_VERSION, cv);
- mClassName = className.replace('.', '/');
- mMethodPredicate = methodPredicate;
- }
-
- @Override
- public void visit(int version, int access, String name, String signature, String superName,
- String[] interfaces) {
- super.visit(version, access, mClassName, signature, superName,
- interfaces);
- }
-
- @Override
- public MethodVisitor visitMethod(int access, String name, String desc, String signature,
- String[] exceptions) {
- // Copied partly from
- // com.android.tools.layoutlib.create.DelegateClassAdapter.visitMethod()
- // but not generating the _Original method.
- boolean isStatic = (access & Opcodes.ACC_STATIC) != 0;
- boolean isNative = (access & Opcodes.ACC_NATIVE) != 0;
- MethodVisitor originalMethod =
- super.visitMethod(access, name, desc, signature, exceptions);
- Type descriptor = Type.getMethodType(desc);
- if (mMethodPredicate.test(name, descriptor)) {
- String methodSignature = mClassName + "#" + name;
- String invokeSignature = methodSignature + desc;
- return new StubMethodAdapter(originalMethod, name, descriptor.getReturnType(),
- invokeSignature, isStatic, isNative);
- }
- return originalMethod;
- }
- }
-
- private static class MyClassLoader extends ClassLoader {
- private final String mName;
- private final byte[] mBytes;
- private boolean findClassCalled;
-
- private MyClassLoader(String name, byte[] bytes) {
- mName = name;
- mBytes = bytes;
- }
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- if (name.equals(mName)) {
- findClassCalled = true;
- return defineClass(name, mBytes, 0, mBytes.length);
- }
- return super.findClass(name);
- }
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create.dataclass;
-
-import com.android.tools.layoutlib.create.DelegateClassAdapterTest;
-
-/**
- * Dummy test class with a native method.
- * The native method is not defined and any attempt to invoke it will
- * throw an {@link UnsatisfiedLinkError}.
- *
- * Used by {@link DelegateClassAdapterTest}.
- */
-public class ClassWithNative {
- public ClassWithNative() {
- }
-
- public int add(int a, int b) {
- return a + b;
- }
-
- // Note: it's good to have a long or double for testing parameters since they take
- // 2 slots in the stack/locals maps.
-
- public int callNativeInstance(int a, double d, Object[] o) {
- return native_instance(a, d, o);
- }
-
- private native int native_instance(int a, double d, Object[] o);
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create.dataclass;
-
-import com.android.tools.layoutlib.create.DelegateClassAdapterTest;
-
-/**
- * The delegate that receives the call to {@link ClassWithNative_Delegate}'s overridden methods.
- *
- * Used by {@link DelegateClassAdapterTest}.
- */
-public class ClassWithNative_Delegate {
- public static int native_instance(ClassWithNative instance, int a, double d, Object[] o) {
- if (o != null && o.length > 0) {
- o[0] = instance;
- }
- return (int)(a + d);
- }
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create.dataclass;
-
-public final class JavaClass {
-
- public static final String test = "test";
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create.dataclass;
-
-import com.android.tools.layoutlib.create.DelegateClassAdapterTest;
-
-/**
- * Test class with an inner class.
- *
- * Used by {@link DelegateClassAdapterTest}.
- */
-public class OuterClass {
- private int mOuterValue = 1;
- public OuterClass() {
- }
-
- // Outer.get returns 1 + a + b
- // Note: it's good to have a long or double for testing parameters since they take
- // 2 slots in the stack/locals maps.
- public int get(int a, long b) {
- return mOuterValue + a + (int) b;
- }
-
- public class InnerClass {
- public InnerClass() {
- }
-
- // Inner.get returns 2 + 1 + a + b
- public int get(int a, long b) {
- return 2 + mOuterValue + a + (int) b;
- }
- }
-
- public static class StaticInnerClass {
- public StaticInnerClass() {
- }
-
- // StaticInnerClass.get returns 100 + a + b
- public int get(int a, long b) {
- return 100 + a + (int) b;
- }
- }
-
- @SuppressWarnings("unused")
- private String privateMethod() {
- return "outerPrivateMethod";
- }
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create.dataclass;
-
-import com.android.tools.layoutlib.create.DelegateClassAdapterTest;
-
-/**
- * Used by {@link DelegateClassAdapterTest}.
- */
-public class OuterClass_Delegate {
- // The delegate override of Outer.get returns 4 + a + b
- public static int get(OuterClass instance, int a, long b) {
- return 4 + a + (int) b;
- }
-
- public static String privateMethod(OuterClass instance) {
- return "outerPrivate_Delegate";
- }
-}
-
+++ /dev/null
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create.dataclass;
-
-import com.android.tools.layoutlib.create.DelegateClassAdapterTest;
-import com.android.tools.layoutlib.create.dataclass.OuterClass.InnerClass;
-
-/**
- * Used by {@link DelegateClassAdapterTest}.
- */
-public class OuterClass_InnerClass_Delegate {
- // The delegate override of Inner.get return 6 + a + b
- public static int get(OuterClass outer, InnerClass inner, int a, long b) {
- return 6 + a + (int) b;
- }
-}
+++ /dev/null
-/*
- * 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.dataclass;
-
-import com.android.tools.layoutlib.create.DelegateClassAdapterTest;
-import com.android.tools.layoutlib.create.dataclass.OuterClass.StaticInnerClass;
-
-/**
- * Used by {@link DelegateClassAdapterTest}.
- */
-public class OuterClass_StaticInnerClass_Delegate {
- // The delegate override of Inner.get return 6 + a + b
- public static int get(StaticInnerClass inner, int a, long b) {
- return 6 + a + (int) b;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tools.layoutlib.create.dataclass;
-
-import com.android.tools.layoutlib.create.StubMethodAdapterTest;
-
-/**
- * Used by {@link StubMethodAdapterTest}
- */
-@SuppressWarnings("unused")
-public class StubClass {
-
- public boolean returnTrue() {
- return true;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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 java.lang;
-
-public class JavaClass {
-
- public static String test = "test";
-}
+++ /dev/null
-A simple data file that should *not* be copied to the output jar.
\ No newline at end of file
+++ /dev/null
-A simple data file that should be copied to the output jar unchanged.
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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 mock_android.dummy;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-
-public class InnerTest {
-
- private int mSomeField;
- private MyStaticInnerClass mInnerInstance;
- private MyIntEnum mTheIntEnum;
- private MyGenerics1<int[][], InnerTest, MyIntEnum, float[]> mGeneric1;
-
- public class NotStaticInner2 extends NotStaticInner1 {
-
- }
-
- public class NotStaticInner1 {
-
- public void someThing() {
- mSomeField = 2;
- mInnerInstance = null;
- }
-
- }
-
- private static class MyStaticInnerClass {
-
- }
-
- private static class DerivingClass extends InnerTest {
-
- }
-
- // enums are a kind of inner static class
- public enum MyIntEnum {
- VALUE0(0),
- VALUE1(1),
- VALUE2(2);
-
- MyIntEnum(int myInt) {
- this.myInt = myInt;
- }
- final int myInt;
- }
-
- public static class MyGenerics1<T, U, V, W> {
- public MyGenerics1() {
- int a = 1;
- }
- }
-
- public <X> void genericMethod1(X a, X[] b) {
- }
-
- public <X, Y> void genericMethod2(X a, List<Y> b) {
- }
-
- public <X, Y extends InnerTest> void genericMethod3(X a, List<Y> b) {
- }
-
- public <T extends InnerTest> void genericMethod4(T[] a, Collection<T> b, Collection<?> c) {
- Iterator<T> i = b.iterator();
- }
-
- public void someMethod(InnerTest self) {
- mSomeField = self.mSomeField;
- MyStaticInnerClass m = new MyStaticInnerClass();
- mInnerInstance = m;
- mTheIntEnum = null;
- mGeneric1 = new MyGenerics1();
- genericMethod4(new DerivingClass[0], new ArrayList<DerivingClass>(), new ArrayList<InnerTest>());
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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 mock_android.util;
-
-import java.lang.JavaClass;
-
-public class EmptyArray {
-
- public static final Object[] OBJECT = new Object[0];
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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 mock_android.view;
-
-import java.lang.JavaClass;
-
-public class View {
-
- String x = JavaClass.test;
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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 mock_android.view;
-
-public class ViewGroup extends View {
-
- public class MarginLayoutParams extends LayoutParams {
-
- }
-
- public class LayoutParams {
-
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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 mock_android.widget;
-
-import mock_android.util.EmptyArray;
-import mock_android.view.ViewGroup;
-
-public class LinearLayout extends ViewGroup {
-
- Object[] mObjects = EmptyArray.OBJECT;
- public class LayoutParams extends MarginLayoutParams {
-
- }
-
-}
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
- *
- * 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 mock_android.widget;
-
-import mock_android.view.ViewGroup;
-
-public class TableLayout extends ViewGroup {
-
- public class LayoutParams extends MarginLayoutParams {
-
- }
-
-}
+++ /dev/null
-#
-# Copyright (C) 2008 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.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-
-LOCAL_JAVA_LIBRARIES := \
- layoutlib_api-prebuilt
-
-LOCAL_MODULE := layoutlib-legacy
-
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-# Build all sub-directories
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$">
- <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- </content>
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="library" name="layoutlib_api-prebuilt" level="project" />
- </component>
-</module>
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge;import com.android.ide.common.rendering.api.RenderSession;
-import com.android.ide.common.rendering.api.Result;
-import com.android.ide.common.rendering.api.Result.Status;
-import com.android.ide.common.rendering.api.SessionParams;
-
-import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
-
-/**
- * Legacy Bridge used in the SDK version of layoutlib
- */
-public final class Bridge extends com.android.ide.common.rendering.api.Bridge {
- private static final String SDK_NOT_SUPPORTED = "The SDK layoutlib version is not supported";
- private static final Result NOT_SUPPORTED_RESULT =
- Status.NOT_IMPLEMENTED.createResult(SDK_NOT_SUPPORTED);
- private static BufferedImage sImage;
-
- private static class BridgeRenderSession extends RenderSession {
-
- @Override
- public synchronized BufferedImage getImage() {
- if (sImage == null) {
- sImage = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
- Graphics2D g = sImage.createGraphics();
- g.clearRect(0, 0, 500, 500);
- g.drawString(SDK_NOT_SUPPORTED, 20, 20);
- g.dispose();
- }
-
- return sImage;
- }
-
- @Override
- public Result render(long timeout, boolean forceMeasure) {
- return NOT_SUPPORTED_RESULT;
- }
-
- @Override
- public Result measure(long timeout) {
- return NOT_SUPPORTED_RESULT;
- }
-
- @Override
- public Result getResult() {
- return NOT_SUPPORTED_RESULT;
- }
- }
-
-
- @Override
- public RenderSession createSession(SessionParams params) {
- return new BridgeRenderSession();
- }
-
- @Override
- public int getApiLevel() {
- return 0;
- }
-}
+++ /dev/null
-This tool is used to rename the PS name encoded inside the ttf font that we ship
-with the SDK. There is bug in Java that returns incorrect results for
-java.awt.Font#layoutGlyphVector() if two fonts with same name but differnt
-versions are loaded. As a workaround, we rename all the fonts that we ship with
-the SDK by appending the font version to its name.
-
-
-The build_font.py copies all files from input_dir to output_dir while renaming
-the font files (*.ttf) in the process.
+++ /dev/null
-#!/usr/bin/env python
-
-# 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.
-
-"""
-Rename the PS name of all fonts in the input directories and copy them to the
-output directory.
-
-Usage: build_font.py /path/to/input_fonts1/ /path/to/input_fonts2/ /path/to/output_fonts/
-
-"""
-
-import glob
-from multiprocessing import Pool
-import os
-import re
-import shutil
-import sys
-import xml.etree.ElementTree as etree
-
-# Prevent .pyc files from being created.
-sys.dont_write_bytecode = True
-
-# fontTools is available at platform/external/fonttools
-from fontTools import ttx
-
-# global variable
-dest_dir = '/tmp'
-
-
-class FontInfo(object):
- family = None
- style = None
- version = None
- ends_in_regular = False
- fullname = None
-
-
-class InvalidFontException(Exception):
- pass
-
-
-# These constants represent the value of nameID parameter in the namerecord for
-# different information.
-# see http://scripts.sil.org/cms/scripts/page.php?item_id=IWS-Chapter08#3054f18b
-NAMEID_FAMILY = 1
-NAMEID_STYLE = 2
-NAMEID_FULLNAME = 4
-NAMEID_VERSION = 5
-
-
-def main(argv):
- if len(argv) < 2:
- sys.exit('Usage: build_font.py /path/to/input_fonts/ /path/to/out/dir/')
- for directory in argv:
- if not os.path.isdir(directory):
- sys.exit(directory + ' is not a valid directory')
- global dest_dir
- dest_dir = argv[-1]
- src_dirs = argv[:-1]
- cwd = os.getcwd()
- os.chdir(dest_dir)
- files = glob.glob('*')
- for filename in files:
- os.remove(filename)
- os.chdir(cwd)
- input_fonts = list()
- for src_dir in src_dirs:
- for dirname, dirnames, filenames in os.walk(src_dir):
- for filename in filenames:
- input_path = os.path.join(dirname, filename)
- extension = os.path.splitext(filename)[1].lower()
- if extension == '.ttf':
- input_fonts.append(input_path)
- elif extension == '.xml':
- shutil.copy(input_path, dest_dir)
- if '.git' in dirnames:
- # don't go into any .git directories.
- dirnames.remove('.git')
- # Create as many threads as the number of CPUs
- pool = Pool(processes=None)
- pool.map(convert_font, input_fonts)
-
-
-def convert_font(input_path):
- filename = os.path.basename(input_path)
- print 'Converting font: ' + filename
- # the path to the output file. The file name is the fontfilename.ttx
- ttx_path = os.path.join(dest_dir, filename)
- ttx_path = ttx_path[:-1] + 'x'
- try:
- # run ttx to generate an xml file in the output folder which represents all
- # its info
- ttx_args = ['-q', '-d', dest_dir, input_path]
- ttx.main(ttx_args)
- # now parse the xml file to change its PS name.
- tree = etree.parse(ttx_path)
- root = tree.getroot()
- for name in root.iter('name'):
- update_tag(name, get_font_info(name))
- tree.write(ttx_path, xml_declaration=True, encoding='utf-8')
- # generate the udpated font now.
- ttx_args = ['-q', '-d', dest_dir, ttx_path]
- ttx.main(ttx_args)
- except InvalidFontException:
- # In case of invalid fonts, we exit.
- print filename + ' is not a valid font'
- raise
- except Exception as e:
- print 'Error converting font: ' + filename
- print e
- # Some fonts are too big to be handled by the ttx library.
- # Just copy paste them.
- shutil.copy(input_path, dest_dir)
- try:
- # delete the temp ttx file is it exists.
- os.remove(ttx_path)
- except OSError:
- pass
-
-
-def get_font_info(tag):
- """ Returns a list of FontInfo representing the various sets of namerecords
- found in the name table of the font. """
- fonts = []
- font = None
- last_name_id = sys.maxint
- for namerecord in tag.iter('namerecord'):
- if 'nameID' in namerecord.attrib:
- name_id = int(namerecord.attrib['nameID'])
- # A new font should be created for each platform, encoding and language
- # id. But, since the nameIDs are sorted, we use the easy approach of
- # creating a new one when the nameIDs reset.
- if name_id <= last_name_id and font is not None:
- fonts.append(font)
- font = None
- last_name_id = name_id
- if font is None:
- font = FontInfo()
- if name_id == NAMEID_FAMILY:
- font.family = namerecord.text.strip()
- if name_id == NAMEID_STYLE:
- font.style = namerecord.text.strip()
- if name_id == NAMEID_FULLNAME:
- font.ends_in_regular = ends_in_regular(namerecord.text)
- font.fullname = namerecord.text.strip()
- if name_id == NAMEID_VERSION:
- font.version = get_version(namerecord.text)
- if font is not None:
- fonts.append(font)
- return fonts
-
-
-def update_tag(tag, fonts):
- last_name_id = sys.maxint
- fonts_iterator = fonts.__iter__()
- font = None
- for namerecord in tag.iter('namerecord'):
- if 'nameID' in namerecord.attrib:
- name_id = int(namerecord.attrib['nameID'])
- if name_id <= last_name_id:
- font = fonts_iterator.next()
- font = update_font_name(font)
- last_name_id = name_id
- if name_id == NAMEID_FAMILY:
- namerecord.text = font.family
- if name_id == NAMEID_FULLNAME:
- namerecord.text = font.fullname
-
-
-def update_font_name(font):
- """ Compute the new font family name and font fullname. If the font has a
- valid version, it's sanitized and appended to the font family name. The
- font fullname is then created by joining the new family name and the
- style. If the style is 'Regular', it is appended only if the original font
- had it. """
- if font.family is None or font.style is None:
- raise InvalidFontException('Font doesn\'t have proper family name or style')
- if font.version is not None:
- new_family = font.family + font.version
- else:
- new_family = font.family
- if font.style is 'Regular' and not font.ends_in_regular:
- font.fullname = new_family
- else:
- font.fullname = new_family + ' ' + font.style
- font.family = new_family
- return font
-
-
-def ends_in_regular(string):
- """ According to the specification, the font fullname should not end in
- 'Regular' for plain fonts. However, some fonts don't obey this rule. We
- keep the style info, to minimize the diff. """
- string = string.strip().split()[-1]
- return string is 'Regular'
-
-
-def get_version(string):
- string = string.strip()
- # 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__':
- main(sys.argv[1:])
+++ /dev/null
-#!/usr/bin/env python
-
-# 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.
-
-"""
-Rename the PS name of the input font.
-
-OpenType fonts (*.otf) are not currently supported. They are copied to the destination without renaming.
-XML files are also copied in case they are passed there by mistake.
-
-Usage: build_font_single.py /path/to/input_font.ttf /path/to/output_font.ttf
-
-"""
-
-import glob
-import os
-import re
-import shutil
-import sys
-import xml.etree.ElementTree as etree
-
-# Prevent .pyc files from being created.
-sys.dont_write_bytecode = True
-
-# fontTools is available at platform/external/fonttools
-from fontTools import ttx
-
-
-class FontInfo(object):
- family = None
- style = None
- version = None
- ends_in_regular = False
- fullname = None
-
-
-class InvalidFontException(Exception):
- pass
-
-
-# A constant to copy the font without modifying. This is useful when running
-# locally and speed up the time to build the SDK.
-COPY_ONLY = False
-
-# These constants represent the value of nameID parameter in the namerecord for
-# different information.
-# see http://scripts.sil.org/cms/scripts/page.php?item_id=IWS-Chapter08#3054f18b
-NAMEID_FAMILY = 1
-NAMEID_STYLE = 2
-NAMEID_FULLNAME = 4
-NAMEID_VERSION = 5
-
-# A list of extensions to process.
-EXTENSIONS = ['.ttf', '.otf', '.xml']
-
-def main(argv):
- if len(argv) < 2:
- print 'Incorrect usage: ' + str(argv)
- sys.exit('Usage: build_font_single.py /path/to/input/font.ttf /path/to/out/font.ttf')
- dest_path = argv[-1]
- input_path = argv[0]
- extension = os.path.splitext(input_path)[1].lower()
- if extension in EXTENSIONS:
- if not COPY_ONLY and extension == '.ttf':
- convert_font(input_path, dest_path)
- return
- shutil.copy(input_path, dest_path)
-
-
-def convert_font(input_path, dest_path):
- filename = os.path.basename(input_path)
- print 'Converting font: ' + filename
- # the path to the output file. The file name is the fontfilename.ttx
- ttx_path = dest_path[:-1] + 'x'
- try:
- # run ttx to generate an xml file in the output folder which represents all
- # its info
- ttx_args = ['-q', '-o', ttx_path, input_path]
- ttx.main(ttx_args)
- # now parse the xml file to change its PS name.
- tree = etree.parse(ttx_path)
- root = tree.getroot()
- for name in root.iter('name'):
- update_tag(name, get_font_info(name))
- tree.write(ttx_path, xml_declaration=True, encoding='utf-8')
- # generate the udpated font now.
- ttx_args = ['-q', '-o', dest_path, ttx_path]
- ttx.main(ttx_args)
- except InvalidFontException:
- # In case of invalid fonts, we exit.
- print filename + ' is not a valid font'
- raise
- except Exception as e:
- print 'Error converting font: ' + filename
- print e
- # Some fonts are too big to be handled by the ttx library.
- # Just copy paste them.
- shutil.copy(input_path, dest_path)
- try:
- # delete the temp ttx file is it exists.
- os.remove(ttx_path)
- except OSError:
- pass
-
-
-def get_font_info(tag):
- """ Returns a list of FontInfo representing the various sets of namerecords
- found in the name table of the font. """
- fonts = []
- font = None
- last_name_id = sys.maxint
- for namerecord in tag.iter('namerecord'):
- if 'nameID' in namerecord.attrib:
- name_id = int(namerecord.attrib['nameID'])
- # A new font should be created for each platform, encoding and language
- # id. But, since the nameIDs are sorted, we use the easy approach of
- # creating a new one when the nameIDs reset.
- if name_id <= last_name_id and font is not None:
- fonts.append(font)
- font = None
- last_name_id = name_id
- if font is None:
- font = FontInfo()
- if name_id == NAMEID_FAMILY:
- font.family = namerecord.text.strip()
- if name_id == NAMEID_STYLE:
- font.style = namerecord.text.strip()
- if name_id == NAMEID_FULLNAME:
- font.ends_in_regular = ends_in_regular(namerecord.text)
- font.fullname = namerecord.text.strip()
- if name_id == NAMEID_VERSION:
- font.version = get_version(namerecord.text)
- if font is not None:
- fonts.append(font)
- return fonts
-
-
-def update_tag(tag, fonts):
- last_name_id = sys.maxint
- fonts_iterator = fonts.__iter__()
- font = None
- for namerecord in tag.iter('namerecord'):
- if 'nameID' in namerecord.attrib:
- name_id = int(namerecord.attrib['nameID'])
- if name_id <= last_name_id:
- font = fonts_iterator.next()
- font = update_font_name(font)
- last_name_id = name_id
- if name_id == NAMEID_FAMILY:
- namerecord.text = font.family
- if name_id == NAMEID_FULLNAME:
- namerecord.text = font.fullname
-
-
-def update_font_name(font):
- """ Compute the new font family name and font fullname. If the font has a
- valid version, it's sanitized and appended to the font family name. The
- font fullname is then created by joining the new family name and the
- style. If the style is 'Regular', it is appended only if the original font
- had it. """
- if font.family is None or font.style is None:
- raise InvalidFontException('Font doesn\'t have proper family name or style')
- if font.version is not None:
- new_family = font.family + font.version
- else:
- new_family = font.family
- if font.style is 'Regular' and not font.ends_in_regular:
- font.fullname = new_family
- else:
- font.fullname = new_family + ' ' + font.style
- font.family = new_family
- return font
-
-
-def ends_in_regular(string):
- """ According to the specification, the font fullname should not end in
- 'Regular' for plain fonts. However, some fonts don't obey this rule. We
- keep the style info, to minimize the diff. """
- string = string.strip().split()[-1]
- return string is 'Regular'
-
-
-def get_version(string):
- string = string.strip()
- # 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__':
- main(sys.argv[1:])
+++ /dev/null
-#!/usr/bin/env python
-
-"""Tests build_font.py by renaming a font.
-
-The test copies Roboto-Regular.ttf to a tmp directory and ask build_font.py to rename it and put in another dir.
-We then use ttx to dump the new font to its xml and check if rename was successful
-
-To test locally, use:
-PYTHONPATH="$PYTHONPATH:/path/to/android/checkout/external/fonttools/Lib" ./test.py
-"""
-
-import unittest
-import build_font
-
-from fontTools import ttx
-import os
-import xml.etree.ElementTree as etree
-import shutil
-import tempfile
-
-class MyTest(unittest.TestCase):
- def test(self):
- font_name = "Roboto-Regular.ttf"
- srcdir = tempfile.mkdtemp()
- print "srcdir: " + srcdir
- shutil.copy(font_name, srcdir)
- destdir = tempfile.mkdtemp()
- print "destdir: " + destdir
- self.assertTrue(build_font.main([srcdir, destdir]) is None)
- out_path = os.path.join(destdir, font_name)
- ttx.main([out_path])
- ttx_path = out_path[:-1] + "x"
- tree = etree.parse(ttx_path)
- root = tree.getroot()
- name_tag = root.find('name')
- fonts = build_font.get_font_info(name_tag)
- shutil.rmtree(srcdir)
- shutil.rmtree(destdir)
- self.assertEqual(fonts[0].family, "Roboto1200310")
- self.assertEqual(fonts[0].fullname, "Roboto1200310 Regular")
-
-
-
-if __name__ == '__main__':
- unittest.main()
+++ /dev/null
-/*
- * 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.idea.editors.theme.widgets;
-
-import com.android.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * {@link ViewGroup} that wraps another view and catches any possible exceptions that the child view
- * might generate.
- * This is used by the theme editor to stop custom views from breaking the preview.
- */
-// TODO: This view is just a temporary solution that will be replaced by adding a try / catch
-// for custom views in the ClassConverter
-public class ErrorCatcher extends ViewGroup {
- public ErrorCatcher(Context context) {
- super(context);
- }
-
- public ErrorCatcher(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public ErrorCatcher(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public ErrorCatcher(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- assert getChildCount() == 1 : "ErrorCatcher can only have one child";
-
- View child = getChildAt(0);
- try {
- measureChild(child, widthMeasureSpec, heightMeasureSpec);
-
- setMeasuredDimension(resolveSize(child.getMeasuredWidth(), widthMeasureSpec),
- resolveSize(child.getMeasuredHeight(), heightMeasureSpec));
- } catch (Throwable t) {
- Bridge.getLog().warning(LayoutLog.TAG_BROKEN, "Failed to do onMeasure for view " +
- child.getClass().getCanonicalName(), t);
- setMeasuredDimension(resolveSize(0, widthMeasureSpec),
- resolveSize(0, heightMeasureSpec));
- }
- }
-
- @Override
- protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
- try {
- return super.drawChild(canvas, child, drawingTime);
- } catch (Throwable t) {
- Bridge.getLog().warning(LayoutLog.TAG_BROKEN, "Failed to draw for view " +
- child.getClass().getCanonicalName(), t);
- }
-
- return false;
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- assert getChildCount() == 1 : "ErrorCatcher can only have one child";
-
- View child = getChildAt(0);
- try {
- child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
- } catch (Throwable e) {
- Bridge.getLog().warning(LayoutLog.TAG_BROKEN, "Failed to do onLayout for view " +
- child.getClass().getCanonicalName(), e);
- }
- }
-}
+++ /dev/null
-/*
- * 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.idea.editors.theme.widgets;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.Button;
-
-@SuppressWarnings("unused")
-public class PressedButton extends Button {
- public PressedButton(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- setPressed(true);
- jumpDrawablesToCurrentState();
- }
-}
+++ /dev/null
-/*
- * 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.idea.editors.theme.widgets;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Custom layout used in the theme editor to display the component preview. It arranges the child
- * Views as a grid of cards.
- * <p/>
- * The Views are measured and the maximum width and height are used to dimension all the child
- * components. Any margin attributes from the children are ignored and only the item_margin element
- * is used.
- */
-@SuppressWarnings("unused")
-public class ThemePreviewLayout extends ViewGroup {
- private final int mMaxColumns;
- private final int mMaxColumnWidth;
- private final int mMinColumnWidth;
- private final int mItemHorizontalMargin;
- private final int mItemVerticalMargin;
-
- /** Item width to use for every card component. This includes margins. */
- private int mItemWidth;
- /** Item height to use for every card component. This includes margins. */
- private int mItemHeight;
-
- /** Calculated number of columns */
- private int mNumColumns;
-
- public ThemePreviewLayout(Context context) {
- this(context, null);
- }
-
- public ThemePreviewLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ThemePreviewLayout(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
-
- if (attrs == null) {
- mMaxColumnWidth = Integer.MAX_VALUE;
- mMinColumnWidth = 0;
- mMaxColumns = Integer.MAX_VALUE;
- mItemHorizontalMargin = 0;
- mItemVerticalMargin = 0;
- return;
- }
-
- DisplayMetrics dm = getResources().getDisplayMetrics();
- int maxColumnWidth = attrs.getAttributeIntValue(null, "max_column_width", Integer
- .MAX_VALUE);
- int minColumnWidth = attrs.getAttributeIntValue(null, "min_column_width", 0);
- int itemHorizontalMargin = attrs.getAttributeIntValue(null, "item_horizontal_margin", 0);
- int itemVerticalMargin = attrs.getAttributeIntValue(null, "item_vertical_margin", 0);
-
- mMaxColumnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- maxColumnWidth,
- dm);
- mMinColumnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- minColumnWidth,
- dm);
- mItemHorizontalMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- itemHorizontalMargin,
- dm);
- mItemVerticalMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
- itemVerticalMargin,
- dm);
- mMaxColumns = attrs.getAttributeIntValue(null, "max_columns", Integer.MAX_VALUE);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Measure the column size.
- // The column has a minimum width that will be used to calculate the maximum number of
- // columns that we can fit in the available space.
- //
- // Once we have the maximum number of columns, we will span all columns width evenly to fill
- // all the available space.
- int wSize = MeasureSpec.getSize(widthMeasureSpec) - mPaddingLeft - mPaddingRight;
-
- // Calculate the desired width of all columns and take the maximum.
- // This step can be skipped if we have a fixed column height so we do not have to
- // dynamically calculate it.
- int childWidthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- int childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
- int itemWidth = 0;
- int itemHeight = 0;
- for (int i = 0; i < getChildCount(); i++) {
- View v = getChildAt(i);
-
- if (v.getVisibility() == GONE) {
- continue;
- }
-
- measureChild(v, childWidthSpec, childHeightSpec);
-
- itemWidth = Math.max(itemWidth, v.getMeasuredWidth());
- itemHeight = Math.max(itemHeight, v.getMeasuredHeight());
- }
-
- itemWidth = Math.min(Math.max(itemWidth, mMinColumnWidth), mMaxColumnWidth);
- mNumColumns = Math.min((int) Math.ceil((double) wSize / itemWidth), mMaxColumns);
-
- // Check how much space this distribution would take taking into account the margins.
- // If it's bigger than what we have, remove one column.
- int wSizeNeeded = mNumColumns * itemWidth + (mNumColumns - 1) * mItemHorizontalMargin;
- if (wSizeNeeded > wSize && mNumColumns > 1) {
- mNumColumns--;
- }
-
- if (getChildCount() < mNumColumns) {
- mNumColumns = getChildCount();
- }
- if (mNumColumns == 0) {
- mNumColumns = 1;
- }
-
- // Inform each child of the measurement
- childWidthSpec = MeasureSpec.makeMeasureSpec(itemWidth, MeasureSpec.EXACTLY);
- childHeightSpec = MeasureSpec.makeMeasureSpec(itemHeight, MeasureSpec.EXACTLY);
- for (int i = 0; i < getChildCount(); i++) {
- View v = getChildAt(i);
-
- if (v.getVisibility() == GONE) {
- continue;
- }
-
- measureChild(v, childWidthSpec, childHeightSpec);
- }
-
- // Calculate the height of the first column to measure our own size
- int firstColumnItems = getChildCount() / mNumColumns + ((getChildCount() % mNumColumns) > 0
- ? 1 : 0);
-
- int horizontalMarginsTotalWidth = (mNumColumns - 1) * mItemHorizontalMargin;
- int verticalMarginsTotalHeight = (firstColumnItems - 1) * mItemVerticalMargin;
- int totalWidth = mNumColumns * itemWidth + horizontalMarginsTotalWidth +
- mPaddingRight + mPaddingLeft;
- int totalHeight = firstColumnItems * itemHeight + verticalMarginsTotalHeight +
- mPaddingBottom + mPaddingTop;
-
- setMeasuredDimension(resolveSize(totalWidth, widthMeasureSpec),
- resolveSize(totalHeight, heightMeasureSpec));
-
- mItemWidth = itemWidth;
- mItemHeight = itemHeight;
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- int itemsPerColumn = getChildCount() / mNumColumns;
- // The remainder items are distributed one per column.
- int remainderItems = getChildCount() % mNumColumns;
-
- int x = mPaddingLeft;
- int y = mPaddingTop;
- int position = 1;
- for (int i = 0; i < getChildCount(); i++) {
- View v = getChildAt(i);
- v.layout(x,
- y,
- x + mItemWidth,
- y + mItemHeight);
-
- if (position == itemsPerColumn + (remainderItems > 0 ? 1 : 0)) {
- // Break column
- position = 1;
- remainderItems--;
- x += mItemWidth + mItemHorizontalMargin;
- y = mPaddingTop;
- } else {
- position++;
- y += mItemHeight + mItemVerticalMargin;
- }
- }
- }
-}
-
-
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
- <component name="NewModuleRootManager" inherit-compiler-output="true">
- <exclude-output />
- <content url="file://$MODULE_DIR$">
- <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- </content>
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="library" name="layoutlib_api-prebuilt" level="project" />
- <orderEntry type="library" name="framework.jar" level="project" />
- <orderEntry type="module" module-name="bridge" />
- </component>
-</module>
\ No newline at end of file