From 0dff1896fa06b8d11734716e793e9dbc195c9800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Varga?= Date: Tue, 18 Apr 2023 09:31:36 +0200 Subject: [PATCH] Add vector graphic support for images --- gradle/libs.versions.toml | 2 + resources-generator/build.gradle.kts | 1 + .../gradle/generator/ImagesGenerator.kt | 5 +- .../android/AndroidImagesGenerator.kt | 53 +++++++++++++++---- .../generator/apple/AppleImagesGenerator.kt | 26 ++++++--- .../dev/icerock/gradle/utils/FileExt.kt | 10 ++++ 6 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 resources-generator/src/main/kotlin/dev/icerock/gradle/utils/FileExt.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ea93900b..014c1730 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,7 @@ [versions] kotlinVersion = "1.8.10" androidGradleVersion = "7.4.2" +androidSdkCommonVersion = "30.4.2" # kotlinx kotlinxSerializationVersion = "1.5.0" @@ -85,6 +86,7 @@ kotlinTestAnnotations = { module = "org.jetbrains.kotlin:kotlin-test-annotations # gradle kotlinGradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlinVersion" } androidGradlePlugin = { module = "com.android.tools.build:gradle", version.ref = "androidGradleVersion" } +androidSdkCommon = { module = "com.android.tools:sdk-common", version.ref = "androidSdkCommonVersion" } kotlinCompilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlinVersion" } detektGradlePlugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version.ref = "detektVersion" } mokoMultiplatformPlugin = { module = "dev.icerock:mobile-multiplatform", version.ref = "mokoMultiplatformPluginVersion" } diff --git a/resources-generator/build.gradle.kts b/resources-generator/build.gradle.kts index a34f7b3a..868f9728 100644 --- a/resources-generator/build.gradle.kts +++ b/resources-generator/build.gradle.kts @@ -18,6 +18,7 @@ dependencies { compileOnly(libs.kotlinGradlePlugin) compileOnly(libs.androidGradlePlugin) compileOnly(libs.kotlinCompilerEmbeddable) + implementation(libs.androidSdkCommon) implementation(libs.kotlinPoet) implementation(libs.kotlinxSerialization) implementation(libs.apacheCommonsText) diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ImagesGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ImagesGenerator.kt index b26d94fd..e7a28ac6 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ImagesGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/ImagesGenerator.kt @@ -31,7 +31,8 @@ abstract class ImagesGenerator( objectBuilder: TypeSpec.Builder ): TypeSpec { val fileMap = inputFileTree.groupBy { file -> - "${file.name.substringBefore("@")}.${file.extension}" + // SVGs do not have scale suffixes, so we need to remove the extension first + "${file.name.substringBefore(".").substringBefore("@")}.${file.extension}" } beforeGenerateResources(objectBuilder, fileMap.keys.sorted()) @@ -93,7 +94,7 @@ abstract class ImagesGenerator( private val mrSettings: MRGenerator.MRSettings ) : ResourceGeneratorFeature { private val stringsFileTree = info.commonResources.matching { - it.include("MR/images/**/*.png", "MR/images/**/*.jpg") + it.include("MR/images/**/*.png", "MR/images/**/*.jpg", "MR/images/**/*.svg") } override fun createCommonGenerator() = diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/android/AndroidImagesGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/android/AndroidImagesGenerator.kt index e8e123bb..407c5700 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/android/AndroidImagesGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/android/AndroidImagesGenerator.kt @@ -10,8 +10,12 @@ import com.squareup.kotlinpoet.KModifier import dev.icerock.gradle.generator.ImagesGenerator import dev.icerock.gradle.generator.NOPObjectBodyExtendable import dev.icerock.gradle.generator.ObjectBodyExtendable +import dev.icerock.gradle.utils.svg import org.gradle.api.file.FileTree import java.io.File +import com.android.ide.common.vectordrawable.Svg2Vector +import java.io.FileOutputStream +import java.io.IOException class AndroidImagesGenerator( inputFileTree: FileTree, @@ -38,22 +42,51 @@ class AndroidImagesGenerator( files.map { key to it } }.forEach { (key, file) -> val scale = file.nameWithoutExtension.substringAfter("@").substringBefore("x") - val drawableDirName = "drawable-" + when (scale) { - "0.75" -> "ldpi" - "1" -> "mdpi" - "1.5" -> "hdpi" - "2" -> "xhdpi" - "3" -> "xxhdpi" - "4" -> "xxxhdpi" + val drawableDirName = "drawable" + when (scale) { + "0.75" -> "-ldpi" + "1" -> "-mdpi" + "1.5" -> "-hdpi" + "2" -> "-xhdpi" + "3" -> "-xxhdpi" + "4" -> "-xxxhdpi" else -> { - println("ignore $file - unknown scale ($scale)") - return@forEach + if (file.svg) { + "" + } else { + println("ignore $file - unknown scale ($scale)") + return@forEach + } } } val drawableDir = File(resourcesGenerationDir, drawableDirName) val processedKey = processKey(key) - file.copyTo(File(drawableDir, "$processedKey.${file.extension}")) + + val resourceExtension = if (file.svg) "xml" else file.extension + val resourceFile = File(drawableDir, "$processedKey.${resourceExtension}") + if (file.svg) { + parseSvgToVectorDrawable(file, resourceFile) + } else { + file.copyTo(resourceFile) + } + } + } + + private fun parseSvgToVectorDrawable(svgFile: File, vectorDrawableFile: File) { + try { + vectorDrawableFile.parentFile.mkdirs() + vectorDrawableFile.createNewFile() + val os = FileOutputStream(vectorDrawableFile, false) + try { + Svg2Vector.parseSvgToXml(svgFile, os) + .takeIf { it.isNotEmpty() } + ?.let { error -> println("parse from $svgFile to xml error: $error") } + + } finally { + os.flush() + } + } catch (e: IOException) { + println("parse from $svgFile to xml error: $e") } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/apple/AppleImagesGenerator.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/apple/AppleImagesGenerator.kt index bd5976db..31be4248 100644 --- a/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/apple/AppleImagesGenerator.kt +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/generator/apple/AppleImagesGenerator.kt @@ -9,6 +9,7 @@ import com.squareup.kotlinpoet.KModifier import dev.icerock.gradle.generator.ImagesGenerator import dev.icerock.gradle.generator.ObjectBodyExtendable import dev.icerock.gradle.generator.apple.AppleMRGenerator.Companion.ASSETS_DIR_NAME +import dev.icerock.gradle.utils.svg import org.gradle.api.file.FileTree import java.io.File @@ -40,7 +41,7 @@ class AppleImagesGenerator( val contentsFile = File(assetDir, "Contents.json") val validFiles = files.filter { file -> - VALID_SIZES.any { size -> file.scale == "${size}x" } + file.svg || VALID_SIZES.any { size -> file.scale == "${size}x" } } val uniqueNames = files.map { it.nameWithoutScale }.distinct() @@ -60,16 +61,23 @@ class AppleImagesGenerator( val imagesContent = validFiles.joinToString(separator = ",\n") { file -> val scale = file.scale + // language=js + val scaleString = if (file.svg) "" else ",\n\t\"scale\" : \"$scale\"" + // language=js return@joinToString """ { "idiom" : "universal", - "filename" : "${file.name}", - "scale" : "$scale" + "filename" : "${file.name}"$scaleString } """.trimIndent() } + val svgProperties = if (validFiles.any { file -> file.svg }) { + // language=js + ",\n\t\"properties\" : {\t\t\"preserves-vector-representation\" : true\n\t}" + } else "" + // language=js val content = """ { @@ -79,7 +87,7 @@ class AppleImagesGenerator( "info" : { "version" : 1, "author" : "xcode" - } + }${svgProperties} } """.trimIndent() @@ -90,9 +98,11 @@ class AppleImagesGenerator( private companion object { val VALID_SIZES: IntRange = 1..3 - private val File.scale: String get() = - nameWithoutExtension.substringAfter("@") - private val File.nameWithoutScale: String get() = - nameWithoutExtension.substringBefore("@") + private val File.scale: String + get() = + nameWithoutExtension.substringAfter("@") + private val File.nameWithoutScale: String + get() = + nameWithoutExtension.substringBefore("@") } } diff --git a/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/FileExt.kt b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/FileExt.kt new file mode 100644 index 00000000..2b337d07 --- /dev/null +++ b/resources-generator/src/main/kotlin/dev/icerock/gradle/utils/FileExt.kt @@ -0,0 +1,10 @@ +/* + * Copyright 2023 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. + */ + +package dev.icerock.gradle.utils + +import java.io.File + +internal val File.svg: Boolean get() = + extension == "svg"