From 4493b7c429e45ddbdeaefdbf5b8536dcedb5d66c Mon Sep 17 00:00:00 2001 From: Diego Perez Date: Fri, 21 Apr 2017 14:20:16 +0100 Subject: [PATCH] Removing layout from frameworks/base The directory is being moved to its own project in frameworks/layoutlib Bug: 36889565 Test: Built manually Change-Id: I69a1a826d0bac8ede1f9a337c9c1d930bbcd04f3 --- tools/layoutlib/.gitignore | 5 - tools/layoutlib/.idea/.name | 1 - .../artifacts/studio_android_widgets_jar.xml | 8 - .../studio_android_widgets_src_jar.xml | 8 - tools/layoutlib/.idea/codeStyleSettings.xml | 82 - tools/layoutlib/.idea/compiler.xml | 25 - tools/layoutlib/.idea/copyright/Android.xml | 9 - .../.idea/copyright/profiles_settings.xml | 3 - tools/layoutlib/.idea/encodings.xml | 6 - .../inspectionProfiles/Project_Default.xml | 20 - .../inspectionProfiles/profiles_settings.xml | 7 - .../.idea/libraries/framework_jar.xml | 13 - tools/layoutlib/.idea/libraries/junit.xml | 11 - .../libraries/layoutlib_api_prebuilt.xml | 11 - tools/layoutlib/.idea/libraries/mockito.xml | 9 - tools/layoutlib/.idea/libraries/objenesis.xml | 9 - tools/layoutlib/.idea/misc.xml | 43 - tools/layoutlib/.idea/modules.xml | 11 - .../.idea/runConfigurations/All_in_bridge.xml | 25 - .../.idea/runConfigurations/All_in_create.xml | 31 - .../.idea/runConfigurations/Bridge_quick.xml | 29 - .../.idea/runConfigurations/Create.xml | 25 - .../layoutlib/.idea/scopes/scope_settings.xml | 5 - tools/layoutlib/.idea/uiDesigner.xml | 125 - tools/layoutlib/.idea/vcs.xml | 7 - tools/layoutlib/Android.mk | 82 - tools/layoutlib/README | 4 - tools/layoutlib/bridge/.classpath | 16 - tools/layoutlib/bridge/.project | 17 - tools/layoutlib/bridge/.settings/README.txt | 2 - .../.settings/org.eclipse.jdt.core.prefs | 93 - tools/layoutlib/bridge/Android.mk | 36 - tools/layoutlib/bridge/bridge.iml | 92 - tools/layoutlib/bridge/resources/bars/README | 8 - .../bridge/resources/bars/navigation_bar.xml | 49 - .../resources/bars/navigation_bar600dp.xml | 49 - .../bridge/resources/bars/status_bar.xml | 27 - .../bridge/resources/bars/title_bar.xml | 6 - .../bars/v18/hdpi/stat_sys_battery_100.png | Bin 604 -> 0 bytes .../v18/hdpi/stat_sys_wifi_signal_4_fully.png | Bin 1541 -> 0 bytes .../bars/v18/mdpi/stat_sys_battery_100.png | Bin 515 -> 0 bytes .../v18/mdpi/stat_sys_wifi_signal_4_fully.png | Bin 1333 -> 0 bytes .../bars/v18/xhdpi/stat_sys_battery_100.png | Bin 728 -> 0 bytes .../xhdpi/stat_sys_wifi_signal_4_fully.png | Bin 1750 -> 0 bytes .../bars/v19/hdpi/ic_sysbar_back.png | Bin 1053 -> 0 bytes .../bars/v19/hdpi/ic_sysbar_home.png | Bin 1064 -> 0 bytes .../bars/v19/hdpi/ic_sysbar_recent.png | Bin 711 -> 0 bytes .../v19/hdpi/stat_sys_wifi_signal_4_fully.png | Bin 1541 -> 0 bytes .../bars/v19/ldrtl-hdpi/ic_sysbar_back.png | Bin 904 -> 0 bytes .../bars/v19/ldrtl-hdpi/ic_sysbar_recent.png | Bin 533 -> 0 bytes .../bars/v19/ldrtl-mdpi/ic_sysbar_back.png | Bin 617 -> 0 bytes .../bars/v19/ldrtl-mdpi/ic_sysbar_recent.png | Bin 423 -> 0 bytes .../bars/v19/ldrtl-xhdpi/ic_sysbar_back.png | Bin 1250 -> 0 bytes .../bars/v19/ldrtl-xhdpi/ic_sysbar_recent.png | Bin 552 -> 0 bytes .../bars/v19/mdpi/ic_sysbar_back.png | Bin 774 -> 0 bytes .../bars/v19/mdpi/ic_sysbar_home.png | Bin 836 -> 0 bytes .../bars/v19/mdpi/ic_sysbar_recent.png | Bin 591 -> 0 bytes .../v19/mdpi/stat_sys_wifi_signal_4_fully.png | Bin 1333 -> 0 bytes .../bars/v19/xhdpi/ic_sysbar_back.png | Bin 1421 -> 0 bytes .../bars/v19/xhdpi/ic_sysbar_home.png | Bin 1421 -> 0 bytes .../bars/v19/xhdpi/ic_sysbar_recent.png | Bin 749 -> 0 bytes .../xhdpi/stat_sys_wifi_signal_4_fully.png | Bin 1750 -> 0 bytes .../bars/v19/xxhdpi/ic_sysbar_back.png | Bin 2811 -> 0 bytes .../bars/v19/xxhdpi/ic_sysbar_home.png | Bin 2229 -> 0 bytes .../bars/v19/xxhdpi/ic_sysbar_recent.png | Bin 1517 -> 0 bytes .../xxhdpi/stat_sys_wifi_signal_4_fully.png | Bin 2202 -> 0 bytes .../bars/v21/hdpi/ic_sysbar_back.png | Bin 1524 -> 0 bytes .../bars/v21/hdpi/ic_sysbar_home.png | Bin 1895 -> 0 bytes .../bars/v21/hdpi/ic_sysbar_recent.png | Bin 611 -> 0 bytes .../bars/v21/hdpi/stat_sys_battery_100.png | Bin 19810 -> 0 bytes .../bars/v21/ldrtl-hdpi/ic_sysbar_back.png | Bin 1535 -> 0 bytes .../bars/v21/ldrtl-mdpi/ic_sysbar_back.png | Bin 965 -> 0 bytes .../bars/v21/ldrtl-xhdpi/ic_sysbar_back.png | Bin 2084 -> 0 bytes .../bars/v21/ldrtl-xxhdpi/ic_sysbar_back.png | Bin 1358 -> 0 bytes .../bars/v21/mdpi/ic_sysbar_back.png | Bin 1010 -> 0 bytes .../bars/v21/mdpi/ic_sysbar_home.png | Bin 1066 -> 0 bytes .../bars/v21/mdpi/ic_sysbar_recent.png | Bin 562 -> 0 bytes .../bars/v21/mdpi/stat_sys_battery_100.png | Bin 19396 -> 0 bytes .../bars/v21/xhdpi/ic_sysbar_back.png | Bin 2109 -> 0 bytes .../bars/v21/xhdpi/ic_sysbar_home.png | Bin 2617 -> 0 bytes .../bars/v21/xhdpi/ic_sysbar_recent.png | Bin 733 -> 0 bytes .../bars/v21/xhdpi/stat_sys_battery_100.png | Bin 19839 -> 0 bytes .../xhdpi/stat_sys_wifi_signal_4_fully.xml | 9 - .../bars/v21/xxhdpi/ic_sysbar_back.png | Bin 1279 -> 0 bytes .../bars/v21/xxhdpi/ic_sysbar_home.png | Bin 2125 -> 0 bytes .../bars/v21/xxhdpi/ic_sysbar_recent.png | Bin 573 -> 0 bytes .../bars/v21/xxhdpi/stat_sys_battery_100.png | Bin 19388 -> 0 bytes .../bars/v9/hdpi/stat_sys_battery_100.png | Bin 788 -> 0 bytes .../v9/hdpi/stat_sys_wifi_signal_4_fully.png | Bin 5146 -> 0 bytes .../bars/v9/ldpi/stat_sys_battery_100.png | Bin 604 -> 0 bytes .../bars/v9/mdpi/stat_sys_battery_100.png | Bin 715 -> 0 bytes .../v9/mdpi/stat_sys_wifi_signal_4_fully.png | Bin 3922 -> 0 bytes .../bridge/resources/icons/shadow-b.png | Bin 215 -> 0 bytes .../bridge/resources/icons/shadow-bl.png | Bin 397 -> 0 bytes .../bridge/resources/icons/shadow-br.png | Bin 406 -> 0 bytes .../bridge/resources/icons/shadow-l.png | Bin 120 -> 0 bytes .../bridge/resources/icons/shadow-r.png | Bin 207 -> 0 bytes .../bridge/resources/icons/shadow-tl.png | Bin 277 -> 0 bytes .../bridge/resources/icons/shadow-tr.png | Bin 397 -> 0 bytes .../bridge/resources/icons/shadow2-b.png | Bin 195 -> 0 bytes .../bridge/resources/icons/shadow2-bl.png | Bin 277 -> 0 bytes .../bridge/resources/icons/shadow2-br.png | Bin 282 -> 0 bytes .../bridge/resources/icons/shadow2-l.png | Bin 108 -> 0 bytes .../bridge/resources/icons/shadow2-r.png | Bin 192 -> 0 bytes .../bridge/resources/icons/shadow2-tl.png | Bin 2855 -> 0 bytes .../bridge/resources/icons/shadow2-tr.png | Bin 286 -> 0 bytes .../android/animation/AnimationThread.java | 176 -- .../PropertyValuesHolder_Delegate.java | 197 -- .../src/android/app/Fragment_Delegate.java | 104 - .../app/SystemServiceRegistry_Accessor.java | 29 - .../content/res/AssetManager_Delegate.java | 47 - .../content/res/BridgeAssetManager.java | 62 - .../android/content/res/BridgeTypedArray.java | 1011 -------- .../content/res/ComplexColor_Accessor.java | 46 - .../content/res/Resources_Delegate.java | 1025 -------- .../content/res/Resources_Theme_Delegate.java | 152 -- .../content/res/TypedArray_Delegate.java | 35 - .../android/graphics/BaseCanvas_Delegate.java | 762 ------ .../src/android/graphics/BidiRenderer.java | 325 --- .../graphics/BitmapFactory_Delegate.java | 156 -- .../graphics/BitmapShader_Delegate.java | 257 -- .../src/android/graphics/Bitmap_Delegate.java | 736 ------ .../src/android/graphics/BlendComposite.java | 287 --- .../graphics/BlurMaskFilter_Delegate.java | 64 - .../src/android/graphics/Canvas_Delegate.java | 484 ---- .../graphics/ColorFilter_Delegate.java | 74 - .../ColorMatrixColorFilter_Delegate.java | 59 - .../graphics/ComposePathEffect_Delegate.java | 71 - .../graphics/ComposeShader_Delegate.java | 79 - .../graphics/CornerPathEffect_Delegate.java | 71 - .../graphics/DashPathEffect_Delegate.java | 89 - .../graphics/DiscretePathEffect_Delegate.java | 71 - .../android/graphics/DrawFilter_Delegate.java | 64 - .../graphics/EmbossMaskFilter_Delegate.java | 65 - .../android/graphics/FontFamily_Delegate.java | 523 ----- .../android/graphics/Gradient_Delegate.java | 212 -- .../LightingColorFilter_Delegate.java | 59 - .../graphics/LinearGradient_Delegate.java | 227 -- .../android/graphics/MaskFilter_Delegate.java | 64 - .../src/android/graphics/Matrix_Delegate.java | 1077 --------- .../android/graphics/NinePatch_Delegate.java | 186 -- .../PaintFlagsDrawFilter_Delegate.java | 64 - .../src/android/graphics/Paint_Delegate.java | 1329 ----------- .../graphics/PathDashPathEffect_Delegate.java | 72 - .../android/graphics/PathEffect_Delegate.java | 69 - .../graphics/PathMeasure_Delegate.java | 223 -- .../src/android/graphics/Path_Delegate.java | 896 ------- .../PorterDuffColorFilter_Delegate.java | 124 - .../graphics/RadialGradient_Delegate.java | 205 -- .../src/android/graphics/Region_Delegate.java | 483 ---- .../src/android/graphics/RoundRectangle.java | 368 --- .../src/android/graphics/Shader_Delegate.java | 97 - .../graphics/SumPathEffect_Delegate.java | 71 - .../graphics/SweepGradient_Delegate.java | 213 -- .../android/graphics/Typeface_Accessor.java | 28 - .../android/graphics/Typeface_Delegate.java | 289 --- .../AnimatedVectorDrawable_Delegate.java | 298 --- ...ble_VectorDrawableAnimatorRT_Delegate.java | 34 - .../drawable/GradientDrawable_Delegate.java | 73 - .../drawable/VectorDrawable_Delegate.java | 1262 ---------- .../android/os/HandlerThread_Delegate.java | 80 - .../src/android/os/Handler_Delegate.java | 57 - .../src/android/os/Looper_Accessor.java | 47 - .../bridge/src/android/os/ServiceManager.java | 95 - .../src/android/os/SystemClock_Delegate.java | 99 - .../android/os/SystemProperties_Delegate.java | 110 - .../preference/BridgePreferenceInflater.java | 61 - .../preference/Preference_Delegate.java | 80 - .../android/text/AndroidBidi_Delegate.java | 63 - .../src/android/text/GreedyLineBreaker.java | 192 -- .../src/android/text/Hyphenator_Delegate.java | 46 - .../bridge/src/android/text/LineBreaker.java | 43 - .../bridge/src/android/text/LineWidth.java | 35 - .../android/text/OptimizingLineBreaker.java | 261 --- .../bridge/src/android/text/Primitive.java | 92 - .../android/text/StaticLayout_Delegate.java | 238 -- .../bridge/src/android/text/TabStops.java | 44 - .../text/format/DateFormat_Delegate.java | 42 - .../android/util/BridgeXmlPullAttributes.java | 313 --- .../bridge/src/android/util/Log_Delegate.java | 51 - .../bridge/src/android/util/LruCache.java | 391 ---- .../src/android/util/PathParser_Delegate.java | 844 ------- .../bridge/src/android/util/Xml_Delegate.java | 45 - .../src/android/view/AttachInfo_Accessor.java | 58 - .../src/android/view/BridgeInflater.java | 496 ---- .../android/view/Choreographer_Delegate.java | 85 - .../src/android/view/Display_Delegate.java | 36 - .../view/HandlerActionQueue_Delegate.java | 37 - .../src/android/view/IWindowManagerImpl.java | 528 ----- .../android/view/LayoutInflater_Delegate.java | 236 -- .../android/view/MenuInflater_Delegate.java | 72 - .../android/view/PointerIcon_Delegate.java | 33 - .../src/android/view/RectShadowPainter.java | 276 --- .../src/android/view/RenderNode_Delegate.java | 335 --- .../src/android/view/ShadowPainter.java | 422 ---- .../bridge/src/android/view/SurfaceView.java | 130 -- .../view/ViewConfiguration_Accessor.java | 29 - .../src/android/view/ViewGroup_Delegate.java | 158 -- .../android/view/ViewRootImpl_Accessor.java | 26 - .../android/view/ViewRootImpl_Delegate.java | 34 - .../src/android/view/View_Delegate.java | 47 - .../src/android/view/WindowCallback.java | 144 -- .../view/WindowManagerGlobal_Delegate.java | 43 - .../accessibility/AccessibilityManager.java | 300 --- .../InputMethodManager_Accessor.java | 27 - .../InputMethodManager_Delegate.java | 49 - .../view/textservice/TextServicesManager.java | 72 - .../bridge/src/android/webkit/WebView.java | 238 -- .../src/android/widget/Toolbar_Accessor.java | 32 - .../util/VirtualRefBasePtr_Delegate.java | 53 - .../internal/util/XmlUtils_Delegate.java | 74 - ...iveInterpolatorFactoryHelper_Delegate.java | 140 -- .../view/menu/BridgeMenuItemImpl.java | 65 - .../view/menu/MenuBuilder_Delegate.java | 38 - .../internal/widget/ActionBarAccessor.java | 32 - .../com/android/layoutlib/bridge/Bridge.java | 670 ------ .../layoutlib/bridge/BridgeConstants.java | 58 - .../layoutlib/bridge/BridgeRenderSession.java | 249 -- .../android/layoutlib/bridge/MockView.java | 107 - .../bridge/android/AndroidLocale.java | 72 - .../bridge/android/BridgeContentProvider.java | 154 -- .../bridge/android/BridgeContentResolver.java | 120 - .../bridge/android/BridgeContext.java | 2059 ----------------- .../android/BridgeIInputMethodManager.java | 258 --- .../BridgeLayoutParamsMapAttributes.java | 164 -- .../bridge/android/BridgePackageManager.java | 958 -------- .../bridge/android/BridgePowerManager.java | 179 -- .../android/BridgeSharedPreferences.java | 138 -- .../bridge/android/BridgeWindow.java | 120 - .../bridge/android/BridgeWindowSession.java | 232 -- .../bridge/android/BridgeXmlBlockParser.java | 494 ---- .../bridge/android/RenderParamsFlags.java | 65 - .../bridge/android/graphics/NopCanvas.java | 307 --- .../bridge/android/support/DesignLibUtil.java | 60 - .../android/support/DrawerLayoutUtil.java | 63 - .../android/support/RecyclerViewUtil.java | 130 -- .../support/SupportPreferencesUtil.java | 282 --- .../android/view/WindowManagerImpl.java | 75 - .../bridge/bars/AppCompatActionBar.java | 207 -- .../bridge/bars/BridgeActionBar.java | 177 -- .../android/layoutlib/bridge/bars/Config.java | 137 -- .../layoutlib/bridge/bars/CustomBar.java | 290 --- .../bridge/bars/FrameworkActionBar.java | 258 --- .../bars/FrameworkActionBarWrapper.java | 379 --- .../layoutlib/bridge/bars/IconLoader.java | 125 - .../layoutlib/bridge/bars/NavigationBar.java | 138 -- .../bridge/bars/OverflowMenuAdapter.java | 99 - .../layoutlib/bridge/bars/StatusBar.java | 123 - .../bars/ThemePreviewNavigationBar.java | 58 - .../layoutlib/bridge/bars/TitleBar.java | 46 - .../bridge/impl/DelegateManager.java | 170 -- .../layoutlib/bridge/impl/GcSnapshot.java | 885 ------- .../android/layoutlib/bridge/impl/Layout.java | 467 ---- .../bridge/impl/LayoutParserWrapper.java | 377 --- .../layoutlib/bridge/impl/ParserFactory.java | 152 -- .../bridge/impl/PlayAnimationThread.java | 49 - .../bridge/impl/PorterDuffUtility.java | 107 - .../layoutlib/bridge/impl/RenderAction.java | 410 ---- .../layoutlib/bridge/impl/RenderDrawable.java | 179 -- .../bridge/impl/RenderSessionImpl.java | 1557 ------------- .../layoutlib/bridge/impl/ResourceHelper.java | 706 ------ .../android/layoutlib/bridge/impl/Stack.java | 70 - .../layoutlib/bridge/impl/SystemViewInfo.java | 51 - .../bridge/impl/binding/AdapterHelper.java | 148 -- .../bridge/impl/binding/AdapterItem.java | 74 - .../bridge/impl/binding/FakeAdapter.java | 132 -- .../impl/binding/FakeExpandableAdapter.java | 236 -- .../libcore/io/BridgeBufferIterator.java | 81 - .../bridge/shadowutil/ShadowBuffer.java | 181 -- .../bridge/shadowutil/SpotShadow.java | 630 ----- .../util/CachedPathIteratorFactory.java | 485 ---- .../android/layoutlib/bridge/util/Debug.java | 23 - .../layoutlib/bridge/util/DynamicIdMap.java | 79 - .../bridge/util/NinePatchInputStream.java | 47 - .../bridge/util/ReflectionUtils.java | 123 - .../bridge/util/SparseWeakArray.java | 329 --- .../src/com/google/android/maps/MapView.java | 121 - .../src/dalvik/system/VMRuntime_Delegate.java | 78 - .../bridge/src/libcore/icu/ICU_Delegate.java | 263 --- .../libcore/io/MemoryMappedFile_Delegate.java | 118 - .../NativeAllocationRegistry_Delegate.java | 70 - tools/layoutlib/bridge/tests/.classpath | 11 - tools/layoutlib/bridge/tests/.project | 17 - tools/layoutlib/bridge/tests/Android.mk | 43 - .../android/layoutlib/testdata/layout1.xml | 49 - tools/layoutlib/bridge/tests/res/empty.xml | 0 .../res/testApp/MyApplication/.gitignore | 14 - .../res/testApp/MyApplication/build.gradle | 48 - .../test/myapplication/test/BuildConfig.class | Bin 792 -> 0 bytes .../myapplication/ArraysCheckWidget.class | Bin 2349 -> 0 bytes .../test/myapplication/BuildConfig.class | Bin 777 -> 0 bytes .../test/myapplication/MyActivity.class | Bin 1420 -> 0 bytes .../test/myapplication/R$array.class | Bin 519 -> 0 bytes .../layoutlib/test/myapplication/R$attr.class | Bin 456 -> 0 bytes .../test/myapplication/R$color.class | Bin 461 -> 0 bytes .../test/myapplication/R$dimen.class | Bin 527 -> 0 bytes .../test/myapplication/R$drawable.class | Bin 569 -> 0 bytes .../layoutlib/test/myapplication/R$id.class | Bin 2014 -> 0 bytes .../test/myapplication/R$integer.class | Bin 492 -> 0 bytes .../test/myapplication/R$layout.class | Bin 881 -> 0 bytes .../layoutlib/test/myapplication/R$menu.class | Bin 452 -> 0 bytes .../test/myapplication/R$string.class | Bin 538 -> 0 bytes .../test/myapplication/R$style.class | Bin 461 -> 0 bytes .../layoutlib/test/myapplication/R.class | Bin 1107 -> 0 bytes .../testApp/MyApplication/golden/activity.png | Bin 36035 -> 0 bytes .../MyApplication/golden/adaptive_icon.png | Bin 6350 -> 0 bytes .../MyApplication/golden/allwidgets.png | Bin 67362 -> 0 bytes .../MyApplication/golden/allwidgets_tab.png | Bin 52614 -> 0 bytes .../MyApplication/golden/animated_vector.png | Bin 15656 -> 0 bytes .../golden/animated_vector_1.png | Bin 13335 -> 0 bytes .../MyApplication/golden/array_check.png | Bin 27242 -> 0 bytes .../golden/expand_horz_layout.png | Bin 2876 -> 0 bytes .../golden/expand_vert_layout.png | Bin 3693 -> 0 bytes .../MyApplication/golden/font_test.png | Bin 52171 -> 0 bytes .../MyApplication/golden/four_corners.png | Bin 19542 -> 0 bytes .../golden/four_corners_translucent.png | Bin 19497 -> 0 bytes .../golden/four_corners_translucent_land.png | Bin 21113 -> 0 bytes .../testApp/MyApplication/golden/scrolled.png | Bin 4474 -> 0 bytes .../MyApplication/golden/shadows_test.png | Bin 11310 -> 0 bytes .../golden/simple_activity-old-theme.png | Bin 8960 -> 0 bytes .../MyApplication/golden/simple_activity.png | Bin 8277 -> 0 bytes .../golden/simple_activity_noactionbar.png | Bin 8177 -> 0 bytes .../MyApplication/golden/vector_drawable.png | Bin 26162 -> 0 bytes .../golden/vector_drawable_91383.png | Bin 11320 -> 0 bytes .../testApp/MyApplication/gradle.properties | 18 - .../gradle/wrapper/gradle-wrapper.jar | Bin 49896 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - .../tests/res/testApp/MyApplication/gradlew | 164 -- .../res/testApp/MyApplication/gradlew.bat | 90 - .../testApp/MyApplication/proguard-rules.pro | 17 - .../src/main/AndroidManifest.xml | 21 - .../test/myapplication/ArraysCheckWidget.java | 57 - .../test/myapplication/MyActivity.java | 35 - .../myapplication.widgets/CustomCalendar.java | 47 - .../myapplication.widgets/CustomDate.java | 47 - .../myapplication.widgets/InsetsWidget.java | 43 - .../myapplication.widgets/package-info.java | 6 - .../src/main/res/color/gradient.xml | 24 - .../src/main/res/drawable/adaptive.xml | 6 - .../src/main/res/drawable/android.xml | 65 - .../src/main/res/drawable/headset.xml | 25 - .../src/main/res/drawable/ic_launcher.xml | 9 - .../src/main/res/drawable/multi_path.xml | 88 - .../src/main/res/font/testfamily.xml | 5 - .../src/main/res/font/testfont.ttf | Bin 133372 -> 0 bytes .../src/main/res/font/testfont2.ttf | Bin 108128 -> 0 bytes .../src/main/res/layout/activity.xml | 21 - .../src/main/res/layout/allwidgets.xml | 403 ---- .../src/main/res/layout/array_check.xml | 7 - .../main/res/layout/expand_horz_layout.xml | 15 - .../src/main/res/layout/expand_layout.xml | 29 - .../main/res/layout/expand_vert_layout.xml | 15 - .../src/main/res/layout/fonts_test.xml | 55 - .../src/main/res/layout/four_corners.xml | 38 - .../src/main/res/layout/layout.xml | 25 - .../src/main/res/layout/scrolled.xml | 57 - .../src/main/res/layout/shadows_test.xml | 97 - .../MyApplication/src/main/res/menu/my.xml | 8 - .../src/main/res/values/arrays.xml | 26 - .../src/main/res/values/attrs.xml | 4 - .../src/main/res/values/dimens.xml | 5 - .../MyApplication/src/main/res/values/ids.xml | 47 - .../src/main/res/values/strings.xml | 8 - .../src/main/res/values/styles.xml | 8 - .../SystemServiceRegistry_AccessorTest.java | 39 - .../android/graphics/Matrix_DelegateTest.java | 48 - .../util/BridgeXmlPullAttributesTest.java | 110 - .../bridge/BridgeRenderSessionTest.java | 37 - .../layoutlib/bridge/TestDelegates.java | 220 -- .../android/BridgeXmlBlockParserTest.java | 137 -- .../bridge/impl/LayoutParserWrapperTest.java | 183 -- .../layoutlib/bridge/intensive/Main.java | 42 - .../bridge/intensive/PerformanceTests.java | 58 - .../bridge/intensive/RenderResult.java | 72 - .../bridge/intensive/RenderTestBase.java | 547 ----- .../bridge/intensive/RenderTests.java | 534 ----- .../intensive/setup/ConfigGenerator.java | 322 --- .../setup/LayoutLibTestCallback.java | 202 -- .../intensive/setup/LayoutPullParser.java | 118 - .../bridge/intensive/util/ImageUtils.java | 341 --- .../intensive/util/ModuleClassLoader.java | 62 - .../intensive/util/TestAssetRepository.java | 54 - .../bridge/intensive/util/TestUtils.java | 36 - .../util/perf/LongStatsCollector.java | 97 - .../util/perf/PerformanceRunner.java | 80 - .../intensive/util/perf/TimedStatement.java | 178 -- .../util/perf/TimedStatementResult.java | 64 - tools/layoutlib/bridge/update_nav_icons.sh | 51 - tools/layoutlib/create/.classpath | 9 - tools/layoutlib/create/.project | 17 - tools/layoutlib/create/.settings/README.txt | 2 - .../.settings/org.eclipse.jdt.core.prefs | 93 - tools/layoutlib/create/Android.mk | 31 - tools/layoutlib/create/README.txt | 268 --- tools/layoutlib/create/create.iml | 27 - tools/layoutlib/create/manifest.txt | 1 - .../annotations/LayoutlibDelegate.java | 27 - .../tools/layoutlib/annotations/Nullable.java | 35 - .../annotations/VisibleForTesting.java | 50 - .../create/AbstractClassAdapter.java | 418 ---- .../tools/layoutlib/create/AsmAnalyzer.java | 914 -------- .../tools/layoutlib/create/AsmGenerator.java | 468 ---- .../create/ClassHasNativeVisitor.java | 102 - .../tools/layoutlib/create/CreateInfo.java | 363 --- .../create/DelegateClassAdapter.java | 143 -- .../create/DelegateMethodAdapter.java | 466 ---- .../layoutlib/create/DependencyFinder.java | 788 ------- .../create/FieldInjectorAdapter.java | 40 - .../tools/layoutlib/create/ICreateInfo.java | 110 - .../create/InjectMethodRunnables.java | 54 - .../create/InjectMethodsAdapter.java | 40 - .../android/tools/layoutlib/create/Log.java | 72 - .../layoutlib/create/LogAbortException.java | 32 - .../android/tools/layoutlib/create/Main.java | 227 -- .../tools/layoutlib/create/MethodAdapter.java | 97 - .../layoutlib/create/MethodListener.java | 75 - .../layoutlib/create/OverrideMethod.java | 152 -- .../create/PromoteClassClassAdapter.java | 64 - .../create/PromoteFieldClassAdapter.java | 51 - .../create/RefactorClassAdapter.java | 104 - .../layoutlib/create/RenameClassAdapter.java | 87 - .../create/ReplaceMethodCallsAdapter.java | 292 --- .../layoutlib/create/StubMethodAdapter.java | 383 --- .../create/TransformClassAdapter.java | 151 -- .../tools/layoutlib/java/AutoCloseable.java | 32 - .../tools/layoutlib/java/Charsets.java | 133 -- .../layoutlib/java/IntegralToString.java | 537 ----- .../java/LinkedHashMap_Delegate.java | 36 - .../android/tools/layoutlib/java/Objects.java | 132 -- .../tools/layoutlib/java/System_Delegate.java | 68 - .../layoutlib/java/UnsafeByteSequence.java | 81 - tools/layoutlib/create/tests/Android.mk | 35 - .../layoutlib/create/AsmAnalyzerTest.java | 258 --- .../layoutlib/create/AsmGeneratorTest.java | 431 ---- .../create/ClassHasNativeVisitorTest.java | 102 - .../layoutlib/create/CreateInfoAdapter.java | 80 - .../create/DelegateClassAdapterTest.java | 535 ----- .../tools/layoutlib/create/LogTest.java | 88 - .../tools/layoutlib/create/MockLog.java | 43 - .../create/PromoteClassClassAdapterTest.java | 170 -- .../create/RenameClassAdapterTest.java | 116 - .../create/StubMethodAdapterTest.java | 132 -- .../create/dataclass/ClassWithNative.java | 45 - .../dataclass/ClassWithNative_Delegate.java | 34 - .../layoutlib/create/dataclass/JavaClass.java | 22 - .../create/dataclass/OuterClass.java | 63 - .../create/dataclass/OuterClass_Delegate.java | 34 - .../OuterClass_InnerClass_Delegate.java | 30 - .../OuterClass_StaticInnerClass_Delegate.java | 30 - .../layoutlib/create/dataclass/StubClass.java | 30 - .../create/tests/data/mock_android.jar | Bin 10198 -> 0 bytes .../tests/mock_data/java/lang/JavaClass.java | 22 - .../mock_android/data/anotherDataFile | 1 - .../mock_data/mock_android/data/dataFile | 1 - .../mock_android/dummy/InnerTest.java | 91 - .../mock_android/util/EmptyArray.java | 24 - .../mock_data/mock_android/view/View.java | 25 - .../mock_android/view/ViewGroup.java | 29 - .../mock_android/widget/LinearLayout.java | 29 - .../mock_android/widget/TableLayout.java | 27 - tools/layoutlib/legacy/Android.mk | 30 - tools/layoutlib/legacy/legacy.iml | 12 - .../com/android/layoutlib/bridge/Bridge.java | 75 - tools/layoutlib/rename_font/README | 9 - .../layoutlib/rename_font/Roboto-Regular.ttf | Bin 114976 -> 0 bytes tools/layoutlib/rename_font/build_font.py | 227 -- .../rename_font/build_font_single.py | 211 -- tools/layoutlib/rename_font/test.py | 45 - .../editors/theme/widgets/ErrorCatcher.java | 94 - .../editors/theme/widgets/PressedButton.java | 31 - .../theme/widgets/ThemePreviewLayout.java | 200 -- .../studio-android-widgets.iml | 14 - 472 files changed, 57487 deletions(-) delete mode 100644 tools/layoutlib/.gitignore delete mode 100644 tools/layoutlib/.idea/.name delete mode 100644 tools/layoutlib/.idea/artifacts/studio_android_widgets_jar.xml delete mode 100644 tools/layoutlib/.idea/artifacts/studio_android_widgets_src_jar.xml delete mode 100644 tools/layoutlib/.idea/codeStyleSettings.xml delete mode 100644 tools/layoutlib/.idea/compiler.xml delete mode 100644 tools/layoutlib/.idea/copyright/Android.xml delete mode 100644 tools/layoutlib/.idea/copyright/profiles_settings.xml delete mode 100644 tools/layoutlib/.idea/encodings.xml delete mode 100644 tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml delete mode 100644 tools/layoutlib/.idea/inspectionProfiles/profiles_settings.xml delete mode 100644 tools/layoutlib/.idea/libraries/framework_jar.xml delete mode 100644 tools/layoutlib/.idea/libraries/junit.xml delete mode 100644 tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml delete mode 100644 tools/layoutlib/.idea/libraries/mockito.xml delete mode 100644 tools/layoutlib/.idea/libraries/objenesis.xml delete mode 100644 tools/layoutlib/.idea/misc.xml delete mode 100644 tools/layoutlib/.idea/modules.xml delete mode 100644 tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml delete mode 100644 tools/layoutlib/.idea/runConfigurations/All_in_create.xml delete mode 100644 tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml delete mode 100644 tools/layoutlib/.idea/runConfigurations/Create.xml delete mode 100644 tools/layoutlib/.idea/scopes/scope_settings.xml delete mode 100644 tools/layoutlib/.idea/uiDesigner.xml delete mode 100644 tools/layoutlib/.idea/vcs.xml delete mode 100644 tools/layoutlib/Android.mk delete mode 100644 tools/layoutlib/README delete mode 100644 tools/layoutlib/bridge/.classpath delete mode 100644 tools/layoutlib/bridge/.project delete mode 100644 tools/layoutlib/bridge/.settings/README.txt delete mode 100644 tools/layoutlib/bridge/.settings/org.eclipse.jdt.core.prefs delete mode 100644 tools/layoutlib/bridge/Android.mk delete mode 100644 tools/layoutlib/bridge/bridge.iml delete mode 100644 tools/layoutlib/bridge/resources/bars/README delete mode 100644 tools/layoutlib/bridge/resources/bars/navigation_bar.xml delete mode 100644 tools/layoutlib/bridge/resources/bars/navigation_bar600dp.xml delete mode 100644 tools/layoutlib/bridge/resources/bars/status_bar.xml delete mode 100644 tools/layoutlib/bridge/resources/bars/title_bar.xml delete mode 100644 tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_battery_100.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_wifi_signal_4_fully.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v18/mdpi/stat_sys_battery_100.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v18/mdpi/stat_sys_wifi_signal_4_fully.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_battery_100.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_wifi_signal_4_fully.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_home.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/hdpi/stat_sys_wifi_signal_4_fully.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/ldrtl-hdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/ldrtl-hdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/ldrtl-mdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/ldrtl-mdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/ldrtl-xhdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/ldrtl-xhdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_home.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/mdpi/stat_sys_wifi_signal_4_fully.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_home.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/xhdpi/stat_sys_wifi_signal_4_fully.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_home.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v19/xxhdpi/stat_sys_wifi_signal_4_fully.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/hdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/hdpi/ic_sysbar_home.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/hdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_battery_100.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/ldrtl-hdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/ldrtl-mdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/ldrtl-xhdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/ldrtl-xxhdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/mdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/mdpi/ic_sysbar_home.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/mdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_battery_100.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/xhdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/xhdpi/ic_sysbar_home.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/xhdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_battery_100.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.xml delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/xxhdpi/ic_sysbar_back.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/xxhdpi/ic_sysbar_home.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/xxhdpi/ic_sysbar_recent.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v21/xxhdpi/stat_sys_battery_100.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v9/hdpi/stat_sys_battery_100.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v9/hdpi/stat_sys_wifi_signal_4_fully.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v9/ldpi/stat_sys_battery_100.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v9/mdpi/stat_sys_battery_100.png delete mode 100644 tools/layoutlib/bridge/resources/bars/v9/mdpi/stat_sys_wifi_signal_4_fully.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow-b.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow-bl.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow-br.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow-l.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow-r.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow-tl.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow-tr.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow2-b.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow2-bl.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow2-br.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow2-l.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow2-r.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow2-tl.png delete mode 100644 tools/layoutlib/bridge/resources/icons/shadow2-tr.png delete mode 100644 tools/layoutlib/bridge/src/android/animation/AnimationThread.java delete mode 100644 tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/app/SystemServiceRegistry_Accessor.java delete mode 100644 tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java delete mode 100644 tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java delete mode 100644 tools/layoutlib/bridge/src/android/content/res/ComplexColor_Accessor.java delete mode 100644 tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/BlendComposite.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/RoundRectangle.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/drawable/GradientDrawable_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/os/HandlerThread_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/os/Handler_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/os/Looper_Accessor.java delete mode 100644 tools/layoutlib/bridge/src/android/os/ServiceManager.java delete mode 100644 tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/os/SystemProperties_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/preference/BridgePreferenceInflater.java delete mode 100644 tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java delete mode 100644 tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/text/LineBreaker.java delete mode 100644 tools/layoutlib/bridge/src/android/text/LineWidth.java delete mode 100644 tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java delete mode 100644 tools/layoutlib/bridge/src/android/text/Primitive.java delete mode 100644 tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/text/TabStops.java delete mode 100644 tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java delete mode 100644 tools/layoutlib/bridge/src/android/util/Log_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/util/LruCache.java delete mode 100644 tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/util/Xml_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java delete mode 100644 tools/layoutlib/bridge/src/android/view/BridgeInflater.java delete mode 100644 tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/Display_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/HandlerActionQueue_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java delete mode 100644 tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/PointerIcon_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/RectShadowPainter.java delete mode 100644 tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/ShadowPainter.java delete mode 100644 tools/layoutlib/bridge/src/android/view/SurfaceView.java delete mode 100644 tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java delete mode 100644 tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/ViewRootImpl_Accessor.java delete mode 100644 tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/View_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/WindowCallback.java delete mode 100644 tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java delete mode 100644 tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java delete mode 100644 tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java delete mode 100644 tools/layoutlib/bridge/src/android/webkit/WebView.java delete mode 100644 tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java delete mode 100644 tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java delete mode 100644 tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeLayoutParamsMapAttributes.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeSharedPreferences.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/graphics/NopCanvas.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DesignLibUtil.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DrawerLayoutUtil.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/SupportPreferencesUtil.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/IconLoader.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ThemePreviewNavigationBar.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/ShadowBuffer.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/SpotShadow.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/CachedPathIteratorFactory.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/Debug.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java delete mode 100644 tools/layoutlib/bridge/src/com/google/android/maps/MapView.java delete mode 100644 tools/layoutlib/bridge/src/dalvik/system/VMRuntime_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/libcore/io/MemoryMappedFile_Delegate.java delete mode 100644 tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java delete mode 100644 tools/layoutlib/bridge/tests/.classpath delete mode 100644 tools/layoutlib/bridge/tests/.project delete mode 100644 tools/layoutlib/bridge/tests/Android.mk delete mode 100644 tools/layoutlib/bridge/tests/res/com/android/layoutlib/testdata/layout1.xml delete mode 100644 tools/layoutlib/bridge/tests/res/empty.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/.gitignore delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build.gradle delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/androidTest/debug/com/android/layoutlib/test/myapplication/test/BuildConfig.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/ArraysCheckWidget.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/BuildConfig.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/MyActivity.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$array.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$attr.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$color.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$dimen.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$drawable.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$integer.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$menu.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$style.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R.class delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/activity.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector_1.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_vert_layout.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/font_test.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/shadows_test.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity-old-theme.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle.properties delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle/wrapper/gradle-wrapper.jar delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle/wrapper/gradle-wrapper.properties delete mode 100755 tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradlew delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradlew.bat delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/proguard-rules.pro delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/AndroidManifest.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/ArraysCheckWidget.java delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/MyActivity.java delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/CustomCalendar.java delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/CustomDate.java delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/InsetsWidget.java delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/package-info.java delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/color/gradient.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/adaptive.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/android.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/headset.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/ic_launcher.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/font/testfamily.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/font/testfont.ttf delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/font/testfont2.ttf delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/activity.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/array_check.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/expand_horz_layout.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/expand_layout.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/expand_vert_layout.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/fonts_test.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/four_corners.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/layout.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/scrolled.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/shadows_test.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/menu/my.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/arrays.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/attrs.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/dimens.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/ids.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/strings.xml delete mode 100644 tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/values/styles.xml delete mode 100644 tools/layoutlib/bridge/tests/src/android/app/SystemServiceRegistry_AccessorTest.java delete mode 100644 tools/layoutlib/bridge/tests/src/android/graphics/Matrix_DelegateTest.java delete mode 100644 tools/layoutlib/bridge/tests/src/android/util/BridgeXmlPullAttributesTest.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/BridgeRenderSessionTest.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/TestDelegates.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/impl/LayoutParserWrapperTest.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/PerformanceTests.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderResult.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTestBase.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/RenderTests.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/ConfigGenerator.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutLibTestCallback.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/setup/LayoutPullParser.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ImageUtils.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/ModuleClassLoader.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/TestAssetRepository.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/TestUtils.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/LongStatsCollector.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/PerformanceRunner.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/TimedStatement.java delete mode 100644 tools/layoutlib/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/perf/TimedStatementResult.java delete mode 100755 tools/layoutlib/bridge/update_nav_icons.sh delete mode 100644 tools/layoutlib/create/.classpath delete mode 100644 tools/layoutlib/create/.project delete mode 100644 tools/layoutlib/create/.settings/README.txt delete mode 100644 tools/layoutlib/create/.settings/org.eclipse.jdt.core.prefs delete mode 100644 tools/layoutlib/create/Android.mk delete mode 100644 tools/layoutlib/create/README.txt delete mode 100644 tools/layoutlib/create/create.iml delete mode 100644 tools/layoutlib/create/manifest.txt delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/LayoutlibDelegate.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/Nullable.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/annotations/VisibleForTesting.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/AbstractClassAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/ClassHasNativeVisitor.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateClassAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/DependencyFinder.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/FieldInjectorAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/ICreateInfo.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/InjectMethodRunnables.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/InjectMethodsAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/Log.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/LogAbortException.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/MethodListener.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/OverrideMethod.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/PromoteClassClassAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/PromoteFieldClassAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/RefactorClassAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/RenameClassAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/ReplaceMethodCallsAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/StubMethodAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/create/TransformClassAdapter.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/java/AutoCloseable.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/java/Charsets.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/java/IntegralToString.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/java/LinkedHashMap_Delegate.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/java/Objects.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/java/System_Delegate.java delete mode 100644 tools/layoutlib/create/src/com/android/tools/layoutlib/java/UnsafeByteSequence.java delete mode 100644 tools/layoutlib/create/tests/Android.mk delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmAnalyzerTest.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/AsmGeneratorTest.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/ClassHasNativeVisitorTest.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/CreateInfoAdapter.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/LogTest.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/MockLog.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/PromoteClassClassAdapterTest.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/RenameClassAdapterTest.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/StubMethodAdapterTest.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/ClassWithNative.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/ClassWithNative_Delegate.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/JavaClass.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_Delegate.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_InnerClass_Delegate.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/OuterClass_StaticInnerClass_Delegate.java delete mode 100644 tools/layoutlib/create/tests/com/android/tools/layoutlib/create/dataclass/StubClass.java delete mode 100644 tools/layoutlib/create/tests/data/mock_android.jar delete mode 100644 tools/layoutlib/create/tests/mock_data/java/lang/JavaClass.java delete mode 100644 tools/layoutlib/create/tests/mock_data/mock_android/data/anotherDataFile delete mode 100644 tools/layoutlib/create/tests/mock_data/mock_android/data/dataFile delete mode 100644 tools/layoutlib/create/tests/mock_data/mock_android/dummy/InnerTest.java delete mode 100644 tools/layoutlib/create/tests/mock_data/mock_android/util/EmptyArray.java delete mode 100644 tools/layoutlib/create/tests/mock_data/mock_android/view/View.java delete mode 100644 tools/layoutlib/create/tests/mock_data/mock_android/view/ViewGroup.java delete mode 100644 tools/layoutlib/create/tests/mock_data/mock_android/widget/LinearLayout.java delete mode 100644 tools/layoutlib/create/tests/mock_data/mock_android/widget/TableLayout.java delete mode 100644 tools/layoutlib/legacy/Android.mk delete mode 100644 tools/layoutlib/legacy/legacy.iml delete mode 100644 tools/layoutlib/legacy/src/com/android/layoutlib/bridge/Bridge.java delete mode 100644 tools/layoutlib/rename_font/README delete mode 100644 tools/layoutlib/rename_font/Roboto-Regular.ttf delete mode 100755 tools/layoutlib/rename_font/build_font.py delete mode 100755 tools/layoutlib/rename_font/build_font_single.py delete mode 100755 tools/layoutlib/rename_font/test.py delete mode 100644 tools/layoutlib/studio-custom-widgets/src/com/android/tools/idea/editors/theme/widgets/ErrorCatcher.java delete mode 100644 tools/layoutlib/studio-custom-widgets/src/com/android/tools/idea/editors/theme/widgets/PressedButton.java delete mode 100644 tools/layoutlib/studio-custom-widgets/src/com/android/tools/idea/editors/theme/widgets/ThemePreviewLayout.java delete mode 100644 tools/layoutlib/studio-custom-widgets/studio-android-widgets.iml diff --git a/tools/layoutlib/.gitignore b/tools/layoutlib/.gitignore deleted file mode 100644 index a2b0c3364a3e8..0000000000000 --- a/tools/layoutlib/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -bin -/.idea/workspace.xml -/out -/bridge/out -/.idea/kotlinc.xml \ No newline at end of file diff --git a/tools/layoutlib/.idea/.name b/tools/layoutlib/.idea/.name deleted file mode 100644 index 10eb5c16808c0..0000000000000 --- a/tools/layoutlib/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -layoutlib \ No newline at end of file diff --git a/tools/layoutlib/.idea/artifacts/studio_android_widgets_jar.xml b/tools/layoutlib/.idea/artifacts/studio_android_widgets_jar.xml deleted file mode 100644 index 0450be35ae4fc..0000000000000 --- a/tools/layoutlib/.idea/artifacts/studio_android_widgets_jar.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - $PROJECT_DIR$/out/artifacts/studio_android_widgets_jar - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/artifacts/studio_android_widgets_src_jar.xml b/tools/layoutlib/.idea/artifacts/studio_android_widgets_src_jar.xml deleted file mode 100644 index a844ca34d8a8b..0000000000000 --- a/tools/layoutlib/.idea/artifacts/studio_android_widgets_src_jar.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - $PROJECT_DIR$/out/artifacts/studio_android_widgets_src_jar - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/codeStyleSettings.xml b/tools/layoutlib/.idea/codeStyleSettings.xml deleted file mode 100644 index ac90d1e540beb..0000000000000 --- a/tools/layoutlib/.idea/codeStyleSettings.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/compiler.xml b/tools/layoutlib/.idea/compiler.xml deleted file mode 100644 index 35961a2896ac5..0000000000000 --- a/tools/layoutlib/.idea/compiler.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/copyright/Android.xml b/tools/layoutlib/.idea/copyright/Android.xml deleted file mode 100644 index d81d75dae18a2..0000000000000 --- a/tools/layoutlib/.idea/copyright/Android.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/copyright/profiles_settings.xml b/tools/layoutlib/.idea/copyright/profiles_settings.xml deleted file mode 100644 index 20145de481f1c..0000000000000 --- a/tools/layoutlib/.idea/copyright/profiles_settings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/encodings.xml b/tools/layoutlib/.idea/encodings.xml deleted file mode 100644 index f758959656c79..0000000000000 --- a/tools/layoutlib/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml b/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index 74fa549f66d4f..0000000000000 --- a/tools/layoutlib/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/inspectionProfiles/profiles_settings.xml b/tools/layoutlib/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 3b312839bf2e9..0000000000000 --- a/tools/layoutlib/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/libraries/framework_jar.xml b/tools/layoutlib/.idea/libraries/framework_jar.xml deleted file mode 100644 index 6695a3631ff13..0000000000000 --- a/tools/layoutlib/.idea/libraries/framework_jar.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/libraries/junit.xml b/tools/layoutlib/.idea/libraries/junit.xml deleted file mode 100644 index ba46ebff7d163..0000000000000 --- a/tools/layoutlib/.idea/libraries/junit.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml b/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml deleted file mode 100644 index a8736000a513c..0000000000000 --- a/tools/layoutlib/.idea/libraries/layoutlib_api_prebuilt.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/libraries/mockito.xml b/tools/layoutlib/.idea/libraries/mockito.xml deleted file mode 100644 index 032963e40b940..0000000000000 --- a/tools/layoutlib/.idea/libraries/mockito.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/libraries/objenesis.xml b/tools/layoutlib/.idea/libraries/objenesis.xml deleted file mode 100644 index 1484de59be6a7..0000000000000 --- a/tools/layoutlib/.idea/libraries/objenesis.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/misc.xml b/tools/layoutlib/.idea/misc.xml deleted file mode 100644 index 44b47f2c91d4a..0000000000000 --- a/tools/layoutlib/.idea/misc.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/modules.xml b/tools/layoutlib/.idea/modules.xml deleted file mode 100644 index 6ffc1cc12b881..0000000000000 --- a/tools/layoutlib/.idea/modules.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml b/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml deleted file mode 100644 index 0b227175c0d2d..0000000000000 --- a/tools/layoutlib/.idea/runConfigurations/All_in_bridge.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/runConfigurations/All_in_create.xml b/tools/layoutlib/.idea/runConfigurations/All_in_create.xml deleted file mode 100644 index b9cd419d24f06..0000000000000 --- a/tools/layoutlib/.idea/runConfigurations/All_in_create.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml b/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml deleted file mode 100644 index b402849f22a37..0000000000000 --- a/tools/layoutlib/.idea/runConfigurations/Bridge_quick.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/tools/layoutlib/.idea/runConfigurations/Create.xml b/tools/layoutlib/.idea/runConfigurations/Create.xml deleted file mode 100644 index 536a23fdfebae..0000000000000 --- a/tools/layoutlib/.idea/runConfigurations/Create.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/scopes/scope_settings.xml b/tools/layoutlib/.idea/scopes/scope_settings.xml deleted file mode 100644 index 922003b8433bc..0000000000000 --- a/tools/layoutlib/.idea/scopes/scope_settings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/tools/layoutlib/.idea/uiDesigner.xml b/tools/layoutlib/.idea/uiDesigner.xml deleted file mode 100644 index 3b0002030884f..0000000000000 --- a/tools/layoutlib/.idea/uiDesigner.xml +++ /dev/null @@ -1,125 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/layoutlib/.idea/vcs.xml b/tools/layoutlib/.idea/vcs.xml deleted file mode 100644 index 9ab281ac88c73..0000000000000 --- a/tools/layoutlib/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk deleted file mode 100644 index 29c933ac7e752..0000000000000 --- a/tools/layoutlib/Android.mk +++ /dev/null @@ -1,82 +0,0 @@ -# -# 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)) diff --git a/tools/layoutlib/README b/tools/layoutlib/README deleted file mode 100644 index 0fea9bd9d9ac9..0000000000000 --- a/tools/layoutlib/README +++ /dev/null @@ -1,4 +0,0 @@ -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 diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath deleted file mode 100644 index 9c4160c8127f7..0000000000000 --- a/tools/layoutlib/bridge/.classpath +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/tools/layoutlib/bridge/.project b/tools/layoutlib/bridge/.project deleted file mode 100644 index e36e71b23ff90..0000000000000 --- a/tools/layoutlib/bridge/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - layoutlib_bridge - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/tools/layoutlib/bridge/.settings/README.txt b/tools/layoutlib/bridge/.settings/README.txt deleted file mode 100644 index 9120b20710a3c..0000000000000 --- a/tools/layoutlib/bridge/.settings/README.txt +++ /dev/null @@ -1,2 +0,0 @@ -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 diff --git a/tools/layoutlib/bridge/.settings/org.eclipse.jdt.core.prefs b/tools/layoutlib/bridge/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 5381a0e16c7de..0000000000000 --- a/tools/layoutlib/bridge/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,93 +0,0 @@ -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 diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk deleted file mode 100644 index 3dd8002bcff5e..0000000000000 --- a/tools/layoutlib/bridge/Android.mk +++ /dev/null @@ -1,36 +0,0 @@ -# -# 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)) - diff --git a/tools/layoutlib/bridge/bridge.iml b/tools/layoutlib/bridge/bridge.iml deleted file mode 100644 index 85ec3eb73b923..0000000000000 --- a/tools/layoutlib/bridge/bridge.iml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/bridge/resources/bars/README b/tools/layoutlib/bridge/resources/bars/README deleted file mode 100644 index c84ef804ccabe..0000000000000 --- a/tools/layoutlib/bridge/resources/bars/README +++ /dev/null @@ -1,8 +0,0 @@ -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. diff --git a/tools/layoutlib/bridge/resources/bars/navigation_bar.xml b/tools/layoutlib/bridge/resources/bars/navigation_bar.xml deleted file mode 100644 index 55bd1d2c67a4c..0000000000000 --- a/tools/layoutlib/bridge/resources/bars/navigation_bar.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - diff --git a/tools/layoutlib/bridge/resources/bars/navigation_bar600dp.xml b/tools/layoutlib/bridge/resources/bars/navigation_bar600dp.xml deleted file mode 100644 index e208a0daf3efe..0000000000000 --- a/tools/layoutlib/bridge/resources/bars/navigation_bar600dp.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - diff --git a/tools/layoutlib/bridge/resources/bars/status_bar.xml b/tools/layoutlib/bridge/resources/bars/status_bar.xml deleted file mode 100644 index 04571e1d6d35b..0000000000000 --- a/tools/layoutlib/bridge/resources/bars/status_bar.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - diff --git a/tools/layoutlib/bridge/resources/bars/title_bar.xml b/tools/layoutlib/bridge/resources/bars/title_bar.xml deleted file mode 100644 index 76d78d9169d46..0000000000000 --- a/tools/layoutlib/bridge/resources/bars/title_bar.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_battery_100.png deleted file mode 100644 index c920ec4fe71abc50728364e286223f30444eff7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 604 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9d!3HD?58j^-q}Y|gW!U_%O?XxI14-? ziy0WWfl9fB7%$ze`vVdzD{xE)(qR1zpMG6sW?*2n@pN$vu{iy9%342WN0HY3)^p!E z@wO~sI;^Z9(4fi7WW%ZNF!`x&fW*8;(S!>XKFrHl8dp3KHAt9MR-YztMrU%X!%ssM z+qAs2XEooSbZPHB$5t9Sah2WfovaTMvN!J%&c0u{q}YxjnTh2aCoui8x~aFy#adllVGYx3 zg_&BL0=HebXIiMu_$g}9vROTsUi|!c>ct9HGp2VNcuKcz;n~11v(vR0bmhLqlByOI<_L5JN*NLo+KQV_gGtD+7aH%O7q>(U6;;l9^VCTSND+NN%78 z8ITRZ`DrEPiAAXljw$&`sS0kHMXBZaMcKs)&cUXITOXSN)iHRw`njxgN@xNAhCb-B diff --git a/tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v18/hdpi/stat_sys_wifi_signal_4_fully.png deleted file mode 100644 index 6248cfd7b09b1a343630fb99d6369955a2765d08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1541 zcmeAS@N?(olHy`uVBq!ia0vp^azHH2!3HF=|Jn-zDajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49ppsArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XRMoSU}&gdW~OIo zVrph)sH0$HU}&Uo07PcGh9*{~W>!Y#3Q(W~w5=#5%__*n4QdyVXRDM^Qc_^0uU}qX zu2*iXmtT~wZ)j<02{OaTNEfI=x41H|B(Xv_uUHvof=g;~a#3bMNoIbY0?5R~r2Ntn zTP2`NAzsKW@b!fooL3ADC}5E3S0onb8|oS8=jMX^1y)^L5|oN?23FO@A(aKG`a!A1 z`K3k4!1zd0hG_To13$di@AxBGt3NZdM%8coXri)O$}TuO$-fPjU7$REnM7; zoh;3Ol#!b$Os{8NaYXaGhgkCh5usfi zEC*Y=l?ny7^eg;oe84Yq$0LYa@M367CuieQjT1XA8mYzIXHI|ewc>Nlcgu&1xaUjG z-T8iw`FFW7u$g`F+BBznK2Y!wI)frPMfWeX^xu z=h3eHpH_Y_v3nr9Y~zCJnPpczInO#Ns!jE8QtbD|9B-wrl$?2_*Ozg3$(PTpXTOFQ#vY26 zaW`^z{U%!;uxjJ^s?eGK-H4B~6Id$*EEcN! z-T8PkyyhCynk#$D@8$IFbNBI6*AKmMBs<2%@KwmfvTckx8TL0!(=HrY#3L$kH2-+r zvaPZ6F1iVxEKR!jC^*1#a>TOEqr&}5`h6a^c-Al+?pvaN_pJek_LIlCA?MR8FYIoN uU&gq`)+YS;mjM6Poi~2HmwWM_!+@dt?jQH`<^Sh`3T97NKbLh*2~7ZL=0WlR diff --git a/tools/layoutlib/bridge/resources/bars/v18/mdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v18/mdpi/stat_sys_battery_100.png deleted file mode 100644 index 943332e5929c7413c0bca3400f852200cb5eae0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 515 zcmeAS@N?(olHy`uVBq!ia0vp^JU}eO!3HGrSK5O(Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G^tAk28_ZrvY{U|E4dh!Eje z>N{V$Mae5mitnJ}4hETqOX3R_d&&nEGs$y zdg9T~d!MJ{RJ?fg6e%f& zmwOlN72LD?>9YBV%0yb1MUbU&|kEN70a*pOTqYiCaVW zuSjm71{shI!TD(=<%vb942~)JNvR5MnMJAP`9;~q3eLf%ge#Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07??9MLn2Bde0{8v^Kf6`()~Xj@TAnpKdC8`Lf!&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+15@d#vkuFe$ZgFK^Nn(X=Ua>OF1ees}t-3#_`hBq$Z(46Le)Ln;eW^@CE2 z^Gl18f$@>14ATq@JNy=b6armi>O)SYT3dzsUfu(?ejQo=P;*9(P z1?ONh1r6WCw{ApUhpEy^rQO>ryA&s6}2uvI1&7nmAYn7g_fxLTMYeC}dk zG#%Kg6F@zd$)34`Ml?ID?=sPOs~o~9{T?^ z!%=zPhc4-wKT-?BGdK-eZPqz`U$LOUw8!zLD0S#Ub=jo~xqpO^j08f@knw)nkF=1P4M;G)0j#k3v&=2r$4@u~VGvGU6; zotMbxUEz4_T_TsV#{b3b>KSJIM{}h2s-7$C4qN>tHsiD6L-k1NXg?hi>x zHuwC0&9F;S`@)?cBC}UaebQaz{M^puX?(?$U9UPy)vmC8)N9_5xQYj26J zPCECAMe0daMBi;Ywhg_L&R^_~>X@=J{H~z*FVdQ&MBb@04HAA0ssI2 diff --git a/tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_battery_100.png deleted file mode 100644 index 36c61e13ade308bb0e1da18a00e570eced97f2e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 728 zcmeAS@N?(olHy`uVBq!ia0vp^5|gW!U_%O?XxI14-? ziy0WWg+Q3`(%rg0Ai=T%$8;bK*3ZDb|4t+W1LF=)7sn8f<8PBBaszoxL1L?5WCkaP0(cRTlIqu(Sm(ZuMF@4?NYn9hNdqz8LD;3R{n{F!-{c?T&>r>Y387(qP^%|nN4es5! z#bC#Le)(T9$J@&neqW|m%&f5O>%;fm_o@R{8BL#mAp1c(>jd>qHmd{2?nrcBZx+Z6 z>hXNNN;|rxgTcJf*Xi2F)jzhkC=?q`)aDSGy~}AE!^e_&-`|}pc**KH%}x0NhY3@! z1DNV}R@l|`;+{?L>y11~IZtM8)P2dN?Ug(!@Bs64k$3CPt@`iJDkZ@-FDQXy&*FQ{ zdd%V$-i+)uv4TH&a#HucvOmRqhwR0bmhLqlByOI<_L5JN*NLo+KQV_gGtD+7aH z%O7q>(U6;;l9^VCTSND+NN%788ITRZ`DrEPiAAXljw$&`sS0kHMXBZaMcKs)&cUXI TTOXSN)iHRw`njxgN@xNAIoBZv diff --git a/tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v18/xhdpi/stat_sys_wifi_signal_4_fully.png deleted file mode 100644 index 459a1a2e83ce8725456c751857420402ee9a363d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1750 zcmbVNYfuwc6b_29LJ=J*zL_;3pg^*l_wEoW$tHrD2q7XOG7ZT>A|x9&O9_ahbx=X; zvm)go3{a`k3ZkN>z7>rW!HUR;MNqNT0TCFnSkc-I5A6@fAKlsAyZ7$-zVn@P&)Llm zQ!I9In&m{J(Og19P$f0`P?y(dbn5OT@GPK)nWQv|jKJf`R5gLog0*-Y280^a378U7 zYtxeJus|AZyiTu*BBSKX5Dji%s_iyRi@`*pX|%u~i%G3X#7H0xOVArdjNUUB7=T_Y zVyxuJLAgnS>GUD#1QwC5P-)T=HL#WuvJq)vVS#6@^~ge?F@4+iCp z(8eQ5R5t31nu!=Xk~ASKR%&W0GnK={i3An|!?2x$%?_X}0?cVfQf&z^nmxxDP|U0$ z^d?e|8v#3`Iu1`EMGQ*mNC*a#T>hTeXdX=zl`@t^ZDK)8kYzB~;~KU$lS=G^jE`EI zRcR)SrNqp53ZbF)Bi?fiOy%y=j_ih%8e}=4r#3~MgyNbM17;*cQ4xcB!_?}v2nY$O zEDE@wfDQ765H%BW#1JZzN!X}>%a)9Bd<@Iui1{$gg+UbNLXeab%o7Mv8AlBBsevuy zjbTHLW>Rg`U}Jvul;2UT@RL|XLSSkVCsa6|G*$s&I-JDKI@|T&>X??F$R+ z8#EFxiV^y+F|CZi4Zv`Q5&g#$fI@*(3QC3i50RrFTMSE430DkL>PN8J|C2QqC5B}$ zkN=d**b-HP_Q&_dPfgyp4`!r#hM=0`sj%JNbB>{Cu*!1p+1;ffs_;3s{+TIC&g|6# zr4!ww_s~V(`ubj$7F>+1$=(EP%VK2xyrNmQMisf;J-7yn_S&NgaW2{IK2^GkjxE$S zMSvaik@c=`m@&-3#oEAsY2CrWl_qO56 zjMrdR?{|4IQ%{zD-W`6Z_H3MEalZ$ve@+8Z1YTZrtu6YQWb@vof-QZHso}dEZgS)V zlQ2!e&N}c zCraGzzuFv*s;nuQKl&#Qd9vFyVGv zdf&#LHiskirv~OZad)P|k@F%P3(gW*xrNYpxlUHSu$$KI4VP~*x%u76FGq&BIhjg% zQA`m7RHW;JDk#t*tH{ zlJfd>9er-rs7*<^<{SKTF=rmu?m_EUDegs=%(aC*75bFERUa@=U%b5ZaR%70vLdIV z2LF9m!}nDz)}PJ|p4_!TE4P=u+SeSR)WPezRr3O_^VC-0wo=z`2YX_ diff --git a/tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_back.png deleted file mode 100644 index 84e6bc89c0829a1dd61d9045baeca62b12199c4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1053 zcmeAS@N?(olHy`uVBq!ia0vp^6+rC4!2%?wi~sxrq?nSt-CY>|xA&jf59DzcctjR6 zFmMZjFyp1Wb$=Kbn8iF@978H@y`5p5ArdIkwtwc$s~HAv!WY##ZmgKgrIoQdL6vQb zprC8A;*luF9F@HqON1RgS{6iTnJFz1;MQ$X(0ayb_#|=O?3_t=f9j@PThruu;!bIM z!9LApGk1Qk`Cj>s^{@dCGFseKk=Gskstuu(xVi=GW|) z^vD0wWVMd(+8409=+)INd27n=dc5xgGS|H0OnstSnn*C2QVT!D6kl)@}mr@t{Oxp5r`=?spET`}m zqm#;|SJL7{7P4>o)b{qzlHSQ8AFl7yt6KWw7w3shXMLBPW9wuWcw~Iov?^m!qn@A8 zq(2Q34ZHtbI;iloc|wDuUSXTf);BF%-=9$WS8eX<ib;2Fw{V%q%|)T>`K7Kc z;M*O!WzM&Pnrii$8i5z@qfg(zUZXAk^yvKUo7!FXeJFhSz0||TFRR2``Bku=c&w`2 zy5}Fdln$_&>0J(&bKQ37fF9qaGj(b=UDf?R2&t^TDy-(*DE7{1kIz{p=V?-A6Vn^r ztTIX^5By&~&FxTXc3;{C_XFl~mmDwN{kTEukfodC-}JLe36nh4UM!q#e&*rhf}Ow4 zzx<)~%%DOiXn{n%u)wlcUCWcs3Z+K)rLI=k^Qv}7j==Iw{>Vu*=!kylgijU|gQQe| z*+#U)HKN41C^fMpGe1uuBr`Xa!BF4OSl`g_-^F$1Kn1EG1u2OosaDA#RjCX{28M>Z zh6cJuW+8^AR>qcA#s<0u=2iv<>wT@7Q8eV{r(~v8qH8d>GBkx~xNu}v7*K-@$cEtj uw370~qErUQl>DSr1-Hzi)bjkI>|zDyVAH~_kIjJU7(8A5T-G@yGywp7CCL>4 diff --git a/tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/v19/hdpi/ic_sysbar_home.png deleted file mode 100644 index 38e4f45719e7fe43e350c20d6b1078391392ca61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1064 zcmeAS@N?(olHy`uVBq!ia0vp^6+rC4!2%?wi~sxrq?nSt-CY>|xA&jf59DzcctjR6 zFmMZjFyp1Wb$=Kbm=!%;978H@y`6bFTR2eUSbcd~)N;>P%v?bQ3p*4vI2K*$?eY=~ zTI?PE?$6^pot{^sL{_?fWOQ1XbdZ;!&<&uaUc?tc7>kQ91K4AWS^7AaIgaXcJvlrF}WrI{Fl}wR|?0fi` zoslQg>rByfruhxK*oFMcm`eY9u6C4AJuT|DdAbmz9dpgG#3@>#Y#)A}Gv=~+z&)X0 z)7r2%lddJ|6-@p7CVi@woMu>s>qI4HAA^IMZJNRl9&bF6{K+S{FGYP)j`!AUp05=b zv^dY=%HQGM`19F)-s30S%=815T~Dy9-JW!JMcUe{H$u%OTvKf6w^?+cxM>;Btjkl5 zOBTgEGH5g6(*(M#zeea}UufdoE$=d=N;}o>B+iO=Xb+s7B=yYxyy-bZF9%Wn`S~_W z4~WG7w>9>=ECy7bx72jOAqG3`Jqu1SPcz`q%l;M?tAE47^4JacRtEWYSGk}BwW!V8 zqc$A4wPo1~gX6JXdzh_sc9tE`o7kZ2GvO(V=BX3Kw@( zKW)=Fv1!lL9)*p0lad{`A6$A!ci#h-N?t*O*<1QE=ST`A6%<51G!u=HzFQ^6vR%tn zZQDjygN6oyq!sz*Yqw^$ADDK=fwKHB;tOvzw5Z%!7wV z&llAkJjB1D`0M}Muls*Q_Wi$dX~MA^vqP@E4Sl7bS@pYV>-mkJV|JD29Mmpx4HSW) zDR0lkN3K)rpY{0AW?&8yEpd$~aV||xA&jf59DzcctjR6 zFmMZjFyp1Wb$=Kb7!P>5IEGZ*dOOoGPsEYOb$&XR$dzWcB^}HK0y}u;H1nz_94~ZlPaATUWXk&O*wC~oZn8J^P0^gZT+8aF8_8<*>)()qv;8E zb{S8^TJt#vMBlTz|C*+J??X#z;+A%2w@I^Y&Th6j>pRK$sp5$b|EB!a?U|_lByQ(x zzeNrj?|$q%es)D2o8|ZW%!YF|zwVT%U;4*!LX4MaXdCCGPXCHsm)+n|c^#{m-;b=rCvBv7IYX|z%MUBP)PAyvr+n9<^ZJRlEF5tKXR`L}nx0S* zXMEqV@T6$7=st$Sj0I=edv7t_x-|Fp`G?V`S+^|RYkM(ik=dSy>bmakr+Y0{DIK2M zDLnC-N~|e24|^}$riuG6XSDB?dpF_gO*^B5OW)M8{7?KU+P`0gcj2i5U!_f6HxOa1 z_>tRgXT`lRL2F)M1dEoqMwB=gr6!hS=I1GdWag$a80s4u>l+&WyST0#s6Z8@ASJOR z)hZdJDwV;=z|c_F&_LJ7EX2^%%GlD%*g)67+{(aUy{}a>iiX_$l+3hBbPeWKhNch= z7mmyd18R@~*$|wcR#Ki=l*-_klAn~S;FejGTAp8&U98|7Y+AVWu^CVugQu&X%Q~lo FCIA(u8jAn` diff --git a/tools/layoutlib/bridge/resources/bars/v19/hdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v19/hdpi/stat_sys_wifi_signal_4_fully.png deleted file mode 100644 index 6248cfd7b09b1a343630fb99d6369955a2765d08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1541 zcmeAS@N?(olHy`uVBq!ia0vp^azHH2!3HF=|Jn-zDajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg49ppsArU1JzCKpT`MG+DAT@dwxdlMo3=B5*6$OdO*{LN8 zNvY|XdA3ULckfqH$V{%1*XSQL?vFu&J;D8jzb> zlBiITo0C^;Rbi_HHrEQs1_|pcDS(xfWZNo192Makpx~Tel&WB=XRMoSU}&gdW~OIo zVrph)sH0$HU}&Uo07PcGh9*{~W>!Y#3Q(W~w5=#5%__*n4QdyVXRDM^Qc_^0uU}qX zu2*iXmtT~wZ)j<02{OaTNEfI=x41H|B(Xv_uUHvof=g;~a#3bMNoIbY0?5R~r2Ntn zTP2`NAzsKW@b!fooL3ADC}5E3S0onb8|oS8=jMX^1y)^L5|oN?23FO@A(aKG`a!A1 z`K3k4!1zd0hG_To13$di@AxBGt3NZdM%8coXri)O$}TuO$-fPjU7$REnM7; zoh;3Ol#!b$Os{8NaYXaGhgkCh5usfi zEC*Y=l?ny7^eg;oe84Yq$0LYa@M367CuieQjT1XA8mYzIXHI|ewc>Nlcgu&1xaUjG z-T8iw`FFW7u$g`F+BBznK2Y!wI)frPMfWeX^xu z=h3eHpH_Y_v3nr9Y~zCJnPpczInO#Ns!jE8QtbD|9B-wrl$?2_*Ozg3$(PTpXTOFQ#vY26 zaW`^z{U%!;uxjJ^s?eGK-H4B~6Id$*EEcN! z-T8PkyyhCynk#$D@8$IFbNBI6*AKmMBs<2%@KwmfvTckx8TL0!(=HrY#3L$kH2-+r zvaPZ6F1iVxEKR!jC^*1#a>TOEqr&}5`h6a^c-Al+?pvaN_pJek_LIlCA?MR8FYIoN uU&gq`)+YS;mjM6Poi~2HmwWM_!+@dt?jQH`<^Sh`3T97NKbLh*2~7ZL=0WlR diff --git a/tools/layoutlib/bridge/resources/bars/v19/ldrtl-hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-hdpi/ic_sysbar_back.png deleted file mode 100644 index 782ebfe3f2ba73a6af893fcc62b25d47c21c970e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 904 zcmV;319$w1P)7l65Lz4(LBx>TWlcdS)J|1>9V5@1(e54b7e{)#a!^`)~^Zwg! z!7vQNFbu;m48t%C!!QiP_#bgaI*b}05gy^FQ4fDaS4JwlOC)A3hU@&Qe1Qggbd?(CaaRxX*RM>MA?RdqqFLhf~t z{Hdy%P@)kbUs%a%J}&1I3!T=2CY0#wf>!dX)VNV~${%Y)RZXg*{&13AD6v^I*H{*a zDCdmrSz!xjd7njE>0=B}-4#RdGjiYLFg?7-+r&A;dX_2CMvXEFC-^0Vr+aVl|gOspC zI7aAYmN&T0C2nz#1$+*lBbMmmJe`P?{xEVwb>~Rv6D?{=(>fKRo5~4AI;V>6X->xq zHJIdtO1iEY&Fc%HNU?m*IUETMYe5sLYOr8)I9vGt)U0l3TXXl-db6dOF<&XsA4)V- zxV1yE(8rqBV||xz)z9R{LLaH32_^b5+uDN3^?~ASr$oe5BcfY(?*lw3y$tb)9b9Fw zc?}S%UB%%#7ZBwhaGpB7jIx!8n+)&-Pd(%XKq$cvSi$oSPzSC5fOTLO-;z+~GWVM| z9>x06;Dz?|xA&jf59DzcctjR6 zFmMZjFyp1Wb$@_@>?NMQuIzVsSVfdXyW9>fU|?We=IP=XQgQ3;jq|?EhCJ;Lud6zF z#0LsG^&F5e;43ajVAktljxI=KY+0~~MGA`8Uto-^J|Qa|=d6IQZ!t z_UX9Yf6s-2Pakbi*>>o)%%+3E9wxSOmZ?FT52bQSpHrKjW1QM1e(a@6-i^n6#_OjR z{QUkr#xU`iS=gLU`W+b-*=vj+&2X<`jIR1~i+A?pXBGGL|J>5w^ZtjB$#sz(lP2Ej zws!uv&N<4NGks3ZJ}c3>=r%s?zkIyUe_TEDP#j`5G8?0-6^6o2<9{p($MXq_Qj z&cwsl=B-ch&3k!t-?@}!ci7fm*R^ul%z6I$-lq+UD>VX?jUV*PO`CnqT3PN?n~V9J zt;=?QS#G)a&74&RYp(g+5I-DoQ&GHT)AtBNLC*A|7b|c7Sd#i?lXHG#Tx!tAaI0q> zeZP-xeOG_Koj2jo$#%2P^}==Evu1`rh}h(B9+CeqVpS#I_nCWbIRDgad86-sXlCE$ z4X2&+tP_mdKI;Vst09F6zQUCw| diff --git a/tools/layoutlib/bridge/resources/bars/v19/ldrtl-mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-mdpi/ic_sysbar_back.png deleted file mode 100644 index a1b806266959124745d646d6291d212fda386a02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 617 zcmV-v0+#)WP)(W9A}Ca)`}p3lAIR1nBfH>tLm~A1J*cDagjSrvchM|nje^T?*>ZNV)kDyo^{!d zvmWz+ZFk$QarTJU?AY=ArrE@^jLcWAd3g{TgLv9ce)XzYM0>>s@rX;lc3iryR?lXR zx?t(;$Tnjxo>3pvHw%M!$oJ|)F$`|hp}}|!^_zl9EYk4-wYc%TunCXB&T~Zi7yeioiT?xWGv!nV>}#cL#00EI>hv{HMn1 zEAc=0Y1-B5)u*;Mi<`!Ay`;C{gGI_00000NkvXXu0mjf D`O+F+ diff --git a/tools/layoutlib/bridge/resources/bars/v19/ldrtl-mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-mdpi/ic_sysbar_recent.png deleted file mode 100644 index fcdbefe9f5065e5578ab3132548b6fc347b329a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 423 zcmV;Y0a*TtP)7x0XRuSK~z}7 z?UzAP!!Qg*pMsao49SJ)4A+K5FO+mz!U`-Fp%B_GB!@5o^w!Q;`quxkAqavX2!h}@ zBerGgT7CJcgo5MR4RR9GtlxmnQ81YsQ8ql%lBvwaC3?0T+-*&$Txz#8b2eL2!BLS+ z#~phTYCJV%KtQF`G|8>^k!M77jS7C+O4M!`J)7hwpK1IBDv+spa2W<5Q_*qH(KE+Y zaXfhqqX-SHH*r#7fnN<{Y3PMpcBnT45_1B|Y#0@k8^oX3$vuCUhOq{{EbroUrC>EF zc&)t!g1Rr=X89acU|>U4n1zP%_3+fI~$Dc^Z^mJYgrKGmP+jY@p;jg?&zUhVcA6|Ju5ClQs;|+cYZaw!H RS2X|t002ovPDHLkV1hP2tWN*{ diff --git a/tools/layoutlib/bridge/resources/bars/v19/ldrtl-xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-xhdpi/ic_sysbar_back.png deleted file mode 100644 index 633d864829381188283ec39fd3774d3f712abc86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1250 zcmV<81ReW{P)003YJ1ONa4FfOqY00002VoOIv0RM-N z%)bBt010qNS#tmY3labT3lag+-G2N4000McNliru+zS&H6Ej-CK+*sJ1anD5K~#9! z?VCYpTvZf?zkA zT)7ab3pZlbjaIOVg&Hi@iY7BjlQB~#ohET6@4er}n;BCPos@ac%=CP3H;~+%Z_d5< z+;d;RFbu;m48t%C!!QiPFbu;m48t%C!!QiPFbu;m)*P<4|9s)l$|&Sera|TUA`P@6 zAw;GMT_2bmA|Px=vVtk3nkiYlq5m*o}omBJ(x{gpA@eUg=MyH06N zMU^zKC;MnKX=@9Tl_|w%hkjOBB~5Ei549Bb^hrdmkvviR0GUr|uz)4*<82~Dj%D_7 zf`BN!KwU=qk^@$Oo$O+iZCsOLM0E$ z#sCXMj4;R|b(T{L$ZQ;(1gk=YFd?^?+pr}yuMLcMOF2@NXqDLujng|a@Xr*`yBFY z&!0o&h3?XfrZlT@ZAj~I-`01vj;X4mimK_=<^qzszBJ1T=U^uTL=19_YLa@c>+(ph zk_LH`+o=H?_<+OsG{(zVAaE@MMCAD%hfggW54^%&<`L`pil=FyZ1!HC^6wuZKm<&u zc-NRC;sp*;L9FKo9%B)oMfRnB5?N7a=2A?7kTG6lfjsM&W{jEE)h2x)utJCHRhK!aP8CB5tOI0jB|3lR=SL>-reGgURA8CCR-MlZKXuvP_T(ayS!4;f~WfDz7foNxJ& zS*o1txS{2!yGUztYG%_=y_dJxM2(OE3WU@NSJBoF*~FvnW93}9_5|kA{cZ#?o=>@- zBiuv40&@g-90RQDSl~#q`K(2J24lo{PP30E_=JmWVFSYq_Q|`kX@}8V)#P z+{7r`8KS_p_IsuOm4O%AH_BJi8u+)h5PZA4>F{{+9dE2x<|gtF5*;3hFQ+2O`tAEQ zCa@*(lDfrp{DUt0e_t>R!!QiPFbu;m48t%C!!QiPFbu;m45JJD2^x1jZULZWyZ`_I M07*qoM6N<$f?Je8UjP6A diff --git a/tools/layoutlib/bridge/resources/bars/v19/ldrtl-xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/ldrtl-xhdpi/ic_sysbar_recent.png deleted file mode 100644 index 4665e2a6fef938d840c431d45c1affa6096e61ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 552 zcmeAS@N?(olHy`uVBq!ia0vp^3xGI*g9S($=xr1NQcOwS?k)`f+xyS#2l6-zJR*x3 z7`TBl+(L|(?$-SQ3bL1Y`ns~;;b9fg;1FK#_L+f!ai^z?V@SoVx3?Vg4jBlvJ~ZEG z9(d((!GGogxfZR&W!yryR+R+KlH7jnzpj9jh8X|t$(~A#K%)@g!}A;e+Dm5Iytu*7 zHu+?5Th*Fl|8{&l%4(thx9Rf?#&cF#f!wjt>lRJst5xpd_^^#tuj*pzZNBCy{>o*B zt+G2`E?Ra>?#CY+lbK6`KM1{xS(mi>!+Fq5eg{q%I%de*JyUo^L~pn9sZp*mg0iX8EN3E%~xttlu1N zTj(7vclybAtX$)E+Qwd!h=z}{T_>;aHCuS^JBPty=be4kQj;$)obr)*Pr1f#`5SjG z`(0CSWZ;~@uzzog!JoBfcPIsg7_ENj!T76c-uHj6SbhYj%f5R*qtV~ZL-6LqO$R?@ zx#Ydh<^TWV`Tps{bqf8?{p`D(cn`M!i{1`sutf3sz=cGpv{rdA(=zg+C0j zdebvG<(}{AGl^+%4VC0yBDyo{kIb5t#rdy&jq%y{W;-5&-9#{Zr!jv*0;-%j73E#fHQaR1HQnHe2YqT1XC%@UMvaGGgFL~3^J zRcPYK$`{-)VTw|cI?K^R_6{Ph+}hrbvlq0oD5^`CPXGN;=UtJd^OU)!+UjR!=S|Pw zZ~pmhoi%f(i_%076`}ve3w0!$)xwG&MH}PSyx22QSI}dl)j%8N1a@y zl3K+g?N>!iYw#(UA{kdOFR$cShv*yA8Np^b6`pg7HXXR}Zb`N6n>D=qD>r?Y3s>#f zS#j}w-KU6){V4`px!3(T6A+m#m1S(6WBGnzhuP%r$NN5Yvv>QinUiE7{C-uwZGg_r zgrxE-!bxi@&aK$lay6%5Ci|PTX`H(RSx+x`mACiX?%R)+RLjKY?rnZ8-FqhH&a-Us zx$8C@c`d@N@AhALXVPu;y)Pc!{8VwUVedET0}szC<}BUUSUPv^o98;qBa_+={$FBr z@Zjzr+NM@_p73UAGY{MIi?V41Y>43m82Ic2e=uV#hDe{Ku0TbX1s zhvtj@^RiW59Q>?f>rQQne>K%h{Pe*Q)5B)ZD10bx@w*9|J_FN-Xo+h?iE~kEVo7Fx zo&k%&R6z<-5=&C8l0m9c8H@}J4Rs9-bdAhH3{9%y{W;-5;O|TTd6qkch)?r*F&_aTICaf77<9HQhtNWwwdZtYg3aF>nX=bS!Nx zGYeZ}HcgE2KeMaOny0&;Y@N^|9DK;J3{a2^#eUanhnY;JSNUG;P zy6%h(a^t-Jvzdvr!q+e_ymRJ`Ri5-m51V(s z@jrZHzs|gFo2GG3^82jK>sDpkeQ$g0>JK!Tt>t>$DntF>H}qeXKcBPZVF3I7UW1gw zp3na*tSh_aEvL2SvZG>~@6BtU)|T7m?lsQ&)c$5o^(kw;8$sfGpG$s!I`7mm?xeG~ z_Z7zeeKAGcHo{@~Z1Hv4lDB5C?|I;CzvA`2Z(;xT)Er2>zxz?}`l>D3LD5gH$4YNbOA>I8DY*CR8{=e+b5dfzTeh4~__H{p zBvIAatU~8wn$J%@S{2Elvc73!s)1gU!+PoP7n|gC9`I#fXFm2UVPDu@(OV54 zcM9@reAy;?V<#`4fpWld*R%Kj&6#y2dHX|&0}h8cHh=kdT*cs&S5Ga^0v+aW9}`)P z!Xo-QADTT664}33digdxg;d`1F9HT0M_o4T@qGWqa8=M!P?X-<`-{~)t>>*okC_KB zb%~a^MwB=gr6!hS=I1GdWag$a80s4u>l+&WyST0#s6Z8@ASJOR)hZdJDwV;=z|c_F z&_LJ7EX2^%%GlD%*g)67+{(aUy{}a>iiX_$l+3hBbPeWKhNch=7mmyd18R@~*$|wc tR#Ki=l*-_klAn~S;FejGTAp8&U98|7Y+AVWu^CVugQu&X%Q~loCIH(yVyXZD diff --git a/tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/mdpi/ic_sysbar_recent.png deleted file mode 100644 index b07f611ab98c121a12873d2c6a8e2b9b351967fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 591 zcmeAS@N?(olHy`uVBq!ia0vp^0YGfP!2%?8-k8<^DW)WEcNd2L?fqx=19_YU9+AZi z4BSE>%y{W;-5&-9Mh{OH$B>A_Z>Qh&JLDkHy5I3#%aL!b1|N6&K56aR_&~I5PsD@= z{zmEAy)%BUyKTEXJw0vv1QpLoDxO7WBmSk^kp# zc;~?_vqFVU#OAM3R|=O}yhLNsl?4xVDwd=ssO>4w;+b+*SHtOOins7vhX*$#a^E@x z@4g}VBI4s2o0Ltf43A0Z%>2G5No>NJ?4Ck4Z#{vJ;jg~knKL70t|Pn6ln3G7iym!J z=d_SsBC`B$Qu1-z4c)WnRCJ%Mytt&Knfcfx^Jj9h#-}e&u)MRWg?n|@g&7w&@U4$O zvnA)$=dzD_WmX4Tg-=M_xNwy(E3x5UL1f2DkL@p3JNa&~Yx)00eL5&G_8+%CZ=0dn z{<>~GFrYH4pg8DQjn5Zl4_Le#Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS=07??9MLn2Bde0{8v^Kf6`()~Xj@TAnpKdC8`Lf!&sHg;q@=(~U%$M( zT(8_%FTW^V-_X+15@d#vkuFe$ZgFK^Nn(X=Ua>OF1ees}t-3#_`hBq$Z(46Le)Ln;eW^@CE2 z^Gl18f$@>14ATq@JNy=b6armi>O)SYT3dzsUfu(?ejQo=P;*9(P z1?ONh1r6WCw{ApUhpEy^rQO>ryA&s6}2uvI1&7nmAYn7g_fxLTMYeC}dk zG#%Kg6F@zd$)34`Ml?ID?=sPOs~o~9{T?^ z!%=zPhc4-wKT-?BGdK-eZPqz`U$LOUw8!zLD0S#Ub=jo~xqpO^j08f@knw)nkF=1P4M;G)0j#k3v&=2r$4@u~VGvGU6; zotMbxUEz4_T_TsV#{b3b>KSJIM{}h2s-7$C4qN>tHsiD6L-k1NXg?hi>x zHuwC0&9F;S`@)?cBC}UaebQaz{M^puX?(?$U9UPy)vmC8)N9_5xQYj26J zPCECAMe0daMBi;Ywhg_L&R^_~>X@=J{H~z*FVdQ&MBb@04HAA0ssI2 diff --git a/tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/xhdpi/ic_sysbar_back.png deleted file mode 100644 index bd60cd65878a39a6389697084a3843d0ef727f81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1421 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 diff --git a/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_back.png deleted file mode 100644 index 79cfcee70c4b8c451e9df859f47ca72b2fa86057..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2811 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 LXD=tZ13LRpt!e`Z diff --git a/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v19/xxhdpi/ic_sysbar_recent.png deleted file mode 100644 index 6e0b071206d546ff1a5015fab217b68bc398b69c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1517 zcmZuwc{tQ*9Dm2Sk0fD`uo+h)cR5DV5QA}B6lT_}7}qGrIHxi5s8!ojY>rG)Emn?P zQIYAlEopm{ESsB|5Sd&n#|(CMbUgjD-{4$RttJfski)t- z`Uvxq(63603geB+Ll|L_igyW006<1@$6=uO1_A&$f`q|%c}0>F$qA9;H6;#V1>dmanS=Y06OxyI)L&#JMy0B9l z+Z*S@luXP_GTNR&&mjnk4;tw0{4+nx0xAyn@_Q<5(6X|A*GD#632$>`;BZV@D%L>? z4kyaO;S3j_LJPO{h^=>Yqs0!u{lyI#KRwqMlax_7DrqX} za>&S#A%TQ507HZUW56*0^BuO}t`ru6oUys8k(pPNIIe7Ty3=PduWD2>gJ zJ{V&^Y%u2EpV=DFT-P92aAabe^aLep_VY`!m#=R(v3jsY>1iw;z5J4+@`FRX7E}VS zJzu-pqwY*l8@YY@d@R%bFnK7dF?MrTb;%~BZNa+DI7Yx=SYM#-C)w*#Gdi(c-Er@X4`e>WgaA|i0!Re)6|#XevClyK9}_12nOP&FZXV*^ z#*W})#yexz6~;tmmUy`nNc@=ih7DVLbybd5*UmRsUBx}XPs}NzD_E@MHAVD^`IDOn zO|zG01R2vUkSOWwJL7yv+Fgo z;Z)Sx#9zTQmXKTRl_L9KEjWG`W$c2Q%)kP!9y}RzUXZR0hHtGy7*#fG2^nCX54#yP z8rz7AFUjNu66sAwv*b%}jv~{adafD1_Pw7sv8RwJ7$EgChg_je$Bx=}6Y~l9kHil| zY?BX#Hc-kYlS0Kk6leni4Rrbl*We@#_GNGN<0Fw$Z{}x6UDm8(!gY4ow#~fNOp2m- zO6<7iZyJUBjBR0cL+?pllPFC+ke*849VH&RciEpHf%5F#k@1^=f!{_3@UK#T74VacH2?NRIM`be^HJ6Pn4$0) N0<4pVo`JP1Qe%B7HdGnDk&5TqJxxT z85jJp(3Cf;ur;uS`&B8G07x9WMi( z+st?j`kjkT!NR;3CFJqZY)Av5sW>uLLLd^+G#ZXbq0(r?6=)KHNWv4~n}#J)7*raA zV4;=tqMG5|=uO4N_@!VwD7(j4OxZe!!Cc63bv~K(P+e2p}k7vIF?>kPgzu zLuxcTf`<0yi6wHC&9L0ILGSYgK#hDWDCKG(CHh^38S+mkpc3f591ej)r~R2ZKp+MB zaR4?Y&<|Gs9xMHSs)mQf;BD>kKkYJUf_u<5{n-5Q;^XlFRq&b7z=vbWo@ZeQgx$3u zV3k0B=ShKLPh{lmtCi;dzTO%>x?Pjw!_^X^#QX>=KB1p zy}u3L^EJtai5|vQ%W5ks9|fXjKvL^Ak*C4&o0^VPtVdK|HRvjInjnwowsg4D z58!Z$-K96~R@S^|s?a6IklW6tk?&hB4&%-jsoxlHUfljoNxKt&R>@~s4~Kz`1>_iN z^kKm>wF55x-e6g5FYO%rw~>wOG#dV^shbY=W6c5WixvpF0b=4Yhpnc6xY>Cwezbqh z%HW%Kr0vKlnx4^D4-)FKhPMSW#=H_TxpdjYCFD?N!?GR6UGoNZxgF9ke6us+rJcu@ zUSK&hG1Y}xmJ)C>X~Qhm%aN$Sm<+@XWaZ^Ae5N^d-S>_E*EC7`<*urkR}?R`kMKKX z;;@Wy+^Skn%YbPs^?r-$YvJ9y=BZqLUe63zVi;a*st#%{%gK@h&5wyCB)!qx!4vSkGL?yQhX@jfdks1@le? zcXqw;D9ek|qh9u>1V=JAWTt(6U~jW!=4zpjLTff_p(+ z$q&_4mxX@_5zp5b2g#V=ms(nb+AGZ)KkH%!zZelPlj|TiCu# zSTeWqP+3&N;)8V?Hdhq$)^#_!4=xx#nB8hb9$VU__-Fn6;(sr9hO*|pz=n|bZa+4b z(WmWxG;Pa3ubQHgl?nE&Vki*gvltiYaY2nd&zd z?D3j#&i$oj{++n**Z$OD_+{PItaAyB%|DnQHP>JA9ol;KuH`{>InoKSdBol|`(AXL P?QbE76ADxWigx?~yZe$B diff --git a/tools/layoutlib/bridge/resources/bars/v21/hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v21/hdpi/ic_sysbar_back.png deleted file mode 100644 index d2760bb912e2f69192881c4ea8663c686fc4a23f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1524 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 diff --git a/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v21/hdpi/stat_sys_battery_100.png deleted file mode 100644 index f17189a0645d103d8b429b04333720099ab89ec2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19810 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 UJP8mFjS6tIU1XDEy?VpH0N0Mcga7~l diff --git a/tools/layoutlib/bridge/resources/bars/v21/ldrtl-hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v21/ldrtl-hdpi/ic_sysbar_back.png deleted file mode 100644 index 2fcfdde08164d7c2bdbf11e09ed5df501fe48532..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1535 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 diff --git a/tools/layoutlib/bridge/resources/bars/v21/mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v21/mdpi/ic_sysbar_recent.png deleted file mode 100644 index 30c65f51a128882c70c4dcdc52ea310396a535e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 562 zcmV-20?qx2P)g-7lE%*HYzkA!--E%Pv53k4y-vm$H8f}=f#qmgax~8^%cA22u9zAcw0QQw zlgUJHn|i(O9qDej`&U+WEIl@`%TYsv);-cNV8K+w;n3ib%H{Hfv_Kk)?dx1ox*Jy; zFAP{PRW6s)Uk!OW9_>k1^7h^Ch6gVUSTOw&lRQnOQa71Qh7NWY)Y*J_hZYZBhw(pJ zt(N!oC=?0@@p$||1$4Ba#Dmx6z}$-{-?}KCe}mH}`=K!`fdBvi07*qoM6N<$f=;pr ANB{r; diff --git a/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_battery_100.png b/tools/layoutlib/bridge/resources/bars/v21/mdpi/stat_sys_battery_100.png deleted file mode 100644 index 2a9757dea17ee1744110476fb1b94f064eed12d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19396 zcmeHPcT`i^x4x(YNU>u>oKRFm(nDfm2qjbj5eO3OH_1(ikYW<0s0b>EWkf`!34@iU zSWpx}MMOYR5W9jh3W(@{Z$Jk}1b#OZiHI|1&HKHz-dee9QF6}S-#O>o-#%xb`$x7d zT;QmyHB}1$09|J%J5Ttp4*WAtQyu;-%CM4u7%6u0l>&hFc=?YSka%D+0BE`M>GXvQ z{X{a6)K4TvIMe9}u|&k>2S5N2^fcLv$M9;JXxaY!y{$`B*j^Wrr=BLl({@MLgqWFT zh9k$!k1{;?M9<^uSbO^s`emt6!*}fp+o|VauCrb1u|~b&p8tVG*X2VLN^7Z<|YtOJ3BYti!cT#K0KM9FC#1(^w7o z7)qtiF)Gx!45$U&)7AtE-I5A1)3$bxeq)=kR4r_aTA?gvu8U^a1i(6Em+djY+CeQW zIew-WkU9cbS|XHZWoxu(Hh9I0)F108DUb^`ZVT zCwokz8O&6|8ET#h**<)UCUUigj}L0PX@&EoITMKBFfh>?RTP{s1s6^j{af2D07#9| zgIC+u8B{SUyP|@)D|gfi z+duqv`K3uXZdthFh>yP&-FokObXw(}ky}_buc944pV#jGY;e!0*qN2bG@DT8F>duP zyTqMsxT8kfZ1>E*KI3jT=Vh&V$8cJ$1#oH=O>JEaGJP3)_@6Gb#xP}tFWUj2HD7e~ zzNzN$Fu%<&Dg(RUS#>(5&H%!=&U;n^z;Zhi6ys)&RjDQb*rkS>owCt?e|55Xq58C| zKh<2-{=Aa7#nz;_$aaja7AI_)WaaGRn`})ZZ=W(STZz7JZ9pjW@QaKUk3toBUl?U6 z9{mZ_Ou1@W5I%B*O_}C+(C}%L8f!b#c$em+gouxZSDi+T+hKyZ5jDZX$R)ma4}|H8GzgLIkLbJyEpudhvj{pbM(A)($p;uhqUi-WZ1;$iK$6< zBxk2u?j#;;yp!cO`e`(cUWzGvJy`=^9DqTUT(dnr*L-9wyZp4#ah;$IZ&yJwE z6Fr}$A7qTRh+b@a;$W`lNsq1R;|XgL$+tI8bapv<;?TZ(Q~f6SwewHDmR%hCY~S<+ zad&*~mNz-Rj(a`)eV~qRq~7MzD4yw*q{$kSc~b%>pNw}sHs#)qDWwby3Hvs_F=2Fq z$eU@FYqnl5=BC!Z`TJ(>(>FsiGBS^4KF`$lZu2f@L}x7b+K}zwjrXd{702{-=^}>Jkx<{xZR)<)T(7y)k9ee>UQt(2g3xA9$q6zy^w-UbToZ0l zJoEJJC+pXm<;Qm#AX_l9(KIctEp+?y3GZgV zoUMP1;F^bpmilMzkK518a?0|^a(sJxDSkbu_Y$2ihB5g!!Hh_ck)Y?)|u1^ zN(3c`XR6OMoay5B#;qmM(=G4V>|^s>=ed^NzIFT1?S}~#NtW10xW=T$q(@1$=T|Nc zT5O)1o_hguK2yK=m~TsNfiPk*+4m^Zd-1XyhZD&sW<1P4k)Jj;EpI{Wf~=H>ylbca z$i0!9aem6FhR5pF*|~z;4Iqy-iFf{b_O+JSOR*a+Zuq6sQbTv^lTld)iw#1hXC)IT zizv?%D-N_+ZMgn^e-oO=tQ=GM7+;q=zI=8uKiMnko+ED(FHgF;Eo#R$mrdoUI2tNR zzvNljrTY1@5385G2)X+qIVmTps5!m*WDBu{-?Fvl*IR^NXQ%k$rFX8C(SP%3sIt=j zbsxsR_IRi}-94OluF)9HM#uP^cy#Lg(ZI}h@ZBWZpESv@b+kGv={fGX?}}Tb!t-V4 z%iXVuQdUIN(l;7+bGk#itAMny8EU-Y+rn+amkjIp7_#2*$}THPHT371C(SlHQ}b-} zY@#=v*wk?KgrQ&A@4HVJwl~IC#8mJ{MJx<`{qT+k_zK){EmUV##MTI(NUL4qDCX2E zY@9`4RSjKQYxl`+zuogB9@d?F5;@<(jFyR7MSV)TNVsTKg5vt#dcaI(ItRE+Bcsf+ ziNb)(wV#{Yw!Tb$sa>~jQarkBnK<}hMbZ0+w22w0apsi$)~->lbKt{p5J2%EP_q0+Nx6jGyeDS&YTHahx7b|X8{RAK+VbO2#F?(^!X4+))AwoI@Xy(O{3llsE9YkQZqk8wzjil|D;oD=Pwvr37aybn z^VOx}tH@`ltAnex>hyk^6S+wJIQ7EzTr(lhMZO@)iJt$lc#5OYZsku{_v-LH9GFLX?6bQTzcN&E7S`GP}+@( z+w-g#M;PxJpBTiJyU)&nk3I^kTJ+Zy{7LxzLG_Y?_D}{D%ANO|%mYrB2SlwJY{O<5h4dYR{kMiz6Ft}^U@Qi*q=dI(Y(w{GPCBF+q>JoLm ze>qU{(pYR4T;J3_vbKG?F6HUko$HRj(75;WS_7T|dX;TrYobGvS7OH!){=|vw`f%l z-#icb>{$Kt=mP|*Z}9v!#tr_{rcL)^d99T@llLWW2u1x>v$Fb7?z%>HMeVB5qIVa^ z$X?vF@7~ckuV7xq($)*I)-%-&<9#mpB%Y+K5WJDSp?1aIb1%(5ke`^Hx70tcCFIh% zb=>wQ{S;Egv-g*R|CreQ@IeaM^4X=f5K;T}_7AlapM^?hbyk$;KM9=Ga-zV!V8wgu zW}7GUXImdwE$OOx{H|u>s=~n3wyGM(cJ+wOm0d9(qDRwzicW|wkJOEPn=+S1Ccm_j zbT)lXqgQe&XQoW*I@DF3J!v93^y7oKk1DF-s}9Ds#>HL{tUucMrts~Qlhq|fCDSk8 z2*P8RzhBhRd^NBp(BR$S+R^Uy>k%7GyZ!z;{lV)_T1V`Z*x2q7!{ggNv+>Ak0I>dr z&tS@!ZmtxzNPq%4A{K-S5{ThK6ac7JL1K{Y56KWLh{qRN8okTEVuavxERB3D+%Rrp zI^@T93XwowAqyDn5PvqAV`N3sq6Sf500ATe5kZ0gp_CG2Y1D&Df&Z5`qm2+fCNh6Z zBOCdE2&UUY1YIP75Edv4BpZXnB1mKu)`CFBV$Bga3>J^ZV$e7;5{sn}NE9p)(f1h9 zwBY}!5)PN*Y3I;49Q?`B$WJB{Q_$$Zz(7&4rUP@1d7pE6b3z% zleoW#AKLXx_jds}>@S|;HIjgywQ<;JC;$>bLYWly!wxwx91}OUFRnw*S0EVDQ!2Ax z3scZX>5!gMMz9z{dqPst8VMV+UklH~c&OD&WuDMLbbbH|HXjm5#^-(qN8a;Y@}MC8 zciiMXy>304>J2p&CXGUuK%h({VTeQlv|hOmT*Tmen5i4c<_qN)v)NSiVEX~p3_wA4 zpbVnHswN;YbCFma152b}2owVRkwn2@6hL|{2VuCu8N>l);7}+Q6g*K84Mnuqj)@30Gdudp4IbFc+@U$^#m1n_Ba$WR+2`kd^cgv-6*c7fvA^>GHz5wJwXt9t-MGrI%%v!ES zH#ds2P$~mq-kj}vXyC&%Kv*sb#BvEp5{ryQ5?DAqJad8t(t^waS$HaGgk?7a% z-$3`zvkzL%FqehJu~>77NCGsMge0(8EF_D=!68{776Wm}L_7q+4EN4V!TlR(cL^Up zjlci}n||Jv8Da>SZ-#Q>%Ow^3b-a5d}@u4rl0zb$?_XnHl% zr<|VMl>)NmCk~A*-)kTa75!D~z_h-2QhN>f-v;o(*Opainv!KwO>+h{N3*FJ->hfbgWl_*HTwf`;#Br+RM!jp(dIAzH2UP2@z=W_8_ zqy>I17RQB1aQ;L6F;)oS;3dizqrmQUV57)|pBz$E=sxZqhG$H<YcBTy8aXT+oQ3s zsIcpmrh`18xx2iN%&1 z-_|6(qYMEvFj_zJ3Ir>ZAXNFqhXNNh@B!PigVEqJ`kOWdw4Oeuyf_J1(^Gtqa2WW3 zuiEg_=c?E}*wy#%T@||ryAF7I3;8k{u5YwK%?e)f+ga~D!wY^R0m+v(xM{HULVgew zz_jDTcLS-sw8Fxp^!NR;f!xmr@KU zWvo({iY}!XP|8@PE)`u$F`$&ON?j_tlwv?BW0ks8bScGvQpPHEspwLQ0i}#p>Qd3A z6az{btJI~UODP7FGFGWeMVC?xC}pftmx?Z>7*NVsr7jg+N-?06u}WPkx|Cu-DPxto zRCFoDfKtXPb*bo5iUFmJRq9gFr4$278LQN#qDv_TlrsKXb!iQJ#{eXRzgQp;{sw^r zJq#26_5lRj$fX4hBjy9k!`5Ch;ebn7k#Lyd<3$l=o0>!4h368EICuD#-VZO| z?KOUb`Y`0gjF3B#CIYioecGz1^`A)TUG(6iYyd3QA9fKjZWufQ;B3FZF57nHrvCsd CnnGUy diff --git a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/ic_sysbar_back.png deleted file mode 100644 index a3562850ef9cc2fa3f7980caab56bea181c75b20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2109 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 diff --git a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/ic_sysbar_home.png deleted file mode 100644 index ba2d0b2642cec7ab389c795cfe5ead07076127e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2617 zcmV-93dZ$`P) zdrVZ>8Nc_=48t1+8DIciS9S%(#o`uXW1v3PUD9eAH(-3F)mWoz*4n0tv5B?SE!osZ zj5a=_ZmU^KOJiCaWu;WB-CDI)sE=9!5qZc%U_cb#PJh2U-6CN7Mcv$L-sF zeG=%KLhs_++YcW;e7&Qi!`9y3ZUt-W?(Y7=Lp|3xbLLEd$<3QLb*fAKhKiH0`67V$ z6u(b_YCxT!d!W0ZZcr_#98`?8KfHJEUYc4@UN8?`{cdPzcz&r>S67=)Fb+r!Oy2N^Y_M$ z8x2V82l!Sc8#aOJ1xP)pRY2Sn>J;D&GN%r7UH+@*A))#RkOscy;ZL19^>mQ5mFw59 zYg`C$bOPWMWEk+&mZ9spJQFEsJm4p zS}Q(AMqP%SnfNYg%ATU$NYEmKzVp74vW3$;3@qAT;@Gic--o0sXuHDen!HzFuaU~$0o05b{Q^|)qSkH!NA+|dJRD!MX3cw;5+52G zni!9fk&)pVI&^5b%jF8e_h1shh9oB^hmRaN(v_H)$hicZuz2y}uR$xnqm2qrg6zaz z$FE+!8bfb}dFZ~rs)jnW9XodLqiG9J--jZ(I zm11jL+y)gK!<=+Xbwh03_Ggq4o$oV;3!2 zGzJcGTAYW1@WQ@-Yc;d{{CrJ=L{tjW%F4>ch%O`uEP`; z)Dn(iz{p<~pE-hqgN-Ruri9`(3?b`7iHS6+P6*|*Y15{KDk%okyKmnWlI*BY~H-t=C|>I8T01NBS12AOq@7z2qH(Bc(fV38yg$*0%}&V52DTm z`as-+Z5$pmW=sMBu3Wit;Lyo{Ml^&H26h9s&$6wXl@OkH;3)Y5(9UYY1cKC9Ybxxi|r^2BL?f55Ox_aW8=Q(~C{QJC4$Ih0r5@%dW;?&)R788&PfYfO7-X{q1# zSFc{pplQ2!@!|)PcFa@>en86Sx17z-9GcwumPd3oCW`SVq+r>|PIDhLugY|)w* z!eI8YAp`}Pi%?8*A@g3)(xpq&vEY)WSm;8y`H?bMvDFs_xPAL}ZSUT_8d9iDoMQ&G z)ov{oii?ZiAr=I4J3ZYTIXO8xN_cufRDFH@MoVsN#_28ht6t8U%-pu53j2nmfTqLh%+8g~B#93ot$%LZ+RmOQM4Z4;oPEbny9yQmgQ6gETK}+O&x+ zg=_5CvDBb}PVkHE1=X(kaJ${i!EShU7F$h`q_uG;=)VK#_pm`0B;dw88>Pg)R%|R1 zlnF^L#9W4wcI6Pli~0V-u3fwG=osh}xu^Y0GZxxIO$t*xY=J#U-0a!2vqarq@oMYU z$88A@$3ew--wxV=_g~{#CaJ5(_rH4@UNANCz&O(;GfNQs47T?i?Z4%>nL0h&5S zQ6TN41I>6eZwGLy6r{wDA&o1dqP~|$ZDLnFLfs;0#Jz0UIx1NgkmDd}Bot7ZnwifZ!a55ec&i!FRjxdS%1l zy$qfXY#t1t;Uh+jaDm(a5|17_4&>&|7Gi2RB*?hoko%ce3aszwb&Ca}WE?_v?a5oO b7aIQs=I2?E`_1=O00000NkvXXu0mjf-}m`p diff --git a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/ic_sysbar_recent.png deleted file mode 100644 index 94a74b189abfd443899527762ab8994320465630..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 733 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 C?#)dA diff --git a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.xml b/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.xml deleted file mode 100644 index 0498b6cedbb85..0000000000000 --- a/tools/layoutlib/bridge/resources/bars/v21/xhdpi/stat_sys_wifi_signal_4_fully.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/tools/layoutlib/bridge/resources/bars/v21/xxhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/v21/xxhdpi/ic_sysbar_back.png deleted file mode 100644 index 29da099f6d82585796c7ae912cd8e1713bf29190..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1279 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 L`njxgN@xNAT9zU! diff --git a/tools/layoutlib/bridge/resources/bars/v9/mdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/v9/mdpi/stat_sys_wifi_signal_4_fully.png deleted file mode 100644 index 19165ab40ea0f9a5c7a6ef9a382b57f7d2bd9f83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3922 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 DL>xig diff --git a/tools/layoutlib/bridge/resources/icons/shadow-bl.png b/tools/layoutlib/bridge/resources/icons/shadow-bl.png deleted file mode 100644 index ee7dbe84600b02a48d363492510414743d60524b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 397 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VTavfC3&S)JbpJm44^V`&z$3Dl zfq`2Xgc%uT&5-~KvX^-Jy0YJ4m*=C^ zUBskinns^fCNFb%@z9C!VQ!KQv-$(}9Sq?Q*zTCdHQGN2f1Wyf{*8RyjT!w2&HE%)H-^6bE}j(6IngP8 z!XvR;CdUuAImC+ux|TJH%$0rS7*$U7vX^Vf&+@Tj jvz(>Q{?F;5^f&%BigCFqoqmge{$}uW^>bP0l+XkK#q*AD diff --git a/tools/layoutlib/bridge/resources/icons/shadow-br.png b/tools/layoutlib/bridge/resources/icons/shadow-br.png deleted file mode 100644 index c45ad77f8d1e40978076e5b320739598c96c122f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VTavfC3&S)JbpJm44^V`&z$3Dl zfq`2Xgc%uT&5-~KvX^-Jy0YJ4m*=+-5zRg{4Jf2k;u=xnoS&PUnpeW$T$GwvlA5AW zo>`Ki;O^-gppc)Zkf`9BnB2ai+!?6)tEY=&h{fr(Q(p5m8*sSwUsk^_oPDO}YTP$= zahF%Bk;02i-!eXFW~*R!jbsW_V31E>VOuc$Ifu^yo#&JG{hu^FSM<0+`kue}rOzg@ zuZ*)}j>=f)68(;0vek^#^}5!4evPY{drnRI6~`>j%fmL~=*dO%E_Pn~yMM07VW!0g z(h7HIbgD4hGPo~S@KkVIF#B23(gf=V2|*VE^|&PFe7Va}?S8}R?b_@nFYD`En_XX& zdIgDo?+W&DJr QAE=eV)78&qol`;+0Kn}dod5s; diff --git a/tools/layoutlib/bridge/resources/icons/shadow-r.png b/tools/layoutlib/bridge/resources/icons/shadow-r.png deleted file mode 100644 index 4af7a333055516371a9146a3a507cbbef2ddb076..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^B0$W@!3HGnP3ltxQfx`y?k)_|K+ygB>_0#e&H|6f zVg?3oVGw3ym^DWND9B#o>FdgVhh3iEf`Nad*lVDWQi*FsiF1B#Zfaf$gL6@8Vo7R> zLV0FMhJw4NZ-7F6ou-ZpGEc)t>pjIL6c=oiv-*L^~3v z9_XW1Qx_3Rw}ZkBt?$ ztsH7(#%6T7?f9+!)yD{^tH!?*dPoZt7&^>OiS9eLfYL2AjhunC4XWEf56#Z?w1+FW bzYoAKVPOJPgfoj300000NkvXXu0mjf?@n(p diff --git a/tools/layoutlib/bridge/resources/icons/shadow-tr.png b/tools/layoutlib/bridge/resources/icons/shadow-tr.png deleted file mode 100644 index 1fd0c77269c0ec88bee1697f30fd6446c8d66f08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 397 zcmeAS@N?(olHy`uVBq!ia0vp^B0wz6!3HEJ^yqE{Qfx`y?k)_|K+ygB>_0#e&H|6f zVg?3oVGw3ym^DWND9B#o>FdgVhh3iET%J{t{UT6Esl+v+#5q4VH#M(>!MP|ku_QG` zp**uBL&4qCH$WjjPa#pkH!-<=MY%Ij^&3wY#}JFtYp1;BI%L4(ntzSQRj~HIdg(3x z|4WL*Z|8NjUdZb??0Jdx$7i8#+tqJa{p=l1aY*bl(2h=!W$;dazPVxr(+u+jR)=N9 zl8&MW5*bdGkCiCxvX<>&kwILtey4l3A?xAy7y*GbEzKIX^cyHLnE7WngeFN=+apRGQ>C*EosiJrpT3 dXcpYFfLVTZC0kxyyWu5}S)Q(bF6*2UngAD7FTnr+ diff --git a/tools/layoutlib/bridge/resources/icons/shadow2-bl.png b/tools/layoutlib/bridge/resources/icons/shadow2-bl.png deleted file mode 100644 index 76124877759e6e64b8b1d2145c30d282238b126e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 277 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4u_bxCy8vk*`02d69!PN(ctjR6 zFmMZlFeAgPITAoY_7YEDSN1y`@*>7Uz4uc!fI_mFArU3c`MJ5Nc_lzD1A}u>YGO%h zib8p2Nrr;Er*A-tUMf3KywcOfF+}2W>4lAaha7mAFHFD3dF&j|pa1+$jZWO&U4G#m zDXv8_)?Nw*4>|re~s)F`6gEVGn^7t51Z8UcBs@J2>9f7(_87%-$u^s zv;2w-%>BNXXm^-ZosFnGbY+LT$)Sw6t%;9azR!9wt&F)|Y~NSL^PgoM?K`9|fL!P4 L>gTe~DWM4fh>==w diff --git a/tools/layoutlib/bridge/resources/icons/shadow2-br.png b/tools/layoutlib/bridge/resources/icons/shadow2-br.png deleted file mode 100644 index 8e20252cbf646601903744cdab6ec51bd03d7753..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 282 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4u_bxCy8vk*`02d69!PN(ctjR6 zFmMZlFeAgPITAoY_7YEDSN1y`@*;-jU*2AR3lx&g42dXl&d<$F%_{+N85o?4QWHy3 zQxwWGOEMJPJ$(aG^itV@;&q-bjv*44b1(REA2JYVd8mGC^8Z`+UoDi={n5BJcaM*^ zjvmj=mh!f{B6AEM_cGe*S+?)dZ+AHDcXi#atBr=UlGd$V=>3Q5-p51B8_hTHTd?kW zC|M!B`1Au)&g2K~zvMsMI%BM!nIp7NY|b_BE%*019W4AV{C3-IBh^pr|5oaYzI6US SKVR1aYGO%h zib8p2Nrr;Er*A-tUMf3KT*cGHF@)o~?g>R91_cg=4L?ivWnI*mcqlUBj?;ob51E{p aJwN{~uI6M8ILo#kWRRz;pUXO@geCwhC^1R^ diff --git a/tools/layoutlib/bridge/resources/icons/shadow2-tl.png b/tools/layoutlib/bridge/resources/icons/shadow2-tl.png deleted file mode 100644 index a8045ed379e02a95113c0430bcf2c07a837e23d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2855 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 Vw8XAiZfyfO)6><@Wt~$(698|BVu1hv diff --git a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java b/tools/layoutlib/bridge/src/android/animation/AnimationThread.java deleted file mode 100644 index ce2aec790119e..0000000000000 --- a/tools/layoutlib/bridge/src/android/animation/AnimationThread.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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. - *

