Skip to content

Commit

Permalink
Merge pull request #613 from usefulness/updates
Browse files Browse the repository at this point in the history
Gracefully ignore non-vector images
  • Loading branch information
mateuszkwiecinski authored May 28, 2024
2 parents 29524ef + 9b867cb commit 9bb117c
Show file tree
Hide file tree
Showing 15 changed files with 299 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
}
Expand All @@ -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)
}
Expand All @@ -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,
Expand All @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -19,11 +18,7 @@ internal fun File.transformImage(outputFile: File, filters: List<EasyLauncherFil
ImageIO.write(image, extension, outputFile)
}

internal fun File.transformXml(outputFile: File, minSdkVersion: Int, filters: List<EasyLauncherFilter>) {
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<EasyLauncherFilter>) {
val drawableRoot = outputFile.parentFile // eg. debug/drawable/

val layers = filters.mapIndexed { index, filter ->
Expand All @@ -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)
Expand All @@ -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(
"""
|<?xml version="1.0" encoding="utf-8"?>
|<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
| <item android:drawable="@${drawableRoot.normalizedName}/easy_$nameWithoutExtension" />
| <item android:drawable="@${drawableRoot.normalizedName}/easy_${file.nameWithoutExtension}" />
|
|$layers
|</layer-list>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -23,7 +24,7 @@ private val regex by lazy { "\\\$\\{([^{}]*)}".toRegex() }
private fun String.applyPlaceholders(manifestPlaceholders: Map<String, Any>): 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
}
Expand All @@ -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
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.project.starter.easylauncher.plugin
import com.project.starter.easylauncher.filter.ChromeLikeFilter
import com.project.starter.easylauncher.filter.ColorRibbonFilter
import com.project.starter.easylauncher.filter.OverlayFilter
import com.project.starter.easylauncher.plugin.models.IconFile
import com.project.starter.easylauncher.plugin.utils.vectorFile
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.BeforeEach
Expand All @@ -14,24 +15,24 @@ internal class IconTransformerTest {

@TempDir
lateinit var tempDir: File
lateinit var sourceIcon: File
lateinit var sourceIcon: IconFile.XmlDrawable.Vector
lateinit var output: File

@BeforeEach
internal fun setUp() {
val drawable = tempDir.resolve("drawable").apply {
mkdir()
}
sourceIcon = drawable.resolve("icon_resource.xml")
sourceIcon.writeText(vectorFile())
val sourceIconFile = drawable.resolve("icon_resource.xml").apply { writeText(vectorFile()) }
sourceIcon = sourceIconFile.tryParseXmlDrawable() as IconFile.XmlDrawable.Vector

output = drawable.resolve("output.xml")
}

@Test
fun `transforms vector icon pre api 26`() {
val expected = tempDir.resolve("drawable-anydpi-v26/output.xml")
sourceIcon.transformXml(
sourceIcon.transform(
outputFile = output,
minSdkVersion = 21,
filters = listOf(
Expand Down Expand Up @@ -65,7 +66,7 @@ internal class IconTransformerTest {
@Test
fun `transforms vector icon since api 26`() {
val expected = tempDir.resolve("drawable-anydpi/output.xml")
sourceIcon.transformXml(
sourceIcon.transform(
outputFile = output,
minSdkVersion = 26,
filters = listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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")
Expand All @@ -247,9 +247,15 @@ 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.Vector(
file = drawableResource,
width = 24,
height = 24,
),
)
}

@Test
Expand All @@ -266,7 +272,7 @@ internal class XmlReaderTest {
""".trimIndent(),
)

val icon = adaptiveIcon.tryParseXmlFile()
val icon = adaptiveIcon.tryParseXmlIcon()

assertThat(icon).isNull()
}
Expand Down
20 changes: 20 additions & 0 deletions sample/example-drawables/build.gradle
Original file line number Diff line number Diff line change
@@ -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")
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -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<MainActivity>(flavor = "insets")
}
}
9 changes: 9 additions & 0 deletions sample/example-drawables/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:icon="@mipmap/ic_launcher"
android:label="${appName}"
/>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="#FFFFFF"
android:viewportWidth="24"
android:viewportHeight="24"
>

<path
android:fillColor="@android:color/white"
android:pathData="M17,5L3,5c-1.1,0 -2,0.89 -2,2v9h2c0,1.65 1.34,3 3,3s3,-1.35 3,-3h5.5c0,1.65 1.34,3 3,3s3,-1.35 3,-3L23,16v-5l-6,-6zM3,11L3,7h4v4L3,11zM6,17.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM13,11L9,11L9,7h4v4zM17.5,17.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM15,11L15,7h1l4,4h-5z"
/>

</vector>
Loading

0 comments on commit 9bb117c

Please sign in to comment.