diff --git a/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/EasyLauncherTask.kt b/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/EasyLauncherTask.kt index a71a30ba..fbd8f0ff 100644 --- a/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/EasyLauncherTask.kt +++ b/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/EasyLauncherTask.kt @@ -64,7 +64,7 @@ abstract class EasyLauncherTask @Inject constructor(private val objects: ObjectF is IconFile.Adaptive -> iconFile.processAdaptiveIcon() - is IconFile.XmlDrawableResource -> iconFile.processDrawable() + is IconFile.XmlDrawable -> iconFile.processDrawable() } } } @@ -86,7 +86,7 @@ abstract class EasyLauncherTask @Inject constructor(private val objects: ObjectF iconNames.flatMap { (iconName, iconType) -> objects.getIconFiles(parent = resDir, iconName = iconName) .map { iconFile -> - iconFile.tryParseXmlFile() ?: when (iconType) { + iconFile.tryParseXmlIcon() ?: when (iconType) { IconType.Default -> IconFile.Raster(iconFile) IconType.Round -> IconFile.RasterRound(iconFile) } @@ -104,7 +104,10 @@ abstract class EasyLauncherTask @Inject constructor(private val objects: ObjectF iconFiles.forEach { iconFile -> val outputFile = iconFile.getOutputFile() if (iconFile.extension == "xml") { - iconFile.transformXml(outputFile, minSdkVersion.get(), filters.get()) + when (val drawable = iconFile.tryParseXmlDrawable()) { + is IconFile.XmlDrawable.Vector -> drawable.transform(outputFile, minSdkVersion.get(), filters.get()) + null -> log.info { "Skipped $iconFile due to unrecognised file format" } + } } else { iconFile.transformImage( outputFile = outputFile, @@ -116,9 +119,10 @@ abstract class EasyLauncherTask @Inject constructor(private val objects: ObjectF } } - private fun IconFile.XmlDrawableResource.processDrawable() { - val outputFile = file.getOutputFile() - file.transformXml(outputFile, minSdkVersion.get(), filters.get()) + private fun IconFile.XmlDrawable.processDrawable() { + when (this) { + is IconFile.XmlDrawable.Vector -> transform(file.getOutputFile(), minSdkVersion.get(), filters.get()) + } } private fun File.getOutputFile(): File = File(outputDir.asFile.get(), "${parentFile.name}/$name") diff --git a/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/IconTransformer.kt b/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/IconTransformer.kt index 012cbefa..7de7203e 100644 --- a/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/IconTransformer.kt +++ b/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/IconTransformer.kt @@ -2,8 +2,7 @@ package com.project.starter.easylauncher.plugin import com.project.starter.easylauncher.filter.Canvas import com.project.starter.easylauncher.filter.EasyLauncherFilter -import com.project.starter.easylauncher.plugin.models.toSize -import groovy.xml.XmlSlurper +import com.project.starter.easylauncher.plugin.models.IconFile import java.awt.image.BufferedImage import java.io.File import javax.imageio.ImageIO @@ -19,11 +18,7 @@ internal fun File.transformImage(outputFile: File, filters: List) { - val iconXml = XmlSlurper().parse(this) - val width = iconXml.property("@android:width")?.toSize().let(::requireNotNull) - val height = iconXml.property("@android:height")?.toSize().let(::requireNotNull) - +internal fun IconFile.XmlDrawable.Vector.transform(outputFile: File, minSdkVersion: Int, filters: List) { val drawableRoot = outputFile.parentFile // eg. debug/drawable/ val layers = filters.mapIndexed { index, filter -> @@ -32,8 +27,8 @@ internal fun File.transformXml(outputFile: File, minSdkVersion: Int, filters: Li densities.forEach { (qualifier, multiplier) -> val overlay = BufferedImage( - (width.value * multiplier).roundToInt(), - (height.value * multiplier).roundToInt(), + (width * multiplier).roundToInt(), + (height * multiplier).roundToInt(), BufferedImage.TYPE_INT_ARGB, ) val canvas = Canvas(overlay, adaptive = true) @@ -57,13 +52,13 @@ internal fun File.transformXml(outputFile: File, minSdkVersion: Int, filters: Li val versionSuffix = if (minSdkVersion >= ANDROID_OREO) "" else "-v26" val v26DrawableRoot = drawableRoot.parentFile.resolve("${drawableRoot.normalizedName}-anydpi$versionSuffix") - copyTo(v26DrawableRoot.resolve("easy_$name"), overwrite = true) + file.copyTo(v26DrawableRoot.resolve("easy_${file.name}"), overwrite = true) v26DrawableRoot.resolve(outputFile.name).writeText( """ | | | - | + | | |$layers | diff --git a/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/XmlReader.kt b/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/XmlReader.kt index a7e15769..c487dfc2 100644 --- a/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/XmlReader.kt +++ b/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/XmlReader.kt @@ -2,6 +2,7 @@ package com.project.starter.easylauncher.plugin import com.project.starter.easylauncher.plugin.models.IconFile import com.project.starter.easylauncher.plugin.models.IconType +import com.project.starter.easylauncher.plugin.models.toSize import groovy.xml.XmlSlurper import groovy.xml.slurpersupport.GPathResult import java.io.File @@ -23,7 +24,7 @@ private val regex by lazy { "\\\$\\{([^{}]*)}".toRegex() } private fun String.applyPlaceholders(manifestPlaceholders: Map): String = replace(regex) { manifestPlaceholders[it.groups[1]?.value]?.toString() ?: it.value } -internal fun File.tryParseXmlFile(): IconFile? { +internal fun File.tryParseXmlIcon(): IconFile? { if (extension != "xml") { return null } @@ -44,7 +45,23 @@ internal fun File.tryParseXmlFile(): IconFile? { monochrome = monochromeDrawable, ) } else { - IconFile.XmlDrawableResource(file = this) + tryParseXmlDrawable() + } +} + +internal fun File.tryParseXmlDrawable(): IconFile.XmlDrawable? { + val iconXml = XmlSlurper().parse(this) + val width = iconXml.property("@android:width")?.toSize()?.value + val height = iconXml.property("@android:height")?.toSize()?.value + + return when { + width != null && height != null -> IconFile.XmlDrawable.Vector( + file = this, + width = width, + height = height, + ) + + else -> null } } diff --git a/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/models/IconFile.kt b/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/models/IconFile.kt index 380d9280..d65a03fc 100644 --- a/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/models/IconFile.kt +++ b/easylauncher/src/main/kotlin/com/project/starter/easylauncher/plugin/models/IconFile.kt @@ -15,5 +15,12 @@ internal sealed class IconFile { val monochrome: String?, ) : IconFile() - data class XmlDrawableResource(val file: File) : IconFile() + sealed class XmlDrawable : IconFile() { + + data class Vector( + val file: File, + val width: Int, + val height: Int, + ) : XmlDrawable() + } } diff --git a/easylauncher/src/test/kotlin/com/project/starter/easylauncher/plugin/IconTransformerTest.kt b/easylauncher/src/test/kotlin/com/project/starter/easylauncher/plugin/IconTransformerTest.kt index 1ca24786..39f378df 100644 --- a/easylauncher/src/test/kotlin/com/project/starter/easylauncher/plugin/IconTransformerTest.kt +++ b/easylauncher/src/test/kotlin/com/project/starter/easylauncher/plugin/IconTransformerTest.kt @@ -31,7 +31,7 @@ internal class IconTransformerTest { @Test fun `transforms vector icon pre api 26`() { val expected = tempDir.resolve("drawable-anydpi-v26/output.xml") - sourceIcon.transformXml( + sourceIcon.transformVectorXml( outputFile = output, minSdkVersion = 21, filters = listOf( @@ -65,7 +65,7 @@ internal class IconTransformerTest { @Test fun `transforms vector icon since api 26`() { val expected = tempDir.resolve("drawable-anydpi/output.xml") - sourceIcon.transformXml( + sourceIcon.transformVectorXml( outputFile = output, minSdkVersion = 26, filters = listOf( diff --git a/easylauncher/src/test/kotlin/com/project/starter/easylauncher/plugin/XmlReaderTest.kt b/easylauncher/src/test/kotlin/com/project/starter/easylauncher/plugin/XmlReaderTest.kt index 8655b02f..cbc529c6 100644 --- a/easylauncher/src/test/kotlin/com/project/starter/easylauncher/plugin/XmlReaderTest.kt +++ b/easylauncher/src/test/kotlin/com/project/starter/easylauncher/plugin/XmlReaderTest.kt @@ -212,7 +212,7 @@ internal class XmlReaderTest { """.trimIndent(), ) - val icon = adaptiveIcon.tryParseXmlFile() as IconFile.Adaptive + val icon = adaptiveIcon.tryParseXmlIcon() as IconFile.Adaptive assertThat(icon.background).isEqualTo("@drawable/ic_launcher_background") assertThat(icon.foreground).isEqualTo("@mipmap/ic_launcher_foreground") @@ -234,7 +234,7 @@ internal class XmlReaderTest { """.trimIndent(), ) - val icon = adaptiveIcon.tryParseXmlFile() as IconFile.Adaptive + val icon = adaptiveIcon.tryParseXmlIcon() as IconFile.Adaptive assertThat(icon.background).isEqualTo("@drawable/ic_launcher_background") assertThat(icon.foreground).isEqualTo("@mipmap/ic_launcher_foreground") @@ -247,9 +247,9 @@ internal class XmlReaderTest { val drawableResource = tempDir.resolve("ic_launcher.xml") drawableResource.writeText(vectorFile()) - val icon = drawableResource.tryParseXmlFile() + val icon = drawableResource.tryParseXmlIcon() - assertThat(icon).isEqualTo(IconFile.XmlDrawableResource(file = drawableResource)) + assertThat(icon).isEqualTo(IconFile.XmlDrawable(file = drawableResource)) } @Test @@ -266,7 +266,7 @@ internal class XmlReaderTest { """.trimIndent(), ) - val icon = adaptiveIcon.tryParseXmlFile() + val icon = adaptiveIcon.tryParseXmlIcon() assertThat(icon).isNull() } diff --git a/sample/example-drawables/build.gradle b/sample/example-drawables/build.gradle new file mode 100644 index 00000000..ba931946 --- /dev/null +++ b/sample/example-drawables/build.gradle @@ -0,0 +1,20 @@ +apply plugin: 'com.starter.application.android' +apply plugin: 'com.starter.easylauncher' + +android { + namespace "com.example.vector" + defaultConfig { + minSdkVersion 28 + } + buildTypes { + named("release") { + debuggable false + signingConfig signingConfigs.debug + } + } + flavorDimensions += "reportedBugs" +} + +dependencies { + implementation project(":adaptive-support") +} diff --git a/sample/example-drawables/screenshots/Icons_doScreenshot(insets).png b/sample/example-drawables/screenshots/Icons_doScreenshot(insets).png new file mode 100644 index 00000000..86df9c6d Binary files /dev/null and b/sample/example-drawables/screenshots/Icons_doScreenshot(insets).png differ diff --git a/sample/example-drawables/src/androidTest/kotlin/com/starter/easylauncher/screenshot/IconsTest.kt b/sample/example-drawables/src/androidTest/kotlin/com/starter/easylauncher/screenshot/IconsTest.kt new file mode 100644 index 00000000..7e090def --- /dev/null +++ b/sample/example-drawables/src/androidTest/kotlin/com/starter/easylauncher/screenshot/IconsTest.kt @@ -0,0 +1,13 @@ +package com.starter.easylauncher.screenshot + +import com.example.custom.adaptive.MainActivity +import com.starter.easylauncher.recordScreenshot +import org.junit.Test + +internal class IconsTest { + + @Test + fun doScreenshot() { + recordScreenshot(flavor = "insets") + } +} diff --git a/sample/example-drawables/src/main/AndroidManifest.xml b/sample/example-drawables/src/main/AndroidManifest.xml new file mode 100644 index 00000000..65d85949 --- /dev/null +++ b/sample/example-drawables/src/main/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/sample/example-drawables/src/main/res/drawable/ic_baseline_airport_shuttle_24.xml b/sample/example-drawables/src/main/res/drawable/ic_baseline_airport_shuttle_24.xml new file mode 100644 index 00000000..da1e953a --- /dev/null +++ b/sample/example-drawables/src/main/res/drawable/ic_baseline_airport_shuttle_24.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/sample/example-drawables/src/main/res/drawable/ic_launcher_background.xml b/sample/example-drawables/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..07d5da9c --- /dev/null +++ b/sample/example-drawables/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sample/example-drawables/src/main/res/drawable/ic_launcher_foreground.xml b/sample/example-drawables/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000..32e4b53d --- /dev/null +++ b/sample/example-drawables/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,6 @@ + + diff --git a/sample/example-drawables/src/main/res/mipmap/ic_launcher.xml b/sample/example-drawables/src/main/res/mipmap/ic_launcher.xml new file mode 100644 index 00000000..6b78462d --- /dev/null +++ b/sample/example-drawables/src/main/res/mipmap/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/sample/settings.gradle b/sample/settings.gradle index 23ba8c56..e6c0bb8f 100644 --- a/sample/settings.gradle +++ b/sample/settings.gradle @@ -6,9 +6,9 @@ if(!gradle.gradleVersion.startsWith("7")) { apply plugin: "org.gradle.toolchains.foojay-resolver-convention" } - include ':example-activity-alias' include ':example-custom' +include ':example-drawables' include ':example-icon-round' include ':example-library' include ':example-manifest-placeholder'