- * 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}. - *

- * Classes should implement {@link #preAnimation()} and {@link #postAnimation()}. - *

- * 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 { - 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 mQueue = new PriorityQueue(); - 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(); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java b/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java deleted file mode 100644 index 28a489ad6ed7a..0000000000000 --- a/tools/layoutlib/bridge/src/android/animation/PropertyValuesHolder_Delegate.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * 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 ID_TO_METHOD = new HashMap(); - private static final Map METHOD_NAME_TO_ID = new HashMap(); - 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java b/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java deleted file mode 100644 index f7654ce231b2a..0000000000000 --- a/tools/layoutlib/bridge/src/android/app/Fragment_Delegate.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/app/SystemServiceRegistry_Accessor.java b/tools/layoutlib/bridge/src/android/app/SystemServiceRegistry_Accessor.java deleted file mode 100644 index 591aee07aa3f7..0000000000000 --- a/tools/layoutlib/bridge/src/android/app/SystemServiceRegistry_Accessor.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java deleted file mode 100644 index b4d5288bc9257..0000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/AssetManager_Delegate.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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} - *

- * 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 getAssignedPackageIdentifiers(AssetManager manager) { - return new SparseArray<>(); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java b/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java deleted file mode 100644 index 2691e5640ff02..0000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeAssetManager.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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()}. - *

- * They will end up using our bridge asset manager. - *

- * {@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() { - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java deleted file mode 100644 index b5996afd7985f..0000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * 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. - *

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 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(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 index. - * - * @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 index. - * - * @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 index. - * - * @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 index. - * - * @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 index. - * - * @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 index. 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 index. - * - * @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 index. 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 index 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 index 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 index. - * - * @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 - * index. 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, not 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/, @+id/ and @android:id/ - // 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 index. 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 index. - * @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 index. - * 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 index. - * - * @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 index. - * - * @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 index - * 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 ""; - } - - /** - * 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 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/ComplexColor_Accessor.java b/tools/layoutlib/bridge/src/android/content/res/ComplexColor_Accessor.java deleted file mode 100644 index 09c0260196cfa..0000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/ComplexColor_Accessor.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.content.res; - -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.res.Resources.Theme; -import android.util.AttributeSet; - -import java.io.IOException; - -/** - * Class that provides access to the {@link GradientColor#createFromXmlInner(Resources, - * XmlPullParser, AttributeSet, Theme)} and {@link ColorStateList#createFromXmlInner(Resources, - * XmlPullParser, AttributeSet, Theme)} methods - */ -public class ComplexColor_Accessor { - public static GradientColor createGradientColorFromXmlInner(@NonNull Resources r, - @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme) - throws IOException, XmlPullParserException { - return GradientColor.createFromXmlInner(r, parser, attrs, theme); - } - - public static ColorStateList createColorStateListFromXmlInner(@NonNull Resources r, - @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Theme theme) - throws IOException, XmlPullParserException { - return ColorStateList.createFromXmlInner(r, parser, attrs, theme); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java deleted file mode 100644 index c20ee12ee30c5..0000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/Resources_Delegate.java +++ /dev/null @@ -1,1025 +0,0 @@ -/* - * 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 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 getResourceInfo(Resources resources, int id, - boolean[] platformResFlag_out) { - // first get the String related to this id in the framework - Pair 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 getResourceValue(Resources resources, int id, - boolean[] platformResFlag_out) { - Pair 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 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 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 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 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 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[] fillValues(Resources resources, ArrayResourceValue resValue, - T[] values) { - int i = 0; - for (Iterator 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 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. - *

- * 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. - *

- * - * @throws NotFoundException if no resource if found - */ - @Nullable - private static ResourceValue getArrayResourceValue(Resources resources, int id) - throws NotFoundException { - Pair 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java deleted file mode 100644 index f1e8fc21ce0e2..0000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(Resources_Theme_Delegate.class); - - public static DelegateManager 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()); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java deleted file mode 100644 index faa8852b494ea..0000000000000 --- a/tools/layoutlib/bridge/src/android/content/res/TypedArray_Delegate.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java deleted file mode 100644 index cc71053fced68..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BaseCanvas_Delegate.java +++ /dev/null @@ -1,762 +0,0 @@ -/* - * 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 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. - *

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)}. - *

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. - *

- * 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 saveCount - * @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); - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java b/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java deleted file mode 100644 index c6827a3c9c5f4..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BidiRenderer.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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 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(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. - *

- * 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. - *

- * This method can also be used to measure the width of the text without actually drawing it. - *

- * @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 getScriptRuns(char[] text, int start, int limit, - boolean isRtl, List fonts) { - LinkedList scriptRuns = new LinkedList(); - - int count = limit - start; - UScriptRun uScriptRun = new UScriptRun(text, start, count); - while (uScriptRun.next()) { - int scriptStart = uScriptRun.getScriptStart(); - int scriptLimit = uScriptRun.getScriptLimit(); - ScriptRun run = new ScriptRun(scriptStart, scriptLimit, isRtl); - run.scriptCode = uScriptRun.getScriptCode(); - setScriptFont(text, run, fonts); - 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 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; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java deleted file mode 100644 index 8bd2a7acafdc7..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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 = 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()); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java deleted file mode 100644 index 4914a48f20cdf..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapShader_Delegate.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java deleted file mode 100644 index 0064537943ab5..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ /dev/null @@ -1,736 +0,0 @@ -/* - * 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 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 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 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 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), 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 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 getPremultipliedBitmapCreateFlags(boolean isMutable) { - Set createFlags = EnumSet.of(BitmapCreateFlags.PREMULTIPLIED); - if (isMutable) { - createFlags.add(BitmapCreateFlags.MUTABLE); - } - return createFlags; - } - - /** - * Creates and returns a copy of a given BufferedImage. - *

- * 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; - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BlendComposite.java b/tools/layoutlib/bridge/src/android/graphics/BlendComposite.java deleted file mode 100644 index 5cc964aee722c..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BlendComposite.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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; - } - }; - } - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java deleted file mode 100644 index d2569c777527f..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/BlurMaskFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java deleted file mode 100644 index 47216eec03bdc..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ /dev/null @@ -1,484 +0,0 @@ -/* - * 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(); - } -} - diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java deleted file mode 100644 index cb013b60a06cc..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java deleted file mode 100644 index 67394847fa444..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java deleted file mode 100644 index bc3df7d848945..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/ComposePathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java deleted file mode 100644 index ab37968a1dea4..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/ComposeShader_Delegate.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java deleted file mode 100644 index 73745c3b0c002..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/CornerPathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java deleted file mode 100644 index 881afded11589..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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; - } -} - diff --git a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java deleted file mode 100644 index 46109f3018e1a..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/DiscretePathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java deleted file mode 100644 index 2e1074080bded..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/DrawFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java deleted file mode 100644 index e5040ccc4b1ef..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/EmbossMaskFilter_Delegate.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java deleted file mode 100644 index d8e049a990ed2..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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 sCache = - new LinkedHashMap(CACHE_SIZE) { - @Override - protected boolean removeEldestEntry(Map.Entry 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 sManager = - new DelegateManager(FontFamily_Delegate.class); - - // ---- delegate helper data ---- - private static String sFontLocation; - private static final List sPostInitDelegate = new - ArrayList(); - private static Set SDK_FONTS; - - - // ---- delegate data ---- - private List mFonts = new ArrayList(); - - /** - * The variant of the Font Family - compact or elegant. - *

- * 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 mPostInitRunnables = new ArrayList(); - /** @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 allFontsList = new HashSet(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}. - *

- * {@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; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java deleted file mode 100644 index 64410e4c6a053..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Gradient_Delegate.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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. - * pos 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); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java deleted file mode 100644 index 0dd9703503139..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java deleted file mode 100644 index cd4393abdf855..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * 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); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java deleted file mode 100644 index e726c5982be29..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/MaskFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java deleted file mode 100644 index 354f9191bedac..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java +++ /dev/null @@ -1,1077 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(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 - *

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 - *

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. - *

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; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java deleted file mode 100644 index 1f0eb3bab55b1..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(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> sChunkCache = - new HashMap>(); - - // ---- 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(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 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(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; - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java deleted file mode 100644 index fa20746e4495b..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/PaintFlagsDrawFilter_Delegate.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java deleted file mode 100644 index 60e5cd99854a8..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(Paint_Delegate.class); - private static long sFinalizer = -1; - - // ---- delegate helper data ---- - - // This list can contain null elements. - private List 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 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 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 infoList = new ArrayList(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; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java deleted file mode 100644 index fd9ba62e2695d..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/PathDashPathEffect_Delegate.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java deleted file mode 100644 index 000481ec7cc91..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(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 ---- - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java deleted file mode 100644 index 7f707c9aa01a8..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/PathMeasure_Delegate.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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} - *

- * 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. - *

- * 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 sManager = - new DelegateManager(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; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java deleted file mode 100644 index 50b9165323197..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java +++ /dev/null @@ -1,896 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(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 points = new ArrayList(); - 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; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java deleted file mode 100644 index ff3f19f3f7429..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java deleted file mode 100644 index b5ba46830a252..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * 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(); - } - - } - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java deleted file mode 100644 index edb7025b7cd73..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java +++ /dev/null @@ -1,483 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(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), 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 ---- - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/RoundRectangle.java b/tools/layoutlib/bridge/src/android/graphics/RoundRectangle.java deleted file mode 100644 index 736f03ec5a8c6..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/RoundRectangle.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * 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 close = EnumSet.of(Zone.CLOSE_OUTSIDE, Zone.CLOSE_INSIDE); - private final EnumSet 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]; - } - }; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java deleted file mode 100644 index 5b750899392c2..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(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(); - } - -} diff --git a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java deleted file mode 100644 index 6d2e9b41cc194..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/SumPathEffect_Delegate.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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 ---- -} diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java deleted file mode 100644 index 30152bc6b0008..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * 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(); - } - - } - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java deleted file mode 100644 index ce669cba9c473..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java deleted file mode 100644 index a04a32425fde5..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * 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 sManager = - new DelegateManager(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 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 fonts = new ArrayList(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 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 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java deleted file mode 100644 index ad2c5647eef27..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * 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} - *

- * 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 sAnimatorSets = new - DelegateManager<>(AnimatorSetHolder.class); - private static DelegateManager 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 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 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 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 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 the type of the property - */ - private static class PropertySetter { - final Consumer mValueSetter; - private PropertyValuesHolder mValues; - - private PropertySetter(@NonNull Consumer 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 { - private IntPropertySetter(Consumer valueSetter) { - super(valueSetter); - } - - private static PropertySetter of(Consumer 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 { - private FloatPropertySetter(Consumer valueSetter) { - super(valueSetter); - } - - private static PropertySetter of(Consumer valueSetter, float... values) { - PropertySetter setter = new FloatPropertySetter(valueSetter); - setter.setValues(values); - - return setter; - } - - public void setFloatValue(Float value) { - mValueSetter.accept(value); - } - - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java deleted file mode 100644 index fc848d9af956b..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/GradientDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/GradientDrawable_Delegate.java deleted file mode 100644 index a3ad2aac7d3df..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/drawable/GradientDrawable_Delegate.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java deleted file mode 100644 index 616784c10aaea..0000000000000 --- a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java +++ /dev/null @@ -1,1262 +0,0 @@ -/* - * 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} - *

- * 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 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: - *

    - *
  1. Serves as base class to store all the delegates in one {@link DelegateManager} - *
  2. Provides setName for all the classes. {@link VPathRenderer_Delegate} does actually - * not need it - *
- */ - abstract static class VNativeObject { - long mNativePtr = 0; - - @NonNull - static 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 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 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 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 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 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(); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/os/HandlerThread_Delegate.java b/tools/layoutlib/bridge/src/android/os/HandlerThread_Delegate.java deleted file mode 100644 index afbe97c06ebb5..0000000000000 --- a/tools/layoutlib/bridge/src/android/os/HandlerThread_Delegate.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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> sThreads = - new HashMap>(); - - public static void cleanUp(BridgeContext context) { - List 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 list = sThreads.get(context); - if (list == null) { - list = new ArrayList(); - 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/os/Handler_Delegate.java b/tools/layoutlib/bridge/src/android/os/Handler_Delegate.java deleted file mode 100644 index 2152c8ad19aee..0000000000000 --- a/tools/layoutlib/bridge/src/android/os/Handler_Delegate.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 sCallbacks = - new ThreadLocal(); - - public static void setCallback(IHandlerCallback callback) { - sCallbacks.set(callback); - } - -} diff --git a/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java b/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java deleted file mode 100644 index 09f3e47d7a146..0000000000000 --- a/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/os/ServiceManager.java b/tools/layoutlib/bridge/src/android/os/ServiceManager.java deleted file mode 100644 index 34c78455f85da..0000000000000 --- a/tools/layoutlib/bridge/src/android/os/ServiceManager.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * 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 null 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 null 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 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); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java deleted file mode 100644 index 9677aaf5d07aa..0000000000000 --- a/tools/layoutlib/bridge/src/android/os/SystemClock_Delegate.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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. - * Note: 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/os/SystemProperties_Delegate.java b/tools/layoutlib/bridge/src/android/os/SystemProperties_Delegate.java deleted file mode 100644 index d299add05eabb..0000000000000 --- a/tools/layoutlib/bridge/src/android/os/SystemProperties_Delegate.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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 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 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 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 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 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. - } -} diff --git a/tools/layoutlib/bridge/src/android/preference/BridgePreferenceInflater.java b/tools/layoutlib/bridge/src/android/preference/BridgePreferenceInflater.java deleted file mode 100644 index aa393a976d12c..0000000000000 --- a/tools/layoutlib/bridge/src/android/preference/BridgePreferenceInflater.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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; - } -} diff --git a/tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java b/tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java deleted file mode 100644 index 2e44a7770aae6..0000000000000 --- a/tools/layoutlib/bridge/src/android/preference/Preference_Delegate.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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} - *

- * 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java deleted file mode 100644 index 38171dc067955..0000000000000 --- a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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(); - } -} diff --git a/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java b/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java deleted file mode 100644 index 50289e9fb447c..0000000000000 --- a/tools/layoutlib/bridge/src/android/text/GreedyLineBreaker.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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 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 mBreaksList = new ArrayList(); - List mWidthsList = new ArrayList(); - List mFlagsList = new ArrayList(); - - public void copyTo(LineBreaks lineBreaks) { - if (lineBreaks.breaks.length != mBreaksList.size()) { - lineBreaks.breaks = new int[mBreaksList.size()]; - lineBreaks.widths = new float[mWidthsList.size()]; - lineBreaks.flags = new int[mFlagsList.size()]; - } - - int i = 0; - for (int b : mBreaksList) { - lineBreaks.breaks[i] = b; - i++; - } - i = 0; - for (float b : mWidthsList) { - lineBreaks.widths[i] = b; - i++; - } - i = 0; - for (boolean b : mFlagsList) { - lineBreaks.flags[i] = b ? TAB_MASK : 0; - i++; - } - - mBreaksList = null; - mWidthsList = null; - mFlagsList = null; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java b/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java deleted file mode 100644 index 499e58a5d4e54..0000000000000 --- a/tools/layoutlib/bridge/src/android/text/Hyphenator_Delegate.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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} - *

- * 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 sDelegateManager = new - DelegateManager(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()); - } -} diff --git a/tools/layoutlib/bridge/src/android/text/LineBreaker.java b/tools/layoutlib/bridge/src/android/text/LineBreaker.java deleted file mode 100644 index 06e9c845c2f6a..0000000000000 --- a/tools/layoutlib/bridge/src/android/text/LineBreaker.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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 mPrimitives; - protected final @NonNull LineWidth mLineWidth; - protected final @NonNull TabStops mTabStops; - - public LineBreaker(@NonNull List primitives, @NonNull LineWidth lineWidth, - @NonNull TabStops tabStops) { - mPrimitives = Collections.unmodifiableList(primitives); - mLineWidth = lineWidth; - mTabStops = tabStops; - } - - public abstract void computeBreaks(@NonNull LineBreaks breakInfo); -} diff --git a/tools/layoutlib/bridge/src/android/text/LineWidth.java b/tools/layoutlib/bridge/src/android/text/LineWidth.java deleted file mode 100644 index 2ea886df88a45..0000000000000 --- a/tools/layoutlib/bridge/src/android/text/LineWidth.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.text; - -// Based on the native implementation of LineWidth in -// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260 -public class LineWidth { - private final float mFirstWidth; - private final int mFirstWidthLineCount; - private float mRestWidth; - - public LineWidth(float firstWidth, int firstWidthLineCount, float restWidth) { - mFirstWidth = firstWidth; - mFirstWidthLineCount = firstWidthLineCount; - mRestWidth = restWidth; - } - - public float getLineWidth(int line) { - return (line < mFirstWidthLineCount) ? mFirstWidth : mRestWidth; - } -} diff --git a/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java b/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java deleted file mode 100644 index ed8e33ae3e9ab..0000000000000 --- a/tools/layoutlib/bridge/src/android/text/OptimizingLineBreaker.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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 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 active = new ArrayList(); - 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 it = active.listIterator(); it.hasNext(); - /* incrementing done in loop */) { - int pos = it.next(); - int lines = opt[pos].mPrevCount; - float maxWidth = mLineWidth.getLineWidth(lines); - // we have to compute metrics every time -- - // we can't really pre-compute this stuff and just deal with breaks - // because of the way tab characters work, this makes it computationally - // harder, but this way, we can still optimize while treating tab characters - // correctly - LineMetrics lineMetrics = computeMetrics(pos, i); - if (lineMetrics.mPrintedWidth <= maxWidth) { - float demerits = computeDemerits(maxWidth, lineMetrics.mPrintedWidth, - finalBreak, p.penalty) + opt[pos].mDemerits; - if (bestBreak == null || demerits < bestBreak.mDemerits) { - if (bestBreak == null) { - bestBreak = new Node(pos, opt[pos].mPrevCount + 1, demerits, - lineMetrics.mPrintedWidth, lineMetrics.mHasTabs); - } else { - bestBreak.mPrev = pos; - bestBreak.mPrevCount = opt[pos].mPrevCount + 1; - bestBreak.mDemerits = demerits; - bestBreak.mWidth = lineMetrics.mPrintedWidth; - bestBreak.mHasTabs = lineMetrics.mHasTabs; - } - } - } else { - it.remove(); - } - } - if (p.penalty == -PENALTY_INFINITY) { - active.clear(); - } - if (bestBreak != null) { - opt[i] = bestBreak; - active.add(i); - lastBreak = i; - } - if (active.isEmpty()) { - // we can't give up! - LineMetrics lineMetrics = new LineMetrics(); - int lines = opt[lastBreak].mPrevCount; - float maxWidth = mLineWidth.getLineWidth(lines); - int breakIndex = desperateBreak(lastBreak, numBreaks, maxWidth, lineMetrics); - opt[breakIndex] = new Node(lastBreak, lines + 1, 0 /*doesn't matter*/, - lineMetrics.mWidth, lineMetrics.mHasTabs); - active.add(breakIndex); - lastBreak = breakIndex; - i = breakIndex; // incremented by i++ - } - } - } - - int idx = numBreaks - 1; - int count = opt[idx].mPrevCount; - resize(breakInfo, count); - while (opt[idx].mPrev != -1) { - count--; - assert count >=0; - - breakInfo.breaks[count] = mPrimitives.get(idx).location; - breakInfo.widths[count] = opt[idx].mWidth; - breakInfo.flags [count] = opt[idx].mHasTabs ? TAB_MASK : 0; - idx = opt[idx].mPrev; - } - } - - private static void resize(LineBreaks lineBreaks, int size) { - if (lineBreaks.breaks.length == size) { - return; - } - int[] breaks = new int[size]; - float[] widths = new float[size]; - int[] flags = new int[size]; - - int toCopy = Math.min(size, lineBreaks.breaks.length); - System.arraycopy(lineBreaks.breaks, 0, breaks, 0, toCopy); - System.arraycopy(lineBreaks.widths, 0, widths, 0, toCopy); - System.arraycopy(lineBreaks.flags, 0, flags, 0, toCopy); - - lineBreaks.breaks = breaks; - lineBreaks.widths = widths; - lineBreaks.flags = flags; - } - - @NonNull - private LineMetrics computeMetrics(int start, int end) { - boolean f = false; - float w = 0, pw = 0; - for (int i = start; i < end; i++) { - Primitive p = mPrimitives.get(i); - if (p.type == PrimitiveType.BOX || p.type == PrimitiveType.GLUE) { - w += p.width; - if (p.type == PrimitiveType.BOX) { - pw = w; - } - } else if (p.type == PrimitiveType.VARIABLE) { - w = mTabStops.width(w); - f = true; - } - } - return new LineMetrics(w, pw, f); - } - - private static float computeDemerits(float maxWidth, float width, boolean finalBreak, - float penalty) { - float deviation = finalBreak ? 0 : maxWidth - width; - return (deviation * deviation) + penalty; - } - - /** - * @return the last break position or -1 if failed. - */ - @SuppressWarnings("ConstantConditions") // method too complex to be analyzed. - private int desperateBreak(int start, int limit, float maxWidth, - @NonNull LineMetrics lineMetrics) { - float w = 0, pw = 0; - boolean breakFound = false; - int breakIndex = 0, firstTabIndex = Integer.MAX_VALUE; - for (int i = start; i < limit; i++) { - Primitive p = mPrimitives.get(i); - - if (p.type == PrimitiveType.BOX || p.type == PrimitiveType.GLUE) { - w += p.width; - if (p.type == PrimitiveType.BOX) { - pw = w; - } - } else if (p.type == PrimitiveType.VARIABLE) { - w = mTabStops.width(w); - firstTabIndex = Math.min(firstTabIndex, i); - } - - if (pw > maxWidth && breakFound) { - break; - } - - // must make progress - if (i > start && - (p.type == PrimitiveType.PENALTY || p.type == PrimitiveType.WORD_BREAK)) { - breakFound = true; - breakIndex = i; - } - } - - if (breakFound) { - lineMetrics.mWidth = w; - lineMetrics.mPrintedWidth = pw; - lineMetrics.mHasTabs = (start <= firstTabIndex && firstTabIndex < breakIndex); - return breakIndex; - } else { - return -1; - } - } - - private static class LineMetrics { - /** Actual width of the line. */ - float mWidth; - /** Width of the line minus trailing whitespace. */ - float mPrintedWidth; - boolean mHasTabs; - - public LineMetrics() { - } - - public LineMetrics(float width, float printedWidth, boolean hasTabs) { - mWidth = width; - mPrintedWidth = printedWidth; - mHasTabs = hasTabs; - } - } - - /** - * A struct to store the info about a break. - */ - @SuppressWarnings("SpellCheckingInspection") // For the word struct. - private static class Node { - // -1 for the first node. - int mPrev; - // number of breaks so far. - int mPrevCount; - float mDemerits; - float mWidth; - boolean mHasTabs; - - public Node(int prev, int prevCount, float demerits, float width, boolean hasTabs) { - mPrev = prev; - mPrevCount = prevCount; - mDemerits = demerits; - mWidth = width; - mHasTabs = hasTabs; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/text/Primitive.java b/tools/layoutlib/bridge/src/android/text/Primitive.java deleted file mode 100644 index 37ed072f2ec1d..0000000000000 --- a/tools/layoutlib/bridge/src/android/text/Primitive.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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. - *

