Initial API skeleton around Material Icons
Adds base Icons object, with documentation, samples, and a test
(currently no-ops, but shows how we will compare with xml vectors).
Also removes width / height parsing from IconParser - Material icons
have recently been updated to all be 24 by 24.
Bug: b/146212531
Test: IconComparisonTest
Change-Id: I818a6bf1e30369a3189cc667f941c94292f05ade
diff --git a/ui/ui-material/build.gradle b/ui/ui-material/build.gradle
index 75c4c45..f981372 100644
--- a/ui/ui-material/build.gradle
+++ b/ui/ui-material/build.gradle
@@ -39,6 +39,7 @@
implementation project(":ui:ui-util")
api project(":ui:ui-core")
api project(":ui:ui-foundation")
+ api project(":ui:ui-material-icons-core")
api project(":ui:ui-text")
implementation project(":ui:ui-framework")
diff --git a/ui/ui-material/icons/core/api/0.1.0-dev05.txt b/ui/ui-material/icons/core/api/0.1.0-dev05.txt
new file mode 100644
index 0000000..fe4ae06
--- /dev/null
+++ b/ui/ui-material/icons/core/api/0.1.0-dev05.txt
@@ -0,0 +1,36 @@
+// Signature format: 3.0
+package androidx.ui.material.icons {
+
+ public final class Icons {
+ method public androidx.ui.material.icons.Icons.Filled getDefault();
+ property public final androidx.ui.material.icons.Icons.Filled Default;
+ field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ }
+
+ public static final class Icons.Filled {
+ field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ }
+
+ public static final class Icons.Outlined {
+ field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ }
+
+ public static final class Icons.Rounded {
+ field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ }
+
+ public static final class Icons.Sharp {
+ field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ }
+
+ public static final class Icons.TwoTone {
+ field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ }
+
+ public final class IconsKt {
+ method public static kotlin.Lazy<androidx.ui.graphics.vector.VectorAsset> lazyMaterialIcon(kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorAssetBuilder,androidx.ui.graphics.vector.VectorAssetBuilder> block);
+ method public static androidx.ui.graphics.vector.VectorAssetBuilder materialPath(androidx.ui.graphics.vector.VectorAssetBuilder, float fillAlpha = 1f, float strokeAlpha = 1f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.PathBuilder,kotlin.Unit> pathBuilder);
+ }
+
+}
+
diff --git a/ui/ui-material/icons/core/api/current.txt b/ui/ui-material/icons/core/api/current.txt
new file mode 100644
index 0000000..fe4ae06
--- /dev/null
+++ b/ui/ui-material/icons/core/api/current.txt
@@ -0,0 +1,36 @@
+// Signature format: 3.0
+package androidx.ui.material.icons {
+
+ public final class Icons {
+ method public androidx.ui.material.icons.Icons.Filled getDefault();
+ property public final androidx.ui.material.icons.Icons.Filled Default;
+ field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ }
+
+ public static final class Icons.Filled {
+ field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ }
+
+ public static final class Icons.Outlined {
+ field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ }
+
+ public static final class Icons.Rounded {
+ field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ }
+
+ public static final class Icons.Sharp {
+ field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ }
+
+ public static final class Icons.TwoTone {
+ field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ }
+
+ public final class IconsKt {
+ method public static kotlin.Lazy<androidx.ui.graphics.vector.VectorAsset> lazyMaterialIcon(kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorAssetBuilder,androidx.ui.graphics.vector.VectorAssetBuilder> block);
+ method public static androidx.ui.graphics.vector.VectorAssetBuilder materialPath(androidx.ui.graphics.vector.VectorAssetBuilder, float fillAlpha = 1f, float strokeAlpha = 1f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.PathBuilder,kotlin.Unit> pathBuilder);
+ }
+
+}
+
diff --git a/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev05.txt b/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev05.txt
new file mode 100644
index 0000000..fe4ae06
--- /dev/null
+++ b/ui/ui-material/icons/core/api/public_plus_experimental_0.1.0-dev05.txt
@@ -0,0 +1,36 @@
+// Signature format: 3.0
+package androidx.ui.material.icons {
+
+ public final class Icons {
+ method public androidx.ui.material.icons.Icons.Filled getDefault();
+ property public final androidx.ui.material.icons.Icons.Filled Default;
+ field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ }
+
+ public static final class Icons.Filled {
+ field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ }
+
+ public static final class Icons.Outlined {
+ field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ }
+
+ public static final class Icons.Rounded {
+ field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ }
+
+ public static final class Icons.Sharp {
+ field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ }
+
+ public static final class Icons.TwoTone {
+ field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ }
+
+ public final class IconsKt {
+ method public static kotlin.Lazy<androidx.ui.graphics.vector.VectorAsset> lazyMaterialIcon(kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorAssetBuilder,androidx.ui.graphics.vector.VectorAssetBuilder> block);
+ method public static androidx.ui.graphics.vector.VectorAssetBuilder materialPath(androidx.ui.graphics.vector.VectorAssetBuilder, float fillAlpha = 1f, float strokeAlpha = 1f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.PathBuilder,kotlin.Unit> pathBuilder);
+ }
+
+}
+
diff --git a/ui/ui-material/icons/core/api/public_plus_experimental_current.txt b/ui/ui-material/icons/core/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..fe4ae06
--- /dev/null
+++ b/ui/ui-material/icons/core/api/public_plus_experimental_current.txt
@@ -0,0 +1,36 @@
+// Signature format: 3.0
+package androidx.ui.material.icons {
+
+ public final class Icons {
+ method public androidx.ui.material.icons.Icons.Filled getDefault();
+ property public final androidx.ui.material.icons.Icons.Filled Default;
+ field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ }
+
+ public static final class Icons.Filled {
+ field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ }
+
+ public static final class Icons.Outlined {
+ field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ }
+
+ public static final class Icons.Rounded {
+ field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ }
+
+ public static final class Icons.Sharp {
+ field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ }
+
+ public static final class Icons.TwoTone {
+ field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ }
+
+ public final class IconsKt {
+ method public static kotlin.Lazy<androidx.ui.graphics.vector.VectorAsset> lazyMaterialIcon(kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorAssetBuilder,androidx.ui.graphics.vector.VectorAssetBuilder> block);
+ method public static androidx.ui.graphics.vector.VectorAssetBuilder materialPath(androidx.ui.graphics.vector.VectorAssetBuilder, float fillAlpha = 1f, float strokeAlpha = 1f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.PathBuilder,kotlin.Unit> pathBuilder);
+ }
+
+}
+
diff --git a/ui/ui-material/icons/core/api/res-0.1.0-dev05.txt b/ui/ui-material/icons/core/api/res-0.1.0-dev05.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ui/ui-material/icons/core/api/res-0.1.0-dev05.txt
diff --git a/ui/ui-material/icons/core/api/restricted_0.1.0-dev05.txt b/ui/ui-material/icons/core/api/restricted_0.1.0-dev05.txt
new file mode 100644
index 0000000..fe4ae06
--- /dev/null
+++ b/ui/ui-material/icons/core/api/restricted_0.1.0-dev05.txt
@@ -0,0 +1,36 @@
+// Signature format: 3.0
+package androidx.ui.material.icons {
+
+ public final class Icons {
+ method public androidx.ui.material.icons.Icons.Filled getDefault();
+ property public final androidx.ui.material.icons.Icons.Filled Default;
+ field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ }
+
+ public static final class Icons.Filled {
+ field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ }
+
+ public static final class Icons.Outlined {
+ field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ }
+
+ public static final class Icons.Rounded {
+ field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ }
+
+ public static final class Icons.Sharp {
+ field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ }
+
+ public static final class Icons.TwoTone {
+ field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ }
+
+ public final class IconsKt {
+ method public static kotlin.Lazy<androidx.ui.graphics.vector.VectorAsset> lazyMaterialIcon(kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorAssetBuilder,androidx.ui.graphics.vector.VectorAssetBuilder> block);
+ method public static androidx.ui.graphics.vector.VectorAssetBuilder materialPath(androidx.ui.graphics.vector.VectorAssetBuilder, float fillAlpha = 1f, float strokeAlpha = 1f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.PathBuilder,kotlin.Unit> pathBuilder);
+ }
+
+}
+
diff --git a/ui/ui-material/icons/core/api/restricted_current.txt b/ui/ui-material/icons/core/api/restricted_current.txt
new file mode 100644
index 0000000..fe4ae06
--- /dev/null
+++ b/ui/ui-material/icons/core/api/restricted_current.txt
@@ -0,0 +1,36 @@
+// Signature format: 3.0
+package androidx.ui.material.icons {
+
+ public final class Icons {
+ method public androidx.ui.material.icons.Icons.Filled getDefault();
+ property public final androidx.ui.material.icons.Icons.Filled Default;
+ field public static final androidx.ui.material.icons.Icons! INSTANCE;
+ }
+
+ public static final class Icons.Filled {
+ field public static final androidx.ui.material.icons.Icons.Filled! INSTANCE;
+ }
+
+ public static final class Icons.Outlined {
+ field public static final androidx.ui.material.icons.Icons.Outlined! INSTANCE;
+ }
+
+ public static final class Icons.Rounded {
+ field public static final androidx.ui.material.icons.Icons.Rounded! INSTANCE;
+ }
+
+ public static final class Icons.Sharp {
+ field public static final androidx.ui.material.icons.Icons.Sharp! INSTANCE;
+ }
+
+ public static final class Icons.TwoTone {
+ field public static final androidx.ui.material.icons.Icons.TwoTone! INSTANCE;
+ }
+
+ public final class IconsKt {
+ method public static kotlin.Lazy<androidx.ui.graphics.vector.VectorAsset> lazyMaterialIcon(kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.VectorAssetBuilder,androidx.ui.graphics.vector.VectorAssetBuilder> block);
+ method public static androidx.ui.graphics.vector.VectorAssetBuilder materialPath(androidx.ui.graphics.vector.VectorAssetBuilder, float fillAlpha = 1f, float strokeAlpha = 1f, kotlin.jvm.functions.Function1<? super androidx.ui.graphics.vector.PathBuilder,kotlin.Unit> pathBuilder);
+ }
+
+}
+
diff --git a/ui/ui-material/icons/core/build.gradle b/ui/ui-material/icons/core/build.gradle
new file mode 100644
index 0000000..39c8b0a
--- /dev/null
+++ b/ui/ui-material/icons/core/build.gradle
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.Publish
+
+import static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("AndroidXUiPlugin")
+ id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+ implementation(KOTLIN_STDLIB)
+
+ api project(":ui:ui-core")
+ api project(":ui:ui-framework")
+}
+
+androidx {
+ name = "AndroidX Core Material Icons"
+ publish = Publish.SNAPSHOT_AND_RELEASE
+ mavenVersion = LibraryVersions.UI
+ mavenGroup = LibraryGroups.UI
+ inceptionYear = "2020"
+ description = "AndroidX Core Material Icons"
+}
diff --git a/ui/ui-material/icons/core/integration-tests/samples/build.gradle b/ui/ui-material/icons/core/integration-tests/samples/build.gradle
new file mode 100644
index 0000000..84bbd18
--- /dev/null
+++ b/ui/ui-material/icons/core/integration-tests/samples/build.gradle
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+import static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("AndroidXUiPlugin")
+ id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+ kotlinPlugin project(path: ":compose:compose-compiler")
+
+ implementation(KOTLIN_STDLIB)
+
+ implementation project(":annotation:annotation-sampled")
+
+ implementation project(":compose:compose-runtime")
+ implementation project(":ui:ui-material-icons-core")
+ implementation project(":ui:ui-vector")
+}
+
+android {
+ tasks.withType(KotlinCompile).configureEach {
+ kotlinOptions {
+ useIR = true
+ }
+ }
+}
diff --git a/ui/ui-material/icons/core/integration-tests/samples/src/main/AndroidManifest.xml b/ui/ui-material/icons/core/integration-tests/samples/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..1f7495d
--- /dev/null
+++ b/ui/ui-material/icons/core/integration-tests/samples/src/main/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<manifest package="androidx.ui.material.icons.samples" />
diff --git a/ui/ui-material/icons/core/integration-tests/samples/src/main/java/androidx/ui/material/icons/samples/IconSamples.kt b/ui/ui-material/icons/core/integration-tests/samples/src/main/java/androidx/ui/material/icons/samples/IconSamples.kt
new file mode 100644
index 0000000..fc5d152c
--- /dev/null
+++ b/ui/ui-material/icons/core/integration-tests/samples/src/main/java/androidx/ui/material/icons/samples/IconSamples.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.material.icons.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.Composable
+import androidx.ui.graphics.vector.DrawVector
+import androidx.ui.graphics.vector.VectorAsset
+import androidx.ui.graphics.vector.VectorAssetBuilder
+import androidx.ui.material.icons.Icons
+import androidx.ui.unit.dp
+
+@Sampled
+@Composable
+@Suppress("LocalVariableName", "UNUSED_VARIABLE")
+fun AppIcons() {
+ val MyAppIcons = Icons.Rounded
+ SomeComposable(icon = MyAppIcons.Menu)
+}
+
+@Sampled
+@Composable
+fun DrawIcon() {
+ DrawVector(vectorImage = Icons.Rounded.Menu)
+}
+
+@Composable
+private fun SomeComposable(icon: VectorAsset) { DrawVector(icon) }
+
+// TODO: b/146212531 remove once main code has merged
+private val Icons.Rounded.Menu get() = VectorAssetBuilder("", 0.dp, 0.dp, 24f, 24f).build()
diff --git a/ui/ui-material/icons/core/src/main/AndroidManifest.xml b/ui/ui-material/icons/core/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..88c6032
--- /dev/null
+++ b/ui/ui-material/icons/core/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<manifest package="androidx.ui.material.icons" />
diff --git a/ui/ui-material/icons/core/src/main/java/androidx/ui/material/icons/Icons.kt b/ui/ui-material/icons/core/src/main/java/androidx/ui/material/icons/Icons.kt
new file mode 100644
index 0000000..7bee4c5
--- /dev/null
+++ b/ui/ui-material/icons/core/src/main/java/androidx/ui/material/icons/Icons.kt
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.material.icons
+
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.SolidColor
+import androidx.ui.graphics.StrokeCap
+import androidx.ui.graphics.StrokeJoin
+import androidx.ui.graphics.vector.PathBuilder
+import androidx.ui.graphics.vector.VectorAsset
+import androidx.ui.graphics.vector.VectorAssetBuilder
+import androidx.ui.graphics.vector.path
+import androidx.ui.unit.dp
+
+/**
+ * Entry point for using [Material Icons](https://material.io/resources/icons) in Compose.
+ *
+ * There are five distinct icon themes: [Filled], [Outlined], [Rounded], [TwoTone], and [Sharp].
+ * Each theme contains the same icons, but with a distinct visual style. You should typically
+ * choose one theme and use it across your application for consistency. For example, you may want
+ * to use a property or a typealias to refer to a specific theme, so it can be accessed in a
+ * semantically meaningful way from inside other composables.
+ *
+ * @sample androidx.ui.material.icons.samples.AppIcons
+ *
+ * Icons maintain the same names defined by Material, but with their snake_case name converted to
+ * PascalCase. For example: add_alarm becomes AddAlarm.
+ *
+ * Note: Icons that start with a number, such as `360`, are prefixed with a '_', becoming '_360'.
+ *
+ * Icons are represented as [androidx.ui.graphics.vector.VectorAsset]s and hence can be drawn by
+ * simply using [androidx.ui.graphics.vector.DrawVector].
+ *
+ * @sample androidx.ui.material.icons.samples.DrawIcon
+ */
+object Icons {
+ /**
+ * [Filled icons](https://material.io/resources/icons/?style=baseline) (previously the only
+ * available theme, also known as the baseline theme) are the default icon theme. You can
+ * also use [Default] as an alias for these icons.
+ */
+ object Filled
+
+ /**
+ * [Outlined icons](https://material.io/resources/icons/?style=outline) make use of a thin
+ * stroke and empty space inside for a lighter appearance.
+ */
+ object Outlined
+
+ /**
+ * [Rounded icons](https://material.io/resources/icons/?style=round) use a corner radius that
+ * pairs well with brands that use heavier typography, curved logos, or circular elements to
+ * express their style.
+ */
+ object Rounded
+
+ /**
+ * [Two-Tone icons](https://material.io/resources/icons/?style=twotone) display corners with
+ * straight edges, for a crisp style that remains legible even at smaller scales. These
+ * rectangular shapes can support brand styles that are not well-reflected by rounded shapes.
+ */
+ object TwoTone
+
+ /**
+ * [Sharp icons](https://material.io/resources/icons/?style=sharp) display corners with
+ * straight edges, for a crisp style that remains legible even at smaller scales. These
+ * rectangular shapes can support brand styles that are not well-reflected by rounded shapes.
+ */
+ object Sharp
+
+ /**
+ * Alias for [Filled], the baseline icon theme.
+ */
+ val Default = Filled
+}
+
+/**
+ * Utility delegate to construct a lazily initialized Material icon with default size information.
+ * This is used by generated icons, and should not be used manually.
+ *
+ * @param block builder lambda to add paths to this vector asset
+ */
+fun lazyMaterialIcon(
+ block: VectorAssetBuilder.() -> VectorAssetBuilder
+): Lazy<VectorAsset> = lazy(LazyThreadSafetyMode.NONE) {
+ VectorAssetBuilder(
+ defaultWidth = MaterialIconDimension.dp,
+ defaultHeight = MaterialIconDimension.dp,
+ viewportWidth = MaterialIconDimension,
+ viewportHeight = MaterialIconDimension
+ ).block().build()
+}
+
+/**
+ * Adds a vector path to this icon with sane Material defaults.
+ *
+ * @param fillAlpha fill alpha for this path
+ * @param strokeAlpha stroke alpha for this path
+ * @param pathBuilder builder lambda to add commands to this path
+ */
+fun VectorAssetBuilder.materialPath(
+ fillAlpha: Float = 1f,
+ strokeAlpha: Float = 1f,
+ pathBuilder: PathBuilder.() -> Unit
+) =
+ // TODO: b/146213225
+ // Some of these defaults are already set when parsing from XML, but do not currently exist
+ // when added programmatically. We should unify these and simplify them where possible.
+ path(
+ fill = SolidColor(Color.Black),
+ fillAlpha = fillAlpha,
+ stroke = null,
+ strokeAlpha = strokeAlpha,
+ strokeLineWidth = 1f,
+ strokeLineCap = StrokeCap.butt,
+ strokeLineJoin = StrokeJoin.bevel,
+ strokeLineMiter = 1f,
+ pathBuilder = pathBuilder
+ )
+
+// All Material icons (currently) are 24dp by 24dp, with a viewport size of 24 by 24.
+private const val MaterialIconDimension = 24f
diff --git a/ui/ui-material/icons/extended/build.gradle b/ui/ui-material/icons/extended/build.gradle
new file mode 100644
index 0000000..29c9bf5
--- /dev/null
+++ b/ui/ui-material/icons/extended/build.gradle
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+import androidx.build.Publish
+
+import static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("AndroidXUiPlugin")
+ id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+ implementation(KOTLIN_STDLIB)
+
+ api project(":ui:ui-material-icons-core")
+
+ androidTestImplementation project(":ui:ui-layout")
+ androidTestImplementation project(":ui:ui-platform")
+ androidTestImplementation project(":ui:ui-test")
+
+ androidTestImplementation(ANDROIDX_TEST_RULES)
+ androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ androidTestImplementation(JUNIT)
+ androidTestImplementation(KOTLIN_REFLECT)
+ androidTestImplementation(TRUTH)
+}
+
+android.buildTypes.all {
+ // Jacoco hangs intermittently due to the large number of files
+ testCoverageEnabled = false
+}
+
+androidx {
+ name = "AndroidX Extended Material Icons"
+ publish = Publish.SNAPSHOT_AND_RELEASE
+ mavenVersion = LibraryVersions.UI
+ mavenGroup = LibraryGroups.UI
+ // This module has a large number (5000+) of generated source files and so doc generation /
+ // API tracking will simply take too long
+ toolingProject = true
+ inceptionYear = "2020"
+ description = "AndroidX Extended Material Icons"
+}
diff --git a/ui/ui-material/icons/extended/src/androidTest/AndroidManifest.xml b/ui/ui-material/icons/extended/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..0faafd1
--- /dev/null
+++ b/ui/ui-material/icons/extended/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<manifest package="androidx.ui.material.icons" xmlns:android="http://schemas.android.com/apk/res/android">
+ <application>
+ <activity android:name="android.app.Activity" android:theme="@style/TestTheme"/>
+ </application>
+</manifest>
diff --git a/ui/ui-material/icons/extended/src/androidTest/java/androidx/ui/material/icons/test/IconComparisonTest.kt b/ui/ui-material/icons/extended/src/androidTest/java/androidx/ui/material/icons/test/IconComparisonTest.kt
new file mode 100644
index 0000000..f3c2838
--- /dev/null
+++ b/ui/ui-material/icons/extended/src/androidTest/java/androidx/ui/material/icons/test/IconComparisonTest.kt
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.ui.material.icons.test
+
+import android.app.Activity
+import android.graphics.Bitmap
+import android.view.ViewGroup
+import androidx.compose.Composable
+import androidx.compose.Compose
+import androidx.test.filters.LargeTest
+import androidx.test.rule.ActivityTestRule
+import androidx.ui.core.AndroidComposeView
+import androidx.ui.core.ContextAmbient
+import androidx.ui.core.TestTag
+import androidx.ui.core.setContent
+import androidx.ui.graphics.Color
+import androidx.ui.graphics.vector.DrawVector
+import androidx.ui.graphics.vector.VectorAsset
+import androidx.ui.layout.Center
+import androidx.ui.layout.Column
+import androidx.ui.layout.Container
+import androidx.ui.res.vectorResource
+import androidx.ui.semantics.Semantics
+import androidx.ui.test.captureToBitmap
+import androidx.ui.test.findByTag
+import androidx.ui.unit.dp
+import com.google.common.truth.Truth
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import kotlin.reflect.KProperty0
+import kotlin.reflect.jvm.javaGetter
+
+const val ProgrammaticTestTag = "programmatic"
+const val XmlTestTag = "Xml"
+
+/**
+ * Test to ensure equality (both structurally, and visually) between programmatically generated
+ * Material [androidx.ui.material.icons.Icons] and their XML source.
+ */
+@LargeTest
+@RunWith(JUnit4::class)
+class IconComparisonTest {
+
+ /**
+ * Running all comparisons inside one test method instead of using a Parameterized test
+ * runner so we can re-use the same Activity instance between test runs. Most of the cost of a
+ * simple test like this is in Activity instantiation so re-using the same activity reduces time
+ * to run this test ~tenfold.
+ */
+ @get:Rule
+ val activityTestRule = ActivityTestRule(Activity::class.java)
+
+ @Test
+ fun compareVectorAssets() {
+ AllIcons.forEach { (property, drawableName) ->
+ var xmlVector: VectorAsset? = null
+ val programmaticVector = property.get()
+
+ activityTestRule.runOnUiThread {
+ activityTestRule.activity.setContent {
+ xmlVector = drawableName.toVectorAsset()
+ DrawVectors(programmaticVector, xmlVector!!)
+ }
+ }
+
+ val iconName = property.javaGetter!!.declaringClass.canonicalName!!
+
+ assertVectorAssetsAreEqual(xmlVector!!, programmaticVector, iconName)
+
+ assertBitmapsAreEqual(
+ findByTag(XmlTestTag).captureToBitmap(),
+ findByTag(ProgrammaticTestTag).captureToBitmap(),
+ iconName
+ )
+
+ // Dispose between composing each pair of icons to ensure correctness
+ activityTestRule.runOnUiThread {
+ val root =
+ (activityTestRule.activity.findViewById(android.R.id.content) as ViewGroup)
+ val composeView = root.getChildAt(0) as AndroidComposeView
+ Compose.disposeComposition(composeView.root, activityTestRule.activity, null)
+ }
+ }
+ }
+}
+
+// TODO: b/146212531 Temporary stub until generation code merges
+private val AllIcons = listOf<Pair<KProperty0<VectorAsset>, String>>()
+
+/**
+ * @return the [VectorAsset] matching the drawable with [this] name.
+ */
+@Composable
+private fun String.toVectorAsset(): VectorAsset {
+ val context = ContextAmbient.current
+ val resId = context.resources.getIdentifier(this, "drawable", context.packageName)
+ return vectorResource(resId)
+}
+
+/**
+ * Compares two [VectorAsset]s and ensures that they are deeply equal, comparing all children
+ * recursively.
+ */
+private fun assertVectorAssetsAreEqual(
+ xmlVector: VectorAsset,
+ programmaticVector: VectorAsset,
+ iconName: String
+) {
+ try {
+ Truth.assertThat(programmaticVector).isEqualTo(xmlVector)
+ } catch (e: AssertionError) {
+ val message = "VectorAsset comparison failed for $iconName\n" + e.localizedMessage
+ throw AssertionError(message, e)
+ }
+}
+
+/**
+ * Compares each pixel in two bitmaps, asserting they are equal.
+ */
+private fun assertBitmapsAreEqual(xmlBitmap: Bitmap, programmaticBitmap: Bitmap, iconName: String) {
+ try {
+ Truth.assertThat(programmaticBitmap.width).isEqualTo(xmlBitmap.width)
+ Truth.assertThat(programmaticBitmap.height).isEqualTo(xmlBitmap.height)
+
+ val xmlPixelArray = with(xmlBitmap) {
+ val pixels = IntArray(width * height)
+ getPixels(pixels, 0, width, 0, 0, width, height)
+ pixels
+ }
+
+ val programmaticPixelArray = with(programmaticBitmap) {
+ val pixels = IntArray(width * height)
+ getPixels(pixels, 0, width, 0, 0, width, height)
+ pixels
+ }
+
+ Truth.assertThat(programmaticPixelArray).isEqualTo(xmlPixelArray)
+ } catch (e: AssertionError) {
+ val message = "Bitmap comparison failed for $iconName\n" + e.localizedMessage
+ throw AssertionError(message, e)
+ }
+}
+
+/**
+ * Renders both vectors in a column using the corresponding [ProgrammaticTestTag] and
+ * [XmlTestTag] for [programmaticVector] and [xmlVector].
+ */
+@Composable
+private fun DrawVectors(programmaticVector: VectorAsset, xmlVector: VectorAsset) {
+ Center {
+ Column {
+ TestTag(ProgrammaticTestTag) {
+ Semantics(container = true) {
+ Container(width = 24.dp, height = 24.dp) {
+ DrawVector(vectorImage = programmaticVector, tintColor = Color.Red)
+ }
+ }
+ }
+ TestTag(XmlTestTag) {
+ Semantics(container = true) {
+ Container(width = 24.dp, height = 24.dp) {
+ DrawVector(vectorImage = xmlVector, tintColor = Color.Red)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ui/ui-material/icons/extended/src/androidTest/res/values/styles.xml b/ui/ui-material/icons/extended/src/androidTest/res/values/styles.xml
new file mode 100644
index 0000000..637be11
--- /dev/null
+++ b/ui/ui-material/icons/extended/src/androidTest/res/values/styles.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources>
+ <style name="TestTheme" parent="@android:style/Theme.Material.Light.NoActionBar">
+ <item name="android:windowBackground">#ffffff</item>
+ <item name="android:windowActionBar">false</item>
+ <item name="android:windowAnimationStyle">@null</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowFullscreen">true</item>
+ <item name="android:windowNoTitle">true</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/ui/ui-material/icons/extended/src/main/AndroidManifest.xml b/ui/ui-material/icons/extended/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..88c6032
--- /dev/null
+++ b/ui/ui-material/icons/extended/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<manifest package="androidx.ui.material.icons" />
diff --git a/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/IconParser.kt b/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/IconParser.kt
index 2bcb590..7b7acbd 100644
--- a/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/IconParser.kt
+++ b/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/IconParser.kt
@@ -42,9 +42,6 @@
check(parser.name == "vector") { "The start tag must be <vector>!" }
- val width = parser.getDpValueAsFloat(WIDTH) ?: 24f
- val height = parser.getDpValueAsFloat(HEIGHT) ?: 24f
-
parser.next()
val nodes = mutableListOf<VectorNode>()
@@ -88,19 +85,13 @@
parser.next()
}
- return Vector(nodes, width, height)
+ return Vector(nodes)
}
}
/**
* @return the float value for the attribute [name], or null if it couldn't be found
*/
-private fun XmlPullParser.getDpValueAsFloat(name: String) =
- getAttributeValue(null, name)?.replace("dp", "")?.toFloatOrNull()
-
-/**
- * @return the float value for the attribute [name], or null if it couldn't be found
- */
private fun XmlPullParser.getValueAsFloat(name: String) =
getAttributeValue(null, name)?.toFloatOrNull()
@@ -125,8 +116,6 @@
private const val PATH = "path"
// XML attribute names
-private const val WIDTH = "android:width"
-private const val HEIGHT = "android:height"
private const val PATH_DATA = "android:pathData"
private const val FILL_ALPHA = "android:fillAlpha"
private const val STROKE_ALPHA = "android:strokeAlpha"
diff --git a/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/vector/Vector.kt b/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/vector/Vector.kt
index 9daea62a..a94083c 100644
--- a/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/vector/Vector.kt
+++ b/ui/ui-material/icons/generator/src/main/kotlin/androidx/ui/material/icons/generator/vector/Vector.kt
@@ -17,12 +17,12 @@
package androidx.ui.material.icons.generator.vector
/**
- * Simplified representation of a vector, with root [nodes] and a preferred [width] and [height].
+ * Simplified representation of a vector, with root [nodes].
*
* [nodes] may either be a singleton list of the root group, or a list of root paths / groups if
* there are multiple top level declaration.
*/
-class Vector(val nodes: List<VectorNode>, val width: Float, val height: Float)
+class Vector(val nodes: List<VectorNode>)
/**
* Simplified vector node representation, as the total set of properties we need to care about
diff --git a/ui/ui-material/icons/generator/src/test/kotlin/androidx/ui/material/icons/generator/IconParserTest.kt b/ui/ui-material/icons/generator/src/test/kotlin/androidx/ui/material/icons/generator/IconParserTest.kt
index fdf9123..70beee6 100644
--- a/ui/ui-material/icons/generator/src/test/kotlin/androidx/ui/material/icons/generator/IconParserTest.kt
+++ b/ui/ui-material/icons/generator/src/test/kotlin/androidx/ui/material/icons/generator/IconParserTest.kt
@@ -34,9 +34,6 @@
val icon = Icon("SimpleVector", "simple_vector", TestVector)
val vector = IconParser(icon).parse()
- Truth.assertThat(vector.width).isEqualTo(50f)
- Truth.assertThat(vector.height).isEqualTo(50f)
-
val nodes = vector.nodes
Truth.assertThat(nodes.size).isEqualTo(2)
@@ -70,8 +67,8 @@
private val TestVector = """
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="50dp"
- android:height="50dp">
+ android:width="24dp"
+ android:height="24dp">
<path
android:fillAlpha=".3"
android:pathData="M20,10, l10,10 0,10 -10, 0z" />