[go: nahoru, domu]

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/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" />