- * Currently, it only stores penalty with values 0 or -infinity. - */ - PENALTY, - /** - * For tabs - variable width space. - */ - VARIABLE, - /** - * Possible breakpoints within a word. Think of this as a high cost {@link #PENALTY}. - */ - WORD_BREAK; - - public Primitive getNewPrimitive(int location) { - assert this == VARIABLE; - return new Primitive(this, location, 0f, 0f); - } - - public Primitive getNewPrimitive(int location, float value) { - assert this == BOX || this == GLUE || this == WORD_BREAK; - if (this == BOX || this == GLUE) { - return new Primitive(this, location, value, 0f); - } else { - return new Primitive(this, location, 0f, value); - } - } - - public Primitive getNewPrimitive(int location, float width, float penalty) { - assert this == PENALTY; - return new Primitive(this, location, width, penalty); - } - - // forced non-break, negative infinity is forced break. - public static final float PENALTY_INFINITY = 1e7f; - } -} - diff --git a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java b/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java deleted file mode 100644 index cc031439226b6..0000000000000 --- a/tools/layoutlib/bridge/src/android/text/StaticLayout_Delegate.java +++ /dev/null @@ -1,238 +0,0 @@ -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} - *

- * 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 sBuilderManager = - new DelegateManager(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 breaks = new ArrayList((int) Math.ceil(length / 5d)); - int loc; - it.first(); - while ((loc = it.next()) != BreakIterator.DONE) { - breaks.add(loc); - } - - List 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 computePrimitives(@NonNull char[] text, @NonNull float[] widths, - int length, @NonNull List 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 primitives = new ArrayList(((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; - } -} diff --git a/tools/layoutlib/bridge/src/android/text/TabStops.java b/tools/layoutlib/bridge/src/android/text/TabStops.java deleted file mode 100644 index 6c2f1e1ff00b4..0000000000000 --- a/tools/layoutlib/bridge/src/android/text/TabStops.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.text; - -import android.annotation.Nullable; - -// Based on the native implementation of TabStops in -// frameworks/base/core/jni/android_text_StaticLayout.cpp revision b808260 -public class TabStops { - @Nullable - private int[] mStops; - private final int mTabWidth; - - public TabStops(@Nullable int[] stops, int defaultTabWidth) { - mTabWidth = defaultTabWidth; - mStops = stops; - } - - public float width(float widthSoFar) { - if (mStops != null) { - for (int i : mStops) { - if (i > widthSoFar) { - return i; - } - } - } - // find the next tabStop after widthSoFar. - return (int) ((widthSoFar + mTabWidth) / mTabWidth) * mTabWidth; - } -} diff --git a/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java b/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java deleted file mode 100644 index 1e4f213597e56..0000000000000 --- a/tools/layoutlib/bridge/src/android/text/format/DateFormat_Delegate.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java deleted file mode 100644 index 9fd1e1557537c..0000000000000 --- a/tools/layoutlib/bridge/src/android/util/BridgeXmlPullAttributes.java +++ /dev/null @@ -1,313 +0,0 @@ -/* - * 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> mFrameworkEnumValueSupplier; - private final Function> mProjectEnumValueSupplier; - - // VisibleForTesting - BridgeXmlPullAttributes(@NonNull XmlPullParser parser, @NonNull BridgeContext context, - boolean platformFile, - @NonNull Function> frameworkEnumValueSupplier, - @NonNull Function> 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. 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 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/util/Log_Delegate.java b/tools/layoutlib/bridge/src/android/util/Log_Delegate.java deleted file mode 100644 index 7f432abdda9fc..0000000000000 --- a/tools/layoutlib/bridge/src/android/util/Log_Delegate.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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; - } - -} diff --git a/tools/layoutlib/bridge/src/android/util/LruCache.java b/tools/layoutlib/bridge/src/android/util/LruCache.java deleted file mode 100644 index 520860655abdc..0000000000000 --- a/tools/layoutlib/bridge/src/android/util/LruCache.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * 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. - * - *

If your cached values hold resources that need to be explicitly released, - * override {@link #entryRemoved}. - * - *

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. - * - *

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: - *

   {@code
- *   int cacheSize = 4 * 1024 * 1024; // 4MiB
- *   LruCache bitmapCache = new LruCache(cacheSize) {
- *       protected int sizeOf(String key, Bitmap value) {
- *           return value.getByteCount();
- *       }
- *   }}
- * - *

This class is thread-safe. Perform multiple cache operations atomically by - * synchronizing on the cache:

   {@code
- *   synchronized (cache) {
- *     if (cache.get(key) == null) {
- *         cache.put(key, value);
- *     }
- *   }}
- * - *

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. - * - *

This class appeared in Android 3.1 (Honeycomb MR1); it's available as part - * of Android's - * Support Package for earlier releases. - */ -public class LruCache { - private final LinkedHashMap 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(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 toEvict = null; - for (Map.Entry 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. - * - *

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. - * - *

The method is called without synchronization: other threads may - * access the cache while this method is executing. - * - *

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. - * - *

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 snapshot() { - return new LinkedHashMap(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); - } -} diff --git a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java b/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java deleted file mode 100644 index 7b69388a0b1e9..0000000000000 --- a/tools/layoutlib/bridge/src/android/util/PathParser_Delegate.java +++ /dev/null @@ -1,844 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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} - *

- * 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 sManager = - new DelegateManager(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 list = new ArrayList(); - 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 source. - */ - @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 nodesFrom can morph into nodesTo - */ - 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 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 nodeFrom and - * nodeTo according to the fraction. - * - * @param nodeFrom The start value as a PathDataNode. - * @param nodeTo The end value as a PathDataNode - * @param fraction The fraction to interpolate. - */ - private void interpolatePathDataNode(@NonNull PathDataNode nodeFrom, - @NonNull PathDataNode nodeTo, float fraction) { - for (int i = 0; i < nodeFrom.mParams.length; i++) { - mParams[i] = nodeFrom.mParams[i] * (1 - fraction) - + nodeTo.mParams[i] * fraction; - } - } - - @SuppressWarnings("PointlessArithmeticExpression") - private static void addCommand(@NonNull Path_Delegate path, float[] current, - char previousCmd, char cmd, @NonNull float[] val) { - - int incr = 2; - float currentX = current[0]; - float currentY = current[1]; - float ctrlPointX = current[2]; - float ctrlPointY = current[3]; - float currentSegmentStartX = current[4]; - float currentSegmentStartY = current[5]; - float reflectiveCtrlPointX; - float reflectiveCtrlPointY; - - switch (cmd) { - case 'z': - case 'Z': - path.close(); - // Path is closed here, but we need to move the pen to the - // closed position. So we cache the segment's starting position, - // and restore it here. - currentX = currentSegmentStartX; - currentY = currentSegmentStartY; - ctrlPointX = currentSegmentStartX; - ctrlPointY = currentSegmentStartY; - path.moveTo(currentX, currentY); - break; - case 'm': - case 'M': - case 'l': - case 'L': - case 't': - case 'T': - incr = 2; - break; - case 'h': - case 'H': - case 'v': - case 'V': - incr = 1; - break; - case 'c': - case 'C': - incr = 6; - break; - case 's': - case 'S': - case 'q': - case 'Q': - incr = 4; - break; - case 'a': - case 'A': - incr = 7; - break; - } - - for (int k = 0; k < val.length; k += incr) { - switch (cmd) { - case 'm': // moveto - Start a new sub-path (relative) - currentX += val[k + 0]; - currentY += val[k + 1]; - - if (k > 0) { - // According to the spec, if a moveto is followed by multiple - // pairs of coordinates, the subsequent pairs are treated as - // implicit lineto commands. - path.rLineTo(val[k + 0], val[k + 1]); - } else { - path.rMoveTo(val[k + 0], val[k + 1]); - currentSegmentStartX = currentX; - currentSegmentStartY = currentY; - } - break; - case 'M': // moveto - Start a new sub-path - currentX = val[k + 0]; - currentY = val[k + 1]; - - if (k > 0) { - // According to the spec, if a moveto is followed by multiple - // pairs of coordinates, the subsequent pairs are treated as - // implicit lineto commands. - path.lineTo(val[k + 0], val[k + 1]); - } else { - path.moveTo(val[k + 0], val[k + 1]); - currentSegmentStartX = currentX; - currentSegmentStartY = currentY; - } - break; - case 'l': // lineto - Draw a line from the current point (relative) - path.rLineTo(val[k + 0], val[k + 1]); - currentX += val[k + 0]; - currentY += val[k + 1]; - break; - case 'L': // lineto - Draw a line from the current point - path.lineTo(val[k + 0], val[k + 1]); - currentX = val[k + 0]; - currentY = val[k + 1]; - break; - case 'h': // horizontal lineto - Draws a horizontal line (relative) - path.rLineTo(val[k + 0], 0); - currentX += val[k + 0]; - break; - case 'H': // horizontal lineto - Draws a horizontal line - path.lineTo(val[k + 0], currentY); - currentX = val[k + 0]; - break; - case 'v': // vertical lineto - Draws a vertical line from the current point (r) - path.rLineTo(0, val[k + 0]); - currentY += val[k + 0]; - break; - case 'V': // vertical lineto - Draws a vertical line from the current point - path.lineTo(currentX, val[k + 0]); - currentY = val[k + 0]; - break; - case 'c': // curveto - Draws a cubic Bézier curve (relative) - path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], - val[k + 4], val[k + 5]); - - ctrlPointX = currentX + val[k + 2]; - ctrlPointY = currentY + val[k + 3]; - currentX += val[k + 4]; - currentY += val[k + 5]; - - break; - case 'C': // curveto - Draws a cubic Bézier curve - path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3], - val[k + 4], val[k + 5]); - currentX = val[k + 4]; - currentY = val[k + 5]; - ctrlPointX = val[k + 2]; - ctrlPointY = val[k + 3]; - break; - case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp) - reflectiveCtrlPointX = 0; - reflectiveCtrlPointY = 0; - if (previousCmd == 'c' || previousCmd == 's' - || previousCmd == 'C' || previousCmd == 'S') { - reflectiveCtrlPointX = currentX - ctrlPointX; - reflectiveCtrlPointY = currentY - ctrlPointY; - } - path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1], - val[k + 2], val[k + 3]); - - ctrlPointX = currentX + val[k + 0]; - ctrlPointY = currentY + val[k + 1]; - currentX += val[k + 2]; - currentY += val[k + 3]; - break; - case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp) - reflectiveCtrlPointX = currentX; - reflectiveCtrlPointY = currentY; - if (previousCmd == 'c' || previousCmd == 's' - || previousCmd == 'C' || previousCmd == 'S') { - reflectiveCtrlPointX = 2 * currentX - ctrlPointX; - reflectiveCtrlPointY = 2 * currentY - ctrlPointY; - } - path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = val[k + 0]; - ctrlPointY = val[k + 1]; - currentX = val[k + 2]; - currentY = val[k + 3]; - break; - case 'q': // Draws a quadratic Bézier (relative) - path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = currentX + val[k + 0]; - ctrlPointY = currentY + val[k + 1]; - currentX += val[k + 2]; - currentY += val[k + 3]; - break; - case 'Q': // Draws a quadratic Bézier - path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]); - ctrlPointX = val[k + 0]; - ctrlPointY = val[k + 1]; - currentX = val[k + 2]; - currentY = val[k + 3]; - break; - case 't': // Draws a quadratic Bézier curve(reflective control point)(relative) - reflectiveCtrlPointX = 0; - reflectiveCtrlPointY = 0; - if (previousCmd == 'q' || previousCmd == 't' - || previousCmd == 'Q' || previousCmd == 'T') { - reflectiveCtrlPointX = currentX - ctrlPointX; - reflectiveCtrlPointY = currentY - ctrlPointY; - } - path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1]); - ctrlPointX = currentX + reflectiveCtrlPointX; - ctrlPointY = currentY + reflectiveCtrlPointY; - currentX += val[k + 0]; - currentY += val[k + 1]; - break; - case 'T': // Draws a quadratic Bézier curve (reflective control point) - reflectiveCtrlPointX = currentX; - reflectiveCtrlPointY = currentY; - if (previousCmd == 'q' || previousCmd == 't' - || previousCmd == 'Q' || previousCmd == 'T') { - reflectiveCtrlPointX = 2 * currentX - ctrlPointX; - reflectiveCtrlPointY = 2 * currentY - ctrlPointY; - } - path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY, - val[k + 0], val[k + 1]); - ctrlPointX = reflectiveCtrlPointX; - ctrlPointY = reflectiveCtrlPointY; - currentX = val[k + 0]; - currentY = val[k + 1]; - break; - case 'a': // Draws an elliptical arc - // (rx ry x-axis-rotation large-arc-flag sweep-flag x y) - drawArc(path, - currentX, - currentY, - val[k + 5] + currentX, - val[k + 6] + currentY, - val[k + 0], - val[k + 1], - val[k + 2], - val[k + 3] != 0, - val[k + 4] != 0); - currentX += val[k + 5]; - currentY += val[k + 6]; - ctrlPointX = currentX; - ctrlPointY = currentY; - break; - case 'A': // Draws an elliptical arc - drawArc(path, - currentX, - currentY, - val[k + 5], - val[k + 6], - val[k + 0], - val[k + 1], - val[k + 2], - val[k + 3] != 0, - val[k + 4] != 0); - currentX = val[k + 5]; - currentY = val[k + 6]; - ctrlPointX = currentX; - ctrlPointY = currentY; - break; - } - previousCmd = cmd; - } - current[0] = currentX; - current[1] = currentY; - current[2] = ctrlPointX; - current[3] = ctrlPointY; - current[4] = currentSegmentStartX; - current[5] = currentSegmentStartY; - } - - private static void drawArc(@NonNull Path_Delegate p, float x0, float y0, float x1, - float y1, float a, float b, float theta, boolean isMoreThanHalf, - boolean isPositiveArc) { - - LOGGER.log(Level.FINE, "(" + x0 + "," + y0 + ")-(" + x1 + "," + y1 - + ") {" + a + " " + b + "}"); - /* Convert rotation angle from degrees to radians */ - double thetaD = theta * Math.PI / 180.0f; - /* Pre-compute rotation matrix entries */ - double cosTheta = Math.cos(thetaD); - double sinTheta = Math.sin(thetaD); - /* Transform (x0, y0) and (x1, y1) into unit space */ - /* using (inverse) rotation, followed by (inverse) scale */ - double x0p = (x0 * cosTheta + y0 * sinTheta) / a; - double y0p = (-x0 * sinTheta + y0 * cosTheta) / b; - double x1p = (x1 * cosTheta + y1 * sinTheta) / a; - double y1p = (-x1 * sinTheta + y1 * cosTheta) / b; - LOGGER.log(Level.FINE, "unit space (" + x0p + "," + y0p + ")-(" + x1p - + "," + y1p + ")"); - /* Compute differences and averages */ - double dx = x0p - x1p; - double dy = y0p - y1p; - double xm = (x0p + x1p) / 2; - double ym = (y0p + y1p) / 2; - /* Solve for intersecting unit circles */ - double dsq = dx * dx + dy * dy; - if (dsq == 0.0) { - LOGGER.log(Level.FINE, " Points are coincident"); - return; /* Points are coincident */ - } - double disc = 1.0 / dsq - 1.0 / 4.0; - if (disc < 0.0) { - LOGGER.log(Level.FINE, "Points are too far apart " + dsq); - float adjust = (float) (Math.sqrt(dsq) / 1.99999); - drawArc(p, x0, y0, x1, y1, a * adjust, b * adjust, theta, - isMoreThanHalf, isPositiveArc); - return; /* Points are too far apart */ - } - double s = Math.sqrt(disc); - double sdx = s * dx; - double sdy = s * dy; - double cx; - double cy; - if (isMoreThanHalf == isPositiveArc) { - cx = xm - sdy; - cy = ym + sdx; - } else { - cx = xm + sdy; - cy = ym - sdx; - } - - double eta0 = Math.atan2((y0p - cy), (x0p - cx)); - LOGGER.log(Level.FINE, "eta0 = Math.atan2( " + (y0p - cy) + " , " - + (x0p - cx) + ") = " + Math.toDegrees(eta0)); - - double eta1 = Math.atan2((y1p - cy), (x1p - cx)); - LOGGER.log(Level.FINE, "eta1 = Math.atan2( " + (y1p - cy) + " , " - + (x1p - cx) + ") = " + Math.toDegrees(eta1)); - double sweep = (eta1 - eta0); - if (isPositiveArc != (sweep >= 0)) { - if (sweep > 0) { - sweep -= 2 * Math.PI; - } else { - sweep += 2 * Math.PI; - } - } - - cx *= a; - cy *= b; - double tcx = cx; - cx = cx * cosTheta - cy * sinTheta; - cy = tcx * sinTheta + cy * cosTheta; - LOGGER.log( - Level.FINE, - "cx, cy, a, b, x0, y0, thetaD, eta0, sweep = " + cx + " , " - + cy + " , " + a + " , " + b + " , " + x0 + " , " + y0 - + " , " + Math.toDegrees(thetaD) + " , " - + Math.toDegrees(eta0) + " , " + Math.toDegrees(sweep)); - - arcToBezier(p, cx, cy, a, b, x0, y0, thetaD, eta0, sweep); - } - - /** - * Converts an arc to cubic Bezier segments and records them in p. - * - * @param p The target for the cubic Bezier segments - * @param cx The x coordinate center of the ellipse - * @param cy The y coordinate center of the ellipse - * @param a The radius of the ellipse in the horizontal direction - * @param b The radius of the ellipse in the vertical direction - * @param e1x E(eta1) x coordinate of the starting point of the arc - * @param e1y E(eta2) y coordinate of the starting point of the arc - * @param theta The angle that the ellipse bounding rectangle makes with the horizontal - * plane - * @param start The start angle of the arc on the ellipse - * @param sweep The angle (positive or negative) of the sweep of the arc on the ellipse - */ - private static void arcToBezier(@NonNull Path_Delegate p, double cx, double cy, double a, - double b, double e1x, double e1y, double theta, double start, - double sweep) { - // Taken from equations at: - // http://spaceroots.org/documents/ellipse/node8.html - // and http://www.spaceroots.org/documents/ellipse/node22.html - // Maximum of 45 degrees per cubic Bezier segment - int numSegments = (int) Math.ceil(Math.abs(sweep * 4 / Math.PI)); - - - double eta1 = start; - double cosTheta = Math.cos(theta); - double sinTheta = Math.sin(theta); - double cosEta1 = Math.cos(eta1); - double sinEta1 = Math.sin(eta1); - double ep1x = (-a * cosTheta * sinEta1) - (b * sinTheta * cosEta1); - double ep1y = (-a * sinTheta * sinEta1) + (b * cosTheta * cosEta1); - - double anglePerSegment = sweep / numSegments; - for (int i = 0; i < numSegments; i++) { - double eta2 = eta1 + anglePerSegment; - double sinEta2 = Math.sin(eta2); - double cosEta2 = Math.cos(eta2); - double e2x = cx + (a * cosTheta * cosEta2) - - (b * sinTheta * sinEta2); - double e2y = cy + (a * sinTheta * cosEta2) - + (b * cosTheta * sinEta2); - double ep2x = -a * cosTheta * sinEta2 - b * sinTheta * cosEta2; - double ep2y = -a * sinTheta * sinEta2 + b * cosTheta * cosEta2; - double tanDiff2 = Math.tan((eta2 - eta1) / 2); - double alpha = Math.sin(eta2 - eta1) - * (Math.sqrt(4 + (3 * tanDiff2 * tanDiff2)) - 1) / 3; - double q1x = e1x + alpha * ep1x; - double q1y = e1y + alpha * ep1y; - double q2x = e2x - alpha * ep2x; - double q2y = e2y - alpha * ep2y; - - p.cubicTo((float) q1x, - (float) q1y, - (float) q2x, - (float) q2y, - (float) e2x, - (float) e2y); - eta1 = eta2; - e1x = e2x; - e1y = e2y; - ep1x = ep2x; - ep1y = ep2y; - } - } - } -} diff --git a/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java b/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java deleted file mode 100644 index 213e848659bfd..0000000000000 --- a/tools/layoutlib/bridge/src/android/util/Xml_Delegate.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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(); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java deleted file mode 100644 index 4445a22385386..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java deleted file mode 100644 index b6e6ec0084499..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java +++ /dev/null @@ -1,496 +0,0 @@ -/* - * 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 mFailedAppCompatViews = new HashSet<>(); - private boolean mIsInMerge = false; - private ResourceReference mResourceReference; - private Map 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 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. - *

- * 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 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 () 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 getDrawerLayoutMap() { - if (mOpenDrawerLayouts == null) { - mOpenDrawerLayouts = new HashMap(4); - } - return mOpenDrawerLayouts; - } - - public void onDoneInflation() { - if (mOpenDrawerLayouts != null) { - mOpenDrawerLayouts.clear(); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java b/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java deleted file mode 100644 index 494ffa1518ab9..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/Choreographer_Delegate.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package 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 mInstance = new AtomicReference(); - - @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 threadInstance = - (ThreadLocal) threadInstanceField.get(null); - threadInstance.remove(); - } catch (ReflectiveOperationException e) { - assert false; - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Unable to clear Choreographer memory.", e, null); - } - } -} diff --git a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java b/tools/layoutlib/bridge/src/android/view/Display_Delegate.java deleted file mode 100644 index 53dc821f65d22..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/Display_Delegate.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/HandlerActionQueue_Delegate.java b/tools/layoutlib/bridge/src/android/view/HandlerActionQueue_Delegate.java deleted file mode 100644 index e580ed0e14f75..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/HandlerActionQueue_Delegate.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - } -} diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java deleted file mode 100644 index 15fd2ceea5fa7..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ /dev/null @@ -1,528 +0,0 @@ -/* - * 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 { - } -} diff --git a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java deleted file mode 100644 index cec6bb3844dbf..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/LayoutInflater_Delegate.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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 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: ", 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: ", 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 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 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, - " can only be used inside of a ViewGroup", - null); - } - - LayoutInflater.consumeChildElements(parser); - } -} diff --git a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java deleted file mode 100644 index 08a97d6479385..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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} - *

- * 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. - *

- * 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. - *

- * 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); - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/PointerIcon_Delegate.java b/tools/layoutlib/bridge/src/android/view/PointerIcon_Delegate.java deleted file mode 100644 index 4a5ea9b5bb656..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/PointerIcon_Delegate.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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. - } -} diff --git a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java deleted file mode 100644 index 08665778373e6..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java b/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java deleted file mode 100644 index 152878bb0fd56..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/RenderNode_Delegate.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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} - *

- * 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 sManager = - new DelegateManager(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; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/ShadowPainter.java b/tools/layoutlib/bridge/src/android/view/ShadowPainter.java deleted file mode 100644 index f09fffd10291e..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/ShadowPainter.java +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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)}. - *

- * 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. - *

- * NOTE: If the shape is rectangular and opaque, consider using {@link - * #drawRectangleShadow(Graphics2D, int, int, int, int)} instead. - * - * @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. - *

- * - * @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"); -} diff --git a/tools/layoutlib/bridge/src/android/view/SurfaceView.java b/tools/layoutlib/bridge/src/android/view/SurfaceView.java deleted file mode 100644 index ebb2af45320ea..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/SurfaceView.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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; - } - }; -} - diff --git a/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java b/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java deleted file mode 100644 index c3533e0182c4b..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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(); - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java deleted file mode 100644 index 4b760a7d46389..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/ViewGroup_Delegate.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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} - *

- * 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Accessor.java b/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Accessor.java deleted file mode 100644 index 0e15b97243b02..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Accessor.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java b/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java deleted file mode 100644 index 14b84ef5b20c9..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/ViewRootImpl_Delegate.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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. - } -} diff --git a/tools/layoutlib/bridge/src/android/view/View_Delegate.java b/tools/layoutlib/bridge/src/android/view/View_Delegate.java deleted file mode 100644 index 408ec54975ace..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/View_Delegate.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/WindowCallback.java b/tools/layoutlib/bridge/src/android/view/WindowCallback.java deleted file mode 100644 index 1ea8a9f2294eb..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/WindowCallback.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.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) { - - } -} diff --git a/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java b/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java deleted file mode 100644 index 2606e55e5dbe9..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/WindowManagerGlobal_Delegate.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java deleted file mode 100644 index 11cb046aa2f8a..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * 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. - *

- * Note: You need to query this only if you application is - * doing its own rendering and does not rely on the platform rendering pipeline. - *

- * - */ - 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 getAccessibilityServiceList() { - return Collections.emptyList(); - } - - public List 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 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) { - } - -} diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java deleted file mode 100644 index dc4f9c8681858..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java deleted file mode 100644 index 7c98847a4cf30..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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; - } - } -} diff --git a/tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java b/tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java deleted file mode 100644 index 8e1f21831a359..0000000000000 --- a/tools/layoutlib/bridge/src/android/view/textservice/TextServicesManager.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/webkit/WebView.java b/tools/layoutlib/bridge/src/android/webkit/WebView.java deleted file mode 100644 index 202f2046a3fd3..0000000000000 --- a/tools/layoutlib/bridge/src/android/webkit/WebView.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java b/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java deleted file mode 100644 index fdd1779d6bd3d..0000000000000 --- a/tools/layoutlib/bridge/src/android/widget/Toolbar_Accessor.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.widget; - -import 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(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java deleted file mode 100644 index 01fe45d2644c2..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/util/VirtualRefBasePtr_Delegate.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 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); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java deleted file mode 100644 index bf998b8737cd3..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/util/XmlUtils_Delegate.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java deleted file mode 100644 index da1ab27b6ff2f..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/view/animation/NativeInterpolatorFactoryHelper_Delegate.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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} - *

- * 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 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)); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java deleted file mode 100644 index bb95c4e353982..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java deleted file mode 100644 index 505fb8172cebd..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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} - *

- * 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); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java b/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java deleted file mode 100644 index 40b6220cf8a0f..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java deleted file mode 100644 index 93fd005ebc057..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ /dev/null @@ -1,670 +0,0 @@ -/* - * 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. - *

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> sRMap = new HashMap<>(); - - /** - * Reverse map compared to sRMap, resource type -> (resource name -> id). - * This is for com.android.internal.R. - */ - private final static Map> 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>> sProjectBitmapCache = - new HashMap<>(); - private final static Map>> sProject9PatchCache = - - new HashMap<>(); - - private final static Map> sFrameworkBitmapCache = new HashMap<>(); - private final static Map> sFramework9PatchCache = - new HashMap<>(); - - private static Map> sEnumValueMap; - private static Map 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 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 platformProperties, - File fontLocation, - Map> 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 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 revRAttrMap = new HashMap<>(2048); - sRevRMap.put(ResourceType.ATTR, revRAttrMap); - // There were 2000 elements in this map at M timeframe. - Map 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 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. - *

- * 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. - *

- * 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 resolveResourceId(int value) { - Pair 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. - *

- * 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 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 getEnumValues(String attributeName) { - if (sEnumValueMap != null) { - return sEnumValueMap.get(attributeName); - } - - return null; - } - - /** - * Returns the platform build properties. - */ - public static Map 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> map = sProjectBitmapCache.get(projectKey); - if (map != null) { - SoftReference ref = map.get(value); - if (ref != null) { - return ref.get(); - } - } - } else { - SoftReference 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> 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> map = sProject9PatchCache.get(projectKey); - - if (map != null) { - SoftReference ref = map.get(value); - if (ref != null) { - return ref.get(); - } - } - } else { - SoftReference 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> map = - sProject9PatchCache.computeIfAbsent(projectKey, k -> new HashMap<>()); - - map.put(value, new SoftReference<>(ninePatch)); - } else { - sFramework9PatchCache.put(value, new SoftReference<>(ninePatch)); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java deleted file mode 100644 index 62287669577c3..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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.
- *
- * Most constants have a prefix defining the content. - *

    - *
  • WS_ Workspace path constant. Those are absolute paths, - * from the project root.
  • - *
  • OS_ OS path constant. These paths are different depending on the platform.
  • - *
  • FN_ File name constant.
  • - *
  • FD_ Folder name constant.
  • - *
  • EXT_ File extension constant. This does NOT include a dot.
  • - *
  • DOT_ File extension constant. This start with a dot.
  • - *
  • RE_ Regexp constant.
  • - *
  • NS_ Namespace constant.
  • - *
  • CLASS_ Fully qualified class name.
  • - *
- * - */ -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"; -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java deleted file mode 100644 index fdf6d63b1cb27..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * 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 getRootViews() { - return mSession != null ? mSession.getViewInfos() : Collections.emptyList(); - } - - @Override - public List getSystemRootViews() { - return mSession != null ? mSession.getSystemViewInfos() : Collections.emptyList(); - } - - @Override - public Map 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 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java deleted file mode 100644 index e10f20dfbbca2..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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. - *

- * 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); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java deleted file mode 100644 index faaf1056bc9d3..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/AndroidLocale.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java deleted file mode 100644 index c827f178279e4..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java deleted file mode 100644 index 8d259d70121e2..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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. - *

- * 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 - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java deleted file mode 100644 index 8bd924ea9cfb0..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ /dev/null @@ -1,2059 +0,0 @@ -/* - * 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 FRAMEWORK_PATCHED_VALUES = new HashMap<>(2); - private static final Map 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 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 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 mScrollYPos = new HashMap<>(); - private final HashMap mScrollXPos = new HashMap<>(); - - private Resources.Theme mTheme; - - private final Map mDefaultPropMaps = new IdentityHashMap<>(); - - // maps for dynamically generated id representing style objects (StyleResourceValue) - @Nullable - private Map mDynamicIdToStyleMap; - private Map 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 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 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 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 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 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 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 currentThemes = mRenderResources.getAllThemes(); - - Pair 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> 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 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 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 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 createStyleBasedTypedArray( - @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException { - List> 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 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) - *

- * - * @param attrs An attribute array reference given to obtainStyledAttributes. - * @return List of attribute information. - */ - private List> searchAttrs(int[] attrs) { - List> 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 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 searchAttr(int attr) { - Pair 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 - *

    - *
  1. {@code int[]}: the attributes for which TypedArray is created
  2. - *
  3. {@code List}: the themes set on the context at the time of - * creation of the TypedArray
  4. - *
  5. {@code Integer}: the default style used at the time of creation
  6. - *
- * - * The class is created by using nested maps resolving one dependency at a time. - *

- * 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, - Map>>> mCache; - - private TypedArrayCache() { - mCache = new IdentityHashMap<>(); - } - - public Pair get(int[] attrs, - List themes, int resId) { - Map, Map>> - cacheFromThemes = mCache.get(attrs); - if (cacheFromThemes != null) { - Map> cacheFromResId = - cacheFromThemes.get(themes); - if (cacheFromResId != null) { - return cacheFromResId.get(resId); - } - } - return null; - } - - public void put(int[] attrs, List themes, int resId, - Pair value) { - Map, Map>> - cacheFromThemes = mCache.computeIfAbsent(attrs, k -> new HashMap<>()); - Map> cacheFromResId = - cacheFromThemes.computeIfAbsent(themes, k -> new HashMap<>()); - cacheFromResId.put(resId, value); - } - - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java deleted file mode 100644 index 4805ed1e61b72..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * 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 getEnabledInputMethodList() throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List getEnabledInputMethodSubtypeList(String arg0, - boolean arg1) throws RemoteException { - // TODO Auto-generated method stub - return null; - } - - @Override - public List 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 - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeLayoutParamsMapAttributes.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeLayoutParamsMapAttributes.java deleted file mode 100644 index f5912e7bdb24f..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeLayoutParamsMapAttributes.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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 mAttributes; - - public BridgeLayoutParamsMapAttributes(Map 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(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java deleted file mode 100644 index 47dad3404beba..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java +++ /dev/null @@ -1,958 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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 getSharedLibraries(@InstallFlags int flags) { - return null; - } - - @Override - public List 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 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 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 getInstalledPackages(int flags) { - return null; - } - - @Override - public List getPackagesHoldingPermissions(String[] permissions, int flags) { - return null; - } - - @Override - public List 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 getInstalledApplications(int flags) { - return null; - } - - @Override - public List getInstalledApplicationsAsUser(int flags, int userId) { - return null; - } - - @Override - public List 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 queryIntentActivities(Intent intent, int flags) { - return null; - } - - @Override - public List queryIntentActivitiesAsUser(Intent intent, int flags, int userId) { - return null; - } - - @Override - public List queryIntentActivityOptions(ComponentName caller, Intent[] specifics, - Intent intent, int flags) { - return null; - } - - @Override - public List queryBroadcastReceivers(Intent intent, int flags) { - return null; - } - - @Override - public List queryBroadcastReceiversAsUser(Intent intent, int flags, int userId) { - return null; - } - - @Override - public ResolveInfo resolveService(Intent intent, int flags) { - return null; - } - - @Override - public List queryIntentServices(Intent intent, int flags) { - return null; - } - - @Override - public List queryIntentServicesAsUser(Intent intent, int flags, int userId) { - return null; - } - - @Override - public List queryIntentContentProvidersAsUser(Intent intent, int flags, - int userId) { - return null; - } - - @Override - public List 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 queryContentProviders(String processName, int uid, int flags) { - return null; - } - - @Override - public InstrumentationInfo getInstrumentationInfo(ComponentName className, int flags) - throws NameNotFoundException { - return null; - } - - @Override - public List 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 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 getIntentFilterVerifications(String packageName) { - return null; - } - - @Override - public List 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 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 outFilters, - List outActivities, String packageName) { - return 0; - } - - @Override - public ComponentName getHomeActivities(List 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 getPackageCandidateVolumes(ApplicationInfo app) { - return null; - } - - @Override - public int movePrimaryStorage(VolumeInfo vol) { - return 0; - } - - @Override - public VolumeInfo getPrimaryStorageCurrentVolume() { - return null; - } - - @Override - public List 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); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java deleted file mode 100644 index ed428ec9cfe89..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeSharedPreferences.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeSharedPreferences.java deleted file mode 100644 index 132ff2f2e08cd..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeSharedPreferences.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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 getAll() { - return null; - } - - @Override - public String getString(String key, String defValue) { - return null; - } - - @Override - public Set getStringSet(String key, Set 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 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) { - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java deleted file mode 100644 index ffbe7c43ceabe..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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; - } - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java deleted file mode 100644 index 2c883940510e7..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * 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. - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java deleted file mode 100644 index ac8712eaa0257..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java +++ /dev/null @@ -1,494 +0,0 @@ -/* - * 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(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java deleted file mode 100644 index 051de9055042e..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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)}. - *

- * The IDE has its own copy of this class which may be newer or older than this one. - *

- * Constants should never be modified or removed from this class. - */ -public final class RenderParamsFlags { - - public static final Key FLAG_KEY_ROOT_TAG = - new Key("rootTag", String.class); - public static final Key FLAG_KEY_DISABLE_BITMAP_CACHING = - new Key("disableBitmapCaching", Boolean.class); - public static final Key FLAG_KEY_RENDER_ALL_DRAWABLE_STATES = - new Key("renderAllDrawableStates", Boolean.class); - /** - * To tell LayoutLib that the IDE supports RecyclerView. - *

- * Default is false. - */ - public static final Key FLAG_KEY_RECYCLER_VIEW_SUPPORT = - new Key("recyclerViewSupport", Boolean.class); - /** - * The application package name. Used via {@link LayoutlibCallback#getFlag(Key)} - */ - public static final Key FLAG_KEY_APPLICATION_PACKAGE = - new Key("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 FLAG_KEY_XML_FILE_PARSER_SUPPORT = - new Key("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 FLAG_DO_NOT_RENDER_ON_CREATE = - new Key("doNotRenderOnCreate", Boolean.class); - - // Disallow instances. - private RenderParamsFlags() {} -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/graphics/NopCanvas.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/graphics/NopCanvas.java deleted file mode 100644 index 131aa1752ba00..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/graphics/NopCanvas.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * 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) { - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DesignLibUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DesignLibUtil.java deleted file mode 100644 index aa873a6476ae2..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DesignLibUtil.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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. - *

- * 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); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DrawerLayoutUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DrawerLayoutUtil.java deleted file mode 100644 index 40d3811cbdf7c..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DrawerLayoutUtil.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java deleted file mode 100644 index ab278195f3286..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/RecyclerViewUtil.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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. - *

- * 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); - } - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/SupportPreferencesUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/SupportPreferencesUtil.java deleted file mode 100644 index 6ad9efc81afa1..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/SupportPreferencesUtil.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * 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 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 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; - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java deleted file mode 100644 index d7d16cf6d764c..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/view/WindowManagerImpl.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.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) { - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java deleted file mode 100644 index cdcf0ea1ca765..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java deleted file mode 100644 index a439e7d034df2..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/BridgeActionBar.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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)); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java deleted file mode 100644 index 7f8d9928d7ce5..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/Config.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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 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 getResourceDirs(int platformVersion) { - // Special case the most used scenario. - if (platformVersion == 0) { - return sDefaultResourceDir; - } - List list = new ArrayList(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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java deleted file mode 100644 index 2984fc0e5abb6..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * 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. - *

- * 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); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java deleted file mode 100644 index fd49c7700ea95..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBar.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java deleted file mode 100644 index 2cdc647b79960..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FrameworkActionBarWrapper.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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; - } - - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/IconLoader.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/IconLoader.java deleted file mode 100644 index 9ab2e82f00c84..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/IconLoader.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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()); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java deleted file mode 100644 index dfbc69bee59c1..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java deleted file mode 100644 index 778305da6d70a..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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 items = mMenu.getNonActionItems(); - if (mExpandedIndex < 0) { - return items.size(); - } - return items.size() - 1; - } - - @Override - public MenuItemImpl getItem(int position) { - ArrayList 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 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; - } - } - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java deleted file mode 100644 index 2dc7c65e20856..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ThemePreviewNavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ThemePreviewNavigationBar.java deleted file mode 100644 index 043528016c2df..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ThemePreviewNavigationBar.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java deleted file mode 100644 index 4fe1001d92297..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java deleted file mode 100644 index 11da445834513..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * 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 the delegate class to manage - */ -public final class DelegateManager { - @SuppressWarnings("FieldCanBeLocal") - private final Class mClass; - private static final SparseWeakArray 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 sJavaReferences = new HashSet<>(); - private static final AtomicLong sDelegateCounter = new AtomicLong(1); - - public DelegateManager(Class theClass) { - mClass = theClass; - } - - /** - * Returns the delegate from the given native int. - *

- * If the int is zero, then this will always return null. - *

- * 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()); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java deleted file mode 100644 index 7526e090be500..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +++ /dev/null @@ -1,885 +0,0 @@ -/* - * 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. - *

- * This is based on top of {@link Graphics2D} but can operate independently if none are available - * yet when setting transforms and clip information. - *

- * 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 mLayers = new ArrayList(); - - /** 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. - *

- * If bitmap 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. - *

- * 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. - *

- * 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 saveCount. - * @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. - *

- * 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. - *

- * 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. - *

- * 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. - *

- * 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. - *

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; - } - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java deleted file mode 100644 index 287334c2fc8b1..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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. - *

- *  +-------------------------------------------------+---+
- *  | Status bar                                      | N |
- *  +-------------------------------------------------+ a |
- *  | Title/Action bar (optional)                     | v |
- *  +-------------------------------------------------+   |
- *  | Content, vertical extending                     | b |
- *  |                                                 | a |
- *  |                                                 | r |
- *  +-------------------------------------------------+---+
- * 
- * or - *
- *  +-------------------------------------+
- *  | Status bar                          |
- *  +-------------------------------------+
- *  | Title/Action bar (optional)         |
- *  +-------------------------------------+
- *  | Content, vertical extending         |
- *  |                                     |
- *  |                                     |
- *  +-------------------------------------+
- *  | Nav bar                             |
- *  +-------------------------------------+
- * 
- * - */ -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; - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java deleted file mode 100644 index 71e7fd2c5eea6..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutParserWrapper.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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 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; // 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 found, but not END_TAG. - - int state = STATE_LAYOUT_NOT_STARTED; - int dataDepth = -1; // depth of the 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(count) : - Collections.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."); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java deleted file mode 100644 index 1ae9cb646cf36..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ParserFactory.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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) { - } - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java deleted file mode 100644 index 7b701802b9a5d..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PlayAnimationThread.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java deleted file mode 100644 index 70e2eb17794a5..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java deleted file mode 100644 index 0c537533479ea..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderAction.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * 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 the {@link RenderParams} implementation - * - */ -public abstract class RenderAction 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. - *

- * This must 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. - *

- * 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. - *

- * 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. - *

- * 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. - *

- * 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); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java deleted file mode 100644 index d797eecad3dd4..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * 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 { - - 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 result; - - if (d instanceof StateListDrawable) { - result = new ArrayList(); - 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; - } - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java deleted file mode 100644 index d21955e35409c..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ /dev/null @@ -1,1557 +0,0 @@ -/* - * 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. - *

- * 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 { - - 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 mViewInfoList; - private List 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. - *

- * This must 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 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 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. - *

- * {@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. - *

- * {@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 - *

- * {@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. - *

- * {@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 measuredView 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 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 - *

- * {@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. - *

- * {@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 - *

- * {@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 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. - *

- * {@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. - *

- * 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 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 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 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 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 childrenWithoutOffset = new ArrayList<>(childCount); - List 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 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 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 getViewInfos() { - return mViewInfoList; - } - - public List getSystemViewInfos() { - return mSystemViewInfoList; - } - - public Map 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(); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java deleted file mode 100644 index 75f9ec527e63d..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +++ /dev/null @@ -1,706 +0,0 @@ -/* - * 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 requireUnit 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< - */ -public class Stack extends ArrayList { - - 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java deleted file mode 100644 index 9fea1677d5f21..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java deleted file mode 100644 index c0ca1d5916e9d..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterHelper.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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 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 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 - } - } - } - } - } - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java deleted file mode 100644 index 8e28dbaf1a4d0..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/AdapterItem.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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 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(); - } - - mChildren.add(child); - } - - List 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java deleted file mode 100644 index 142eac172502b..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeAdapter.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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 mTypes = new ArrayList(); - private final LayoutlibCallback mCallback; - private final ResourceReference mAdapterRef; - private final List mItems = new ArrayList(); - 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 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java deleted file mode 100644 index 344b17eab039c..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/binding/FakeExpandableAdapter.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * 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 mItems = new ArrayList(); - - // don't use a set because the order is important. - private final List mGroupTypes = new ArrayList(); - private final List mChildrenTypes = new ArrayList(); - - public FakeExpandableAdapter(ResourceReference adapterRef, AdapterBinding binding, - LayoutlibCallback callback) { - mAdapterRef = adapterRef; - mCallback = callback; - - createItems(binding, binding.getItemCount(), binding.getRepeatCount(), mGroupTypes, 1); - } - - private void createItems(Iterable iterable, final int itemCount, - final int repeatCount, List 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 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 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 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 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(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java deleted file mode 100644 index 96cba783d367d..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/libcore/io/BridgeBufferIterator.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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(); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/ShadowBuffer.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/ShadowBuffer.java deleted file mode 100644 index ae33e1ddf2112..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/ShadowBuffer.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/SpotShadow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/SpotShadow.java deleted file mode 100644 index 33375ffb74879..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/shadowutil/SpotShadow.java +++ /dev/null @@ -1,630 +0,0 @@ -/* - * 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.
- * 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))); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/CachedPathIteratorFactory.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/CachedPathIteratorFactory.java deleted file mode 100644 index 0a9b9ecde2f8c..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/CachedPathIteratorFactory.java +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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 typesArray = Lists.newArrayList(); - ArrayList 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; - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/Debug.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/Debug.java deleted file mode 100644 index 82eab8560acb8..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/Debug.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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; - -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java deleted file mode 100644 index 161bf4155a1ad..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/DynamicIdMap.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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, Integer> mDynamicIds = new HashMap<>(); - private final SparseArray> 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 resource) { - Integer value = mDynamicIds.get(resource); - if (value == null) { - value = ++mDynamicSeed; - mDynamicIds.put(resource, value); - mRevDynamicIds.put(value, resource); - } - - return value; - } - - public Pair resolveId(int id) { - return mRevDynamicIds.get(id); - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java deleted file mode 100644 index f149b6cd8ef95..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/NinePatchInputStream.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java deleted file mode 100644 index b89718ff5ea67..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/ReflectionUtils.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.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}. - *

- * 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); - } - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java deleted file mode 100644 index a2a8aa96b1553..0000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/util/SparseWeakArray.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * 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 { - - 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 null - * 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 0...size()-1, returns - * the key from the indexth key-value mapping that this - * SparseArray stores. - */ - public long keyAt(int index) { - if (mGarbage) { - gc(); - } - - return mKeys[index]; - } - - /** - * Given an index in the range 0...size()-1, returns - * the value from the indexth 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 0...size()-1, sets a new - * value for the indexth 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; -} diff --git a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java b/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java deleted file mode 100644 index 6d013bbe6b057..0000000000000 --- a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * 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; - } -} diff --git a/tools/layoutlib/bridge/src/dalvik/system/VMRuntime_Delegate.java b/tools/layoutlib/bridge/src/dalvik/system/VMRuntime_Delegate.java deleted file mode 100644 index 36efc3a27479b..0000000000000 --- a/tools/layoutlib/bridge/src/dalvik/system/VMRuntime_Delegate.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package dalvik.system; - -import com.android.tools.layoutlib.annotations.LayoutlibDelegate; - -/** - * Delegate used to provide implementation of a select few native methods of {@link VMRuntime} - *

- * 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"); - } - } - -} diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java deleted file mode 100644 index 9c5801080e17e..0000000000000 --- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * 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. - 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(); - } -} diff --git a/tools/layoutlib/bridge/src/libcore/io/MemoryMappedFile_Delegate.java b/tools/layoutlib/bridge/src/libcore/io/MemoryMappedFile_Delegate.java deleted file mode 100644 index 723d5c4b0d0cb..0000000000000 --- a/tools/layoutlib/bridge/src/libcore/io/MemoryMappedFile_Delegate.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package 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 sManager = new - DelegateManager(MemoryMappedFile_Delegate.class); - - private static final Map sMemoryMappedFileMap = - new HashMap(); - - 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); - } - -} diff --git a/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java b/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java deleted file mode 100644 index 04fabc242454c..0000000000000 --- a/tools/layoutlib/bridge/src/libcore/util/NativeAllocationRegistry_Delegate.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 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); - } -} diff --git a/tools/layoutlib/bridge/tests/.classpath b/tools/layoutlib/bridge/tests/.classpath deleted file mode 100644 index 2b32e097de901..0000000000000 --- a/tools/layoutlib/bridge/tests/.classpath +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/tools/layoutlib/bridge/tests/.project b/tools/layoutlib/bridge/tests/.project deleted file mode 100644 index 2325eed166277..0000000000000 --- a/tools/layoutlib/bridge/tests/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - layoutlib_bridge-tests - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk deleted file mode 100644 index 1b65eee729e65..0000000000000 --- a/tools/layoutlib/bridge/tests/Android.mk +++ /dev/null @@ -1,43 +0,0 @@ -# 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)) diff --git a/tools/layoutlib/bridge/tests/res/com/android/layoutlib/testdata/layout1.xml b/tools/layoutlib/bridge/tests/res/com/android/layoutlib/testdata/layout1.xml deleted file mode 100644 index b8fc9472ed83b..0000000000000 --- a/tools/layoutlib/bridge/tests/res/com/android/layoutlib/testdata/layout1.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - diff --git a/tools/layoutlib/bridge/tests/res/empty.xml b/tools/layoutlib/bridge/tests/res/empty.xml deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/.gitignore b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/.gitignore deleted file mode 100644 index a2ce0dcae9e26..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -.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/ diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build.gradle b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build.gradle deleted file mode 100644 index 478166022d738..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build.gradle +++ /dev/null @@ -1,48 +0,0 @@ -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']) -} diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/androidTest/debug/com/android/layoutlib/test/myapplication/test/BuildConfig.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/androidTest/debug/com/android/layoutlib/test/myapplication/test/BuildConfig.class deleted file mode 100644 index 1ca7e01d80aedccdebf9c26673b1ef5e6a676cb4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 792 zcmbVK+iuf95Ixf*juYHlpg_2nYf`99c|)y`ax02tlBh`|(U)rDEMY6hj+`}8KMU~y z;(-s~qY&dXq(Qv#vfeX0bLN~G|NQm+2Y^?w^Dywh#C9GJ@hFE39%u0+i>HK4y-_`W zOP~|NTBXx*o3%=>*>0US>x6=PCO!$r7s1Hs>PQ8neZp!j45nHHx-a}#ns`RYSC5-+ z{j~SK(=bsY7>919-##)?CRqK(Q8yv1wd)P;(@e1>T8g(S@3?A*s}5A4^czB|RPGbf zwQwj2>#ho9D;^JI)Dr`rBLz3~gx?pDO7J|G)*scBupNFyb)xgnm zs-5w*bu7xa2!t4JQz3xeiC>bQ5H<{7lFAGOz=PT&*tVNMeV-_@Ui|^J&0&e3DBNKNQ#oMzN ZAXixVhSV3N69VFne+aUS?lD@y{om}|sp0?t diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/ArraysCheckWidget.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/ArraysCheckWidget.class deleted file mode 100644 index f73528a556e20b24bf748af712dace2491d1c96a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2349 zcmbVO%U2s!9R6+|+$2naQUgs2A{E>4oECvns8x)jsVTLDQd{a{NCp@hCYVepxN+k` zcdlgb#es_{gLh!-q=03mQ`}^IQ-=F{b6u>05BX|Y#YPbN03x6r04%}8kOA>b^ zJ{D-ZVcC{*Q{Y-6ZP>YD!OH2`g6){LqbJq8@63A_Wyi|v3yxE?*2|8WF`fD0Re?aV zkTV53)0S;6m3P+7;)=1J=Sg?EkTvqFM$uCH+F`)ivPuFs(%Hg}UbmPx4hm%_Z>{T& zS#tE917mkLZ)FX~D%ko$v1lBWl3Ql>@qH_|Nvi_V^>N=3hqN99a*HX| zaz-)jc2AQd_3|dG4a_E~%bnoAK!5$NE_I9)lwE6L*|9nb_}0kybIkych8i2yqn5y6 zV)%dAH*)IKEVK2fUlGO4l0aV~HQek+i=*vCr|dd7sKE5Rt3lAJ-+Wm1jC|R=vmp>A zs3~$UunwxKZfd4`T1HbEe<=nAt5tL@X% zu(HRF)YU29WeoC}kMcVL@bf?__HsPW-7W6@oI@j{WBwzEpSkuS#xcSfcoh-@h;#K? z6^9Gx_so2-5_#zd&?kXOs0zJiHPjQ&0m13&F zMWX$#iJ__qu}>2b-W@6v(ZCV>qZI_^g0WzCTLp5iE!OsQM*3$$(NI+Wh~8LRG&DI! zhhpI)guV%hpI-b)Y`B6*D>kmM6Enm{!@r=t4*!F2t%5VH@PAaT0`|L^oP@^pB?fUB zok(B;!+bpwn8zrek}}4h)Oq`_jFjoxT zOWUEBwnHy%hqbgR+z4d@wEr!wjWKoOl%7W03uZVhF(IK#ToFRzs>GyVU7sQT99~HE0JZJy_ diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/BuildConfig.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/BuildConfig.class deleted file mode 100644 index ceb56bff3e7fa74a4be5834011b765d6bc2114bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 777 zcmbVK+iuf95IvKN;{^8>C=l-DniQ}pLcCBRasJAmh~3ovlU#7+TsaW9W7?&t6zhlhl0qggw8 zL!e{AdbQhiTlH$c)oGu!8ib;IDn1Iw7s1%+=|~0RSA?~C7|gT?^g#HrH1UW~s2#Q3 z#!3HOw`rnGFb>@6pmS)VLa+wS!(KvI?=+gM(@Jwov=VPu-*VM1SM94n>DPpGxiTPR z>fuNdHe40Rc03u%s4s>-M~ZIf34b6WmEc7%qd%w_;ic<^6GsH2C{!bE{49*MuZE76 zGwn>y#B}N_PiPeePAyjch`qd5i7Rv8^B3}kUKmH7JWz?)=1Q8KOvA!uT;c9?6w4eQ zTX=$}7IH8NFaAfHCC-Q38Jud~a3qKEn0Tg0@7d1?TjzAO zF!ZGec-T`B&Eyhpm;YUC6;seeeVLnT+wwZZ9EV0xxrB&YbhxGiUy@zyJRH1z-tVNn}t^Ls3IHdK3kc7{P)X z3=NN>M=9l5#8L{&c&uS1dX!Mx89dSORKqid#Hw(GTxWnVN9<+je80 zx87U(4tcUQ&$gUBt0mOB>x{|I!e>~i*kLzaI{V=& zA|wi$F--KUI~&3f5rkkSLz)g^A8cFAZX=VsUb|)U*Fv>AGicJn7pr6GxQ6RGCU8T; zbB4uBH+yF;ybHSJ-b6QDm$#~p<@?;%@d6bct5{<&u0U0d)3C1NC0=RR(6Nas!~7Kp zqORjMW*C+)oiu0)!&px%BrT&SD2CFdVLJ>XK9^O`mE4tkqzlqR!Bm3FeBx4R#B@J8 zB(@eqzEHg2M!VZ2{sr+;;~~@c3PpM!J)HsI3N#=0BO=#hPtMT zo(YrtMd!$Wm(Us=Y8G<@zeiEjvOmbsL&besMeqRgWTz-MiV_~uK{c{@vMI8&nEVF} CvQ0w( diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$array.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$array.class deleted file mode 100644 index b87f193c68a0a4e05136bffa46d4887be2ef5121..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 519 zcmb7AO-sW-6r7hPtxZ!~>u2@qL3=RTtKy{~6pBKXUS*RmbxXQil8w-lzsZx}!5`p{ z5?_K~k9yeIoq2EPJ?8W4{R2QBM?NaptKp!AF2NINDpmv<5}E^}Gb^;6h$NSl7Z)JZ zm9~#%Qy~x`$ZV?g>{oLL)hnfyy(UynPA3F+V5XAL8YwMr^F<`n2N5N#bVeo?$wZ{8 z;6I{kpH#-aL#<^xNJN%Nru|WD7NOA7)Tn8gh?U80qN32s%!Z4VSS}M43#*I{$H(P< zmjwUbBT@Wi#Y z+TRfBXXi6QW8~(F(3xnf?#gAV@<*8(R(cbcNi&nV4*XYa_-9@4r=N^uY^};iMizx) zbvVh~Qb;?`ot_ILH?H(Xr^2hk3*KwBGCGr9J1eHA!QqM!Ke#f_)U6JYt?9)=u4RHP zY)3dIh<_Rqy1{_6?UT4q7b^3F!QV|VM2)W*&eTT(&2TPeHAGxdSc@@cMN}MU4&Feo i)yNKGi)G*d31d>#O|;Ri`g;}j(BU`cUXAB=(fMK9egG7e0Uw zWxO--0d#YE&$-RH$@lgB@d;pzlL&R}hd2yz#L!wgktu0B1Di5*Cf4L$7{3s@koDIH zU})Ybqx>yH{rqCV(3sdvGIVFk$opcQNcSWXO-X-dQ=u2asnY+34gaiih9I@tI)->^ zjC2z%@?26po~3rpg~^;%8P{TK3$Inez05sdZ^dS#RVuu)hR@Hcife}G(H1V1cd9(v zoR3!GMZ{>K9paeb^1qD?y|RI>n- zp^V>d4DqO!X=kSMb<%!*y?+20py#5DgBp%%=rHtnXyr=U^>nU{eAdeHc$#oClZt`e zF*Jr+rIsr@;c+I)FAl)a*`!v&SQ&0Ixz8A?*HTG)!%#jwn=n*{IuZ=ckyPS7O9Ek@ zco37)9%;%>xRE*k5i52sQwArJiJ%hRol?RKW1gmh9TA@qv9 WgC^RAzgOTsc4>9VE8!3=biV=Q!+?AM diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$drawable.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$drawable.class deleted file mode 100644 index e2936771bfa46ab8262f68b050b13f9a4554b278..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 569 zcmbV}%Sr<=6o&uP+tglct=D>6DQFiCDy|ea1))$Bs&re@nP5}WOqt0jUHMF|1Q$Ml z4<()%D|9I?a+2>qCx1?o&#(6n0B6`QA&aJi9S6GvM;Jd0luw`zq1p~iWQDPPp<|hS z$pBn3lEROqO^^s>I(BzTl=Pod1;4l{#c!{~Rz-8vj0#|t_C0F5CX9qWB pAm4fey{48c91AQ1hiGuDr0YCZv61FC)3}9oo=cp|U>j>_egiQCe`x>! diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$id.class deleted file mode 100644 index d6268bf9601e714e7b9a5deb290907675ae95b84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2014 zcmb8wSyvND7zW_4*a9KQ;))wCs4PMR_kAX)BQqJDK_)umTInu31)Z)~U2(hdH+khb zUibt2Q6Aqa2z=f-H^q70bZuW%H($Sf{z62HWCab&$Z3;3&y{mJOL9SC zSkwsR))B0+@>EqV$;{ZT_j>lO3Xy9?t6t9Vttbv3Qt z__$k8Db_Mo_Kr@SvOeoUR~2jLpY!e&G|+JvyN?BD{SyTioby3H3(ossfCU$PP-MYH z9}KeKk`GEOxa@-=YynHMD9>%Syd8oDUs~BzRr$`e!-|Im6%(uD?PLUd@=0gkqv)iY zGEtSS0*+z65Oto}iQ1$(Q_^mavkM2ovrv!S7(CVaR#Eq0@Rl`+Re4^Kp{9E=7K=i+ zeLrTQlH)&Sp_uyxjlOE@XdO4eVe=IkC*cAdz&uvQ+H7y)Ao{Z?%yS4Ev(jIs&BYu> zdGg4bH0^A4!Y9~h)aWEfaGi3c);GHx^=#=Z+qfdfJl|*+H5UBI9N%J?a1wN~e%IvT zG)@TWbvU^2=xNl-qchJ*EUx3w`4kI6Nv2p3>M@ON`z~#(I-|^B+s-6O%Fc5R*?VJ} zzG~QO?iV_XSLT||w7VgwduqBSsAtK<3Ky%2gTB{p)|FkA^%Tii)kHF_Nvpj#!yebr zcptlTjKPITKth_R*cTgOs7&M3 zL%sN#;FE%^0QWNwz(wXkxWqgJ?_eH=N0>+9G3K4{F6Q0v9_GF9KIU`7C^n`8<4q`67IY z`7(Tk`6_&k`8s@q`6m1e^RIA)c?rJ7d>g*Q{2P3ic^Uql`470t{3m>m`9Ay?^WX3a z^8Bb6r9J`>2V0+C)O59!9`-Hu^}-bA)26}ve`Q}xMbNScY7Erf0LDog+IU_ zWqfy`u+(ODXJ+5*#77wi9*#U56Ut5+0u2d`fi{=P+Zg}eKd_t%U>{Jq(BW2`Wwuof%C?d^Ddt_swCn8Zf--s3WtWtufjFU5& z5Q3pGG8t%*rjm`zQEV5XFw?}UX{g28W=^XpbTW0}Vl9?StzzMnHR1Sl6LLlHA8eMy z@>b;^*T%iMScw2W>K;0T{{J%xtvrJpm|1uq&1LKe-M{DH0wvxs7(1w-ns2dSTnJmg z_%=J-A9conUxWn*s@-?cTQSmLtg#F{VTUm&?o~9=F8sX$_p!^T&t3_KXrc21Xqs{( diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$layout.class deleted file mode 100644 index f9be1ca4583c92025f96bad19985f9d343a4b70c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 881 zcmb7?OK%e~6orrTnlwpiDUTA~j{rqY&5ApjfP6b3Na=*10|&|NQm+2Y_dI(m@^j5e5++F|>K+gp)YkVoUnz|+=*mn&BThbOu6-bEr!SUhUTu8GjtX_#s*0yq)PJ~mX6L~E+n@p$DX=}vd)H_@eq6b?Qsk+tvWOs3~mM=2K z7Pdni6U09a2?KAyx6PBdPu41Rgz?`^FhRgc`j|#&qvPXZ79iw`{I?h*Rz$;r&iEbl i){JntJWPxRF=O1+9rQ40`g;uy(dRefUVsDaV)O$mKWdx+ diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/build/intermediates/classes/debug/com/android/layoutlib/test/myapplication/R$string.class deleted file mode 100644 index a4205a8c4e94c1fa596b5ed9059580f3e43cbbb8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 538 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%0D+onpXA9jt6V?e2)^5C= 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 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/adaptive_icon.png deleted file mode 100644 index 7014ddbbb7dad23c98f670c89fccfe3f6010debe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6350 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 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets.png deleted file mode 100644 index 4391f47bd35f3fb760fd8600a96cb2a16bc0a64f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67362 zcmb@ObySpJ*Y{PryCjG17^DSsK#>*@q;mj~1_?=lp`-?oE=535xbriDG=b^#l3aw7J=dudCgn5?m%zd zLR-Ve1V3qKAkVpV>&-1i`G?OuCpR;&YAAj-9Emg>r%g|%wKI@;iycvZEPWgmLhT)c z;Z242o|zIIqdo8rr5&dx23~{y1LBA6fnnq%&*b|qw=*2CN0((iG9-k{t+Qs1Uk~nI zWR@TIrB)rymd~D6SB~o27E)kC5X7(%u66XA>l4)9Z~y%Qd;Ir@|NX*AU~<~?JdhVLg+ec5Dsxc;-nI?H!uGLlXLI{tb!L)nWV zoxAO_ljd6}9ZHu!9SL4-XaIRMU zuQ({>e-ioaqWLdhfVOg7N zY9d2RIBN?W{-_W$Z!mYJv-tWF{FxF3|0xm~izI~-Abya*z2Ti@o3!7 z__nIW1=(-GVkCcc)kWv3^3d07Q2O{@er?;_!S5eh8=J_0pM?h1^G#P9O{sQb-bb6J z;P>xt#t&H>x38WF)c&fIpxXXa(6Nm`tnU?nB{!UtFj>1DX_IiI;G_9U>dyQ8ruZX| ztJ78Gzj2}1(xib0%ZDboPdj(@t!i*VT;~I@>Z%m!UjK?!ZC6Y55~+F98A(ItAZ$I5 zJ}-N{FFW&x->9xe33Z_Xk*JgX!aOzi?e%^jf#`U%{n!V&(C;w0Ii`24a1eT7)DE@F ziE(%|>m%eYgq5V55g6T9kE8A;*rb_Uu0K~TE6=uB38OjRn67mtONwiv7lK~7gLr#g z)9A4?`_KKSyZOr?@V<#E?bE);GZo?8uA@&;uQHidXfznSN*;g=SXw$X z5y@UW{kwvmSX>^C32+;)L&2$KX!xoEqc1Cj1>Cb=7IVJG_OW4R@7bSL=5`fUAx}F5 z{1y<@{t=XXZ|%#69@AnZ8M-Jsp&+66oHL}));^la691yD-dfG_-yU5`EwenH^Y^cr z5uLIltEW#fxe%gCKtvM5uww&U2c@f-NaWlJg1m*g3aXG2JKy$OH)`ht@o*<~{?6oc z>AVShV&9p^4^=S=-@cc)G}C6viM%*Q;=!2Q|3r)k=JM%fGBT%Wp)EA&m*-D%sNeT3 z@L-$dt`UzLA^Zp>JxK~rHgTNpCq*rbg4A#bJw>s{uLRU0>o6Ll5afA7k z?$0?4JW50_f8)ubQ+>{UHIo^}IW9;be5U37q7fOL^Gh+Z?k&Z+l4_L*{Hck#608>vtG%gS+E7R_zCQXGbO>+EXT1I2GmVB=4%vU7#1X7PXCiV9=#FyVAAAgIpHCKh?M1%ORW8nr;cOxNM)mF(mK^;VQer2w$Bk5Jx83@Lx)3x< zN1<*Q$6Bcmwp%}kknzeW&y1LeOQj6C5p3!GW z5YpHh)t||3u8_YG{_mHtPOFB)QM|vuUMKmxKL6Jxix~FzK@7B=KRUjDQ=tgE^%2_>MGDHHym&u%#?1k%s%r0 zb+v`c#AgV(OFu#cR;BzGef~$z2qw=9%`mJzw<5A;T**lP%5au?Y82zv=PbD zU2Hk}>cDTAwSB0bLByMcFmO%u1C7w9fjg@XE5ytpb0+KXL}_MHxs zE(wCW_c(QHoXq5WjzMbLfbH=$!JY+CWciTx_0AYrEi>GDwAJeSYHzV)BDfEH)b>@D z@6m)>-%Z7ih9U6PzZW+g=?i*nPg|)E>%LCp)g$$ZJHPX&+Ja_7r`UJ~E>VP$C}33g zOtujnBJ40Nj%6Ow_+@pY_IF;|w8!Sb4|R_@xgy)1cU&o0{skfItS2&KZ;=c2F&l}? zTT|7JVLJ@`D~XBZO`yX(Jg3kO!ulxY(xi!ubv zjTw1ZQbMt#)}o>U5SOPx{Jq`>YeRPD296Cs3)?d01+M3Vh+18L5D6NgOjBCChB#p> zYae3>GkyLjdKhVJJf^F0aq=Ghg0vYcGLrL6IzQZ?dbK%TN;78YsydGKE!y@+u5!|s ztn2R|D<U5Vkep zQ{B8GyvI|mEHU>NGt2f*QSufzG-RF64V{Bsla|S#K13g{$n&}g_pgzYCQ zOy`>e9B5iw?>t#T^nrHgSK`8TjBV zg2)n6ABS@xk=^|86aM5h>|;$CNShb!{VcEbd=*%TCvO33joR&n%L(f&OG)*~g`=E7 zQ0gxQ<+xN)$f5Qfw$y$E#k*zVD3bkPeN9^44BpiyBdW#0qKMGg7bO*QA-40K(dS<$ zVeDSpHmi?h^|M%We_LFZi5}d}N^21FI08L2CBN+}+Y}_yMjIA#y|U2>i)V!sbFT0& z_LAg+Zqq^9X4)!u0d#;SbM1w%t}lrG0K+cu|AUD?ILCJfUbjn zjDecz?)Uzkp=qa!l@q>Bqogg`y~nbTrcAqGVcNFMFKlxu@nbF>v zS(1;fEgYauWdiu_#u!?(ugyqF}#Y_aHy& zJshnQRa=W4|MUqD*3goxtJrlNSy8U$C%T1kMrZsgBaPb8Uv%a8fdy$}%BUbfODA|- z1M!qpCx!Y9@)DdS8aUW2Ry`n2!63=zXM(QVnRaA{rL{Ju*-5$lLa_%~; ziqD{Gl9I)q9LTa2qN1?hthT2tQNpE>)w?BD&M2$Uq}kgeGxs8cwH&+chq~+xJj=Z> zjILhiEO^XR2uk-O@wYJxxXn*dyGx?30s++;5ILV)y?w257(R1$Z9hnYa2wZOJP@L! z!xVB5JzJ=hfdn-#OY6yC(+ro!SDEdK?zMT7kvqdeM*Q)Zqa#91i7Nw0AX~-dw<&lq zTbZ{FeLNJvQ17sEWwxt_tCcyWhDDI!FOx&DmFh#=J2>^KEaEm+!#OgsWvMo3U6q-w zHX({FjWAeV0xpfgAVEu}lMkdVs>^}enQelGI$O*dlepfw)abxU!Ks+wMGfvjo2@Tw zW!8I#0Lux{r^u1S5+=c z?BRnGzfxR%bP;JEQ^{P^pDbiyUR*y7>nsrR>(A$8XYP-qZRkpl!1?etZ8CcBfWAkc z^k$1qxZXD257Ac$f&Mv?M>SpqBm{&n4}D^GV5n+ZlWdZ-{rJu`3CX2`65KsQ6M?Z0 zECz*{gha*?vY4%})L|DdEsqm*p{Arz1b`IWX4`Aw>eTI|7f4LEu_pRi%k-e_SiI zGis!bePIY$dhY+2jtQO}@VQ+*S$wxpq}{XwhsIy9oxtpNt_CkPWr1I;z|&#qXI3~a z8PxAWZPI!XYn45Lo8w3SwnYr9&m^}eH$A}LbU-&-s6 zeez&!qP$xYCTwSPSJ-L*-(h2z&1X>NV^?jtw?}o6Tvv4eXhY_?v`MMe)a>z`Nj;4H zrI8|N*kE~gVIku@!{#50FutP65!W@vutJs$;A=eSt}=^;O! &|DIz?y!%T3nWXi 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%0AK47+9`{6yh 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 Cu9mX^ diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/allwidgets_tab.png deleted file mode 100644 index bb69ca885d697cb33ef4876467d520f0a9013914..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52614 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�lu*a*s{OLbo2(-t%Xh!{s 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 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/animated_vector.png deleted file mode 100644 index e33f92d7e1bda4043278c91ab4a97e391865fecb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15656 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 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/array_check.png deleted file mode 100644 index 0835d5139f1973cb4fd2d45ee5c4bc753d2174d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27242 zcmd43cT^PJwmsS?hyhdtB}fzn1Qcj;wv}KYNK{Zj1qls^N>Eaxpa@84MM8ss@tt$-ckVsEH{Km@j5pptjrH|N9>ew4;_Wu5f3g=OsmAS#1DJo@v8rwmn zkf`gb-G1~33VX|(I!o8blEVs#)Kx0(O1@=ho|)rTi|U4El^A9h3RmZ}`NhfV*?z7p zx~P6!-@AMKy%i6fRwjv*N$=|TSXn1)>MV7Oc$O)P(#1oz?2qN$`61byjK2Bl$y96V zC6h8@^K1F=ttje(1$OkH6};?N*1$&Yz_;c&#i-@g&X0cdMLrw4RJ*##_iodsxiT52 zWAaSt2>1b+vn1r5`aKU@q1N7$|5#A|Of7d>x%}K> zGs*GpxEh|x3iXh7bH$0e^2k4W+**6ZN~%sPD3qKXQ-G@k&~L2`=qCj-0w| z8hn}~Bfo3_r${y)+VemcMq%`_2DP?`jDM$e2_s4T{T}7 zAufn?=Wq4ocdU^2`3#D^>et27{CdIs)X^u{_#$yXkIL(hFY2W*GLM&19dY zutLw(ndNH%fqNDy3l@}y)V$jny9m*oZyf>xUl>nUC;8}?Tev(5U4PKyy@kvu9Xral zV_h~EGxp}*? zw_G~?v>FWz{&4tTv>C|2WcfID7pAtW_{@;D-ut(hjEgVsmR!zHkN3z*yl|3evGn5W ztn8hi@8T20EUK@=J&qAaS2yFQs#g0aO#|EqpRx)+Fys=(jHE`HPh{$C`1#BoklCC{ zpf38DPhNTDAC%#q<&%5;ec^a?%X}H-u(a&*tmd=+jn1P^l`X{s$UK+ayoG_W>j{n? z|Dr{#3*~CS4a}0gBS@+&zK!{miTstu0_LVm<0MkNa<6j&bzF5TJ$^QfQ@(JN+#(e* z!^)p9Q5Q0j>{VpGB@*c@ge}aHC3{o1R(%;z#fz-eA&V&k9|C!G)&?2KLGw6IAzDK8 zWE$o0xi@VIngdZAoy4s&YU$hYF`i97pUV%YJklq;&crCVVo5ma$iQaor>%+S4=HQI zVQ@#61rnuObijh_(@hPkynTF8l>meoEWl^dQix@9Wt(H-K3<&=e)4+YclB0g29(869bqm(d zMLq$IPPM`QDChld_;nuYu+P#@5_Q9Zn%!CrZ^2N|Oe}b7)tzrrWWBup+K=5TNq*{E zgov`XoROmNJ~T?awsvWAU4<{VTE?mWXT&0-HU8^^a_{-itRk~w^{5XAm&iWUStrFw z2T|4Uz0FnUPSmSSw5~O@(x>V!yWeDIey0M_ZBohau+=T%MkjfeIFN0*Sw>wM*!%4E z=+2wCt(1*bpJ7>CGR&LU$-dbrpYODE@PiEJkdT=nSQAxlQ;2J<)THcDwjACf z$KF!&Qx=Vc?TB+Fg5v zGAhAtUVT7YD?Uoq97o)oTOPYxY1@(%pYWMe7G81*(=L!>T9RcEs?3HFAc~$Nlq9;% z_V*QS4Uj#3@&|25Dr5%|DQRT_9z>0XT(f0blZ3yLZ|=y!6p`>m4Er=`Wio%Ogcw=1 z{NtMP0ChY)AuBj#0Ymrbm|n%fI7^@X7=a@mIi3D$)NnM0FLF-?j6O_ztcLraD@~_2 zHWYnEXQj9#n|tkCuC{X;y_4lJM6ubnaJI3I?+A-?=z5zdD5UjTuAp@+WwB3PRVvO1MuZk`-Pi(L^$mW&2 zRU5#7x*@lbYOy)Q`oA60xuQL2NGc7ujq&uUo)Y^K9~G~)@8@Vy{&(*m+p2hH{C!g!pzMk!n5?vSIhg#Zw; z3TRNf#Oi~2RI42W_Ap&FonG8rBzZ#a_&`s9Dt>rZl)UqZRetpbcBRKYzau7gfsDkT z9r@g|{qEo4GCG3dgBhviX9QU%bA#zi6Hp?sd(jp?Tgz{8XIehW$8=33jW^QMqx|pU z)b)>#^@Fq zme1m|Ck@hEDrd&q(rxJXa|$s?A=Ty2=)qf8OAj!kl!h<@SOe20fz4WGT^4S^W`di} zY0Kq_juH+wsHXnz`0jW2EM=f{a~H5#Rlng@_Hd~o)eL=pUcqf8pcVZcE!r3(o&ENt zh`)b&@0VrW7^#z@BjKGH*8fB)kas-dZHwb&rV+py zk9a}oId-l7iL$s;;oV-X#;A=;=q|E>dc|A6q+G8Ruk_w67(E(v`K1im3o1C*s-oM} z)i(EJr(nnnzFG;sTB1&uS3c>+DRe;ga~mi&7SNE`v;Fmx^@b)l&7EkqX@$wX$Q3Ti^-tIcuT~z6uV8y2AasQ;4!tX)5layDlx4B#1SKhu0%|5hV!^hDg)1LyjhYO&dLiQ}Hg_oYkz|(!KGE)@*)wjR$ zcpv&w)M>}A2j5}L#2Q$)XXt77;vh&IN%L@8CXRoHp;EG(rs(6lL$!N& z1fWgIIzSAyx0fC?6NHR(+BFn1PO)+`tV6G87_{*|B{X?ux&c;$^|K6rmo`>_;bfEnHZc$j)C`8;Nzg$R)ZF^LusQ^jY0ddK_ta$ekLQg=ZoExWXOipux>TC@y z3P97p3gUmOR)4Eu|E~+zxlhZJokbnlS7hHgkA~Xpe8gMxeYNI*sujORu$EOsc(_w34xf{^< z3&)@DBzg-hHQk141M?b(IErd;i%qiKfa5F_>tda%O~|Wqv#FP&%I_!Jkm8%FDI1eh zaS!@4Kb*=19Qz(yWd>_$=sJpt@rmHGl6@EZ<^R1g0 z^da!8*m^Jmdt2!C9g#Y$pIKm8XML^I;VV4s%KC2rb`1anqe7rJn3j+CUg@6NTwko( z%c?i06C;&5?5(u5)b{jdV)(mRG2$lrsHC-4opa9Bf+T(MSY=N)QuTcB0*y7mTt|{L ztnaDsiRU6_N8#Qj-+N}_f;psxJy-i46hZS18H*v8cM*DXQ^!l`XXOvyOmv_*GAie_ zb~klc^CL&6QR*3UNFIO40X?q@M*~bFGY!&>tHVgD)XMw#J@Y@S$ukw9AH~G5hFR^O zUhVOAg-)$OCr$w(O5DY_5o*Z3eYy9BzuaaP(8^#}#d+Pl$>Eb3Wrv0JnXeGfPpPtv zP1X!^Q^HAQD=jukKIJ=>SJfsDi>zawGfK>&StE?wY>fd)=JC#IAx16oN$=CJ_`tN% zCEO7Akk>rPm_`uWsSqcEy)xwSd?l@{RTKgf(Rdy-Jk&sL1(uL>r3 z721(m%^xOC?@8vlpod}KI@9WyoGG}MRQxNrC(>>7;cV4vOf!?T;CeNe>u7UawscKO zFOU5F6h}wh7L|r5F|n!GL*Cj!G4V;=*%$E_Vl!L6v&~w~{Cxj(P#Ejn6DJaSWyw5= zs9in{Yq&=y6>>VmMZEiTNoUO7REUWZ$781DE_Q7yxeBFU3R-vEh33SO+*zx_l(s;w zT=*v9sJNU~LaTSaOr)OQD~0Bb*^Qvk{PEJ3`S*Q(q2D2E=}OTByCvor;q5x*Q$u}qT3zXNic+Y9(_Jp1kUR@q@PQu;t)Fy6 zh+K(jcAn}gi0l3MU&t5q55B_w<1_@;7)HQfIGs+PLFBYEem92c*hJ7q zk{U6n*wQItpEkKlt?5#^_H`#*?ALI?EAeF~95*hMU9ji9bvh<%vFO#bNcb*-6LG6_ z$vxhOvaa8B&u(;PcdXG&-JCtjU#m^ubWNT4oJ;fcm%v+BoqJ@{zEN6EmKi*bU6~Jz zNy>80sQoG8zMfFGdCKnlxOQS(GikB)l9;PE`{WnzNA1qmcAl_$Ly_6aSnnSq#W?Ra*W#LKm(BX&4NT9b*5UZg&y z$#+^oA6cF2?p7*mzx+zW-#5j|=9j8r7*6ILasaSv;(oter&S=QxI0}|vbQu`B{rJz zoow9&`>3F^-N5`TaawrIKZQt`V?^^Q45poXdQJOPsmJofr}rBAxdQ%^&&Qlv@3b2c zCbN!lxp7IKsgl>}VNEw0R6U3hV2n0u=7W(w?x$6~=lI^qBz6abf)!mBY;LHL^{HbR z>t9fkGjEDMhN3W6v>Uy?em3bV--bbBv_!Jw^hJicQwIFZ;ic+4k=5r%-&_!E7Abm- zu}}~t5hT;E)CJOsH#9z%Jct>|OpnKQoi^Ud3LKjW9l@|M_E3$R<&#T+B1Q z8^@IE`l~!EJT{?&mge+Mr|seXYW%fzwBNS%9#!^3@7xQC#;G z-7rh(t*yPc?kJ!g)4m*g!Db}H`t2QVRcunL>uZHmn^#?ei%EKVb4P*G>b6Occ3^#e z6A&3g1+SzJWz$qOvfS99hcys)*zRWJ9p|;V!L-DmxksX=a>su5Mwwt68mD4)IIfoL zO1905HzwWW_0@`)1jdl95F-$Gxa?bFg~auWwuPN7^j3gov@h*8G)Wg4F%5iiZW^oD zswbCEqv{O#pQ!` zY{)Il=Ol87X>@Rfq$i%=I*`3dp`)O7*n|C#CT1 zvC+2zA0@@j{(Nt6t+K#jkhAVWC;MImm|a^_Pvr2HT_CFo4jYdK+-w;?gz{XOvUA@Y zOMbckfJLFzg@#8)?VQXdY`HrOlzNLx1(jBRIy;{G2@$;esX8<7m$Px|vnu_bE-81U zX)W+HH!drXH5j!_MfCFT1$;Qf<)#WmV$UHu$ju~Z2QIT+G?k8c0LX+o6PJC^pvfN_g>-Kq26*F*K$&R?=QKPXFRy8inyK}ed2&y-GO;dQ*8#e zxm-TM1>h+N6bkxo1um)z&fQP0a96setIVZ$l%*C5T&-w@-cF-V?D{j~67_ZOY=-nOa^U*yq4HsNbyW7irOGflW94A= z>8lhazK!o|3Hy+!{XdZ-u*Uz!i2Ucn|G|^|pHXeq^4#FL1BXy-=9rPS`Qh$Hf@BeZ zIS+(SIDkd~7(i))cCO+Vi|E1yT*u-!$lRoDQz0$U=MtPwJ?M;u;D+{&*J zL4=>5v)T-Q39;WRhMfHE+X(GMk!=4%{#X@nkKVasfU(b=uD?#iRo%Y9E`Q&u)MdQY z^i&9RI1JBuVWGV?N`5 zn&#{Q5d)G$Bp5)(a0mzglw}Z{{Lc@NbF}RLb@3TQs6f8)pDzBlyOc9qxy}3}oH8pf zuJdO+ssv;3@E=e6>!$yHo4?)hzYhQQQvZ62gLY*tB5jnMQYY(eS+*eL~xCXgc%u(*ERX&ekiCA8imu#xWMqpguy6T*4DTGg$d1lHcynpRUN@hL`tPvaMOSfF8HBx6`i? zn%sEMLePq?6NYUv5bc``zKwB;4+>%B=S}Yi7N1+`;pNE#;i^<%eH3Ske5e#tZJlgK znA0`Fej@ip%m|2cjH9@PuYwi#pd(fThFk?TLe6tzw;L~eVF=DjV8$VU3aUY^K#kZgqPoqHhTau;onh~Y%O5T1JLaeACFb*XFeMsu*62U zpFExw%`fo7>)UEbplc-D=0-g|0hYJyYr(VHKFYM)@0%C+XZJ`Wq3v$`scWUsHzSE; z07rJLkr&W;-Iad;S+tlm`*_cp_x{e6(ElK5V#%-Zz4ItXs44{36tI^6I0tdX5lVyv zf%DnD{fgd4!u!-2wJ2+&qyzv^hL3Q7q8WWK`_>WubCh=(DOh*S@FpWe3WLZjxjGWI-tRff zICc(+B&I!R7-G_qQ>N{fedVs+<&U8EmEjb-UhU<6hUctkAYRp{@%C^H4NA2J?tst) z@azAUq5mJJ<^K)CAfDsb2u*w;qQfE$j0|pb%>m$NH}FSA+YP6nPGh{sM5e<)wKuoG zb~lP7WEgF0kUASRg4tSHitXA8nFVzoW}rU&+C|vMdb%BZ{Tpp`J5YeXKkh*JF$r^{D3r^o`r5e(uY&|h8=di; zsa!Zg-T0}$UQZ`MrOzTU&i zS|g}UX0db+fjMLBJ$3c%o4ZGDpdR54pqIsqyvZwR_|^-JJG`hA?*m6rY?ZtQWdQzL zZ(1WPs1Qng4I>cakCbPGAJGqKtaM*21o-Fq7G{x_z;=i067%n!7lW-#AwYBe1vctl zE4T`ifo~|hV&N@)6iA4+R$8EbmhaL$dd!343jg)T@9WZdTM>xmrAlW+wZ#F>`+I*u zIKT?Grk%S`yH3}uow{UNu>drVtI~PeH;{0pb8(J=JCJeK5}k`~rY{1q%(w;tUXzmw1G*7D=E)Q%4hgX83lZws@?nw^n-7c$rJ2jP|cAG>FMg z5wRV@2SD+o@)kJ_RHyM8EZ>lb(!x<8#@#_trP33es@Ky<(&+rkg^M+mf+vrkftcrs zKWQqu08C57ei>kU{I`H#8vE-BdFE9;ELKU8X;Y79`m1`Suy#NNa)TRziV;X*?)`js z>Zt4;7p3!37-jNQ5hGb6L*gViO8f?91cpPq1TE3h*OIJxjhpw=H^|qqE1tk*E5n5U zf`*{j&S20NuXl}k&%YStJ_j9snr#W3bz20v6NOrmudl6j12mprJmG3C zCGlC5$bA|m{tJ^fQ~!d$JIAExB7O88W&tatax6!n9s#@T3M;2MQq<&S6Eu@Dl?su3 zY{2=SdZ!hqARP-P0dSSbfN;R(0ZHzk00vU>e?I&R7yS!k{0%MrPq^`Ki0HrW4UhTt zVmCTnH=!AF;44V(IrgkY5I<7{oA|E?Z>+r1W!a4=Qvb?34~GJ`F$TAa*VtzoREJ+9 zSQcJwt1C#Lft1@01+$FAdT;D|qQ7OSBv8MIyMzQw{}&x1HQ@X*Xu7MtJ!K#k5e;7Z zV^Th51lZD?j>=biB!KX2YPd5{J$(YXcnX2A6CK(1+Dg+q)Gd4)We2>%k<|fih3h4- zczQ@6k(p)FaUj9(hL}Pm5eZ=S9n^|k|KHGt3!6!{_VPLd=aqJl+1pa*wOq@6GD!PU zaXz#CRp!SbrxWY*EQtN+w`yYnBdNBn;~Ib`qL$X+EA|z-?bRuKA{#$`5`6|5Xra!@ z*DFChl%&N$vG`Hi4bhU|r$zgcE##G|4rf_oHIk1e4BE1e(1T^hPfKcE)T~@e(RoCx zZGYcxG*eLPhb8#2uljvjQ!X%)5mC@w0HrhmB3B|OVqZb7f=uFoH4dW4-(DSfd-Gfk zW8I7L)q)j<=nI^~kU2BFf`OG?DGy^rL>-0t+MWyRmcV@_FG#fN=>jI7I}1eg zIF*-q^2DDorlQpq>3WwKKLm!CAF^tdj`d)+YCW-U8*^-j=Qig42P)r2;Ey!r>r=wJ zA*(e2^8~<}P{-p_ImtYPC=dJSU=XQ(jm{+H&bz^&9OjUk41f?_`Nva>fXVT<%mGJA zE9C%>ii4@t0yH7!LWms1V+GA?>)l`w-VA%F6|>d$T|N`-nJ|F6(L0$DRAricAMk7| znFx|6BRTJC!6#(WtZ(=>0!1I|+qk|s>Z!c6u}D%~MZ>RTkLG3ezMiHX`{V9wD7uk7 zs}OA6u!4`SD0{BtMD2lC`any#JNN5jnkiw7+wu#A9Bf9+}hs)lB`j^nfIe zzvY|19sYaj`QPN5?e@lV#bM>sJ~1nR?PEQkr}`>nV^w`{GOiQtNW-v=W`JX`0WVbZ zHktt-&<#Ccl^p7g2mbxNVU1F#MN^=_A&5p#^1;kc6^mLBmN-JYo1-Nx3y}uYbMDt; zRv02JGGo#%D_F1HN$StBe8(7%cr&6Ca2s|qFcSKF0!|-&>AC^OSE@k}$HXbQqpuZN zYv%^0o4pykgkJ|aun_Jn!?n0Rng9_wRb*<=wldvY1WoFXnCRB&B)dyZ2%eT+ogK)h z3xLUw%3~jQ#0U1glB(4LVHQzAVcMMrnj=qL`{6=?TJQb>=5+HIDC8au9}Xq*pKSmw z1r|_J+6iTx3-6sW$SjSo<%@0-*(I$rA`l2ISFZ&f;E!VGKi?vHWLmn*@-YIwb?@#C zbA&SUzx+1k30AwbnAf(u7LnM^r1J}87W|>G8n57*W%uk3EdhbAbZKD0NnE0|&_)c% z#?(}5p&r)yX)T=_Zy!xLiV@hM-;?74c@I_yDB{|2epOm1acpKXe4FiloT`SF@0HtB zmUn@Rn{zoRz%E9(^@`j%_0hIiR zmmg5JFCr%IMniwF4V;nxDSd+usqqf*7ycGIQ8oPAQuKe!C{V_h-n&mM{Au`S&OkJm zyTNO-!emv@675>*=?`!}OoV$c`9PwN-jqnwi8HmMf-7R#&gZWm78v^8F60{mZ)T|* zllih!6<+K2#h9U+d%OqTnQ!5=7j0ymkDDr}<5+>#A^V?+Vr=+O6J~w55=JC-r3zX! z8E9+$y-Ba-hqp7dI7Yw=G&?{bfCcVUkhaLHMKJwRQ<4BmO~n_sbJAO0XPBY1Zuh!i zc7uI#>b;sgF=P9}{S$!O|M7e~o%w0W!TK_g)Vm5A7T|_bL>%vqSN1GK6g@~PZymbP ze`OUN{2p+5IK=$S3x?!p1Lbo05R&--edZG`kgJOiHR-~`C1|)&m!aYgJJ6-f(GnUI}7yo63OKqILrItO|H9OM7`#ag}!U_h0;J zh$<7UOy->__IV*?Rr}j@Tt?5f&K-bd-%=68psZN~=+8$>1MTfyXC>;iaJ{<^FMlrv zGeFgzb#9-{`PS99H*5Sa^3=-NbdyXPbvS9{8SnWr01&+_zP+aRMR`TP zhg2{vHkw5)6}gdoLAY-Pz>TPDxLD=f*%};TCb}u9CS`_X@+*Vi{(?%e{_`GN7sRxN%mt1gr@k#Zp%iY+G175`P1Rc-oW`zyNtq&8&Y*Y$O3$Qs&_b&~-fot0nQ_;{bc9Nw?_hz9 z1DB9zH!Q9q@MM*N>xz0hxl}l28Mik0tViw?j3Zg5W=@jA3IoFu>z~a=#Kt)Q%0&WM!KTB>@Ld7|WQd7Yfh#4WH07JrT8o|> zaR6L**W7k#lbC2y`U;Z6bP03J-kz+Ev3((RG>{^9yBQz|B0#NdH!Gs9__c=ejBiAP`V0h1)ZhR&I5gb+I4*x{ z?S6%IDjSngn!NBSLw@{HDgV6+j+{Gm1l#7!g(NaS0D&9>W<4_(spi?E+R&z$q|aId z^_e;=7&F&ua}pUpM!IuLk578ODK1ylc=f7Jc4W_m*rIPoUge(E4QT#ghYILPPIBZw z=sMxjD=ex`O{jDuyNc8snu%nJVMexA2gJPNi~X}~X^oTvQdSLlM$C+RXiV@l2dzA~ zw)r)wq0Fi37I!J4Q=^GN>aG-{CS8}~prL!an{vrw!L-6!CyX}ZSBINAKXMGN7W<#*Tv0aUVnFG(ixqUJSB+M;4G z73j)`$C0O}IESS)U6Pn8bFheUk#p}Rcw3G?)$zVXOBfoB*U|5~;}Q;UMG~%m;!?gD zoi9LL9F6zP8yuY;5jeR3L(yryuC4ilCGf8P%9^j%J$#__YgldE1YTxsrFHLP@7jHi zG^tb(nA1AM2cvtBbDc8!4I2GntBbn`&=SaKmkNRuTu)1I35~YJW*x{4{q;h%A8=;* z!rP(OEjfpa#!F3GD%vEOt#EZB`IW72&1jE8oM;NvKZ$k{AX;c)SqH*mUTm&bNDm2d z9d=!r>P|~bUz>H~JBMHA0_13G8UvvG*NeSq@KHEo&4UC|pkyt1iCJ^bkm%V&%+vXj zZ3i_mX?iVIPmOk_BXh7HE#Zj6y>k&2!8aeeKB53+$2j&}+Ue$jI|cPFuM8rjeP{^- zdc{B0B1p*Ak+%oXd>h2yt4(5O*te{|ZAS2DtBosMy8X;hGy3Ab-*WN1ZSGy3qLwcP zWHbUJ%-ZaLi`G6j2VyA3x{Hng>#>AWo#p9+Zksj$$e(EYKXvH5aqI;0Fwf=q=A<2~B5q*;5G|xx0fP$#0of#6h{*L$y&lZgBjK7gs zi|!77`ZQcS&p%dcstrXnC*++;se?)W-nQs>Vts}aK;C! zXsCa*f{wcz@kw2aP>Ojm^sXS9y%C-&9NN$$aZ@Vh0H^FwAqd zOtE<1?coxMxy~KI%Y2M;L^CF$;NkpGnk(YV-u@;&FRU0Gr{>Cd+YyjRb#C%I>IA*e zy-i{&VVDl3X3!D9E*F?~TQI2B`8h|Stu-3E=aD}+E|2XEFCRO9ZRHFT=K?vBkViai zJ=8RNw1LL3>P4ryXKtd~Z%}=_J;YnuS(=nuYMHco^ehk7h4@NQl+O+z98-vb@S!Gi z07bbWw}LGF*H)w1PAe3Rl!dt4Esz8a8PP4QCx|{$5hXn`8%O?>0ehu;DM2u%et~Qp zSFoBKrjn(+xak}?%0;^U_2mghZ<|)$wmZdas4xJC%?mzF2;XHs!_Vs&ilF$>9Wa}! zdLpfzbi3KjlOlzulMUStodZZo$R>_t>@J?MpzAa^~1u4B*G3phiuKPW{>V zM#b}%TX9&MTfU!MTnwJXxG}RL??CX)?`L63zO(T3MgaAP?yWWGku=)Gm)HcVK`80D zJGD^}%r_4LRep$8Lua*-$q3^9{7%+uA7!$W<}+g$UeSLR#WrNYqBAjD+(DWE8?I0# z@|uG6#roF9X8vi>TH?88lgItd>t60Z3kX0m$4^TuD9vtgl<$XO(4M8%z?p?4%el#X zVxBJKHz*&fflxoiJYmNTR+9QfHTg)|1Vb6afdbKUqHo^=xao2D*jwr-Imm@lCF))J zzts^Q?*9A7|50(+IRvZ-;{6+V)3<^ok**bJ0aTR20)U{nvXQg&8Nlz+<|5dkHVZwC z9T3x12t;P=aU{a>@pptSX0~QA;GO5{omA3Ai%NKT#!-`E+ZPW|mro#SuJSeL`uw1$ zTvY;6tsILTi<=g~S1QE6ojjc^=8n`#O5cob@xe;JyME<%^36LRU zFF>ohes*5i9OlbVBU$eSyIlVEUjPzKiaP;RYv6AJR|MqFZZy&e?nZAa`8Gn?7>}cY zmXN<*T*+5!gBroR6YdktTl01g8q{Tnu6|k%m>=kJS%mK?&+qd@1Wk8I5G3@;6li6i zfy--hd#4^00~rF#4Z?v=cNe9*>CUf*ta8^u z?c#pS%lyc211u!tSKcD%!5jdOJLdZU|GA}qP#OGzCBvOY1pDK8 znbiZ=oT`jGh#OTu5P_3x71_Qg1KyHIlF+up5!up37t^KUbBf7$h+NQE3++T~^F6?3 zdAkT}Ikm239DB1QHks1 z5B*ML(}C>N(bdBVMB{`^KsgUr$LGe}5_-Y(e+^HwCQnCzvLf$czqw*)*>dvLlVb7E)wYT9NZ4uU5(=dOt$6p>nd$yv_Rkfem)V-`jC(&pyrcT~ z3+f?yl_c$0nT~$lpPm+eS{&k^fEu^g4xXnPNF{%!+5@|r6IawxVg%`#zD`UUa_tU` z04`qUgc{%XygkCXdjfnd-}-88b|jelur$ZT0ALg#4*1gTD_?ji>(F(1d|i|JBFR^J zhh@4mkdA3KWW=pAMLI+ys7wK@YcG9%8mrK1TK=$fdPAdRFPe!vIr(9k<|%KGrJvHs zOn1dTfQkg{1$Q>5RV!*>hRXCvQ>I?cbs26%J|6cj+YG}|B5L=T0=|KWiSUDTHaMb3 zUGrlGv|dJr=EZI*&A-bhVhDTHphV(U?Ad{J=E)U?cOABX91& z^3#4=e}I>`BNjtGBv?co@8X`~GcRc{*C)M6E zt9?`baoo&6mazaMTB1DHZ2G(fphxDkUL070Q%NO2E342UI@6c!5uf4>mpS)YD7;WM z{KxKEi@Kd$R;_$hM%0U;zGBm}%v)+38%b?CCAoPb8*{(Qo{vNc#y?E59OSrp3b+vI zDTUA%KfV}NB@~P4WRnaztonVZTe#SRPDmB){cQ7IRj~GwpOzP8d)>j7l9oMau1Joi zW4E0I1mqfICu@lZtnh)RkENcdF=|@u8%J2Hb#=|@^F5j=2Duk$!+}ZCR*RcCS=yjV zHkP()p%?I8iBsTVbq72C(NGBxPxLX?K>2PRv1&EV&q~b1;@zQjKUx~rT!YJ`@zq+m zq-brd>@s#a;nmip{DxnOPm6|J=CLgi=`1q6aD7S~){@v?`KoyMz6s1j1o$IX?%8!{W)pq22!rz| zjZ@3R8L3OG?y@Y)N5}Gc!$XZdfaLOAu57JVxh)Ve+2r}|?%>&)?fs#1iy3^`R8fW9 zokZ%;b1@k%#paF0e-S0lUmZ_vf9A*sm(4c+{!m5zFMh60$q4xC!7ohB7}r+O&*X z%8vQGjt;6mDyA57ccCuiZfh2AsEW|KcQVf<+`wj~oCNU_#U{UM#k9eG%o=~e{!9?| z@h-{wSA_I5F^s_0bq&WT3oO*70E{(ghm5`Is-eiPDBYk9#-%Ix3*;T2H{`3_%@H>Y zvAzDu=4+L8Ju^Gi=%g3=>*NOdIH}jgli5s*dzFQy(eu={GrI_d&(i>+Y_V9~N-7j4 z)_Wr3-=mw-XnICH$w}MdnPAz=mEp|Q>;R*JMJ}7<8#=2^y6FiChGGL#?ZUJrd$rUj zk1nrp9pSPOC)XQtsT)eyBc8<6jT1B=pTKQXE?JBWvcby8W9#dUdF2uxvHM_O`RY}_ ztc)9BJ^4BxPsRnDK6^o7O2L}$&I8IAK30Wnyx3G69(p%c%C7ZInCZkM=UF2^txY0( ziG^!bZubt*j99FOu8*&08!?{gggCd2rLwKO;;;_6!oRc2?x8GWgf<`LcAZ7OOlvZ);@9y{5shLqE{ ztbzm%IGp&=0d8{G_7%vNZD-*Zom)0#F}19d-J+V>p~MXw(X9=@2pN5Me^-uizCQAO zOG5U%9^O{EOsi!p^{K0wsK-^Ax2aFvq#9mjHU*L_Jt)!Cw2l>c#90N{$X1KSZ045r zV->=9cZxIkY3UvIRBkM;h+KQFl-m?&o%MJ>T3wo(FUG*Mqp^0GWx5TkoN_0?I&sNM z;xmpAQQp>K;tJd7g}o_k-LGbNN-((^{k5*C&fV?yl|8w2(qO+7vimj2T{vywrxkO=F zA$P?Ff0Bda+N>ngD(u?(*i%w>u~TB*tY;v(S`<@8{_^_|tFLHpPCK^ta(cH{FPC7y zokvbIn}h&5c-?M@OT*b%bgzj^vyO<$0T=w9T;B@}-eD@23mi0lTC}&PawTNb5{lW; zakU4bsMZ1kd#J$hK4a$yC6V2%BHzoLA8^&Gx zv#pR9s|_CY3Do#_H0e#in}ak0F~`2`C+f@=^{q&t1&NN0XRf=xdq5lWj`FU5W4TUs zn8=@@p4b`7eusQ)qr83gq{4u4x9mu1=4`CR#2c}d*#V1K3Az4zN>NK(buk7;>4Ran z#TI5yEBIYuL>sAyWP)w8rf+zoZIwIWnJxC)>f*Nq8}RNphH)jVcAbvD@+8KXzYO70 zBstYG_OvXq3=PmH?Mhb7BT{B-#y9BCDuoShhAQ?MY*js2e5WG&A6uDiXDp)h{B2Lx z-wwAmp#L(-0-N-=yZn#C@4taF?M9q%zhK<`aAx-y$6Y^{c-X+*mykA51~&8Vg64;3 zX)?(EeEuYW+=XT!_{Y5Q-LM%Bd_lzsFlsm=dKC}k{v~8r*8D+#9DaSijwiO%3~a8v zu)}MZ4;*FAuoWrI5y0beJst7~3}olzcR=9n!U&WCvExuv3Qp;H{=-()R0=t5vfO$QG?5V&<@4fduN+cXfvij6eyWpU3uuLu1ZAY z0Pdmd_nO(*+hd(eDxx0h%vZuzE_1Ru#RS0UI(fW75^+S5T;pK7?RYtO4JJl|hDQfR z0Ty4f@Z8uhW>((rVm8mP*lV~Y`b7n-BQxt-KIG}L5|X>DYTG=+(Aqr1_Qo@Sp=Rr^ zX)YhDuN7NHgeUm>AYYL^&W89WYbFkDu@;m95{Pv6{P#_{kUprpJ=4Jc=9{T|$>$ud zUooTDAU&shwO+EuZ2;=C%N84meFkyDKb%@K-xS^3n1vAlHXC=AW$Jdm$PU}|$)HcA zM={nNSw>s~qo6PpfgR4!<5_`4OTj{KC5%;S-u#EhJ4@^XR{JI-xkhKFTNzr|fw>E? z;hz00#`g%f7Y!1d+s(n2iw@UrpPz$v!JbZ|dss7399+!$b@5=*si|h7y`}$NsPfxu zk-hI=mJK%=RQ6UEt}cL=*Kj|2yp&bUd}_k=^J2*8k6vD8X|eHx^E${L?)ytdm6O7C zdzpB9%q(;GrID77CRylvyPpj^m>)@Cro1{Hli)FN(%yu|MX?_EowWOW`eop~2^I7n zjeFqXy$M>OOHPcgpH{oM;VCOJzvyrEQwC6?-sJ(o;QFT=+Mxp~Yi~MdB_qv*gzGD~ ztdcIIW9u`X3nZfX(k{-CJcj}W{cC*_QL4{*nYU}X%ahB^xkN;>BH!QY%v*hmx;~}WC)dOW>>O#nP+*u z6Iv`LAc7qCZFLEFCrqnYdb5|XkWS|kg6u<4oimbAyAsC8ZCLW!_0-NIaRJvHdAOR| zY!3E3J%PGNOBfq|Nipiqd}P;gPnzPZQ}#S2rdaIarv9wUW>SfN&*5+C7y*jHj7xk5 z)5X>2`zv!x!$NC}U?4HwO}qx}QeCI%4_^JzuXQ{D-2d*}OU339r@XB%c0!NVAdJ2GC4cs6con|qi|V?A46 zn8ZY(06yNTe!j$dKVpACfnzl)#5XIJwfx3MUw?Z<_q;?;Na{&6KKAI(D*QpF+YNk8 zc8ljDS_HSGu_vd8SxWXAjhtf7*fWoqeD8)L+f*kp0(pvkqrfes=HG)3l9Bwy^oly4 zqH-NDO(q^MiEGrn)7ZzG`a8yM!#>D}Tk+4c!k??tcaD8G?F?|JnLp>ZgcFnSE975sgwcD(>aCxaN2t!ZPe@z1nD4T8cONvY zCUX9Ttc(RSDXP$Acy%!5#`q-p7*>4U1)}ulo}$2Y2h)((JKr3@2xK)a61^;&!zc=N zQs>m$3@rA(`nVr$ce5{VaUS5ci;x#f{1%th&<0{$Q>h|RcB5OAdZu}qoA_hfp4+edL57+3a)91vW4#`^-S2=(k;8CRd<)lhU;UU zmp|33Cs!KM?WcGu%wH=(L%p5qvm2mA8JyTo|+0upW13%d6nuBsj zbjP2wVcL2Fd;CrDfnOV1Q#t+50#)F*>2~`H!>l&`g68>L*b=>TaOv@G^gO$c<|)Rf z)bXUWtcN9f6=KD~8kV-F>KnJvh~L-QqeXEe zKHN{QJMD`QDt^{8H_2xAGPFAAtx@R;|BvbMFka@)h&fxb%ag_3B8YQh*!8e$zhft@ z8~{cC>05`#bc(t(a*fI@Ku~Nlt|DZJnWgd8X8pMxOEc+RHL5=^O=M>fgpB{M*3LW{%7^d&Qz{Zkd?{t?TSC@hC=;cq$Xd1*MjB+sR*ZeA@ueht z+gOr4*^-@xN+Jx|jU`E98cQ+u?fG2p`+R@*?>Xl=&wcLm{O3&L>bfp-eb(3eJ%e)X zf`^1-tZ)u$ar2ia1Z$GpqaC!fF>Z>Rr8YZdzv3U1=X_^s7SH}%tiEG?T2@Fz z=+B6h8T^(fW1_o*ZPYlkzUY*7ChTcVGct*)U9>6E=ZfT3jLT}r+x_kyw}u#8g(kJ) z4on{6Ec(@qol?dO%$i3zm^1krH9wG_EHZy8CtE^R?7qT!_RaqzHmAD9tCW!-r=659 z?f+`}os`Ctf(xV@#euB{AN;=b07Zg&@UmRB5 zbhBc#Rl?z=&uNK%eZhe!>1`BOkfpv?XxHHzJ<~z^Etwc%mx+kwAIaGRH?f`1{=hgq;>AQH zO5`wUqZM)zP1$Y6`)`By(+BBlZ5m%L=Ud5x4RhFgReNkRA|uJ-Aq)ZTbSLv)(3EBw z&UL?}AIvSdPq#|dNvRIfqYhrA&jucl zQacOpN15>W{%&Cf^unyGPf|JiYB#dAcD0-_m3qLJ!{Mnn<3$g!20SFAX30!QKCxF7fZ9{G;t;8-a~gBa)s(fM^Qm z*#!MpO%1d#2++>5D8H2sFRff9H^JiiHGEQ7JkK^;cc0eN7we8t%gat(NBS{D z42Spxb+@QBV{989_7=1a-vuxMA1k5X0B~U6Zwu%!X&)m+2VLc%p_V5JZ&=n$L06YP z7q*>mW|;~WB>H_aAS}2R5BG<)G7d-x4KX*GUi?^C?#_r=XTVTpk{#;6fJz`}WPp$J zP=RLaJy>>(UIHm{^%e@WHkd?t(V}Uy9E;XhmVdp1eNrdch`#K_%q^8xALiHtq6In9 zN(Ewr;q=xE+@LOsNneS791v2qGTnG#8J0WQ*Q%kk!Z>X>OgW{5OakYGXk*Wx7=(uD z?fL=?uhzFwz%?n;tjA0$p$4F?{!Xz%Fqg}4`(P8BTY@xQyAd0JY5yWl-7G|CXx4aP zc0rsV--{t?({uxtVTGDMJgfEM+@SaV%qFT9w~>ac7HXUye?an#{`pSdmhOj}Hf)Z* z6WLOpe*sNVt|2@9)ZB##xAMw0!Y&$iTx0eHev8u?!`0wJ;xwg-bm#Xr&m;JL z@ZGXVSR{6u4L$>)y50NRv#Ei~?t;a`aj9+oI1ps^x>Z5DmYc5!Qs?h);11~bohj@G zEt!Sa%8d{m;?0*`UY$vr#*&}H0%R8bVbEbzW+{YEDbHD(f>t{pGpIdtb#?KKwbaYb zuu%_CD^-KegaV&&lJP>xku9oDy&Xj@uvA-uEBnB2*|On1bLo-T#d)aXyW$!yPn5zM zKEq#a)>elYc0fUEw98=i#&mF?7pOX~IE$_tP4|^BmG`$u3~1oo+9r`EVc^v&)X*l< z^&Pb{$g;MP=>rSOxVgRKyzZ!#CJ-Ev4c>{T>8rL5m6U2qGzQS|MwQ1|b5iXSm*pBBEx-j926)BmPUzm;&QxqgD8 zH2GVDDcwZNh>th)TEb0D&8yb@e}sOkx@x@TP1&Yz5oOKCJ68e|mDhi^H|9=Onkpsf zXi)aPcsZG;G2ivXEnqYO_Me@96ragAjh;H_6Wli6)7RJctLKVydHRnsGfgRvLm zbxM)k2fcWeT-SRJ{P-WVc=LsRN!RA2eZ|7G2z`5g4Aa;_qU*6vW`PU%{|vp-TPsf4 znNI&jgJBxsJwE4JY+yJdr z`LvrHXnLunYcGjYX`?%}qbTsfrQOl2;TJuSl=0fJilKdq{X*($uHWxi-QOV%nuC;pupM&kXYkNVz1> zN9klHmR8=jD)em~e?jWZxb55) zin14};)2tXwTo$NEY4k?vtTArFzhSlO0+8H%^4>#swm?!29`x}$mme%vlw5BO4`6s z`Va@2p{8)t>hPd`#WuqxKZ1v2#SNT{iur1##S4XXPsV4X0BSr-DP5_#O$4Aa`175N z3Qg$%El=0#A~0yWg7|67A@MJsaD+FdDeCBgdDFt>7~G~~oRRIno+LdM4#ZiO$@#pQ zCJsFi#+D3zMHopa=c^mqgTKNU`h!HEEqu;UtI$gyIp3vv*;V%boko6q+x#A$F@vi3 zr`je(H;%qPtKn{9&K5zxusBuL8lYFO^;GKWD;xhrj}v#r*iJTz#R|j-4E)NEep((A zLbf|n5&@0xwKxblWp+Y0x5Td~wz9PmBxtVe6fZBqV|gbEIIOVq$3<^lH_UdoklL)@ z(WtDZS{>w7JbE}$R>1cl;w~gv|KarlL+DToca0$3Bg$H$L)Egpa2~ z`L_03CO(Xu%z<{`IU9KK@xIWO7y<72($b4LKjTkmY_<-N_G;1~ctlPgk*HI!TA{-X z{i++)PW)Wdrsu9vi1PKP$hTY-PDlI17|>FvsC%Rdejv_%b;^9d6p*w6 z&R872A_LR!B4~tV9-3vBtMHK|7!e)6^QU02`;ti3BP|?C6z7jW2@2ku0KN1Ny9;@= zcHciq*(oZJW$3_KoKDUdXz3<2fb98X9fX(;M#f*A$$y!x|BMJ^oQ>38`sJb$pFXZB z!J3`z90(hu-Z0yN24a)Wm4jqZhZeo2hWiffjAO>x7g*|YNcP?pO2aH;ON}RtE5mre z8iutG|8jO0ql2-M_s;lw0qoWrf;2oXL>w3@y8B$($7{)#&z2h<&iVXGXCoIB+=^_H z{w@UqMmYn!l|FRk<8X^p3+oIc+*7oz?xC;z{*k=5_7#V%h4jCK&B0QITdH;07!zEA z_&L#?jDqkvacSugnaiEE?&qVnw+=@&^AnW!EA?wie4jr?ILozOyUVnaTjIo{3N>}= zSb3|`ld8xAg^z&G>)nYqZDotaapj))9Tl1KnR}lKe*m8?54x4eOUz8e;xnmx|K!EL z2j0YD0egSgX1LD4W8S$aLZ9`MUtM+JHo8|gurM8tw2dGCGC040KOl7|)ZPBO#YFMI zT|6Cn$e~!)%*T{lwj5}2vj+XC>jbF8glFHUkxnlX&kX3bx}{ovXEV>9(nYLP$a-s< z{9(PdH3~lu*_7yTacg-o+=q^DGxy{9?f+qZcRM3{&=6a!fO@69?cb7XeboP30{R~c zyG}*{QGk1mn0&yPwF#!sPc5N{r9;=8H~?Z5I#|e2Xo*-=CX;z&7LNno!toVHTNTKC>tBR3(a(%zj!7A3_~LZfAzUU+1(f|-Zt z)E+T2>a0kercSeKC{)dU{Fi{`i3;`wm;fVvKu01!&n)0t#ghw2<>(p}S`nYTV%=Kl zPQ!F}Q0q8sz-GsBZ@?tD$yLmJTNSd~e0w+4b~>Rp-9>fZ2G`d-yI$^D2-)ZS;@Dvy zLfmWvJS?H}yQne_d%Rh#XRpi&ji`e)8i}d|E+K63lkJ>lVu(4aUc`bK5Auw-rsQ`y*s8PX3Gi z+U4KJl;OQYET%_o$B);u^;*K`*GQl%$3ADO15!X@Hr_ajdbM>61yq;aTPZ+8h2MzM z>3&cSS^;)um#+knNCbBfxoI^ceh#_R{BEnCGGXjq=< zQ_$&%I2gI_03a(pMn2B8jV6hma#q9}Z)7h=g@%#TUJV9v_TlWP3frzW>pgjp;18eu z)dO1Oy6$*z{h`f*l~~#kR9{NUV2IsV3C|0`iU<#ktZI>?M02P};z}_z7SA`{aU&G&k2vCMxKgXs zO}Cvn(I76(^L`HMJ2xZPMg;eqvKB+6N&!0p+fQB?sIUe??NN24HVct_HjJl%pNR5t z4Kt2OCbQid^}LVV1U2q9Tl)ID-c>ah5Lm5NIq&D2DsS)J1J6?lm>Ps{MO6TgB-gpf z?#ucNC+jeG?EXC(8dOw=x#8b1^;&lvS-K{^*KPJ>>;r;0{R?9H3#-47nzN?H<};Cj zE2+D!)hMsIQ4bxvF7Vf#iFT3cu0G^9ws4%6fS6DsBx*CV>D3i?;aBOy??&lW|Lu;1 z#Qc9s|NrI3e_N~j?}~r_lVd~9{2zqHP{$$%+!G=;6S)2fg{pWM|Mxrw+2{YqyZ^tB zB37^9ZUA}05%%-+^YYY(iEhouCbz?pM?4{j*+;6+S(HGFN`r~Q(3j7DL|`Y&HlqEm zDrmZCP76TBHy}n#yi`L9nrxs zVZ%%6TAx!|X{jm}Vql?D3H_sbTG3AI_^WY*r|r)RL%h{IV3TVHuLUj3)Vo(tl=R6h zH{#Y}a>3Epw#GAGl88dSFru#dGtPVD(fC_79(Q@EbWn8?KcCk70(qz3UNghjskqaO z4zYj3*P0Z*49S|-d~}#gGvosH>ut7;+*H&K8=~Wg=-LB#Yx}$VZ`J>}&Z9Q=d>mxi zO-K$Ok2TcDBF=!}*DXV-#AGhTfYKdkODAyTrrEVTv+RCu4qhadko_K6#j))g-(D%GUP?NQ#8wAR^O3NsQ)$biE;31j2 zytN9HALHPQN%QD)DivQBC*SFXXO~#fpSp^eJ3HY_P9-vE;pZq6hZ8;E-KRsckpF<_;5A7h3}JwktuRcm2ov&CdP;$C2)> zPoE~b1IA%Sunn2H%dyQS$$u{EuP21c1jyRA^B23T*NQW8MZLdAPh!YiWWBvG3d;O} zi#JtQSEs`O`}lzqS_-=WS)lhzAd729IBDUB@8_RVO{kNWo&zIRe*)kBAPr1J?6b{s zU+z#)ynY?}JE2xM!Fyn$%eJ{c z3%A2E>(O2Y{7$`sLqHrU+Nw6i=GvPT-M5DmT*VnJd`S6_yaM~Lk2fm4aIbbYt= z5nb1IQJid0`;)pDJicvt3Dl82eyi216E2g-;98nodu*RrzD8D^d4hI;`384&0NoHEz}Zug{Qc;JSNam0?H{mnhjU$>ia6m-f*?RIb3{)8CIn5yb6_ zw_*PZMj)r7G$S9t2_anmh`^on))=PopKee!WJha;>&0Wx1+X;RIOENQkH2^ghgY2B zQ=&wu{gfP9^|n>}fwZcU1F zms7I2YOT&cxq2&<`WW$8Zjkx7Zm7mc3#r7_?J`kz)C_S}d{~Ja1c~FMBJzJ+(!Ti} z?w6UMT^E!aSxJjEqHALHMn1;XF;lh==K4NWormvQA?V*@Fqw@WgZ`fL;NGs8fdq!? zad-mrb|`~HB9Gt5xpcsT%#~gOx!;_8wkli$VnDE2VZ;cBkgU1uSn}P9QVui+df))z zdc@Ih_ZmWC81gKrZq%{E50sQWbSL0Z&)K2WT7w3q?RZLUnUw-^wGuiFwMfnJo X5xU5xPI34SDU^=3fmYrrYw~{qW<*6M diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/expand_horz_layout.png deleted file mode 100644 index 781d617cc975d1b0bb0ab14bc4574daf2f283d15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2876 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 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/font_test.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/font_test.png deleted file mode 100644 index 7e0c29afd41d30cda5a1d0ff61e855345593bbc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52171 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

s0??hNo|e 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 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners.png deleted file mode 100644 index ffba2b504560e2e57a7fa31cf55303c6fc1260dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19542 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 ULX!ZvFO0+Zve~7w3)f@*2gP<;82|tP diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent.png deleted file mode 100644 index b73b359f1270bdf20cc55d71e1c795a91bde6c96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19497 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 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/four_corners_translucent_land.png deleted file mode 100644 index 09fd2790f213b48bc8f83d6be6d540e59d0025c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21113 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 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/scrolled.png deleted file mode 100644 index cf1a769f0550c6cfafe67291f1c6b58b9e6f5076..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4474 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 MsKJqJ^|QbH1KI$J-T(jq diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/simple_activity_noactionbar.png deleted file mode 100644 index ef207272b4643f36a3249434a1b27e5caef068d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8177 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 Ola+q_ph(i_<-Y-WCv0p0 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable_91383.png deleted file mode 100644 index e9dca69281be02ca5c69ce51226c1952ad8dee80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11320 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 E0nI-RfB*mh diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle.properties b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle.properties deleted file mode 100644 index 5d08ba75bb97f..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# 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 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle/wrapper/gradle-wrapper.jar b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 8c0fb64a8698b08ecc4158d828ca593c4928e9dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49896 zcmagFb986H(k`5d^NVfUwr$(C?M#x1ZQHiZiEVpg+jrjgoQrerx!>1o_ul)D>ebz~ zs=Mmxr&>W81QY-S1PKWQ%N-;H^tS;2*XwVA`dej1RRn1z<;3VgfE4~kaG`A%QSPsR z#ovnZe+tS9%1MfeDyz`RirvdjPRK~p(#^q2(^5@O&NM19EHdvN-A&StN>0g6QA^VN z0Gx%Gq#PD$QMRFzmK+utjS^Y1F0e8&u&^=w5K<;4Rz|i3A=o|IKLY+g`iK6vfr9?+ z-`>gmU&i?FGSL5&F?TXFu`&Js6h;15QFkXp2M1H9|Eq~bpov-GU(uz%mH0n55wUl- zv#~ccAz`F5wlQ>e_KlJS3@{)B?^v*EQM=IxLa&76^y51a((wq|2-`qON>+4dLc{Oo z51}}o^Zen(oAjxDK7b++9_Yg`67p$bPo3~BCpGM7uAWmvIhWc5Gi+gQZ|Pwa-Gll@<1xmcPy z|NZmu6m)g5Ftu~BG&Xdxclw7Cij{xbBMBn-LMII#Slp`AElb&2^Hw+w>(3crLH!;I zN+Vk$D+wP1#^!MDCiad@vM>H#6+`Ct#~6VHL4lzmy;lSdk>`z6)=>Wh15Q2)dQtGqvn0vJU@+(B5{MUc*qs4!T+V=q=wy)<6$~ z!G>e_4dN@lGeF_$q9`Ju6Ncb*x?O7=l{anm7Eahuj_6lA{*#Gv*TaJclevPVbbVYu z(NY?5q+xxbO6%g1xF0r@Ix8fJ~u)VRUp`S%&rN$&e!Od`~s+64J z5*)*WSi*i{k%JjMSIN#X;jC{HG$-^iX+5f5BGOIHWAl*%15Z#!xntpk($-EGKCzKa zT7{siZ9;4TICsWQ$pu&wKZQTCvpI$Xvzwxoi+XkkpeE&&kFb!B?h2hi%^YlXt|-@5 zHJ~%AN!g_^tmn1?HSm^|gCE#!GRtK2(L{9pL#hp0xh zME}|DB>(5)`iE7CM)&_+S}-Bslc#@B5W4_+k4Cp$l>iVyg$KP>CN?SVGZ(&02>iZK zB<^HP$g$Lq*L$BWd?2(F?-MUbNWTJVQdW7$#8a|k_30#vHAD1Z{c#p;bETk0VnU5A zBgLe2HFJ3032$G<`m*OB!KM$*sdM20jm)It5OSru@tXpK5LT>#8)N!*skNu1$TpIw zufjjdp#lyH5bZ%|Iuo|iu9vG1HrIVWLH>278xo>aVBkPN3V$~!=KnlXQ4eDqS7%E% zQ!z^$Q$b^6Q)g#cLpwur(|<0gWHo6A6jc;n`t(V9T;LzTAU{IAu*uEQ%Ort1k+Kn+f_N`9|bxYC+~Z1 zCC1UCWv*Orx$_@ydv9mIe(liLfOr7mhbV@tKw{6)q^1DH1nmvZ0cj215R<~&I<4S| zgnr;9Cdjqpz#o8i0CQjtl`}{c*P)aSdH|abxGdrR)-3z+02-eX(k*B)Uqv6~^nh** z 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 \(.*\)$'` - 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 "$@" diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradlew.bat b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradlew.bat deleted file mode 100644 index aec99730b4e8f..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/proguard-rules.pro b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/proguard-rules.pro deleted file mode 100644 index b0fcd2d26ee6e..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# 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 *; -#} diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/AndroidManifest.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/AndroidManifest.xml deleted file mode 100644 index 2067474351b18..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/AndroidManifest.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/ArraysCheckWidget.java b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/ArraysCheckWidget.java deleted file mode 100644 index e7f22bfba00a2..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/ArraysCheckWidget.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/MyActivity.java b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/MyActivity.java deleted file mode 100644 index 59de45784d297..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/java/com/android/layoutlib/test/myapplication/MyActivity.java +++ /dev/null @@ -1,35 +0,0 @@ -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); - } -} diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/CustomCalendar.java b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/CustomCalendar.java deleted file mode 100644 index 3b819e58e45e0..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/CustomCalendar.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/CustomDate.java b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/CustomDate.java deleted file mode 100644 index f3877f1b3d903..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/CustomDate.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/InsetsWidget.java b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/InsetsWidget.java deleted file mode 100644 index 36e5c26464207..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/InsetsWidget.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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); - } -} diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/package-info.java b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/package-info.java deleted file mode 100644 index 58ad46deec2a0..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/myapplication.widgets/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * 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 diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/color/gradient.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/color/gradient.xml deleted file mode 100644 index fc0afa6617513..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/color/gradient.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/adaptive.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/adaptive.xml deleted file mode 100644 index 8f862c86873cd..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/adaptive.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/android.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/android.xml deleted file mode 100644 index 42e3beb50b814..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/android.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/headset.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/headset.xml deleted file mode 100644 index 897c4113ead67..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/headset.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/ic_launcher.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/ic_launcher.xml deleted file mode 100644 index 67481d4d0a682..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/ic_launcher.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml deleted file mode 100644 index 0998b25a221e4..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/font/testfamily.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/font/testfamily.xml deleted file mode 100644 index b1e9206bc9f64..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/font/testfamily.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/font/testfont.ttf b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/font/testfont.ttf deleted file mode 100644 index 2852302935807dcfd82b8201014fe22b8ebd3a83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133372 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¥EaoenoywenSSy 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%0DX`?L?5P)&`0TG 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%0DNS=lXa`PGK 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 `lNq)9J zxNcR#^oA)CjoVX?4dBya)9du9Ky}5le)C$lJ-Bx5O0PTXnQX4#P+d`(G`GW*)FUiQ z6c^m-aJY{z_N?)Ycw~jb<~o`laJ;Y z5v36g=la?8Ji0z0{i(v59pTPlg3uN>&;x5y@oDh(3V7?Uy{W$L=Gy+%0}VGT8j~7CSC(R=U9B2k6m{HJ_jz%W?a8f#bN-8S)%AntjMmZ8nB{At^-h z7($`!CM_&<2JQ`qoz$?H_c_zZb@>rFH_UF`2)QXUhXSylW;@-)R*Fc293MP^4#fkl ztA`J>ymFxS=DPZ!OnX0LE3PWkY}7Zl8QmrJg0SA+ysLjs%Zs;oBSm)2+7mgx606gI zyZ7rfa5R9!0wnyR)&vPFh24pe%@sag7A!1N$x7>&`O0Eta#>m7ahK6#a)rY_-(^w! zT0vnVgnz$oHWy~P=7XBoVFPrT{^3I;d?afpGD4G5J`ERq9U)E2B`R zw+vQlT6Qfjz328wwM(1ht}dhY&*mtWa1bvx%0!n?F_uJe7E2hMj34eD%n-xyjd1Z~ zz{~J-W}xvV1>RHhvGhSDfxIqSS!kcblERTzL$~IIjfuDm*NsX_d^SppV6zE1Cv?^m zWJoCVc-+Bz%a1R112wh)hbBR-p^yeG$BQsM;CWqElP z(yg#~Z%#N1p&bo|Bc9{%c{`!2I39^uPY4wiL7@8iLT?!VB=QnAo0snG9A$ESh{*?u zv4D(^Og}^L1r85}5gq`OvS7`TY+hu`_i(`;(hy9RR)*SYgX-9y0QX!0lkw?6Jik>|>-2s&v{yb=%)IPZoH$cpSGm)DEHArrLG6&VhxL4qZ zZ)UEarM(o*a-ryIx^Z#Z=kI*#%97pfA;l+AY?-0@#C%jgf}!lsp!!7WpR%dO>8!IG zUheQx#cqfUQ5pfdT|s|IEHs%Fr3lL0gEA8H4!(hx!MHTMD2UVFnY8=WBHQ8NHNh>C zt(E^-fPeTi4j;k-{q_mV5hKOdDaT6g(J$d4n6pN z#R=L=C0w+a{w2BAV6SDr15zAT8y4j>47#3!*wqi0blf5^Oa7X8yrI(HF)}i^cfh}N zWOV!HK8L;eP+VzC-?<1OCy0!J)D7fl=@| zH0<9sFgo6ce{Y%?9UAK&+C^NAMKcU!@tVa6t7gx{zP@2l@{bYsV*{f@yZz&b_7Cjt z+cn_t9~c`N97YwpM@Ib<_$BH>o%B1f2xbQM4(u8q9T^_lg@)R>Thx_tHe zP*L&9ys0I=%E|9$w}ho@b_2oQTn7-gmQ;9I}&CH!9l4N@FgXDadB zfifeYu@`UqF&;)xdO!O~REF?0EJRVyD4vEG{q>+dER3P_D)!qEWP2R|g$dB;L%BBm zZWq28M(F{3_9L!?|NlW@BP%(k)aQryR+RDR7j}Z~5Ga#m)%aVRMJdfmnvZNQhZu*{ z3gh6RkMXjP@pm)68xeNn=WN+YDyoG_9m2mm!IK~Fl59k6obkxpcnD>weMvrQYySBr z@Jekx20BCdZMyx&AkFoyGJjiV%aE4O&uIElj~{nkCK!jq>^thwF?`SaV~p`L#AF+X z4EynUH-1Ze5-tW%mhdu+Cz5nG+JX9K0^jqVB00F6>G!Cg(=9W=P(pGM8i<2k_${Gq zAO21#-(=&4FgFf97Gf2T2?yEVDCo^b2vH!^MHN~xNcsQwURvtevO=c}+C+07Bv{G# zCVZ0A)DFaX8mr?dN3GQceyHX6r`hk&xS5OC8iv?U<9miyl*u}X*4R6Xk1>3+Qs}}6 lT#mJ6J$_bUoYE+e`64#G8~v4D$M{$2pAw=mN?04^{{kk - - - - - diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml deleted file mode 100644 index 456b5f645945b..0000000000000 --- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/layout/allwidgets.xml +++ /dev/null @@ -1,403 +0,0 @@ - - - - - - - - - - - - - - -